Files
queueful/frontend/app/src/config/store.ts
2024-04-20 17:37:41 +03:00

138 lines
4.5 KiB
TypeScript

import {
ReducerType,
configureStore,
createAction,
createReducer,
} from "@reduxjs/toolkit";
import { setupListeners } from "@reduxjs/toolkit/query";
import { AuthApi, User } from "../slice/AuthApi";
import { QueueApi } from "../slice/QueueApi";
import { NewsApi } from "../slice/NewsApi";
export type AuthDataType = {
token: string | null;
clientId: string | null;
user: { name: string | null; username: string } | null;
};
const initialAuthDataState: AuthDataType = {
token: null,
clientId: null,
user: null,
};
export type SettingsType = {
language: string | undefined;
theme: string | undefined;
};
const initialSettingsState: SettingsType = {
language: undefined,
theme: undefined,
};
export type StorePrototype = {
AuthApi: ReducerType;
auth: AuthDataType;
settings: SettingsType;
};
export const updateToken = createAction<string>("auth/updateToken");
export const getLocalToken = createAction("auth/getLocalToken");
export const updateClient = createAction<string | null>("auth/updateClient");
export const getLocalClient = createAction("auth/getLocalClient");
export const updateUser = createAction<User>("auth/updateUser");
export const logOut = createAction("auth/logOut");
export const setLanguage = createAction<string>("settings/setLanguage");
export const loadLanguage = createAction("settings/loadLanguage");
export const setTheme = createAction<string>("settings/setTheme");
export const loadTheme = createAction("settings/loadTheme");
export const store = configureStore({
reducer: {
// Add the generated reducer as a specific top-level slice
[AuthApi.reducerPath]: AuthApi.reducer,
[QueueApi.reducerPath]: QueueApi.reducer,
[NewsApi.reducerPath]: NewsApi.reducer,
auth: createReducer(initialAuthDataState, (builder) => {
builder.addCase(updateToken, (state, action) => {
state.token = action.payload;
localStorage.setItem("token", action.payload);
});
builder.addCase(getLocalToken, (state) => {
const token: string | null = localStorage.getItem("token");
if (token) {
state.token = token;
}
});
builder.addCase(updateClient, (state, action) => {
if (action.payload) {
state.clientId = action.payload;
localStorage.setItem("clientId", action.payload);
} else {
localStorage.removeItem("clientId");
}
});
builder.addCase(getLocalClient, (state) => {
const clientId: string | null = localStorage.getItem("clientId");
if (clientId) {
state.clientId = clientId;
}
});
builder.addCase(updateUser, (state, action) => {
state.user = action.payload;
});
builder.addCase(logOut, (state) => {
localStorage.removeItem("token");
state.token = null;
state.user = null;
});
}),
settings: createReducer(initialSettingsState, (builder) => {
builder.addCase(setLanguage, (state, action) => {
state.language = action.payload || "en";
localStorage.setItem("language", action.payload || "en");
});
builder.addCase(loadLanguage, (state) => {
const language: string | null = localStorage.getItem("language");
if (language) {
state.language = language;
} else {
const clientLanguage = navigator.language.startsWith("en-")
? "en"
: "ru";
state.language = clientLanguage;
}
});
builder.addCase(setTheme, (state, action) => {
state.theme = action.payload || "dark";
localStorage.setItem("theme", action.payload || "dark");
});
builder.addCase(loadTheme, (state) => {
const theme: string | null = localStorage.getItem("theme");
if (theme) {
state.theme = theme;
} else {
const darkThemeMq = window.matchMedia("(prefers-color-scheme: dark)");
state.theme = darkThemeMq.matches ? "dark" : "light";
}
});
}),
},
// Adding the api middleware enables caching, invalidation, polling,
// and other useful features of `rtk-query`.
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware()
.concat(AuthApi.middleware)
.concat(QueueApi.middleware)
.concat(NewsApi.middleware),
});
// optional, but required for refetchOnFocus/refetchOnReconnect behaviors
// see `setupListeners` docs - takes an optional callback as the 2nd arg for customization
setupListeners(store.dispatch);
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;