'use client' import React, { useState, useEffect, useCallback } from 'react' // ============================================================================= // TYPES // ============================================================================= interface Portfolio { id: string name: string description: string status: 'DRAFT' | 'ACTIVE' | 'REVIEW' | 'APPROVED' | 'ARCHIVED' department: string business_unit: string owner: string owner_email: string total_assessments: number total_roadmaps: number total_workshops: number avg_risk_score: number high_risk_count: number compliance_score: number auto_update_metrics: boolean require_approval: boolean created_at: string updated_at: string approved_at: string | null approved_by: string | null } interface PortfolioItem { id: string portfolio_id: string item_type: 'ASSESSMENT' | 'ROADMAP' | 'WORKSHOP' | 'DOCUMENT' item_id: string title: string status: string risk_level: string risk_score: number feasibility: string sort_order: number tags: string[] notes: string created_at: string } interface PortfolioStats { total_items: number items_by_type: Record risk_distribution: Record avg_risk_score: number compliance_score: number } interface ActivityEntry { timestamp: string action: string item_type: string item_id: string item_title: string user_id: string } interface CompareResult { portfolios: Portfolio[] risk_scores: Record compliance_scores: Record item_counts: Record common_items: string[] unique_items: Record } // ============================================================================= // API // ============================================================================= const API_BASE = '/api/sdk/v1/portfolio' 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', REVIEW: 'bg-yellow-100 text-yellow-700', APPROVED: 'bg-purple-100 text-purple-700', ARCHIVED: 'bg-red-100 text-red-700', } const statusLabels: Record = { DRAFT: 'Entwurf', ACTIVE: 'Aktiv', REVIEW: 'In Pruefung', APPROVED: 'Genehmigt', ARCHIVED: 'Archiviert', } function PortfolioCard({ portfolio, onSelect, onDelete }: { portfolio: Portfolio onSelect: (p: Portfolio) => void onDelete: (id: string) => void }) { const totalItems = portfolio.total_assessments + portfolio.total_roadmaps + portfolio.total_workshops return (
onSelect(portfolio)}>

{portfolio.name}

{portfolio.department && {portfolio.department}}
{statusLabels[portfolio.status] || portfolio.status}
{portfolio.description && (

{portfolio.description}

)}
{portfolio.compliance_score}%
Compliance
{portfolio.avg_risk_score.toFixed(1)}
Risiko
{totalItems}
Items
{portfolio.high_risk_count > 0 && (
{portfolio.high_risk_count} Hoch-Risiko
)}
{portfolio.owner || 'Kein Owner'}
) } function CreatePortfolioModal({ onClose, onCreated }: { onClose: () => void onCreated: () => void }) { const [name, setName] = useState('') const [description, setDescription] = useState('') const [department, setDepartment] = useState('') const [owner, setOwner] = useState('') const [saving, setSaving] = useState(false) const handleCreate = async () => { if (!name.trim()) return setSaving(true) try { await api('', { method: 'POST', body: JSON.stringify({ name: name.trim(), description: description.trim(), department: department.trim(), owner: owner.trim(), }), }) onCreated() } catch (err) { console.error('Create portfolio error:', err) } finally { setSaving(false) } } return (
e.stopPropagation()}>

Neues Portfolio

setName(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. KI-Portfolio Q1 2026" />