Skip to content
Snippets Groups Projects
routine.reducer.ts 4.28 KiB
Newer Older
  • Learn to ignore specific revisions
  • import { debugMessage } from '@helper/debug'
    
    import { PayloadAction, createSlice } from '@reduxjs/toolkit'
    import { RoutineManager } from '@utils/routine.manager'
    import { RootState } from '../../stores'
    import { startListening } from '../../stores/middleware/listener.middleware'
    import { setToken } from './user.reducer'
    
    // ---------------- thunk types ---------------- 
    
    
    interface ThunkEntityDTO {
    
    Matthias Feyll's avatar
    Matthias Feyll committed
        payload: Object
    
         * Only one subscription per category is allowed.
         * New subscription will unsubscribe and overwrite the old one
    
        category: CATEGORIES
    
    /**
     *  This Wrapper holds the actual thunk information 
     *  as well as additional information 
     */
    interface ThunkWrapper extends ThunkEntityDTO {
    
        id?: number
        locked: boolean
    
    }
    
    export enum CATEGORIES {
        TABLE,
    
    // ---------------- reducer types ---------------- 
    
    export interface ReducerState {
        thunks: { [key in keyof typeof CATEGORIES]: ThunkWrapper | null }
    }
    
    
    Matthias Feyll's avatar
    Matthias Feyll committed
    const initialState: ReducerState = {
    
        thunks: {
            TABLE: null,
    
    Matthias Feyll's avatar
    Matthias Feyll committed
    const RoutineSlice = createSlice({
        name: 'routine',
    
        initialState,
        reducers: {
    
            addRoutine: (state: any, { payload }: PayloadAction<ThunkEntityDTO>) => {
    
                if (state.thunks[CATEGORIES[payload.category]]?.locked) {
    
                }
    
                const newThunk: ThunkWrapper = { ...payload, locked: true }
    
                state.thunks[CATEGORIES[payload.category]] = newThunk
    
            setThunkId: (state, { payload }: PayloadAction<{ id: number; category: CATEGORIES }>) => {
    
    Matthias Feyll's avatar
    Matthias Feyll committed
                const thunk = state.thunks[CATEGORIES[payload.category] as any]
    
    
                if (!thunk) {
    
                    debugMessage("Desired thunk of category " + payload.category + " is not available")
                    return
    
    Matthias Feyll's avatar
    Matthias Feyll committed
                state.thunks[CATEGORIES[payload.category] as any] = { ...thunk, id: payload.id, locked: false }
    
            removeAll: (state) => {
    
                state.thunks = initialState.thunks
    
    Matthias Feyll's avatar
    Matthias Feyll committed
    export const { addRoutine } = RoutineSlice.actions
    
    Matthias Feyll's avatar
    Matthias Feyll committed
    // on logout remove all routine
    
    startListening({
    
        predicate: (action) => setToken.match(action) && action.payload === null,
    
        effect: async (_, listenerApi) => {
    
            RoutineManager.unsubscribeAll()
    
            listenerApi.dispatch(RoutineSlice.actions.removeAll())
    
    Matthias Feyll's avatar
    Matthias Feyll committed
    // on rehydrate add all persistet routines
    
    // TODO -> thunk does not have the thunk function object due to its coming from the store that ignores the value.
    // at this point we have to figure out how to get the thunk function out of the "string" name
    // startListening({
    //     predicate: ({ type }) => type === REHYDRATE,
    //     effect: async (_, listenerApi) => {
    //         const { routine } = listenerApi.getState() as RootState
    //         for (const [_, thunk] of Object.entries<ThunkEntity>(routine.thunks)) {
    //             if (!thunk) {
    //                 continue
    //             }
    //             const dto: ThunkEntityDTO = thunk
    //             listenerApi.dispatch(addRoutine(dto))
    //         }
    //     },
    // })
    
    /**
     * 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({
    
    Matthias Feyll's avatar
    Matthias Feyll committed
        predicate: (action) => addRoutine.match(action),
    
        effect: async (action, listenerApi) => {
    
            const { thunk } = action.payload as ThunkWrapper
    
            const subscription = await listenerApi.dispatch(thunk(action.payload.payload))
            const thunkId = await RoutineManager.add(subscription.payload)
            listenerApi.dispatch(
                RoutineSlice.actions.setThunkId({ id: thunkId, category: action.payload.category })
            )
    
    // unsubscribe old routine
    startListening({
        predicate: (action) => addRoutine.match(action),
        effect: async (action, listenerApi) => {
            const { routine } = listenerApi.getOriginalState() as RootState
    
    Matthias Feyll's avatar
    Matthias Feyll committed
            const lastThunk = routine.thunks[CATEGORIES[action.payload.category] as any]
    
    Matthias Feyll's avatar
    Matthias Feyll committed
                if (!lastThunk.id) {
                    throw new Error()
                    // TODO
                }
    
    
                RoutineManager.unsubscribe(lastThunk.id)
            }
        },
    })
    
    
    Matthias Feyll's avatar
    Matthias Feyll committed
    export default RoutineSlice.reducer