148 lines
4.1 KiB
TypeScript
148 lines
4.1 KiB
TypeScript
import { create } from 'zustand';
|
|
import type { Family, Category, User, FamilyMember, Theme, Locale } from '../types';
|
|
|
|
const getStoredPreferences = () => {
|
|
const theme = (localStorage.getItem('theme') as Theme) || 'light';
|
|
const locale = (localStorage.getItem('locale') as Locale) || 'ru';
|
|
return { theme, locale };
|
|
};
|
|
|
|
interface CacheEntry<T> {
|
|
data: T;
|
|
timestamp: number;
|
|
}
|
|
|
|
interface CacheState {
|
|
categories: Map<number, CacheEntry<Category[]>>;
|
|
members: Map<number, CacheEntry<FamilyMember[]>>;
|
|
}
|
|
|
|
const CACHE_TTL = 5 * 60 * 1000;
|
|
|
|
interface AppState {
|
|
user: User | null;
|
|
isAuthenticated: boolean;
|
|
isLoading: boolean;
|
|
selectedFamily: Family | null;
|
|
families: Family[];
|
|
categories: Category[];
|
|
familyMembers: FamilyMember[];
|
|
preferences: { theme: Theme; locale: Locale };
|
|
cache: CacheState;
|
|
|
|
setUser: (user: User | null) => void;
|
|
setIsLoading: (loading: boolean) => void;
|
|
setSelectedFamily: (family: Family | null) => void;
|
|
setFamilies: (families: Family[]) => void;
|
|
setCategories: (categories: Category[]) => void;
|
|
setFamilyMembers: (members: FamilyMember[]) => void;
|
|
setPreferences: (prefs: Partial<{ theme: Theme; locale: Locale }>) => void;
|
|
logout: () => void;
|
|
|
|
getCachedCategories: (familyId: number) => Category[] | null;
|
|
setCachedCategories: (familyId: number, categories: Category[]) => void;
|
|
getCachedMembers: (familyId: number) => FamilyMember[] | null;
|
|
setCachedMembers: (familyId: number, members: FamilyMember[]) => void;
|
|
clearCache: () => void;
|
|
}
|
|
|
|
export const useStore = create<AppState>((set, get) => ({
|
|
user: null,
|
|
isAuthenticated: false,
|
|
isLoading: true,
|
|
selectedFamily: null,
|
|
families: [],
|
|
categories: [],
|
|
familyMembers: [],
|
|
preferences: getStoredPreferences(),
|
|
cache: {
|
|
categories: new Map(),
|
|
members: new Map(),
|
|
},
|
|
|
|
setUser: (user) => set({ user, isAuthenticated: !!user }),
|
|
|
|
setIsLoading: (isLoading) => set({ isLoading }),
|
|
|
|
setSelectedFamily: (family) => set({ selectedFamily: family }),
|
|
|
|
setFamilies: (families) => set({ families }),
|
|
|
|
setCategories: (categories) => set({ categories }),
|
|
|
|
setFamilyMembers: (familyMembers) => set({ familyMembers }),
|
|
|
|
setPreferences: (prefs) => set((state) => {
|
|
const newPrefs = { ...state.preferences, ...prefs };
|
|
if (prefs.theme) localStorage.setItem('theme', prefs.theme);
|
|
if (prefs.locale) localStorage.setItem('locale', prefs.locale);
|
|
return { preferences: newPrefs };
|
|
}),
|
|
|
|
getCachedCategories: (familyId: number) => {
|
|
const cached = get().cache.categories.get(familyId);
|
|
if (!cached) return null;
|
|
if (Date.now() - cached.timestamp > CACHE_TTL) {
|
|
set((state) => {
|
|
const newCache = { ...state.cache };
|
|
newCache.categories.delete(familyId);
|
|
return { cache: newCache };
|
|
});
|
|
return null;
|
|
}
|
|
return cached.data;
|
|
},
|
|
|
|
setCachedCategories: (familyId: number, categories: Category[]) => {
|
|
set((state) => {
|
|
const newCache = { ...state.cache };
|
|
newCache.categories.set(familyId, { data: categories, timestamp: Date.now() });
|
|
return { cache: newCache };
|
|
});
|
|
},
|
|
|
|
getCachedMembers: (familyId: number) => {
|
|
const cached = get().cache.members.get(familyId);
|
|
if (!cached) return null;
|
|
if (Date.now() - cached.timestamp > CACHE_TTL) {
|
|
set((state) => {
|
|
const newCache = { ...state.cache };
|
|
newCache.members.delete(familyId);
|
|
return { cache: newCache };
|
|
});
|
|
return null;
|
|
}
|
|
return cached.data;
|
|
},
|
|
|
|
setCachedMembers: (familyId: number, members: FamilyMember[]) => {
|
|
set((state) => {
|
|
const newCache = { ...state.cache };
|
|
newCache.members.set(familyId, { data: members, timestamp: Date.now() });
|
|
return { cache: newCache };
|
|
});
|
|
},
|
|
|
|
clearCache: () => {
|
|
set((state) => ({
|
|
cache: {
|
|
categories: new Map(),
|
|
members: new Map(),
|
|
},
|
|
}));
|
|
},
|
|
|
|
logout: () => set({
|
|
user: null,
|
|
isAuthenticated: false,
|
|
selectedFamily: null,
|
|
families: [],
|
|
categories: [],
|
|
familyMembers: [],
|
|
cache: {
|
|
categories: new Map(),
|
|
members: new Map(),
|
|
},
|
|
}),
|
|
}));
|