export const AUTOSAVE_KEY = "frivolite-studio-v1"; export const PROJECTS_KEY = "realknot-projects-v1"; export type StoredProject = { id: string; /** Владелец схемы — id пользователя из auth-service. */ ownerId: string; title: string; updatedAt: number; elements: number; thumb: string; data: unknown; }; const safe = (fn: () => T, fallback: T): T => { try { return fn(); } catch { return fallback; } }; /** SUPABASE: `supabase.from("projects").select("*")` (RLS по owner_id). */ export const listAllProjects = (): StoredProject[] => safe(() => { const raw = localStorage.getItem(PROJECTS_KEY); const arr = raw ? (JSON.parse(raw) as StoredProject[]) : []; return arr .map((p) => ({ ...p, ownerId: p.ownerId ?? "admin" })) .sort((a, b) => b.updatedAt - a.updatedAt); }, []); export const listProjects = (ownerId: string): StoredProject[] => listAllProjects().filter((p) => p.ownerId === ownerId); const write = (list: StoredProject[]) => safe(() => localStorage.setItem(PROJECTS_KEY, JSON.stringify(list)), undefined); export const upsertProject = (p: StoredProject) => { const list = listAllProjects().filter((x) => x.id !== p.id); list.unshift(p); write(list); return listProjects(p.ownerId); }; export const removeProject = (id: string, ownerId: string) => { write(listAllProjects().filter((x) => x.id !== id)); return listProjects(ownerId); }; export const renameProject = (id: string, title: string, ownerId: string) => { write(listAllProjects().map((x) => (x.id === id ? { ...x, title } : x))); return listProjects(ownerId); }; /** Удаление всех схем пользователя (например, при удалении аккаунта). */ export const removeProjectsOfOwner = (ownerId: string) => { write(listAllProjects().filter((x) => x.ownerId !== ownerId)); }; export const countProjectsByOwner = (): Record => listAllProjects().reduce>((acc, p) => { acc[p.ownerId] = (acc[p.ownerId] ?? 0) + 1; return acc; }, {}); export const formatStamp = (ts: number) => new Date(ts).toLocaleString("ru-RU", { day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit", }); export const newId = () => Math.random().toString(36).slice(2, 10);