File size: 2,384 Bytes
eddc354
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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);