'use client' import React, { useState, useEffect } from 'react' import Link from 'next/link' import { useParams, useRouter } from 'next/navigation' import { DSRRequest, DSR_TYPE_INFO, DSR_STATUS_INFO, getDaysRemaining, isOverdue, isUrgent, DSRCommunication, DSRVerifyIdentityRequest } from '@/lib/sdk/dsr/types' import { fetchSDKDSR, updateSDKDSRStatus } from '@/lib/sdk/dsr/api' import { DSRWorkflowStepper, DSRIdentityModal, DSRCommunicationLog, DSRErasureChecklistComponent, DSRDataExportComponent } from '@/components/sdk/dsr' // ============================================================================= // MOCK COMMUNICATIONS // ============================================================================= const mockCommunications: DSRCommunication[] = [ { id: 'comm-001', dsrId: 'dsr-001', type: 'outgoing', channel: 'email', subject: 'Eingangsbestaetigung Ihrer Anfrage', content: 'Sehr geehrte(r) Antragsteller(in),\n\nwir bestaetigen den Eingang Ihrer Anfrage und werden diese innerhalb der gesetzlichen Frist bearbeiten.\n\nMit freundlichen Gruessen\nIhr Datenschutz-Team', sentAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(), sentBy: 'System', createdAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(), createdBy: 'System' }, { id: 'comm-002', dsrId: 'dsr-001', type: 'outgoing', channel: 'email', subject: 'Identitaetspruefung erforderlich', content: 'Sehr geehrte(r) Antragsteller(in),\n\nbitte senden Sie uns zur Bearbeitung Ihrer Anfrage einen Identitaetsnachweis zu.\n\nMit freundlichen Gruessen', sentAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(), sentBy: 'DSB Mueller', createdAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(), createdBy: 'DSB Mueller' } ] // ============================================================================= // COMPONENTS // ============================================================================= function StatusBadge({ status }: { status: string }) { const info = DSR_STATUS_INFO[status as keyof typeof DSR_STATUS_INFO] if (!info) return null return ( {info.label} ) } function DeadlineDisplay({ request }: { request: DSRRequest }) { const daysRemaining = getDaysRemaining(request.deadline.currentDeadline) const overdue = isOverdue(request) const urgent = isUrgent(request) const isTerminal = request.status === 'completed' || request.status === 'rejected' || request.status === 'cancelled' if (isTerminal) { return (
Abgeschlossen am
{request.completedAt ? new Date(request.completedAt).toLocaleDateString('de-DE') : '-' }
) } return (
Frist
{overdue ? `${Math.abs(daysRemaining)} Tage ueberfaellig` : `${daysRemaining} Tage` }
bis {new Date(request.deadline.currentDeadline).toLocaleDateString('de-DE')}
{request.deadline.extended && (
(Verlaengert)
)}
) } function ActionButtons({ request, onVerifyIdentity, onExtendDeadline, onComplete, onReject, onAssign }: { request: DSRRequest onVerifyIdentity: () => void onExtendDeadline: () => void onComplete: () => void onReject: () => void onAssign: () => void }) { const isTerminal = request.status === 'completed' || request.status === 'rejected' || request.status === 'cancelled' if (isTerminal) { return (
) } return (
{!request.identityVerification.verified && ( )}
) } function AuditLog({ request }: { request: DSRRequest }) { type AuditEvent = { action: string; timestamp: string; user: string } const events: AuditEvent[] = [ { action: 'Erstellt', timestamp: request.createdAt, user: request.createdBy } ] if (request.assignment.assignedAt) { events.push({ action: `Zugewiesen an ${request.assignment.assignedTo}`, timestamp: request.assignment.assignedAt, user: request.assignment.assignedBy || 'System' }) } if (request.identityVerification.verifiedAt) { events.push({ action: 'Identitaet verifiziert', timestamp: request.identityVerification.verifiedAt, user: request.identityVerification.verifiedBy || 'System' }) } if (request.completedAt) { events.push({ action: request.status === 'rejected' ? 'Abgelehnt' : 'Abgeschlossen', timestamp: request.completedAt, user: request.updatedBy || 'System' }) } return (

Aktivitaeten

{events.map((event, idx) => (
{event.action}
{new Date(event.timestamp).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' })} {' - '} {event.user}
))}
) } // ============================================================================= // MAIN PAGE // ============================================================================= export default function DSRDetailPage() { const params = useParams() const router = useRouter() const requestId = params.requestId as string const [request, setRequest] = useState(null) const [communications, setCommunications] = useState([]) const [isLoading, setIsLoading] = useState(true) const [showIdentityModal, setShowIdentityModal] = useState(false) const [activeContentTab, setActiveContentTab] = useState<'details' | 'communication' | 'type-specific'>('details') // Load data from SDK backend useEffect(() => { const loadData = async () => { setIsLoading(true) try { const found = await fetchSDKDSR(requestId) if (found) { setRequest(found) // Communications are loaded as mock for now (no backend API yet) setCommunications(mockCommunications.filter(c => c.dsrId === requestId)) } } catch (error) { console.error('Failed to load DSR:', error) } finally { setIsLoading(false) } } loadData() }, [requestId]) const handleVerifyIdentity = async (verification: DSRVerifyIdentityRequest) => { if (!request) return try { await updateSDKDSRStatus(request.id, 'verified') setRequest({ ...request, identityVerification: { verified: true, method: verification.method, verifiedAt: new Date().toISOString(), verifiedBy: 'Current User', notes: verification.notes }, status: request.status === 'identity_verification' ? 'processing' : request.status }) } catch (err) { console.error('Failed to verify identity:', err) // Still update locally as fallback setRequest({ ...request, identityVerification: { verified: true, method: verification.method, verifiedAt: new Date().toISOString(), verifiedBy: 'Current User', notes: verification.notes }, status: request.status === 'identity_verification' ? 'processing' : request.status }) } } const handleSendCommunication = async (message: any) => { const newComm: DSRCommunication = { id: `comm-${Date.now()}`, dsrId: requestId, ...message, createdAt: new Date().toISOString(), createdBy: 'Current User', sentAt: message.type === 'outgoing' ? new Date().toISOString() : undefined, sentBy: message.type === 'outgoing' ? 'Current User' : undefined } setCommunications(prev => [newComm, ...prev]) } if (isLoading) { return (
) } if (!request) { return (

Anfrage nicht gefunden

Die angeforderte DSR-Anfrage existiert nicht oder wurde geloescht.

Zurueck zur Uebersicht
) } const typeInfo = DSR_TYPE_INFO[request.type] const overdue = isOverdue(request) const urgent = isUrgent(request) return (
{/* Header */}
{request.referenceNumber} {typeInfo.article} {typeInfo.label}

{request.requester.name}

{/* Workflow Stepper */}
{/* Main Content: 2/3 + 1/3 Layout */}
{/* Left Column - 2/3 */}
{/* Content Tabs */}
{/* Details Tab */} {activeContentTab === 'details' && (
{/* Request Info */}

Antragsteller

{request.requester.name}
{request.requester.email}
{request.requester.phone && (
{request.requester.phone}
)}

Eingereicht

{new Date(request.receivedAt).toLocaleDateString('de-DE', { day: '2-digit', month: 'long', year: 'numeric' })}
Quelle: {request.source === 'web_form' ? 'Kontaktformular' : request.source === 'email' ? 'E-Mail' : request.source === 'letter' ? 'Brief' : request.source === 'phone' ? 'Telefon' : request.source}
{/* Identity Verification */}
{request.identityVerification.verified ? ( ) : ( )}
{request.identityVerification.verified ? 'Identitaet verifiziert' : 'Identitaetspruefung ausstehend' }
{request.identityVerification.verified && (
Methode: {request.identityVerification.method === 'id_document' ? 'Ausweisdokument' : request.identityVerification.method === 'email' ? 'E-Mail' : request.identityVerification.method === 'existing_account' ? 'Bestehendes Konto' : request.identityVerification.method} {' | '} {new Date(request.identityVerification.verifiedAt!).toLocaleDateString('de-DE')}
)}
{!request.identityVerification.verified && ( )}
{/* Request Text */} {request.requestText && (

Anfragetext

{request.requestText}
)} {/* Notes */} {request.notes && (

Notizen

{request.notes}
)}
)} {/* Communication Tab */} {activeContentTab === 'communication' && ( )} {/* Type-Specific Tab */} {activeContentTab === 'type-specific' && (
{/* Art. 17 - Erasure */} {request.type === 'erasure' && ( setRequest({ ...request, erasureChecklist: checklist })} /> )} {/* Art. 15/20 - Data Export */} {(request.type === 'access' || request.type === 'portability') && ( { // Mock generation setRequest({ ...request, dataExport: { format, generatedAt: new Date().toISOString(), generatedBy: 'Current User', fileName: `datenexport_${request.referenceNumber}.${format}`, fileSize: 125000, includesThirdPartyData: true } }) }} /> )} {/* Art. 16 - Rectification */} {request.type === 'rectification' && request.rectificationDetails && (

Zu korrigierende Daten

{request.rectificationDetails.fieldsToCorrect.map((field, idx) => (
{field.field}
Aktueller Wert
{field.currentValue}
Angeforderter Wert
{field.requestedValue}
{field.corrected && (
Korrigiert am {new Date(field.correctedAt!).toLocaleDateString('de-DE')}
)}
))}
)} {/* Art. 21 - Objection */} {request.type === 'objection' && request.objectionDetails && (

Widerspruchsdetails

Verarbeitungszweck
{request.objectionDetails.processingPurpose}
Rechtsgrundlage
{request.objectionDetails.legalBasis}
Widerspruchsgruende
{request.objectionDetails.objectionGrounds}
{request.objectionDetails.decision !== 'pending' && (
Widerspruch {request.objectionDetails.decision === 'accepted' ? 'angenommen' : 'abgelehnt'}
{request.objectionDetails.decisionReason && (
{request.objectionDetails.decisionReason}
)}
)}
)} {/* Default for restriction */} {request.type === 'restriction' && (
Einschraenkung der Verarbeitung

Markieren Sie die betroffenen Daten im System als eingeschraenkt. Die Daten duerfen nur noch gespeichert, aber nicht mehr verarbeitet werden.

)}
)}
{/* Right Column - 1/3 Sidebar */}
{/* Status Card */}

Status

{/* Priority */}
Prioritaet
{request.priority === 'critical' ? 'Kritisch' : request.priority === 'high' ? 'Hoch' : request.priority === 'normal' ? 'Normal' : 'Niedrig'}
{/* Assignment */}
Zugewiesen an
{request.assignment.assignedTo || 'Nicht zugewiesen'}
{/* Actions Card */}

Aktionen

setShowIdentityModal(true)} onExtendDeadline={() => alert('Fristverlaengerung - Coming soon')} onComplete={() => alert('Abschliessen - Coming soon')} onReject={() => alert('Ablehnen - Coming soon')} onAssign={() => alert('Zuweisen - Coming soon')} />
{/* Audit Log Card */}
{/* Identity Modal */} setShowIdentityModal(false)} onVerify={handleVerifyIdentity} requesterName={request.requester.name} requesterEmail={request.requester.email} />
) }