"use client"; import { useEffect, useState } from "react"; export interface ActivityItem { id: string; namespace: string; moduleLabel: string; label: string; action: "creat" | "actualizat"; timestamp: string; // ISO } export interface DashboardKpis { registraturaThisWeek: number; registraturaOpen: number; deadlinesThisWeek: number; overdueDeadlines: number; contactsThisMonth: number; inventoryActive: number; } const MODULE_LABELS: Record = { registratura: "Registratură", "address-book": "Agendă", "it-inventory": "IT Inventory", "password-vault": "Parole", "digital-signatures": "Semnături", "word-templates": "Șabloane Word", "tag-manager": "Tag Manager", "prompt-generator": "Prompt Generator", }; /** Extract a human-readable label from a stored entity */ function pickLabel(obj: Record): string { const candidates = ["subject", "name", "label", "title", "number"]; for (const key of candidates) { const val = obj[key]; if (typeof val === "string" && val.trim()) return val.trim(); } return "(fără titlu)"; } function startOfWeek(): Date { const d = new Date(); d.setHours(0, 0, 0, 0); d.setDate(d.getDate() - d.getDay() + 1); // Monday return d; } function startOfMonth(): Date { const d = new Date(); d.setHours(0, 0, 0, 0); d.setDate(1); return d; } function readAllNamespaceItems(): Record[]> { if (typeof window === "undefined") return {}; const PREFIX = "architools:"; const result: Record[]> = {}; for (let i = 0; i < window.localStorage.length; i++) { const fullKey = window.localStorage.key(i); if (!fullKey?.startsWith(PREFIX)) continue; const rest = fullKey.slice(PREFIX.length); const colonIdx = rest.indexOf(":"); if (colonIdx === -1) continue; const ns = rest.slice(0, colonIdx); try { const raw = window.localStorage.getItem(fullKey); if (!raw) continue; const parsed = JSON.parse(raw) as unknown; if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) { if (!result[ns]) result[ns] = []; result[ns].push(parsed as Record); } } catch { // ignore malformed entries } } return result; } export function useDashboardData() { const [activity, setActivity] = useState([]); const [kpis, setKpis] = useState({ registraturaThisWeek: 0, registraturaOpen: 0, deadlinesThisWeek: 0, overdueDeadlines: 0, contactsThisMonth: 0, inventoryActive: 0, }); useEffect(() => { const allItems = readAllNamespaceItems(); const weekStart = startOfWeek(); const monthStart = startOfMonth(); const now = new Date(); // --- Activity feed --- const activityItems: ActivityItem[] = []; for (const [ns, items] of Object.entries(allItems)) { const moduleLabel = MODULE_LABELS[ns] ?? ns; for (const item of items) { const updatedAt = typeof item.updatedAt === "string" ? item.updatedAt : null; const createdAt = typeof item.createdAt === "string" ? item.createdAt : null; const id = typeof item.id === "string" ? item.id : String(Math.random()); if (!updatedAt && !createdAt) continue; const timestamp = updatedAt ?? createdAt ?? ""; const created = createdAt ? new Date(createdAt) : null; const updated = updatedAt ? new Date(updatedAt) : null; const action: "creat" | "actualizat" = created && updated && Math.abs(updated.getTime() - created.getTime()) < 2000 ? "creat" : "actualizat"; activityItems.push({ id: `${ns}:${id}`, namespace: ns, moduleLabel, label: pickLabel(item), action, timestamp, }); } } activityItems.sort((a, b) => b.timestamp.localeCompare(a.timestamp)); setActivity(activityItems.slice(0, 20)); // --- KPIs --- const registraturaItems = allItems["registratura"] ?? []; const registraturaThisWeek = registraturaItems.filter((e) => { const d = typeof e.date === "string" ? new Date(e.date) : null; return d && d >= weekStart; }).length; const registraturaOpen = registraturaItems.filter( (e) => e.status === "deschis", ).length; // Deadlines let deadlinesThisWeek = 0; let overdueDeadlines = 0; for (const entry of registraturaItems) { const deadlines = Array.isArray(entry.trackedDeadlines) ? (entry.trackedDeadlines as Record[]) : []; for (const dl of deadlines) { if (dl.resolution !== "pending") continue; const dueDate = typeof dl.dueDate === "string" ? new Date(dl.dueDate) : null; if (!dueDate) continue; if (dueDate < now) overdueDeadlines++; if ( dueDate >= weekStart && dueDate <= new Date(weekStart.getTime() + 7 * 86400000) ) deadlinesThisWeek++; } } const contactItems = allItems["address-book"] ?? []; const contactsThisMonth = contactItems.filter((c) => { const d = typeof c.createdAt === "string" ? new Date(c.createdAt) : null; return d && d >= monthStart; }).length; const inventoryItems = allItems["it-inventory"] ?? []; const inventoryActive = inventoryItems.filter( (i) => i.status === "active", ).length; setKpis({ registraturaThisWeek, registraturaOpen, deadlinesThisWeek, overdueDeadlines, contactsThisMonth, inventoryActive, }); }, []); return { activity, kpis }; }