import { create } from 'zustand'; import { createJSONStorage, persist, type StateStorage } from 'zustand/middleware'; import { appConfig } from '@/config/appConfig'; import type { CatalogueViewMode, Difficulty, MachineCategory, ReleasePhase, SortKey } from '@/types/catalogue'; export type ThemeMode = 'system' | 'dark' | 'light'; export type ResolvedTheme = 'dark' | 'light'; interface PreferencesState { themeMode: ThemeMode; setThemeMode: (themeMode: ThemeMode) => void; toggleThemeMode: () => void; favourites: string[]; toggleFavourite: (slug: string) => void; isFavourite: (slug: string) => boolean; clearFavourites: () => void; catalogueQuery: string; setCatalogueQuery: (query: string) => void; selectedCategories: MachineCategory[]; setSelectedCategories: (categories: MachineCategory[]) => void; toggleCategory: (category: MachineCategory) => void; selectedDifficulties: Difficulty[]; setSelectedDifficulties: (difficulties: Difficulty[]) => void; toggleDifficulty: (difficulty: Difficulty) => void; selectedPhases: ReleasePhase[]; setSelectedPhases: (phases: ReleasePhase[]) => void; togglePhase: (phase: ReleasePhase) => void; sortKey: SortKey; setSortKey: (sortKey: SortKey) => void; favouritesOnly: boolean; setFavouritesOnly: (favouritesOnly: boolean) => void; catalogueViewMode: CatalogueViewMode; setCatalogueViewMode: (viewMode: CatalogueViewMode) => void; resetCatalogueFilters: () => void; } type PersistedPreferencesState = Pick< PreferencesState, | 'themeMode' | 'favourites' | 'catalogueQuery' | 'selectedCategories' | 'selectedDifficulties' | 'selectedPhases' | 'sortKey' | 'favouritesOnly' | 'catalogueViewMode' >; function createMemoryStorage(): StateStorage { const storage = new Map(); return { getItem: (name) => storage.get(name) ?? null, setItem: (name, value) => { storage.set(name, value); }, removeItem: (name) => { storage.delete(name); } }; } function getStorage(): StateStorage { if (typeof window === 'undefined') { return createMemoryStorage(); } return window.localStorage; } function toggleValue(values: TValue[], value: TValue): TValue[] { return values.includes(value) ? values.filter((candidate) => candidate !== value) : [...values, value]; } const themeCycle: ThemeMode[] = ['system', 'dark', 'light']; export const usePreferencesStore = create()( persist( (set, get) => ({ themeMode: 'system', setThemeMode: (themeMode) => set({ themeMode }), toggleThemeMode: () => { const current = get().themeMode; const currentIndex = themeCycle.indexOf(current); const next = themeCycle[(currentIndex + 1) % themeCycle.length] ?? 'system'; set({ themeMode: next }); }, favourites: [], toggleFavourite: (slug) => { const favourites = get().favourites; const exists = favourites.includes(slug); set({ favourites: exists ? favourites.filter((candidate) => candidate !== slug) : [slug, ...favourites] }); }, isFavourite: (slug) => get().favourites.includes(slug), clearFavourites: () => set({ favourites: [] }), catalogueQuery: '', setCatalogueQuery: (catalogueQuery) => set({ catalogueQuery }), selectedCategories: [], setSelectedCategories: (selectedCategories) => set({ selectedCategories }), toggleCategory: (category) => set((state) => ({ selectedCategories: toggleValue(state.selectedCategories, category) })), selectedDifficulties: [], setSelectedDifficulties: (selectedDifficulties) => set({ selectedDifficulties }), toggleDifficulty: (difficulty) => set((state) => ({ selectedDifficulties: toggleValue(state.selectedDifficulties, difficulty) })), selectedPhases: [], setSelectedPhases: (selectedPhases) => set({ selectedPhases }), togglePhase: (phase) => set((state) => ({ selectedPhases: toggleValue(state.selectedPhases, phase) })), sortKey: 'name', setSortKey: (sortKey) => set({ sortKey }), favouritesOnly: false, setFavouritesOnly: (favouritesOnly) => set({ favouritesOnly }), catalogueViewMode: 'comfortable', setCatalogueViewMode: (catalogueViewMode) => set({ catalogueViewMode }), resetCatalogueFilters: () => set({ catalogueQuery: '', selectedCategories: [], selectedDifficulties: [], selectedPhases: [], sortKey: 'name', favouritesOnly: false }) }), { name: appConfig.storageKeys.preferences, version: 2, storage: createJSONStorage(getStorage), partialize: (state) => ({ themeMode: state.themeMode, favourites: state.favourites, catalogueQuery: state.catalogueQuery, selectedCategories: state.selectedCategories, selectedDifficulties: state.selectedDifficulties, selectedPhases: state.selectedPhases, sortKey: state.sortKey, favouritesOnly: state.favouritesOnly, catalogueViewMode: state.catalogueViewMode }) }, ), );