diff --git a/src/app/dashboard/documents/shared/page.tsx b/src/app/dashboard/documents/shared/page.tsx new file mode 100644 index 0000000..29b0268 --- /dev/null +++ b/src/app/dashboard/documents/shared/page.tsx @@ -0,0 +1,146 @@ +'use client'; + +import { useMemo, useState } from 'react'; +import { useQuery } from '@tanstack/react-query'; +import Link from 'next/link'; +import { apiFetch } from '../../../../lib/api'; +import { useSession } from '../../../../components/session-provider'; + +interface Document { + id: string; title: string; type: string | null; classification: string | null; + tags: string[]; status: string | null; createdAt: string; updatedAt: string; +} + +const SHARED_TAGS = ['shared', 'partajat', 'public', 'distribuit', 'trimis']; + +function isShared(doc: Document) { + const tags = doc.tags.map((t) => t.toLowerCase()); + const status = (doc.status ?? '').toLowerCase(); + return tags.some((t) => SHARED_TAGS.includes(t)) || status === 'shared' || status === 'sent'; +} + +const CLS_CLS: Record = { + C0: 'bg-signal-ok/10 text-signal-ok', + C1: 'bg-primary/10 text-primary', + C2: 'bg-warn/10 text-warn', + C3: 'bg-signal-danger/10 text-signal-danger', + C4: 'bg-signal-danger/20 text-signal-danger', +}; + +export default function SharedDocsPage() { + const { activeTenant } = useSession(); + const tenantId = activeTenant?.tenantId ?? ''; + const [search, setSearch] = useState(''); + const [clsFilter, setClsFilter] = useState('all'); + + const { data: allDocs = [], isLoading } = useQuery({ + queryKey: ['docs-shared', tenantId], + queryFn: () => apiFetch('/v1/documents?limit=500', { tenantId }), + enabled: Boolean(tenantId), staleTime: 60_000, + }); + + const shared = useMemo(() => allDocs.filter(isShared), [allDocs]); + + const filtered = useMemo(() => { + return shared.filter((d) => { + if (clsFilter !== 'all' && d.classification !== clsFilter) return false; + if (search && !d.title.toLowerCase().includes(search.toLowerCase())) return false; + return true; + }); + }, [shared, clsFilter, search]); + + const classGroups = useMemo(() => { + const counts: Record = {}; + for (const d of shared) { + const cls = d.classification ?? 'C1'; + counts[cls] = (counts[cls] ?? 0) + 1; + } + return counts; + }, [shared]); + + return ( +
+
+
+

Documente Partajate

+

+ {isLoading ? 'Se încarcă…' : `${shared.length} documente partajate (tag: shared / partajat / public)`} +

+
+ Toate documentele → +
+ + {shared.length === 0 && !isLoading && ( +
+

+ Pentru a marca un document ca partajat, adaugă tagul shared sau partajat documentului. +

+
+ )} + + {/* Classification breakdown */} + {shared.length > 0 && ( +
+ {Object.entries(classGroups).sort().map(([cls, count]) => ( +
+

{count}

+

{cls}

+
+ ))} +
+ )} + + {shared.length > 0 && ( +
+

+ ⚠ Documentele C3/C4 partajate extern necesită revizuire GDPR. Verifică dacă destinatarii au dreptul de acces. +

+
+ )} + +
+ setSearch(e.target.value)} + className="rounded-lg border bg-card px-3 py-2 text-sm text-ink focus:outline-none focus:ring-2 focus:ring-ring" /> +
+ {['all', 'C0', 'C1', 'C2', 'C3', 'C4'].map((cls) => ( + + ))} +
+
+ + {isLoading ? ( +
Se încarcă…
+ ) : filtered.length === 0 ? ( +
+

🔗

+

Niciun document partajat.

+
+ ) : ( +
+ {filtered.map((doc) => ( +
+
+

{doc.title}

+
+ {doc.type && {doc.type}} + {new Date(doc.updatedAt).toLocaleDateString('ro-RO')} +
+
+
+ {doc.tags.filter((t) => SHARED_TAGS.includes(t.toLowerCase())).map((t) => ( + {t} + ))} + + {doc.classification ?? 'C1'} + +
+
+ ))} +
+ )} +
+ ); +}