'use client' import React, { useState, useEffect } from 'react' import { useSDK } from '@/lib/sdk' // ============================================================================= // TYPES // ============================================================================= interface SecurityItem { id: string title: string description: string | null type: 'vulnerability' | 'misconfiguration' | 'compliance' | 'hardening' severity: 'critical' | 'high' | 'medium' | 'low' status: 'open' | 'in-progress' | 'resolved' | 'accepted-risk' source: string | null cve: string | null cvss: number | null affected_asset: string | null assigned_to: string | null created_at: string due_date: string | null remediation: string | null } interface Stats { open: number in_progress: number critical: number high: number overdue: number total: number } interface NewItem { title: string description: string type: string severity: string source: string cve: string cvss: string affected_asset: string assigned_to: string remediation: string } const EMPTY_NEW_ITEM: NewItem = { title: '', description: '', type: 'vulnerability', severity: 'medium', source: '', cve: '', cvss: '', affected_asset: '', assigned_to: '', remediation: '', } // ============================================================================= // COMPONENTS // ============================================================================= function SecurityItemCard({ item, onEdit, onDelete, onStatusChange, }: { item: SecurityItem onEdit: (item: SecurityItem) => void onDelete: (id: string) => void onStatusChange: (id: string, status: string) => void }) { const typeLabels = { vulnerability: 'Schwachstelle', misconfiguration: 'Fehlkonfiguration', compliance: 'Compliance', hardening: 'Haertung', } const typeColors = { vulnerability: 'bg-red-100 text-red-700', misconfiguration: 'bg-orange-100 text-orange-700', compliance: 'bg-purple-100 text-purple-700', hardening: 'bg-blue-100 text-blue-700', } const severityColors = { critical: 'bg-red-500 text-white', high: 'bg-orange-500 text-white', medium: 'bg-yellow-500 text-white', low: 'bg-green-500 text-white', } const statusColors = { open: 'bg-blue-100 text-blue-700', 'in-progress': 'bg-yellow-100 text-yellow-700', resolved: 'bg-green-100 text-green-700', 'accepted-risk': 'bg-gray-100 text-gray-600', } const statusLabels = { open: 'Offen', 'in-progress': 'In Bearbeitung', resolved: 'Behoben', 'accepted-risk': 'Akzeptiert', } const isOverdue = item.due_date && new Date(item.due_date) < new Date() && item.status !== 'resolved' return (
{item.severity.toUpperCase()} {typeLabels[item.type]} {statusLabels[item.status]}

{item.title}

{item.description &&

{item.description}

}
{item.affected_asset && (
Betroffenes Asset: {item.affected_asset}
)} {item.source && (
Quelle: {item.source}
)} {item.cve && (
CVE: {item.cve}
)} {item.cvss !== null && (
CVSS: = 9 ? 'text-red-600' : item.cvss >= 7 ? 'text-orange-600' : item.cvss >= 4 ? 'text-yellow-600' : 'text-green-600' }`}>{item.cvss}
)} {item.assigned_to && (
Zugewiesen: {item.assigned_to}
)} {item.due_date && (
Frist: {new Date(item.due_date).toLocaleDateString('de-DE')} {isOverdue && ' (ueberfaellig)'}
)}
{item.remediation && (
Empfohlene Massnahme: {item.remediation}
)}
Erstellt: {new Date(item.created_at).toLocaleDateString('de-DE')}
{item.status !== 'resolved' && ( <> )}
) } // ============================================================================= // MODAL // ============================================================================= function ItemModal({ item, onClose, onSave, }: { item: NewItem onClose: () => void onSave: (data: NewItem) => void }) { const [form, setForm] = useState(item) return (

Sicherheitsbefund erfassen

setForm(p => ({ ...p, title: e.target.value }))} placeholder="Kurzbeschreibung des Befunds" className="w-full border rounded px-3 py-2 text-sm" />