99 lines
2.3 KiB
TypeScript
99 lines
2.3 KiB
TypeScript
import { createAsyncThunk, createSlice, PayloadAction } from "@reduxjs/toolkit";
|
|
|
|
export interface SidebarLink {
|
|
id?: string;
|
|
title: string;
|
|
path: string;
|
|
icon?: string;
|
|
groups?: string[];
|
|
children?: SidebarLink[];
|
|
}
|
|
|
|
export interface SidebarPayload {
|
|
links: SidebarLink[];
|
|
}
|
|
|
|
export type FieldGroupMap = Record<string, Record<string, string>>;
|
|
|
|
export interface AppMetadata {
|
|
success: boolean;
|
|
message?: string;
|
|
field_names?: FieldGroupMap;
|
|
job_titles?: string[];
|
|
groups?: string[];
|
|
merchants?: string[];
|
|
countries?: string[];
|
|
sidebar?: SidebarPayload;
|
|
transaction_status?: string[];
|
|
}
|
|
|
|
interface MetadataState {
|
|
data: AppMetadata | null;
|
|
status: "idle" | "loading" | "succeeded" | "failed";
|
|
error: string | null;
|
|
lastFetchedAt: number | null;
|
|
}
|
|
|
|
const initialState: MetadataState = {
|
|
data: null,
|
|
status: "idle",
|
|
error: null,
|
|
lastFetchedAt: null,
|
|
};
|
|
|
|
export const fetchMetadata = createAsyncThunk<
|
|
AppMetadata,
|
|
void,
|
|
{ rejectValue: string }
|
|
>("metadata/fetch", async (_, { rejectWithValue }) => {
|
|
try {
|
|
const res = await fetch("/api/metadata", {
|
|
method: "GET",
|
|
cache: "no-store",
|
|
});
|
|
const data = await res.json();
|
|
if (!res.ok) {
|
|
return rejectWithValue(data?.message || "Failed to fetch metadata");
|
|
}
|
|
return data as AppMetadata;
|
|
} catch (err) {
|
|
return rejectWithValue((err as Error)?.message || "Network error");
|
|
}
|
|
});
|
|
|
|
const metadataSlice = createSlice({
|
|
name: "metadata",
|
|
initialState,
|
|
reducers: {
|
|
clearMetadata(state) {
|
|
state.data = null;
|
|
state.error = null;
|
|
state.status = "idle";
|
|
state.lastFetchedAt = null;
|
|
},
|
|
},
|
|
extraReducers: builder => {
|
|
builder
|
|
.addCase(fetchMetadata.pending, state => {
|
|
state.status = "loading";
|
|
state.error = null;
|
|
})
|
|
.addCase(
|
|
fetchMetadata.fulfilled,
|
|
(state, action: PayloadAction<AppMetadata>) => {
|
|
state.status = "succeeded";
|
|
state.data = action.payload;
|
|
state.lastFetchedAt = Date.now();
|
|
}
|
|
)
|
|
.addCase(fetchMetadata.rejected, (state, action) => {
|
|
state.status = "failed";
|
|
state.error = (action.payload as string) || "Unknown error";
|
|
});
|
|
},
|
|
});
|
|
|
|
export const { clearMetadata } = metadataSlice.actions;
|
|
|
|
export default metadataSlice.reducer;
|