import { PayloadAction, createSlice } from '@reduxjs/toolkit' import { CategoryType } from '@shared/types/category.type' import { ThunkDTO, ThunkPersist } from '@shared/types/thunk.type' import { RoutineManager } from '@utils/routine.manager' import { RootState } from '../../stores' import { startListening } from '../../stores/middleware/listener.middleware' import { setToken } from './user.reducer' export interface ReducerState { thunks: Record<CategoryType, ThunkPersist | null> } const initialState: ReducerState = { thunks: { DEVICE: null, TABLE: null, TAB: null }, } const RoutineSlice = createSlice({ name: 'routine', initialState, reducers: { addRoutine: (state: any, { payload }: PayloadAction<ThunkDTO>) => { const thunk: ThunkPersist = { category: payload.category, payload: payload.payload, thunkId: payload.thunk.id, lastupdate: Date.now() } state.thunks[payload.category] = thunk }, refreshUpdateTimer: (state: any, { payload }: PayloadAction<CategoryType>) => { state.thunks[payload].lastupdate = Date.now() }, removeAll: (state) => { state.thunks = initialState.thunks }, }, }) export const { addRoutine, refreshUpdateTimer } = RoutineSlice.actions // on logout remove all routine startListening({ predicate: (action) => setToken.match(action) && action.payload === null, effect: async (_, listenerApi) => { RoutineManager.unsubscribeAll() listenerApi.dispatch(RoutineSlice.actions.removeAll()) }, }) /** * Add new routine * * This listener handles the connection between the RoutingManager that * stores the non persistable thunk object and the peristable thunk information. * The persistable information are stored in this reducer */ startListening({ predicate: (action) => addRoutine.match(action), effect: async (action, listenerApi) => { const { thunk } = action.payload as ThunkDTO const subscription = await listenerApi.dispatch(thunk(action.payload.payload)) if (subscription.error) { throw new Error('Error during routine execution: ' + subscription.error.message) } RoutineManager.add(subscription.payload, action.payload.category) }, }) // unsubscribe old routine that is in the same category startListening({ predicate: (action) => addRoutine.match(action), effect: async (action, listenerApi) => { const { routine } = listenerApi.getOriginalState() as RootState const category = action.payload.category; const lastThunk = routine.thunks[category as CategoryType] if (lastThunk) { RoutineManager.unsubscribe(category) } }, }) export default RoutineSlice.reducer