|
@@ -0,0 +1,108 @@
|
|
|
+import { createSlice, Draft, PayloadAction } from '@reduxjs/toolkit';
|
|
|
+import {
|
|
|
+ EntitiesState,
|
|
|
+ FiltersState,
|
|
|
+ PaginationState,
|
|
|
+ SelectionState,
|
|
|
+ UIState,
|
|
|
+} from './type.model';
|
|
|
+
|
|
|
+export function createEntityListSlices<T, F extends object>(
|
|
|
+ namespace: string,
|
|
|
+ fetchThunk,
|
|
|
+ deleteThunk
|
|
|
+) {
|
|
|
+ const entitiesSlice = createSlice({
|
|
|
+ name: `${namespace}/entities`,
|
|
|
+ initialState: { data: [], total: 0 } as EntitiesState<T>,
|
|
|
+ reducers: {},
|
|
|
+ extraReducers(builder) {
|
|
|
+ builder.addCase(
|
|
|
+ fetchThunk.fulfilled,
|
|
|
+ (state, action: PayloadAction<{ data: T[]; total: number }>) => {
|
|
|
+ state.data = action.payload.data as unknown as Draft<T>[];
|
|
|
+ state.total = action.payload.total;
|
|
|
+ // return {
|
|
|
+ // ...state,
|
|
|
+ // data: action.payload.data,
|
|
|
+ // total: action.payload.total,
|
|
|
+ // };
|
|
|
+ }
|
|
|
+ );
|
|
|
+ builder.addCase(
|
|
|
+ deleteThunk.fulfilled,
|
|
|
+ (state, action: PayloadAction<string[]>) => {
|
|
|
+ state.data = state.data.filter(
|
|
|
+ (item) => !action.payload.includes((item as { id: string }).id)
|
|
|
+ );
|
|
|
+ }
|
|
|
+ );
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ const filtersSlice = createSlice({
|
|
|
+ name: `${namespace}/filters`,
|
|
|
+ initialState: {} as FiltersState<F>,
|
|
|
+ reducers: {
|
|
|
+ setFilters(state, action: PayloadAction<Partial<FiltersState<F>>>) {
|
|
|
+ return { ...state, ...action.payload };
|
|
|
+ },
|
|
|
+ resetFilters() {
|
|
|
+ return {} as FiltersState<F>;
|
|
|
+ },
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ const paginationSlice = createSlice({
|
|
|
+ name: `${namespace}/pagination`,
|
|
|
+ initialState: { page: 1, pageSize: 10 } as PaginationState,
|
|
|
+ reducers: {
|
|
|
+ setPage(state, action: PayloadAction<number>) {
|
|
|
+ state.page = action.payload;
|
|
|
+ },
|
|
|
+ setPageSize(state, action: PayloadAction<number>) {
|
|
|
+ state.pageSize = action.payload;
|
|
|
+ },
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ const selectionSlice = createSlice({
|
|
|
+ name: `${namespace}/selection`,
|
|
|
+ initialState: { selectedIds: [] } as SelectionState,
|
|
|
+ reducers: {
|
|
|
+ setSelectedIds(state, action: PayloadAction<string[]>) {
|
|
|
+ state.selectedIds = action.payload;
|
|
|
+ },
|
|
|
+ clearSelection(state) {
|
|
|
+ state.selectedIds = [];
|
|
|
+ },
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ const uiSlice = createSlice({
|
|
|
+ name: `${namespace}/ui`,
|
|
|
+ initialState: { loading: false, error: null } as UIState,
|
|
|
+ reducers: {},
|
|
|
+ extraReducers(builder) {
|
|
|
+ builder.addCase(fetchThunk.pending, (state) => {
|
|
|
+ state.loading = true;
|
|
|
+ state.error = null;
|
|
|
+ });
|
|
|
+ builder.addCase(fetchThunk.fulfilled, (state) => {
|
|
|
+ state.loading = false;
|
|
|
+ });
|
|
|
+ builder.addCase(fetchThunk.rejected, (state, action) => {
|
|
|
+ state.loading = false;
|
|
|
+ state.error = action.error.message ?? 'Unknown error';
|
|
|
+ });
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ return {
|
|
|
+ entitiesSlice,
|
|
|
+ filtersSlice,
|
|
|
+ paginationSlice,
|
|
|
+ selectionSlice,
|
|
|
+ uiSlice,
|
|
|
+ };
|
|
|
+}
|