@@ -2,46 +2,50 @@ import type { ActionReducerMapBuilder } from '@reduxjs/toolkit';
22import { createSlice } from '@reduxjs/toolkit' ;
33import { parseApiError } from '../../../api-contract/utils' ;
44import type { CreateVisit } from '../../types' ;
5- import type { VisitsInfo } from '../types' ;
5+ import type { LoadVisits , VisitsInfo } from '../types' ;
66import { createNewVisits } from '../visitCreation' ;
77import type { createVisitsAsyncThunk } from './createVisitsAsyncThunk' ;
88
9- interface VisitsReducerOptions < State extends VisitsInfo , AT extends ReturnType < typeof createVisitsAsyncThunk > > {
9+ interface VisitsReducerOptions < State , T extends LoadVisits > {
1010 name : string ;
11- asyncThunk : AT ;
12- initialState : State ;
13- filterCreatedVisits : ( state : State , createdVisits : CreateVisit [ ] ) => CreateVisit [ ] ;
14- extraReducers ?: ( builder : ActionReducerMapBuilder < State > ) => void ;
11+ asyncThunk : ReturnType < typeof createVisitsAsyncThunk < T > > ;
12+ initialState : VisitsInfo < State > ;
13+ filterCreatedVisits : ( state : VisitsInfo < State > , createdVisits : CreateVisit [ ] ) => CreateVisit [ ] ;
14+ extraReducers ?: ( builder : ActionReducerMapBuilder < VisitsInfo < State > > ) => void ;
1515}
1616
17- export const createVisitsReducer = < State extends VisitsInfo , AT extends ReturnType < typeof createVisitsAsyncThunk > > (
18- { name, asyncThunk, initialState, filterCreatedVisits, extraReducers } : VisitsReducerOptions < State , AT > ,
17+ export const createVisitsReducer = < State , T extends LoadVisits > (
18+ { name, asyncThunk, initialState, filterCreatedVisits, extraReducers } : VisitsReducerOptions < State , T > ,
1919) => {
2020 const { pending, rejected, fulfilled, progressChanged, fallbackToInterval } = asyncThunk ;
2121 const { reducer, actions } = createSlice ( {
2222 name,
2323 initialState,
2424 reducers : {
25- cancelGetVisits : ( state ) => ( { ... state , cancelLoad : true } ) ,
25+ cancelGetVisits : ( ) => ( { status : 'canceled' as const } ) ,
2626 } ,
2727 extraReducers : ( builder ) => {
28- builder . addCase ( pending , ( ) => ( { ...initialState , loading : true } ) ) ;
29- builder . addCase ( rejected , ( _ , { error } ) => (
30- { ...initialState , errorData : parseApiError ( error ) ?? null }
31- ) ) ;
32- builder . addCase ( fulfilled , ( state , { payload } ) => (
33- // Unpack the whole payload, as it could have different props depending on the concrete reducer
34- { ...state , ...payload , loading : false , progress : null , errorData : null }
28+ builder . addCase ( pending , ( ) => ( { status : 'loading' , progress : null } ) ) ;
29+ builder . addCase ( progressChanged , ( state , { payload : progress } ) => (
30+ // Update progress only if already loading
31+ state . status !== 'loading' ? state : { status : 'loading' , progress }
3532 ) ) ;
3633
37- builder . addCase ( progressChanged , ( state , { payload : progress } ) => ( { ...state , progress } ) ) ;
38- builder . addCase ( fallbackToInterval , ( state , { payload : fallbackInterval } ) => (
39- { ...state , fallbackInterval }
34+ builder . addCase ( rejected , ( _ , { error } ) => ( { status : 'error' , error : parseApiError ( error ) } ) ) ;
35+
36+ // Unpack the whole payload, as it could have different props depending on the concrete reducer
37+ builder . addCase ( fulfilled , ( state , { payload } ) => ( { ...state , ...payload , status : 'loaded' } ) ) ;
38+
39+ builder . addCase ( fallbackToInterval , ( _ , { payload : fallbackInterval } ) => (
40+ { status : 'fallback' , fallbackInterval }
4041 ) ) ;
4142
4243 builder . addCase ( createNewVisits , ( state , { payload } ) => {
44+ if ( state . status !== 'loaded' ) {
45+ return state ;
46+ }
47+
4348 const { visits } = state ;
44- // @ts -expect-error TODO Fix type inference
4549 const newVisits = filterCreatedVisits ( state , payload . createdVisits ) . map ( ( { visit } ) => visit ) ;
4650
4751 return ! newVisits . length ? state : { ...state , visits : [ ...newVisits , ...visits ] } ;
0 commit comments