86 lines
2.3 KiB
TypeScript

import { createSlice, PayloadAction } from "@reduxjs/toolkit";
interface Notification {
id: string;
message: string;
type: "info" | "success" | "error" | "warning";
}
interface UiState {
theme: "light" | "dark";
accentColor: string;
notifications: Notification[];
isMobileSidebarOpen: boolean;
isPreviewMode: boolean;
}
const getInitialTheme = (): "light" | "dark" => {
const saved = localStorage.getItem("theme");
if (saved === "dark" || saved === "light") return saved;
return window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light";
};
const initialState: UiState = {
theme: getInitialTheme(),
accentColor: localStorage.getItem("accentColor") || "#007bff",
notifications: [],
isMobileSidebarOpen: false,
isPreviewMode: false,
};
const uiSlice = createSlice({
name: "ui",
initialState,
reducers: {
toggleTheme: (state) => {
state.theme = state.theme === "light" ? "dark" : "light";
localStorage.setItem("theme", state.theme);
},
setTheme: (state, action: PayloadAction<"light" | "dark">) => {
state.theme = action.payload;
localStorage.setItem("theme", state.theme);
},
setAccentColor: (state, action: PayloadAction<string>) => {
state.accentColor = action.payload;
localStorage.setItem("accentColor", action.payload);
},
addNotification: (
state,
action: PayloadAction<Omit<Notification, "id">>
) => {
const id = `notification-${Date.now()}-${Math.random()
.toString(36)
.substr(2, 9)}`;
state.notifications.push({ ...action.payload, id });
},
removeNotification: (state, action: PayloadAction<string>) => {
state.notifications = state.notifications.filter(
(n) => n.id !== action.payload
);
},
toggleMobileSidebar: (state) => {
state.isMobileSidebarOpen = !state.isMobileSidebarOpen;
},
closeMobileSidebar: (state) => {
state.isMobileSidebarOpen = false;
},
togglePreviewMode: (state) => {
state.isPreviewMode = !state.isPreviewMode;
},
},
});
export const {
toggleTheme,
setTheme,
setAccentColor,
addNotification,
removeNotification,
toggleMobileSidebar,
closeMobileSidebar,
togglePreviewMode,
} = uiSlice.actions;
export default uiSlice.reducer;