Files
magikarp-collection/src/lib/checklist.ts

85 lines
2.7 KiB
TypeScript

export const CHECKLIST_KEY_V1 = 'magikarp-checklist-v1';
export const CHECKLIST_KEY_V2 = 'magikarp-checklist-v2';
export type VariantKey = 'base' | 'holofoil' | 'reverseHolofoil';
export type VariantState = Partial<Record<VariantKey, boolean>>;
export type ChecklistV2 = Record<string, VariantState>; // cardId -> variant flags
// Legacy loader (v1)
export function loadChecklistV1(): Set<string> {
if (typeof window === 'undefined') return new Set();
try {
const raw = localStorage.getItem(CHECKLIST_KEY_V1);
if (!raw) return new Set();
const arr = JSON.parse(raw) as string[];
return new Set(arr);
} catch {
return new Set();
}
}
// Local-only helpers (kept for migration / fallback)
export function loadChecklistLocal(): ChecklistV2 {
if (typeof window === 'undefined') return {};
try {
const v2 = localStorage.getItem(CHECKLIST_KEY_V2);
if (v2) return JSON.parse(v2) as ChecklistV2;
const v1 = loadChecklistV1();
if (v1.size === 0) return {};
const migrated: ChecklistV2 = {};
v1.forEach((id) => { migrated[id] = { base: true }; });
return migrated;
} catch {
return {};
}
}
export function saveChecklistLocal(state: ChecklistV2) {
if (typeof window === 'undefined') return;
try {
localStorage.setItem(CHECKLIST_KEY_V2, JSON.stringify(state));
} catch {
// ignore
}
}
// Server-backed persistence
export async function loadChecklistServer(): Promise<ChecklistV2> {
try {
const res = await fetch('/api/checklist', { cache: 'no-store' });
if (!res.ok) throw new Error('failed');
const json = await res.json();
const serverData = (json?.data || {}) as ChecklistV2;
// If server is empty, try migrate from local and push
const hasServerData = serverData && Object.keys(serverData).length > 0;
if (!hasServerData && typeof window !== 'undefined') {
const local = loadChecklistLocal();
const hasLocal = Object.keys(local).length > 0;
if (hasLocal) {
await saveChecklistServer(local);
// Clear legacy keys after successful push
try { localStorage.removeItem(CHECKLIST_KEY_V2); } catch {}
try { localStorage.removeItem(CHECKLIST_KEY_V1); } catch {}
return local;
}
}
return serverData || {};
} catch {
// As a fallback (e.g., during dev with API not ready), use local
return loadChecklistLocal();
}
}
export async function saveChecklistServer(state: ChecklistV2): Promise<void> {
try {
await fetch('/api/checklist', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(state),
});
} catch {
// best-effort: persist locally so user doesn't lose progress offline
saveChecklistLocal(state);
}
}