import { useSyncExternalStore } from 'react'; import { api, ApiError, type HomeResponse } from '@/api'; import { KEYS, store } from '@/lib/storage'; /** * کتابی که دانش‌آموز در هر پایه انتخاب کرده («هندسه»، «حسابان»، …). یک منبعِ حقیقت برای هر دو تبِ «آزمون‌ها» و * «درس‌ها»: هر دو از `home` در AppData می‌خوانند و `home` همیشه نقشه‌ی همین کتاب است، پس جابه‌جایی در یکی در * دیگری هم دیده می‌شود. * * هر پایه جدا نگه داشته می‌شود (با عوض‌کردنِ پایه، انتخابِ پایه‌ی قبلی نباید به دوازدهم بپرد) و در * localStorage می‌ماند تا بعد از بستنِ اپ همان کتاب باز شود. منبعِ حقیقتِ فهرستِ کتاب‌ها سرور است * (`home.subjects`)؛ این فقط «کدام» را می‌گوید. */ type SubjectMap = Record; function read(): SubjectMap { try { const parsed: unknown = JSON.parse(store.get(KEYS.subjects) ?? '{}'); return parsed && typeof parsed === 'object' ? (parsed as SubjectMap) : {}; } catch { return {}; } } let current: SubjectMap = read(); const listeners = new Set<() => void>(); export const subjectStore = { get: (gradeId: number): string | null => current[String(gradeId)] ?? null, set(gradeId: number, key: string | null) { const id = String(gradeId); if ((current[id] ?? null) === key) return; const next = { ...current }; if (key) next[id] = key; else delete next[id]; current = next; store.set(KEYS.subjects, JSON.stringify(next)); listeners.forEach((l) => l()); }, subscribe(listener: () => void) { listeners.add(listener); return () => listeners.delete(listener); }, snapshot: () => current, }; /** کتابِ انتخاب‌شده‌ی این پایه؛ null یعنی هنوز انتخابی نشده (سرور اولین کتاب را می‌دهد). */ export function useSelectedSubject(gradeId: number | null | undefined): string | null { const map = useSyncExternalStore(subjectStore.subscribe, subjectStore.snapshot, subjectStore.snapshot); return gradeId == null ? null : map[String(gradeId)] ?? null; } /** * نقشه‌ی کتابِ انتخاب‌شده. کلیدِ ذخیره‌شده‌ای که سرور دیگر نمی‌شناسد (کتاب برداشته شده یا پایه عوض شده) * ۴۰۰ می‌گیرد؛ آن را پاک می‌کنیم و نقشه‌ی پیش‌فرض را می‌گیریم تا کاربر صفحه‌ی خالی نبیند. */ export async function fetchHome(gradeId: number | null | undefined): Promise { const wanted = gradeId == null ? null : subjectStore.get(gradeId); try { return await api.home(wanted ?? undefined); } catch (err) { if (wanted && gradeId != null && err instanceof ApiError && err.status === 400) { subjectStore.set(gradeId, null); return api.home(); } throw err; } }