import { createSlice, type PayloadAction, type WithSlice, } from "@reduxjs/toolkit"; import { clearAll } from "../actions/clearAll.js"; import { reducer } from "../store.js"; import type { ObjectError } from "../../../util/error.js"; export type LoadingSlice = Record; export type LoadingState = ( | { status: "loading"; } | { status: "refreshing"; } | { status: "error"; error: ObjectError; } | { status: "loaded"; } ) & { type: string; params: unknown; }; const initialLoadingSlice: LoadingSlice = {}; const loadingSlice = createSlice({ name: "loading", initialState: initialLoadingSlice, selectors: { getLoading: (state, id: string): LoadingState | null => state[id] ?? null, getLoadingStatus: (state, id: string): LoadingState["status"] | null => state[id]?.status ?? null, }, reducers: { setLoading: ( state, action: PayloadAction<[id: string, state: LoadingState]>, ) => { state[action.payload[0]] = action.payload[1]; }, clearLoading: (state, action: PayloadAction) => { delete state[action.payload]; }, }, extraReducers(builder) { builder.addCase(clearAll, () => initialLoadingSlice); }, }); declare module "../store.js" { export interface LazySlices extends WithSlice {} } export const { selectors: { getLoading, getLoadingStatus }, actions: { setLoading, clearLoading }, selectSlice: selectLoading, } = loadingSlice.injectInto(reducer);