'use client' import React, { useState } from 'react' import { DSFA, DSFAReviewSchedule, DSFAReviewTrigger } from '@/lib/sdk/dsfa/types' interface ReviewScheduleSectionProps { dsfa: DSFA onUpdate: (data: Record) => Promise isSubmitting: boolean } const REVIEW_FREQUENCIES = [ { value: 6, label: '6 Monate', description: 'Empfohlen bei hohem Risiko oder dynamischer Verarbeitung' }, { value: 12, label: '12 Monate (jaehrlich)', description: 'Standardempfehlung fuer die meisten Verarbeitungen' }, { value: 24, label: '24 Monate (alle 2 Jahre)', description: 'Bei stabilem, niedrigem Risiko' }, { value: 36, label: '36 Monate (alle 3 Jahre)', description: 'Bei sehr stabiler Verarbeitung mit minimalem Risiko' }, ] const TRIGGER_TYPES = [ { value: 'scheduled', label: 'Planmaessig', description: 'Regelmaessige Ueberpruefung nach Zeitplan', icon: '📅' }, { value: 'risk_change', label: 'Risiko-Aenderung', description: 'Aenderung der Risikobewertung', icon: '⚠️' }, { value: 'new_technology', label: 'Neue Technologie', description: 'Einfuehrung neuer technischer Systeme', icon: '🔧' }, { value: 'new_purpose', label: 'Neuer Zweck', description: 'Aenderung oder Erweiterung des Verarbeitungszwecks', icon: '🎯' }, { value: 'incident', label: 'Sicherheitsvorfall', description: 'Datenschutzvorfall oder Sicherheitsproblem', icon: '🚨' }, { value: 'regulatory', label: 'Regulatorisch', description: 'Gesetzes- oder Behoerden-Aenderung', icon: '📜' }, { value: 'other', label: 'Sonstiges', description: 'Anderer Ausloser', icon: '📋' }, ] export function ReviewScheduleSection({ dsfa, onUpdate, isSubmitting }: ReviewScheduleSectionProps) { const existingSchedule = dsfa.review_schedule const existingTriggers = dsfa.review_triggers || [] const [nextReviewDate, setNextReviewDate] = useState(existingSchedule?.next_review_date || '') const [reviewFrequency, setReviewFrequency] = useState(existingSchedule?.review_frequency_months || 12) const [reviewResponsible, setReviewResponsible] = useState(existingSchedule?.review_responsible || '') const [triggers, setTriggers] = useState(existingTriggers) const [selectedTriggerTypes, setSelectedTriggerTypes] = useState( [...new Set(existingTriggers.map(t => t.trigger_type))] ) // Calculate suggested next review date based on frequency const suggestNextReviewDate = () => { const date = new Date() date.setMonth(date.getMonth() + reviewFrequency) return date.toISOString().split('T')[0] } const toggleTriggerType = (type: string) => { setSelectedTriggerTypes(prev => prev.includes(type) ? prev.filter(t => t !== type) : [...prev, type] ) } const handleSave = async () => { const schedule: DSFAReviewSchedule = { next_review_date: nextReviewDate, review_frequency_months: reviewFrequency, last_review_date: existingSchedule?.last_review_date, review_responsible: reviewResponsible, } // Generate triggers from selected types const newTriggers: DSFAReviewTrigger[] = selectedTriggerTypes.map(type => { const existingTrigger = triggers.find(t => t.trigger_type === type) if (existingTrigger) return existingTrigger const triggerInfo = TRIGGER_TYPES.find(t => t.value === type) return { id: crypto.randomUUID(), trigger_type: type as DSFAReviewTrigger['trigger_type'], description: triggerInfo?.description || '', detected_at: new Date().toISOString(), detected_by: 'system', review_required: true, review_completed: false, changes_made: [], } }) await onUpdate({ review_schedule: schedule, review_triggers: newTriggers, }) } // Check if review is overdue const isOverdue = existingSchedule?.next_review_date ? new Date(existingSchedule.next_review_date) < new Date() : false return (
{/* Info Banner */}

Art. 35 Abs. 11 DSGVO

"Der Verantwortliche ueberprueft erforderlichenfalls, ob die Verarbeitung gemaess der Datenschutz-Folgenabschaetzung durchgefuehrt wird, zumindest wenn hinsichtlich des mit den Verarbeitungsvorgaengen verbundenen Risikos Aenderungen eingetreten sind."

{/* Overdue Warning */} {isOverdue && (

Review ueberfaellig!

Das naechste Review war fuer den{' '} {new Date(existingSchedule!.next_review_date).toLocaleDateString('de-DE')} geplant. Bitte aktualisieren Sie die DSFA.

)} {/* Version Info */}

Versionsinformation

Aktuelle Version

{dsfa.version || 1}

Erstellt am

{new Date(dsfa.created_at).toLocaleDateString('de-DE')}

Letzte Aenderung

{new Date(dsfa.updated_at).toLocaleDateString('de-DE')}

{existingSchedule?.last_review_date && (
Letztes Review

{new Date(existingSchedule.last_review_date).toLocaleDateString('de-DE')}

)}
{/* Review Schedule */}

Review-Planung

{/* Review Frequency */}
{REVIEW_FREQUENCIES.map((freq) => ( ))}
{/* Next Review Date */}
setNextReviewDate(e.target.value)} className="flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500" />
{nextReviewDate && (

Das naechste Review ist in{' '} {Math.ceil((new Date(nextReviewDate).getTime() - Date.now()) / (1000 * 60 * 60 * 24))} Tagen faellig.

)}
{/* Review Responsible */}
setReviewResponsible(e.target.value)} className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500" placeholder="Name oder Rolle der verantwortlichen Person/Abteilung..." />
{/* Review Triggers */}

Review-Ausloser definieren

Waehlen Sie die Ereignisse aus, bei denen eine Ueberpruefung der DSFA ausgeloest werden soll.

{TRIGGER_TYPES.map((trigger) => ( ))}
{/* Existing Pending Triggers */} {triggers.filter(t => t.review_required && !t.review_completed).length > 0 && (

Offene Review-Trigger ({triggers.filter(t => t.review_required && !t.review_completed).length})

{triggers .filter(t => t.review_required && !t.review_completed) .map((trigger) => { const triggerInfo = TRIGGER_TYPES.find(t => t.value === trigger.trigger_type) return (
{triggerInfo?.icon || '📋'} {triggerInfo?.label || trigger.trigger_type}

{trigger.description}

Erkannt am {new Date(trigger.detected_at).toLocaleDateString('de-DE')} von {trigger.detected_by}

) })}
)} {/* Save Button */}
) }