'use client' /** * Loeschfristen - Data Retention Management * * Art. 17 DSGVO - Recht auf Loeschung * Art. 5 Abs. 1 lit. e DSGVO - Speicherbegrenzung * * Verwaltet: * - Aufbewahrungsfristen * - Consent-Deadlines * - Automatische Loeschungen */ import { useState, useEffect } from 'react' import { PagePurpose } from '@/components/common/PagePurpose' const API_BASE = '/api/admin/consent' interface RetentionPolicy { id: string dataCategory: string retentionPeriod: string legalBasis: string autoDelete: boolean lastRun?: string nextRun?: string itemsToDelete?: number } interface ConsentDeadline { id: string userId: string documentName: string versionNumber: string deadlineAt: string reminderCount: number daysRemaining: number status: 'pending' | 'overdue' | 'completed' } interface DeletionJob { id: string dataCategory: string scheduledAt: string status: 'scheduled' | 'running' | 'completed' | 'failed' itemsProcessed: number itemsTotal: number completedAt?: string } export default function LoeschfristenPage() { const [activeTab, setActiveTab] = useState<'policies' | 'deadlines' | 'jobs' | 'manual'>('policies') const [loading, setLoading] = useState(false) const [processing, setProcessing] = useState(false) // Mock data - in production, this comes from API const retentionPolicies: RetentionPolicy[] = [ { id: 'pol_1', dataCategory: 'Nutzerkonten (inaktiv)', retentionPeriod: '3 Jahre nach letzter Aktivitaet', legalBasis: 'Art. 5 Abs. 1 lit. e DSGVO', autoDelete: true, lastRun: '2024-12-01', nextRun: '2025-01-01', itemsToDelete: 23 }, { id: 'pol_2', dataCategory: 'Consent-Nachweise', retentionPeriod: '6 Jahre nach Widerruf', legalBasis: 'Nachweispflicht', autoDelete: true, lastRun: '2024-12-01', nextRun: '2025-01-01', itemsToDelete: 0 }, { id: 'pol_3', dataCategory: 'System-Logs', retentionPeriod: '90 Tage', legalBasis: 'Berechtigtes Interesse (IT-Sicherheit)', autoDelete: true, lastRun: '2024-12-14', nextRun: '2024-12-15', itemsToDelete: 15420 }, { id: 'pol_4', dataCategory: 'Security-Logs', retentionPeriod: '2 Jahre', legalBasis: 'Berechtigtes Interesse (Sicherheit)', autoDelete: true, lastRun: '2024-12-01', nextRun: '2025-01-01', itemsToDelete: 0 }, { id: 'pol_5', dataCategory: 'Lernfortschrittsdaten', retentionPeriod: 'Ende Schuljahr + 1 Jahr', legalBasis: 'Vertragserfuellung', autoDelete: false, itemsToDelete: 45 }, { id: 'pol_6', dataCategory: 'KI-Verarbeitungsdaten', retentionPeriod: 'Sofortige Loeschung', legalBasis: 'Datenminimierung', autoDelete: true, lastRun: '2024-12-15', nextRun: 'Kontinuierlich', itemsToDelete: 0 }, ] const consentDeadlines: ConsentDeadline[] = [ { id: 'dl_1', userId: 'usr_456', documentName: 'AGB', versionNumber: 'v2.1.0', deadlineAt: '2025-01-15', reminderCount: 2, daysRemaining: 20, status: 'pending' }, { id: 'dl_2', userId: 'usr_789', documentName: 'Datenschutz', versionNumber: 'v3.0.0', deadlineAt: '2024-12-28', reminderCount: 3, daysRemaining: 3, status: 'pending' }, { id: 'dl_3', userId: 'usr_012', documentName: 'AGB', versionNumber: 'v2.1.0', deadlineAt: '2024-12-10', reminderCount: 4, daysRemaining: -5, status: 'overdue' }, ] const deletionJobs: DeletionJob[] = [ { id: 'job_1', dataCategory: 'System-Logs', scheduledAt: '2024-12-14T02:00:00', status: 'completed', itemsProcessed: 12500, itemsTotal: 12500, completedAt: '2024-12-14T02:15:00' }, { id: 'job_2', dataCategory: 'Inaktive Sessions', scheduledAt: '2024-12-14T03:00:00', status: 'completed', itemsProcessed: 450, itemsTotal: 450, completedAt: '2024-12-14T03:02:00' }, { id: 'job_3', dataCategory: 'System-Logs', scheduledAt: '2024-12-15T02:00:00', status: 'scheduled', itemsProcessed: 0, itemsTotal: 15420 }, ] async function triggerDeadlineProcessing() { setProcessing(true) try { const token = localStorage.getItem('bp_admin_token') const res = await fetch(`${API_BASE}/deadlines`, { method: 'POST', headers: token ? { 'Authorization': `Bearer ${token}` } : {} }) if (res.ok) { alert('Deadline-Verarbeitung gestartet') } else { alert('Fehler bei der Verarbeitung') } } catch { alert('Verbindungsfehler') } finally { setProcessing(false) } } const tabs = [ { id: 'policies', label: 'Aufbewahrungsfristen' }, { id: 'deadlines', label: 'Consent-Deadlines' }, { id: 'jobs', label: 'Loeschjobs' }, { id: 'manual', label: 'Manuelle Loeschung' }, ] const getStatusBadge = (status: string) => { switch (status) { case 'completed': return Abgeschlossen case 'running': return Laeuft case 'scheduled': return Geplant case 'failed': return Fehlgeschlagen case 'pending': return Ausstehend case 'overdue': return Ueberfaellig default: return null } } return (
{/* Quick Stats */}
{retentionPolicies.length}
Aufbewahrungsrichtlinien
{consentDeadlines.filter(d => d.status === 'pending').length}
Offene Deadlines
{consentDeadlines.filter(d => d.status === 'overdue').length}
Ueberfaellige
{retentionPolicies.reduce((sum, p) => sum + (p.itemsToDelete || 0), 0).toLocaleString()}
Zur Loeschung vorgemerkt
{/* Tabs */}
{tabs.map((tab) => ( ))}
{/* Policies Tab */} {activeTab === 'policies' && (

Aufbewahrungsfristen

{retentionPolicies.map((policy) => (

{policy.dataCategory}

{policy.autoDelete ? ( Auto-Loeschung ) : ( Manuell )} {(policy.itemsToDelete || 0) > 0 && ( {policy.itemsToDelete} zur Loeschung )}
Frist: {policy.retentionPeriod}
Rechtsgrundlage: {policy.legalBasis}
{policy.lastRun && (
Letzter Lauf: {policy.lastRun}
)} {policy.nextRun && (
Naechster Lauf: {policy.nextRun}
)}
{(policy.itemsToDelete || 0) > 0 && ( )}
))}
)} {/* Deadlines Tab */} {activeTab === 'deadlines' && (

Consent-Deadlines

Nutzer haben 30 Tage Zeit, neue Pflichtdokumente zu akzeptieren. Nach Ablauf wird der Account gesperrt, bis die Zustimmung erteilt wird.

{consentDeadlines.map((deadline) => ( ))}
Nutzer Dokument Deadline Erinnerungen Status Aktionen
{deadline.userId}
{deadline.documentName}
{deadline.versionNumber}
{deadline.deadlineAt}
{deadline.daysRemaining < 0 ? `${Math.abs(deadline.daysRemaining)} Tage ueberfaellig` : `${deadline.daysRemaining} Tage verbleibend`}
{deadline.reminderCount} gesendet {getStatusBadge(deadline.status)} {deadline.status === 'overdue' && ( )}
)} {/* Jobs Tab */} {activeTab === 'jobs' && (

Loeschjobs

{deletionJobs.map((job) => (

{job.dataCategory}

{getStatusBadge(job.status)}
Geplant: {new Date(job.scheduledAt).toLocaleString('de-DE')}
0 ? (job.itemsProcessed / job.itemsTotal) * 100 : 0}%` }} />
{job.itemsProcessed.toLocaleString()} / {job.itemsTotal.toLocaleString()}
{job.completedAt && (
Abgeschlossen: {new Date(job.completedAt).toLocaleString('de-DE')}
)}
))}
)} {/* Manual Tab */} {activeTab === 'manual' && (

Manuelle Loeschung

Achtung: Manuelle Loeschung

Manuelle Loeschungen sind unwiderruflich. Stellen Sie sicher, dass keine gesetzlichen Aufbewahrungsfristen verletzt werden und alle notwendigen Backups erstellt wurden.

Nutzer-Daten loeschen

Loescht alle personenbezogenen Daten eines Nutzers (Art. 17 DSGVO)

Alte Logs bereinigen

)}
{/* Info */}

Speicherbegrenzung (Art. 5)

Personenbezogene Daten duerfen nur so lange gespeichert werden, wie es fuer die Zwecke erforderlich ist. Die automatische Loeschung stellt die Einhaltung dieser Vorgabe sicher.

) }