feat(CC-077): add Retention Policies page (7 data categories with legal basis)
This commit is contained in:
parent
4f9718dce4
commit
ea7ecb5cf9
1 changed files with 122 additions and 0 deletions
122
src/app/dashboard/privacy/retention/page.tsx
Normal file
122
src/app/dashboard/privacy/retention/page.tsx
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
|
||||
interface RetentionPolicy {
|
||||
id: string; category: string; dataTypes: string[]; retentionDays: number;
|
||||
legalBasis: string; autoDelete: boolean; notes: string;
|
||||
}
|
||||
|
||||
const POLICIES: RetentionPolicy[] = [
|
||||
{
|
||||
id: 'personal-data', category: 'Date Personale (C3)', dataTypes: ['Contacte', 'Persoane', 'Date GDPR'],
|
||||
retentionDays: 365 * 3, legalBasis: 'Consimțământ + Interes legitim', autoDelete: false,
|
||||
notes: 'Ștergere manuală la revocare consimțământ. Anonimizare alternativă permisă.',
|
||||
},
|
||||
{
|
||||
id: 'financial', category: 'Date Financiare (C2)', dataTypes: ['Tranzacții', 'Facturi', 'Contracte'],
|
||||
retentionDays: 365 * 10, legalBasis: 'Obligație legală (Codul Fiscal RO art. 25)', autoDelete: false,
|
||||
notes: 'Retenție 10 ani obligatorie conform legislație fiscală. Nu se poate scurta.',
|
||||
},
|
||||
{
|
||||
id: 'documents', category: 'Documente (C1-C4)', dataTypes: ['Documente OCR', 'Fișiere', 'Atașamente'],
|
||||
retentionDays: 365 * 5, legalBasis: 'Proceduri interne', autoDelete: false,
|
||||
notes: 'C4 (secret) — ștergere securizată la expirare. C0/C1 — arhivare permisă indefinit.',
|
||||
},
|
||||
{
|
||||
id: 'audit-logs', category: 'Audit Logs (C1)', dataTypes: ['Log acces', 'Modificări', 'Sesiuni'],
|
||||
retentionDays: 365 * 2, legalBasis: 'Securitate + Conformitate', autoDelete: true,
|
||||
notes: 'Ștergere automată după 2 ani. Evenimentele critice se păstrează 5 ani.',
|
||||
},
|
||||
{
|
||||
id: 'ai-data', category: 'Activitate AI (C2)', dataTypes: ['Cereri AI', 'Aprobări', 'Costuri'],
|
||||
retentionDays: 365, legalBasis: 'Proceduri interne', autoDelete: true,
|
||||
notes: 'Cereri AI se șterg automat după 1 an. Metadatele anonimizate se păstrează pentru analiză.',
|
||||
},
|
||||
{
|
||||
id: 'observations', category: 'Observații Personale (C2)', dataTypes: ['KPI personal', 'Energie', 'Educație'],
|
||||
retentionDays: 365 * 5, legalBasis: 'Consimțământ explicit', autoDelete: false,
|
||||
notes: 'Utilizatorul controlează complet. Ștergere disponibilă din Export & Deletion.',
|
||||
},
|
||||
{
|
||||
id: 'communications', category: 'Comunicații (C2)', dataTypes: ['Email import', 'Follow-ups', 'Interacțiuni'],
|
||||
retentionDays: 365 * 3, legalBasis: 'Interes legitim', autoDelete: false,
|
||||
notes: 'Emailuri importate necesită consimțământ explicit al expeditorului dacă sunt persoane fizice.',
|
||||
},
|
||||
];
|
||||
|
||||
function formatDays(days: number) {
|
||||
if (days >= 365 * 10) return '10 ani';
|
||||
if (days >= 365 * 5) return '5 ani';
|
||||
if (days >= 365 * 3) return '3 ani';
|
||||
if (days >= 365 * 2) return '2 ani';
|
||||
if (days >= 365) return '1 an';
|
||||
if (days >= 30) return `${Math.floor(days/30)} luni`;
|
||||
return `${days} zile`;
|
||||
}
|
||||
|
||||
export default function RetentionPoliciesPage() {
|
||||
return (
|
||||
<div className="max-w-4xl space-y-6 p-6">
|
||||
<div>
|
||||
<h1 className="font-display text-2xl font-semibold text-ink">Politici de Retenție</h1>
|
||||
<p className="text-sm text-ink-faint mt-1">
|
||||
Reguli de retenție per categorie de date — GDPR + legislație fiscală RO/DE.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="card p-4 bg-primary/5 border-primary/20">
|
||||
<p className="text-xs font-semibold text-ink mb-1">Principii generale</p>
|
||||
<div className="space-y-1 text-xs text-ink-faint">
|
||||
<p>• Datele se rețin doar cât este necesar scopului pentru care au fost colectate.</p>
|
||||
<p>• La expirarea perioadei: ștergere securizată sau anonimizare ireversibilă.</p>
|
||||
<p>• Utilizatorul poate solicita ștergerea anticipată prin <Link href="/dashboard/privacy/export" className="text-primary hover:underline">Export & Deletion</Link>.</p>
|
||||
<p>• Obligațiile legale de retenție (ex: fiscal) nu pot fi reduse prin cerere individuală.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
{POLICIES.map((policy) => (
|
||||
<div key={policy.id} className="card p-5 space-y-3">
|
||||
<div className="flex items-start justify-between gap-3 flex-wrap">
|
||||
<div>
|
||||
<p className="text-sm font-semibold text-ink">{policy.category}</p>
|
||||
<div className="flex flex-wrap gap-1 mt-1">
|
||||
{policy.dataTypes.map((dt) => (
|
||||
<span key={dt} className="rounded-full bg-muted px-2 py-0.5 text-[9px] text-ink-faint">{dt}</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<p className="text-lg font-bold text-ink">{formatDays(policy.retentionDays)}</p>
|
||||
<div className="flex items-center gap-2 justify-end mt-0.5">
|
||||
{policy.autoDelete ? (
|
||||
<span className="text-[10px] text-signal-ok">🤖 auto-ștergere</span>
|
||||
) : (
|
||||
<span className="text-[10px] text-warn">👤 manual</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-1 border-t border-border/50 pt-3">
|
||||
<p className="text-[10px] font-semibold text-ink-faint">Temei legal: {policy.legalBasis}</p>
|
||||
<p className="text-[10px] text-ink-faint">{policy.notes}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Link href="/dashboard/privacy/export" className="rounded-lg border px-4 py-2 text-sm text-ink hover:bg-muted/50">
|
||||
Cerere ștergere date →
|
||||
</Link>
|
||||
<Link href="/dashboard/privacy/audit" className="rounded-lg border px-4 py-2 text-sm text-ink hover:bg-muted/50">
|
||||
Audit log →
|
||||
</Link>
|
||||
<Link href="/dashboard/privacy/consents" className="rounded-lg border px-4 py-2 text-sm text-ink hover:bg-muted/50">
|
||||
Consimțăminte GDPR →
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue