Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | 25x 1x 1x 2x 25x 25x 25x 25x 193x 193x 193x 193x 193x 193x 193x 193x | import { createAction, createAsyncThunk, type UnknownAction } from '@reduxjs/toolkit';
import { projectService } from '@/entities/project/model/project.service';
import { createAsyncEntitySlice } from '@/shared/lib/store';
import type { Project } from '@/shared/types';
import {
ENTITY_LOADING_STATUSES,
NAMES,
PROJECT_SLICE_ACTIONS,
} from '@/shared/constants';
// ───────────────────────────────────────────────
// Base async slice
// ───────────────────────────────────────────────
export const {
reducer: baseReducer,
adapter: projectsAdapter,
thunks: {
fetchAllThunk: fetchProjects,
createOneThunk: createProject,
updateOneThunk: updateProject,
deleteOneThunk: deleteProject,
},
} = createAsyncEntitySlice<
Project,
{ name: string },
{ id: string; changes: Partial<Project> }
>({
name: NAMES.PROJECTS,
fetchAll: projectService.getProjects,
createOne: projectService.createProject,
updateOne: projectService.updateProject,
deleteOne: async (id: string): Promise<string> => {
await projectService.deleteWithRelations(id);
return id;
},
sortComparer: (a, b) => b.updatedAt - a.updatedAt,
});
// ───────────────────────────────────────────────
// Clear all
// ───────────────────────────────────────────────
export const clearAllProjects = createAsyncThunk(
PROJECT_SLICE_ACTIONS.PROJECTS_CLEAR_ALL,
async (_, { dispatch }) => {
await projectService.clearAll();
await dispatch(fetchProjects());
},
);
// ───────────────────────────────────────────────
// State
// ───────────────────────────────────────────────
type BaseProjectsState = ReturnType<typeof baseReducer>;
export interface ProjectsState extends BaseProjectsState {
activeId: string | null;
}
export const initialState: ProjectsState = {
...(baseReducer(undefined, { type: '@@INIT' }) as BaseProjectsState),
activeId: null,
};
// ───────────────────────────────────────────────
// Actions
// ───────────────────────────────────────────────
export const setActiveProjectId = createAction<string | null>(
PROJECT_SLICE_ACTIONS.PROJECT_SET_ACTIVE_ID,
);
// add an action for direct insert a project to entities
export const upsertProject = createAction<Project>(PROJECT_SLICE_ACTIONS.PROJECT_UPSET);
// ───────────────────────────────────────────────
// Reducer
// ───────────────────────────────────────────────
export function projectsReducer(
state: ProjectsState = initialState,
action: UnknownAction,
): ProjectsState {
Iif (setActiveProjectId.match(action)) {
return { ...state, activeId: action.payload };
}
Iif (upsertProject.match(action)) {
const nextState = projectsAdapter.upsertOne(state, action.payload);
return { ...nextState, activeId: state.activeId };
}
let next = baseReducer(state, action) as ProjectsState;
Iif (deleteProject.fulfilled.match(action)) {
const deletedId = action.payload as string;
if (next.activeId === deletedId) next = { ...next, activeId: null };
}
Iif (clearAllProjects.pending.match(action)) {
return { ...next, loading: ENTITY_LOADING_STATUSES.PENDING };
}
Iif (clearAllProjects.fulfilled.match(action)) {
return { ...next, activeId: null, loading: ENTITY_LOADING_STATUSES.SUCCEEDED };
}
Iif (clearAllProjects.rejected.match(action)) {
return { ...next, loading: ENTITY_LOADING_STATUSES.FAILED };
}
return next;
}
|