'use client' /** * Meine Aufgaben - Personal Task Dashboard * * Zeigt dem angemeldeten Benutzer seine Compliance-Aufgaben: * - Offene Control-Reviews * - Faellige Evidence-Uploads * - Ausstehende Sign-offs * - Risiko-Behandlungen */ import { useState, useEffect } from 'react' import { useRouter } from 'next/navigation' import AdminLayout from '@/components/admin/AdminLayout' import { Language } from '@/lib/compliance-i18n' interface Task { id: string type: 'control_review' | 'evidence_upload' | 'signoff' | 'risk_treatment' title: string description: string priority: 'critical' | 'high' | 'medium' | 'low' due_date: string | null days_remaining: number | null status: 'overdue' | 'due_soon' | 'pending' | 'in_progress' related_entity: { type: string id: string name: string } } interface TaskStats { total: number overdue: number due_soon: number in_progress: number completed_this_week: number } // Mock-Daten fuer die Demonstration const MOCK_TASKS: Task[] = [ { id: '1', type: 'control_review', title: 'PRIV-001 Review faellig', description: 'Quartalsreview des Verarbeitungsverzeichnisses', priority: 'high', due_date: '2026-01-20', days_remaining: 2, status: 'due_soon', related_entity: { type: 'control', id: 'PRIV-001', name: 'Verarbeitungsverzeichnis' } }, { id: '2', type: 'evidence_upload', title: 'SAST-Report hochladen', description: 'Aktueller Semgrep-Scan fuer SDLC-001', priority: 'medium', due_date: '2026-01-25', days_remaining: 7, status: 'pending', related_entity: { type: 'control', id: 'SDLC-001', name: 'SAST Scanning' } }, { id: '3', type: 'signoff', title: 'Audit Sign-off: DSGVO Art. 32', description: 'Sign-off fuer technische Massnahmen im Q1 Audit', priority: 'critical', due_date: '2026-01-19', days_remaining: 1, status: 'due_soon', related_entity: { type: 'requirement', id: 'gdpr-art32', name: 'DSGVO Art. 32' } }, { id: '4', type: 'risk_treatment', title: 'RISK-003 Behandlung', description: 'Risiko-Behandlungsplan fuer Key-Rotation definieren', priority: 'high', due_date: '2026-01-22', days_remaining: 4, status: 'in_progress', related_entity: { type: 'risk', id: 'RISK-003', name: 'Unzureichende Key-Rotation' } }, { id: '5', type: 'control_review', title: 'IAM-002 MFA-Check', description: 'Ueberpruefung der MFA-Abdeckung fuer Admin-Accounts', priority: 'medium', due_date: '2026-01-28', days_remaining: 10, status: 'pending', related_entity: { type: 'control', id: 'IAM-002', name: 'MFA fuer Admin-Accounts' } }, { id: '6', type: 'evidence_upload', title: 'Backup-Test Protokoll', description: 'Nachweis fuer erfolgreichen Backup-Restore-Test', priority: 'low', due_date: '2026-02-01', days_remaining: 14, status: 'pending', related_entity: { type: 'control', id: 'OPS-002', name: 'Backup & Recovery' } }, ] const MOCK_STATS: TaskStats = { total: 6, overdue: 0, due_soon: 2, in_progress: 1, completed_this_week: 3 } const TYPE_LABELS = { de: { control_review: 'Control-Review', evidence_upload: 'Nachweis-Upload', signoff: 'Sign-off', risk_treatment: 'Risiko-Behandlung' }, en: { control_review: 'Control Review', evidence_upload: 'Evidence Upload', signoff: 'Sign-off', risk_treatment: 'Risk Treatment' } } const PRIORITY_COLORS = { critical: 'bg-red-500', high: 'bg-orange-500', medium: 'bg-yellow-500', low: 'bg-slate-400' } const STATUS_COLORS = { overdue: 'text-red-500 bg-red-500/10', due_soon: 'text-orange-500 bg-orange-500/10', pending: 'text-slate-400 bg-slate-400/10', in_progress: 'text-blue-500 bg-blue-500/10' } export default function MyTasksPage() { const router = useRouter() const [language, setLanguage] = useState('de') const [tasks, setTasks] = useState(MOCK_TASKS) const [stats, setStats] = useState(MOCK_STATS) const [filter, setFilter] = useState('all') const [sortBy, setSortBy] = useState<'due_date' | 'priority'>('due_date') const [loading, setLoading] = useState(false) useEffect(() => { const storedLang = localStorage.getItem('compliance_language') as Language if (storedLang) { setLanguage(storedLang) } // In Zukunft: Lade Tasks vom Backend // loadTasks() }, []) const filteredTasks = tasks .filter(task => filter === 'all' || task.type === filter) .sort((a, b) => { if (sortBy === 'due_date') { const aDate = a.due_date ? new Date(a.due_date).getTime() : Infinity const bDate = b.due_date ? new Date(b.due_date).getTime() : Infinity return aDate - bDate } else { const priorityOrder = { critical: 0, high: 1, medium: 2, low: 3 } return priorityOrder[a.priority] - priorityOrder[b.priority] } }) const getTypeIcon = (type: Task['type']) => { switch (type) { case 'control_review': return ( ) case 'evidence_upload': return ( ) case 'signoff': return ( ) case 'risk_treatment': return ( ) } } return (
{/* Header */}

{language === 'de' ? 'Meine Aufgaben' : 'My Tasks'}

{language === 'de' ? 'Uebersicht Ihrer Compliance-Aufgaben' : 'Overview of your compliance tasks'}

{/* Stats Cards */}
{/* Filters */}
{language === 'de' ? 'Filter:' : 'Filter:'}
{language === 'de' ? 'Sortieren:' : 'Sort by:'}
{/* Task List */}
{filteredTasks.length === 0 ? (

{language === 'de' ? 'Keine Aufgaben' : 'No Tasks'}

{language === 'de' ? 'Sie haben aktuell keine offenen Compliance-Aufgaben.' : 'You currently have no open compliance tasks.'}

) : ( filteredTasks.map((task) => (
{/* Icon */}
{getTypeIcon(task.type)}
{/* Content */}

{task.title}

{task.priority.toUpperCase()} {TYPE_LABELS[language][task.type]}

{task.description}

{language === 'de' ? 'Betrifft:' : 'Related:'}{' '} {task.related_entity.name} {task.due_date && ( {language === 'de' ? 'Faellig:' : 'Due:'}{' '} {new Date(task.due_date).toLocaleDateString(language === 'de' ? 'de-DE' : 'en-US')} {task.days_remaining !== null && ( ({task.days_remaining} {language === 'de' ? 'Tage' : 'days'}) )} )}
{/* Actions */}
)) )}
{/* Footer */}

{language === 'de' ? 'Aufgaben werden automatisch basierend auf Control-Review-Zyklen, Evidence-Ablauf und Audit-Sessions generiert.' : 'Tasks are automatically generated based on control review cycles, evidence expiry, and audit sessions.'}

) } // Stat Card Component function StatCard({ label, value, color, bgColor }: { label: string; value: number; color: string; bgColor: string }) { return (

{label}

{value}

) }