'use client' import React, { useState, useEffect, useMemo } from 'react' import Link from 'next/link' import { useSDK } from '@/lib/sdk' import { StepHeader, STEP_EXPLANATIONS } from '@/components/sdk/StepHeader' import { DSRRequest, DSRType, DSRStatus, DSRStatistics, DSR_TYPE_INFO, DSR_STATUS_INFO, getDaysRemaining, isOverdue, isUrgent } from '@/lib/sdk/dsr/types' import { fetchSDKDSRList } from '@/lib/sdk/dsr/api' import { DSRWorkflowStepperCompact } from '@/components/sdk/dsr' // ============================================================================= // TYPES // ============================================================================= type TabId = 'overview' | 'intake' | 'processing' | 'completed' | 'settings' interface Tab { id: TabId label: string count?: number countColor?: string } // ============================================================================= // COMPONENTS // ============================================================================= function TabNavigation({ tabs, activeTab, onTabChange }: { tabs: Tab[] activeTab: TabId onTabChange: (tab: TabId) => void }) { return (
) } function StatCard({ label, value, color = 'gray', icon, trend }: { label: string value: number | string color?: 'gray' | 'blue' | 'yellow' | 'red' | 'green' | 'purple' icon?: React.ReactNode trend?: { value: number; label: string } }) { const colorClasses = { gray: 'border-gray-200 text-gray-900', blue: 'border-blue-200 text-blue-600', yellow: 'border-yellow-200 text-yellow-600', red: 'border-red-200 text-red-600', green: 'border-green-200 text-green-600', purple: 'border-purple-200 text-purple-600' } return (
{label}
{value}
{trend && (
= 0 ? 'text-green-600' : 'text-red-600'}`}> {trend.value >= 0 ? '+' : ''}{trend.value} {trend.label}
)}
{icon && (
{icon}
)}
) } function RequestCard({ request }: { request: DSRRequest }) { const typeInfo = DSR_TYPE_INFO[request.type] const statusInfo = DSR_STATUS_INFO[request.status] const daysRemaining = getDaysRemaining(request.deadline.currentDeadline) const overdue = isOverdue(request) const urgent = isUrgent(request) return (
{/* Header Badges */}
{request.referenceNumber} {typeInfo.article} {typeInfo.labelShort} {!request.identityVerification.verified && request.status !== 'completed' && request.status !== 'rejected' && ( ID fehlt )}
{/* Requester Info */}

{request.requester.name}

{request.requester.email}

{/* Workflow Status */}
{/* Right Side - Deadline */}
{request.status === 'completed' || request.status === 'rejected' || request.status === 'cancelled' ? statusInfo.label : overdue ? `${Math.abs(daysRemaining)} Tage ueberfaellig` : `${daysRemaining} Tage` }
{new Date(request.receivedAt).toLocaleDateString('de-DE')}
{/* Notes Preview */} {request.notes && (
{request.notes}
)} {/* Footer */}
{request.assignment.assignedTo ? `Zugewiesen: ${request.assignment.assignedTo}` : 'Nicht zugewiesen' }
{request.status !== 'completed' && request.status !== 'rejected' && request.status !== 'cancelled' && ( <> {!request.identityVerification.verified && ( ID pruefen )} Bearbeiten )} {request.status === 'completed' && ( Details )}
) } function FilterBar({ selectedType, selectedStatus, selectedPriority, onTypeChange, onStatusChange, onPriorityChange, onClear }: { selectedType: DSRType | 'all' selectedStatus: DSRStatus | 'all' selectedPriority: string onTypeChange: (type: DSRType | 'all') => void onStatusChange: (status: DSRStatus | 'all') => void onPriorityChange: (priority: string) => void onClear: () => void }) { const hasFilters = selectedType !== 'all' || selectedStatus !== 'all' || selectedPriority !== 'all' return (
Filter: {/* Type Filter */} {/* Status Filter */} {/* Priority Filter */} {/* Clear Filters */} {hasFilters && ( )}
) } // ============================================================================= // MAIN PAGE // ============================================================================= export default function DSRPage() { const { state } = useSDK() const [activeTab, setActiveTab] = useState('overview') const [requests, setRequests] = useState([]) const [statistics, setStatistics] = useState(null) const [isLoading, setIsLoading] = useState(true) // Filters const [selectedType, setSelectedType] = useState('all') const [selectedStatus, setSelectedStatus] = useState('all') const [selectedPriority, setSelectedPriority] = useState('all') // Load data from SDK backend useEffect(() => { const loadData = async () => { setIsLoading(true) try { const { requests: dsrRequests, statistics: dsrStats } = await fetchSDKDSRList() setRequests(dsrRequests) setStatistics(dsrStats) } catch (error) { console.error('Failed to load DSR data:', error) } finally { setIsLoading(false) } } loadData() }, []) // Calculate tab counts const tabCounts = useMemo(() => { return { intake: requests.filter(r => r.status === 'intake' || r.status === 'identity_verification').length, processing: requests.filter(r => r.status === 'processing').length, completed: requests.filter(r => r.status === 'completed' || r.status === 'rejected' || r.status === 'cancelled').length, overdue: requests.filter(r => isOverdue(r)).length } }, [requests]) // Filter requests based on active tab and filters const filteredRequests = useMemo(() => { let filtered = [...requests] // Tab-based filtering if (activeTab === 'intake') { filtered = filtered.filter(r => r.status === 'intake' || r.status === 'identity_verification') } else if (activeTab === 'processing') { filtered = filtered.filter(r => r.status === 'processing') } else if (activeTab === 'completed') { filtered = filtered.filter(r => r.status === 'completed' || r.status === 'rejected' || r.status === 'cancelled') } // Type filter if (selectedType !== 'all') { filtered = filtered.filter(r => r.type === selectedType) } // Status filter if (selectedStatus !== 'all') { filtered = filtered.filter(r => r.status === selectedStatus) } // Priority filter if (selectedPriority !== 'all') { filtered = filtered.filter(r => r.priority === selectedPriority) } // Sort by urgency return filtered.sort((a, b) => { const getUrgency = (r: DSRRequest) => { if (r.status === 'completed' || r.status === 'rejected' || r.status === 'cancelled') return 100 const days = getDaysRemaining(r.deadline.currentDeadline) if (days < 0) return -100 + days // Overdue items first return days } return getUrgency(a) - getUrgency(b) }) }, [requests, activeTab, selectedType, selectedStatus, selectedPriority]) const tabs: Tab[] = [ { id: 'overview', label: 'Uebersicht' }, { id: 'intake', label: 'Eingang', count: tabCounts.intake, countColor: 'bg-blue-100 text-blue-600' }, { id: 'processing', label: 'In Bearbeitung', count: tabCounts.processing, countColor: 'bg-yellow-100 text-yellow-600' }, { id: 'completed', label: 'Abgeschlossen', count: tabCounts.completed, countColor: 'bg-green-100 text-green-600' }, { id: 'settings', label: 'Einstellungen' } ] const stepInfo = STEP_EXPLANATIONS['dsr'] const clearFilters = () => { setSelectedType('all') setSelectedStatus('all') setSelectedPriority('all') } return (
{/* Step Header */} Anfrage erfassen {/* Tab Navigation */} {/* Loading State */} {isLoading ? (
) : activeTab === 'settings' ? ( /* Settings Tab */

Einstellungen

DSR-Portal-Einstellungen, E-Mail-Vorlagen und Workflow-Konfiguration werden in einer spaeteren Version verfuegbar sein.

) : ( <> {/* Statistics (Overview Tab) */} {activeTab === 'overview' && statistics && (
0 ? 'red' : 'green'} />
)} {/* Overdue Alert */} {tabCounts.overdue > 0 && (

Achtung: {tabCounts.overdue} ueberfaellige Anfrage(n)

Die gesetzliche Frist ist abgelaufen. Handeln Sie umgehend, um Bussgelder zu vermeiden.

)} {/* Info Box (Overview Tab) */} {activeTab === 'overview' && (

Fristen beachten

Nach Art. 12 DSGVO muessen Anfragen innerhalb von einem Monat beantwortet werden. Eine Verlaengerung um zwei weitere Monate ist bei komplexen Anfragen moeglich, sofern der Betroffene innerhalb eines Monats darueber informiert wird.

)} {/* Filters */} {/* Requests List */}
{filteredRequests.map(request => ( ))}
{/* Empty State */} {filteredRequests.length === 0 && (

Keine Anfragen gefunden

{selectedType !== 'all' || selectedStatus !== 'all' || selectedPriority !== 'all' ? 'Passen Sie die Filter an oder' : 'Es sind noch keine Anfragen vorhanden.' }

{(selectedType !== 'all' || selectedStatus !== 'all' || selectedPriority !== 'all') ? ( ) : ( Erste Anfrage erfassen )}
)} )}
) }