Spaces:
Sleeping
Sleeping
| 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 = <T,>(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<string, number> => | |
| listAllProjects().reduce<Record<string, number>>((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); | |