84 lines
1.9 KiB
TypeScript
84 lines
1.9 KiB
TypeScript
import { create } from "zustand";
|
|
import type { Language } from "@/types";
|
|
import i18n from "@/i18n";
|
|
|
|
type Theme = "dark" | "light";
|
|
|
|
interface UiState {
|
|
theme: Theme;
|
|
language: Language;
|
|
sidebarOpen: boolean;
|
|
setTheme: (theme: Theme) => void;
|
|
toggleTheme: () => void;
|
|
setLanguage: (lang: Language) => void;
|
|
toggleSidebar: () => void;
|
|
setSidebarOpen: (open: boolean) => void;
|
|
}
|
|
|
|
function applyTheme(theme: Theme): void {
|
|
const root = document.documentElement;
|
|
if (theme === "dark") root.classList.add("dark");
|
|
else root.classList.remove("dark");
|
|
try {
|
|
localStorage.setItem("airpg_theme", theme);
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
}
|
|
|
|
function applyLanguage(lang: Language): void {
|
|
void i18n.changeLanguage(lang);
|
|
try {
|
|
localStorage.setItem("airpg_lang", lang);
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
}
|
|
|
|
function initialTheme(): Theme {
|
|
try {
|
|
const stored = localStorage.getItem("airpg_theme") as Theme | null;
|
|
if (stored === "dark" || stored === "light") return stored;
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
// Default: dark
|
|
return "dark";
|
|
}
|
|
|
|
function initialLanguage(): Language {
|
|
const detected = i18n.language as Language | undefined;
|
|
if (detected === "en" || detected === "ru") return detected;
|
|
return "en";
|
|
}
|
|
|
|
const initialThemeValue = initialTheme();
|
|
applyTheme(initialThemeValue);
|
|
const initialLangValue = initialLanguage();
|
|
applyLanguage(initialLangValue);
|
|
|
|
export const useUiStore = create<UiState>((set, get) => ({
|
|
theme: initialThemeValue,
|
|
language: initialLangValue,
|
|
sidebarOpen: false,
|
|
|
|
setTheme: (theme) => {
|
|
applyTheme(theme);
|
|
set({ theme });
|
|
},
|
|
|
|
toggleTheme: () => {
|
|
const next: Theme = get().theme === "dark" ? "light" : "dark";
|
|
applyTheme(next);
|
|
set({ theme: next });
|
|
},
|
|
|
|
setLanguage: (lang) => {
|
|
applyLanguage(lang);
|
|
set({ language: lang });
|
|
},
|
|
|
|
toggleSidebar: () => set({ sidebarOpen: !get().sidebarOpen }),
|
|
setSidebarOpen: (open) => set({ sidebarOpen: open }),
|
|
}));
|