'use client' import React, { useState, useEffect, useCallback, useRef } from 'react' // ============================================================================= // TYPES // ============================================================================= interface Roadmap { id: string title: string description: string version: number status: 'draft' | 'active' | 'completed' | 'archived' assessment_id: string | null portfolio_id: string | null total_items: number completed_items: number progress: number start_date: string | null target_date: string | null created_at: string updated_at: string } interface RoadmapItem { id: string roadmap_id: string title: string description: string category: 'TECHNICAL' | 'ORGANIZATIONAL' | 'PROCESSUAL' | 'DOCUMENTATION' | 'TRAINING' priority: 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW' status: 'PLANNED' | 'IN_PROGRESS' | 'BLOCKED' | 'COMPLETED' | 'DEFERRED' control_id: string | null regulation_ref: string | null effort_days: number effort_hours: number estimated_cost: number assignee_name: string department: string planned_start: string | null planned_end: string | null actual_start: string | null actual_end: string | null evidence_required: boolean evidence_provided: boolean sort_order: number created_at: string updated_at: string } interface RoadmapStats { by_status: Record by_priority: Record by_category: Record by_department: Record overdue_items: number upcoming_items: number total_effort_days: number progress: number } interface ImportJob { id: string status: 'pending' | 'parsing' | 'validating' | 'completed' | 'failed' filename: string total_rows: number valid_rows: number invalid_rows: number items: ParsedItem[] } interface ParsedItem { row: number title: string description: string category: string priority: string is_valid: boolean errors: string[] warnings: string[] matched_control: string | null match_confidence: number } // ============================================================================= // API // ============================================================================= const API_BASE = '/api/sdk/v1/roadmap' async function api(path: string, options?: RequestInit): Promise { const res = await fetch(`${API_BASE}${path}`, { headers: { 'Content-Type': 'application/json' }, ...options, }) if (!res.ok) { const err = await res.json().catch(() => ({ error: res.statusText })) throw new Error(err.error || err.message || `HTTP ${res.status}`) } return res.json() } // ============================================================================= // COMPONENTS // ============================================================================= const statusColors: Record = { draft: 'bg-gray-100 text-gray-700', active: 'bg-green-100 text-green-700', completed: 'bg-purple-100 text-purple-700', archived: 'bg-red-100 text-red-700', } const statusLabels: Record = { draft: 'Entwurf', active: 'Aktiv', completed: 'Abgeschlossen', archived: 'Archiviert', } const itemStatusColors: Record = { PLANNED: 'bg-gray-100 text-gray-700', IN_PROGRESS: 'bg-blue-100 text-blue-700', BLOCKED: 'bg-red-100 text-red-700', COMPLETED: 'bg-green-100 text-green-700', DEFERRED: 'bg-yellow-100 text-yellow-700', } const itemStatusLabels: Record = { PLANNED: 'Geplant', IN_PROGRESS: 'In Arbeit', BLOCKED: 'Blockiert', COMPLETED: 'Erledigt', DEFERRED: 'Verschoben', } const priorityColors: Record = { CRITICAL: 'bg-red-100 text-red-700', HIGH: 'bg-orange-100 text-orange-700', MEDIUM: 'bg-yellow-100 text-yellow-700', LOW: 'bg-green-100 text-green-700', } const categoryLabels: Record = { TECHNICAL: 'Technisch', ORGANIZATIONAL: 'Organisatorisch', PROCESSUAL: 'Prozessual', DOCUMENTATION: 'Dokumentation', TRAINING: 'Schulung', } function RoadmapCard({ roadmap, onSelect, onDelete }: { roadmap: Roadmap onSelect: (r: Roadmap) => void onDelete: (id: string) => void }) { return (
onSelect(roadmap)}>

{roadmap.title}

{statusLabels[roadmap.status] || roadmap.status}
{roadmap.description && (

{roadmap.description}

)}
{roadmap.completed_items}/{roadmap.total_items} Items {roadmap.progress}%
{(roadmap.start_date || roadmap.target_date) && (
{roadmap.start_date && Start: {new Date(roadmap.start_date).toLocaleDateString('de-DE')}} {roadmap.target_date && Ziel: {new Date(roadmap.target_date).toLocaleDateString('de-DE')}}
)}
v{roadmap.version}
) } function CreateRoadmapModal({ onClose, onCreated }: { onClose: () => void onCreated: () => void }) { const [title, setTitle] = useState('') const [description, setDescription] = useState('') const [startDate, setStartDate] = useState('') const [targetDate, setTargetDate] = useState('') const [saving, setSaving] = useState(false) const handleCreate = async () => { if (!title.trim()) return setSaving(true) try { await api('', { method: 'POST', body: JSON.stringify({ title: title.trim(), description: description.trim(), start_date: startDate || null, target_date: targetDate || null, }), }) onCreated() } catch (err) { console.error('Create roadmap error:', err) } finally { setSaving(false) } } return (
e.stopPropagation()}>

Neue Roadmap

setTitle(e.target.value)} className="w-full px-3 py-2 border rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent" placeholder="z.B. AI Act Compliance Roadmap" />