Files
abode/src/react/store/slices/loading.ts
T
2026-06-29 23:07:14 +00:00

65 lines
1.5 KiB
TypeScript

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<string, LoadingState>;
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<string>) => {
delete state[action.payload];
},
},
extraReducers(builder) {
builder.addCase(clearAll, () => initialLoadingSlice);
},
});
declare module "../store.js" {
export interface LazySlices extends WithSlice<typeof loadingSlice> {}
}
export const {
selectors: { getLoading, getLoadingStatus },
actions: { setLoading, clearLoading },
selectSlice: selectLoading,
} = loadingSlice.injectInto(reducer);