'use client' import React, { useState } from 'react' import Link from 'next/link' import { useSDK, UseCaseAssessment, UseCaseIntake } from '@/lib/sdk' // ============================================================================= // WIZARD STEPS // ============================================================================= const WIZARD_STEPS = [ { id: 1, name: 'Grunddaten', description: 'Name, Beschreibung, Kategorie und Branche' }, { id: 2, name: 'Datenkategorien', description: 'Welche Daten werden verarbeitet?' }, { id: 3, name: 'Verarbeitungszweck', description: 'Rechtsgrundlage und Zweck' }, { id: 4, name: 'Technologie & Modell', description: 'KI-Technologien und Modell-Nutzung' }, { id: 5, name: 'Automatisierung', description: 'Grad der Automatisierung' }, { id: 6, name: 'Hosting & Transfer', description: 'Hosting und Datentransfer' }, { id: 7, name: 'Datenhaltung', description: 'Aufbewahrung und Vertraege' }, { id: 8, name: 'Zusammenfassung', description: 'Ueberpruefung und Abschluss' }, ] const TOTAL_STEPS = WIZARD_STEPS.length const DOMAINS = [ { value: 'healthcare', label: 'Gesundheit' }, { value: 'finance', label: 'Finanzen' }, { value: 'education', label: 'Bildung' }, { value: 'retail', label: 'Handel' }, { value: 'it_services', label: 'IT-Dienstleistungen' }, { value: 'consulting', label: 'Beratung' }, { value: 'manufacturing', label: 'Produktion' }, { value: 'hr', label: 'Personalwesen' }, { value: 'marketing', label: 'Marketing' }, { value: 'legal', label: 'Recht' }, { value: 'public', label: 'Oeffentlicher Sektor' }, { value: 'general', label: 'Allgemein' }, ] // ============================================================================= // RISK CALCULATION (client-side) // ============================================================================= function calculateRiskScore(form: WizardFormData): { score: number; level: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL'; dsfaRequired: boolean } { let score = 0 if (form.processesPersonalData) score += 10 if (form.specialCategories) score += 25 if (form.biometricData) score += 20 if (form.healthData) score += 15 if (form.minorsData) score += 15 if (form.financialData) score += 5 if (form.purposeProfiling) score += 15 if (form.purposeAutomatedDecision) score += 20 if (form.automation === 'fully_automated') score += 25 else if (form.automation === 'semi_automated') score += 10 if (form.internationalTransfer) score += 10 if (form.modelTraining) score += 10 if (form.modelFinetune) score += 5 let level: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL' if (score >= 60) level = 'CRITICAL' else if (score >= 40) level = 'HIGH' else if (score >= 20) level = 'MEDIUM' else level = 'LOW' const dsfaRequired = score >= 40 || form.specialCategories || (form.purposeAutomatedDecision && form.automation === 'fully_automated') return { score, level, dsfaRequired } } // ============================================================================= // USE CASE CARD // ============================================================================= function UseCaseCard({ useCase, isActive, onSelect, onDelete, }: { useCase: UseCaseAssessment isActive: boolean onSelect: () => void onDelete: () => void }) { const completionPercent = Math.round((useCase.stepsCompleted / TOTAL_STEPS) * 100) return (
{/* Delete Button */}
{completionPercent === 100 ? ( ) : ( )}

{useCase.name}

{useCase.description}

Fortschritt {completionPercent}%
{useCase.assessmentResult && (
Risiko: {useCase.assessmentResult.riskLevel} {useCase.assessmentResult.dsfaRequired && ( DSFA erforderlich )}
)}
) } // ============================================================================= // WIZARD FORM DATA // ============================================================================= interface WizardFormData { // Step 1: Grunddaten name: string description: string category: string domain: string // Step 2: Datenkategorien dataCategories: string[] processesPersonalData: boolean specialCategories: boolean healthData: boolean biometricData: boolean minorsData: boolean financialData: boolean customDataTypes: string[] // Step 3: Verarbeitungszweck legalBasis: string purposeProfiling: boolean purposeAutomatedDecision: boolean purposeMarketing: boolean purposeAnalytics: boolean purposeServiceDelivery: boolean // Step 4: Technologie & Modell aiTechnologies: string[] modelInference: boolean modelRag: boolean modelFinetune: boolean modelTraining: boolean // Step 5: Automatisierung automation: 'assistive' | 'semi_automated' | 'fully_automated' // Step 6: Hosting & Transfer hostingProvider: string hostingRegion: string internationalTransfer: boolean transferCountries: string[] transferMechanism: string // Step 7: Datenhaltung & Vertraege retentionDays: number retentionPurpose: string hasDpa: boolean hasAiaDocumentation: boolean hasRiskAssessment: boolean subprocessors: string // Notes notes: string } // ============================================================================= // WIZARD COMPONENT // ============================================================================= function UseCaseWizard({ onComplete, onCancel, }: { onComplete: (useCase: UseCaseAssessment) => void onCancel: () => void }) { const [currentStep, setCurrentStep] = useState(1) const [isSubmitting, setIsSubmitting] = useState(false) const [uccaError, setUccaError] = useState(null) const [formData, setFormData] = useState({ name: '', description: '', category: '', domain: 'general', dataCategories: [], processesPersonalData: false, specialCategories: false, healthData: false, biometricData: false, minorsData: false, financialData: false, customDataTypes: [], legalBasis: 'consent', purposeProfiling: false, purposeAutomatedDecision: false, purposeMarketing: false, purposeAnalytics: false, purposeServiceDelivery: false, aiTechnologies: [], modelInference: true, modelRag: false, modelFinetune: false, modelTraining: false, automation: 'assistive', hostingProvider: 'self_hosted', hostingRegion: 'eu', internationalTransfer: false, transferCountries: [], transferMechanism: 'none', retentionDays: 90, retentionPurpose: '', hasDpa: false, hasAiaDocumentation: false, hasRiskAssessment: false, subprocessors: '', notes: '', }) const updateFormData = (updates: Partial) => { setFormData(prev => ({ ...prev, ...updates })) } const buildIntake = (): UseCaseIntake => ({ domain: formData.domain, dataCategories: formData.dataCategories, processesPersonalData: formData.processesPersonalData, specialCategories: formData.specialCategories, healthData: formData.healthData, biometricData: formData.biometricData, minorsData: formData.minorsData, financialData: formData.financialData, customDataTypes: formData.customDataTypes.filter(s => s.trim()), legalBasis: formData.legalBasis, purposes: { profiling: formData.purposeProfiling, automatedDecision: formData.purposeAutomatedDecision, marketing: formData.purposeMarketing, analytics: formData.purposeAnalytics, serviceDelivery: formData.purposeServiceDelivery, }, automation: formData.automation, hosting: { provider: formData.hostingProvider, region: formData.hostingRegion, }, modelUsage: { inference: formData.modelInference, rag: formData.modelRag, finetune: formData.modelFinetune, training: formData.modelTraining, }, aiTechnologies: formData.aiTechnologies, internationalTransfer: { enabled: formData.internationalTransfer, countries: formData.transferCountries, mechanism: formData.transferMechanism, }, retention: { days: formData.retentionDays, purpose: formData.retentionPurpose, }, contracts: { hasDpa: formData.hasDpa, hasAiaDocumentation: formData.hasAiaDocumentation, hasRiskAssessment: formData.hasRiskAssessment, subprocessors: formData.subprocessors, }, }) const handleNext = async () => { if (currentStep < TOTAL_STEPS) { setCurrentStep(prev => prev + 1) return } // Final step — create use case + call UCCA API setIsSubmitting(true) setUccaError(null) const risk = calculateRiskScore(formData) const intake = buildIntake() const newUseCase: UseCaseAssessment = { id: `uc-${Date.now()}`, name: formData.name, description: formData.description, category: formData.category, stepsCompleted: TOTAL_STEPS, steps: WIZARD_STEPS.map(s => ({ id: `step-${s.id}`, name: s.name, completed: true, data: {}, })), assessmentResult: { riskLevel: risk.level, applicableRegulations: ['DSGVO', 'AI Act'], recommendedControls: buildRecommendations(formData, risk), dsfaRequired: risk.dsfaRequired, aiActClassification: formData.aiTechnologies.length > 0 ? (risk.level === 'CRITICAL' || risk.level === 'HIGH' ? 'HIGH' : 'LIMITED') : 'MINIMAL', }, intake, createdAt: new Date(), updatedAt: new Date(), } // Call UCCA API in background try { const uccaIntake = { title: formData.name, use_case_text: formData.description, domain: formData.domain, data_types: { personal_data: formData.processesPersonalData, special_categories: formData.specialCategories, health_data: formData.healthData, biometric_data: formData.biometricData, minors_data: formData.minorsData, financial_data: formData.financialData, custom_data_types: formData.customDataTypes.filter(s => s.trim()), }, purpose: { profiling: formData.purposeProfiling, automated_decision: formData.purposeAutomatedDecision, marketing: formData.purposeMarketing, analytics: formData.purposeAnalytics, service_delivery: formData.purposeServiceDelivery, }, automation: formData.automation, hosting: { provider: formData.hostingProvider, region: formData.hostingRegion }, model_usage: { inference: formData.modelInference, rag: formData.modelRag, finetune: formData.modelFinetune, training: formData.modelTraining, }, legal_basis: formData.legalBasis, international_transfer: { enabled: formData.internationalTransfer, countries: formData.transferCountries, mechanism: formData.transferMechanism, }, retention: { days: formData.retentionDays, purpose: formData.retentionPurpose }, contracts: { has_dpa: formData.hasDpa, has_aia_documentation: formData.hasAiaDocumentation, has_risk_assessment: formData.hasRiskAssessment, subprocessors: formData.subprocessors, }, store_raw_text: true, } const resp = await fetch('/api/sdk/v1/ucca/assess', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(uccaIntake), }) if (resp.ok) { const data = await resp.json() // Merge UCCA result if available if (data.assessment?.id) { newUseCase.uccaAssessmentId = data.assessment.id } if (data.result) { newUseCase.assessmentResult = { ...newUseCase.assessmentResult!, riskLevel: data.result.risk_level || newUseCase.assessmentResult!.riskLevel, dsfaRequired: data.result.dsfa_required ?? newUseCase.assessmentResult!.dsfaRequired, } } } else { setUccaError('UCCA-API nicht erreichbar — lokale Risikobewertung wird verwendet.') } } catch { setUccaError('UCCA-API nicht erreichbar — lokale Risikobewertung wird verwendet.') } setIsSubmitting(false) onComplete(newUseCase) } const handleBack = () => { if (currentStep > 1) setCurrentStep(prev => prev - 1) } const risk = calculateRiskScore(formData) return (
{/* Header */}

Neuer Use Case

{/* Progress */}
{WIZARD_STEPS.map((step, index) => (
{step.id < currentStep ? ( ) : ( step.id )}
{index < WIZARD_STEPS.length - 1 && (
)} ))}

Schritt {currentStep} von {TOTAL_STEPS}: {WIZARD_STEPS[currentStep - 1].description}

{/* Content */}
{/* ============================================ */} {/* STEP 1: Grunddaten */} {/* ============================================ */} {currentStep === 1 && (
updateFormData({ name: e.target.value })} placeholder="z.B. Marketing-KI fuer Kundensegmentierung" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent" />