'use client' /** * Löschfristen - Data Retention Management * * Art. 17 DSGVO - Recht auf Löschung * Art. 5 Abs. 1 lit. e DSGVO - Speicherbegrenzung * * Migriert auf SDK API: /sdk/v1/dsgvo/retention-policies */ import { useState, useEffect } from 'react' import { PagePurpose } from '@/components/common/PagePurpose' interface RetentionPolicy { id: string tenant_id: string namespace_id?: string name: string description: string data_category: string retention_period_days: number retention_period_text: string legal_basis: string legal_reference?: string deletion_method: string // automatic, manual, anonymization deletion_procedure?: string exception_criteria?: string applicable_systems?: string[] responsible_person: string responsible_department: string status: string // draft, active, archived last_review_at?: string next_review_at?: string created_at: string updated_at: string } export default function LoeschfristenPage() { const [policies, setPolicies] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [showCreateModal, setShowCreateModal] = useState(false) const [newPolicy, setNewPolicy] = useState({ name: '', description: '', data_category: '', retention_period_days: 365, retention_period_text: '1 Jahr', legal_basis: 'legal_requirement', legal_reference: '', deletion_method: 'automatic', deletion_procedure: '', responsible_person: '', responsible_department: '', status: 'draft' }) useEffect(() => { loadPolicies() }, []) async function loadPolicies() { setLoading(true) setError(null) try { const res = await fetch('/sdk/v1/dsgvo/retention-policies', { headers: { 'X-Tenant-ID': localStorage.getItem('bp_tenant_id') || '', 'X-User-ID': localStorage.getItem('bp_user_id') || '', } }) if (!res.ok) { throw new Error(`HTTP ${res.status}`) } const data = await res.json() setPolicies(data.policies || []) } catch (err) { console.error('Failed to load retention policies:', err) setError('Fehler beim Laden der Löschfristen') } finally { setLoading(false) } } async function createPolicy() { try { const res = await fetch('/sdk/v1/dsgvo/retention-policies', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Tenant-ID': localStorage.getItem('bp_tenant_id') || '', 'X-User-ID': localStorage.getItem('bp_user_id') || '', }, body: JSON.stringify(newPolicy) }) if (!res.ok) { throw new Error(`HTTP ${res.status}`) } setShowCreateModal(false) setNewPolicy({ name: '', description: '', data_category: '', retention_period_days: 365, retention_period_text: '1 Jahr', legal_basis: 'legal_requirement', legal_reference: '', deletion_method: 'automatic', deletion_procedure: '', responsible_person: '', responsible_department: '', status: 'draft' }) loadPolicies() } catch (err) { console.error('Failed to create policy:', err) alert('Fehler beim Erstellen der Löschfrist') } } async function exportPolicies(format: 'csv' | 'json') { try { const res = await fetch(`/sdk/v1/dsgvo/export/retention?format=${format}`, { headers: { 'X-Tenant-ID': localStorage.getItem('bp_tenant_id') || '', 'X-User-ID': localStorage.getItem('bp_user_id') || '', } }) if (!res.ok) { throw new Error(`HTTP ${res.status}`) } const blob = await res.blob() const url = window.URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = `loeschfristen-export.${format}` a.click() window.URL.revokeObjectURL(url) } catch (err) { console.error('Export failed:', err) alert('Export fehlgeschlagen') } } const getStatusBadge = (status: string) => { switch (status) { case 'active': return Aktiv case 'draft': return Entwurf case 'archived': return Archiviert default: return null } } const getDeletionMethodBadge = (method: string) => { switch (method) { case 'automatic': return Auto-Löschung case 'manual': return Manuell case 'anonymization': return Anonymisierung default: return null } } const getLegalBasisLabel = (basis: string) => { const labels: Record = { 'legal_requirement': 'Gesetzliche Pflicht', 'consent': 'Einwilligung', 'legitimate_interest': 'Berechtigtes Interesse', 'contract': 'Vertragserfüllung', } return labels[basis] || basis } // Group policies by status const activePolicies = policies.filter(p => p.status === 'active') const draftPolicies = policies.filter(p => p.status === 'draft') if (loading) { return (
Lade Löschfristen...
) } return (
{error && (
{error}
)} {/* Header Actions */}
{/* Quick Stats */}
{policies.length}
Löschfristen gesamt
{activePolicies.length}
Aktive Richtlinien
{draftPolicies.length}
Entwürfe
{policies.filter(p => p.deletion_method === 'automatic').length}
Auto-Löschung
{/* Policies List */} {policies.length === 0 ? (
🗑️

Keine Löschfristen definiert

Legen Sie Aufbewahrungsfristen für verschiedene Datenkategorien an.

) : (

Aufbewahrungsfristen

{policies.map((policy) => (

{policy.name}

{getStatusBadge(policy.status)} {getDeletionMethodBadge(policy.deletion_method)}
{policy.description && (

{policy.description}

)}
Datenkategorie: {policy.data_category}
Frist: {policy.retention_period_text} ({policy.retention_period_days} Tage)
Rechtsgrundlage: {getLegalBasisLabel(policy.legal_basis)}
{policy.legal_reference && (
Referenz: {policy.legal_reference}
)}
{policy.responsible_person && ( Verantwortlich: {policy.responsible_person} )} {policy.responsible_department && ( Abteilung: {policy.responsible_department} )} {policy.last_review_at && ( Letzte Prüfung: {new Date(policy.last_review_at).toLocaleDateString('de-DE')} )} {policy.next_review_at && ( Nächste Prüfung: {new Date(policy.next_review_at).toLocaleDateString('de-DE')} )}
{policy.applicable_systems && policy.applicable_systems.length > 0 && (
{policy.applicable_systems.map((sys, idx) => ( {sys} ))}
)}
))}
)} {/* Info */}

Speicherbegrenzung (Art. 5)

Personenbezogene Daten dürfen nur so lange gespeichert werden, wie es für die Zwecke erforderlich ist. Die automatische Löschung stellt die Einhaltung dieser Vorgabe sicher.

{/* Create Modal */} {showCreateModal && (

Neue Löschfrist anlegen

setNewPolicy({ ...newPolicy, name: e.target.value })} className="w-full border border-slate-300 rounded-lg px-3 py-2" placeholder="z.B. Aufbewahrung Nutzerkonten" />