Files
ai-rpg/frontend/src/stores/uiStore.ts

84 lines
1.9 KiB
TypeScript
Raw Normal View History

2026-06-20 19:13:05 +03:00
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 }),
}));