diff --git a/admin-compliance/app/sdk/company-profile/page.tsx b/admin-compliance/app/sdk/company-profile/page.tsx index ee58e22..597821d 100644 --- a/admin-compliance/app/sdk/company-profile/page.tsx +++ b/admin-compliance/app/sdk/company-profile/page.tsx @@ -2333,67 +2333,6 @@ function StepMachineBuilder({ // GENERATE DOCUMENTS BUTTON // ============================================================================= -const DOC_TYPES = [ - { id: 'dsfa', label: 'DSFA', desc: 'Datenschutz-Folgenabschätzung' }, - { id: 'vvt', label: 'VVT', desc: 'Verarbeitungsverzeichnis' }, - { id: 'tom', label: 'TOM', desc: 'Technisch-Organisatorische Maßnahmen' }, - { id: 'loeschfristen', label: 'Löschfristen', desc: 'Löschfristen-Katalog' }, - { id: 'obligation', label: 'Pflichten', desc: 'Compliance-Pflichten' }, -] - -function GenerateDocumentsButton() { - const [generating, setGenerating] = useState(null) - const [results, setResults] = useState>({}) - - const handleGenerate = async (docType: string) => { - setGenerating(docType) - try { - const res = await fetch(`/api/sdk/v1/compliance/generation/apply/${docType}`, { method: 'POST' }) - if (res.ok) { - const data = await res.json() - setResults(prev => ({ ...prev, [docType]: { ok: true, count: data.change_requests_created || 0 } })) - } else { - setResults(prev => ({ ...prev, [docType]: { ok: false, count: 0 } })) - } - } catch { - setResults(prev => ({ ...prev, [docType]: { ok: false, count: 0 } })) - } finally { - setGenerating(null) - } - } - - return ( -
- {DOC_TYPES.map(dt => ( -
-
- {dt.label} - ({dt.desc}) -
- {results[dt.id] ? ( - - {results[dt.id].ok ? `${results[dt.id].count} CR erstellt` : 'Fehler'} - - ) : ( - - )} -
- ))} - {Object.keys(results).length > 0 && ( - - Zur Änderungsanfragen-Inbox → - - )} -
- ) -} - // ============================================================================= // MAIN COMPONENT // ============================================================================= @@ -2500,7 +2439,7 @@ export default function CompanyProfilePage() { } as any setFormData(backendProfile) if (backendProfile.isComplete) { - setCurrentStep(6) + setCurrentStep(99) } return } @@ -2513,7 +2452,7 @@ export default function CompanyProfilePage() { if (!cancelled && state.companyProfile) { setFormData(state.companyProfile) if (state.companyProfile.isComplete) { - setCurrentStep(6) + setCurrentStep(99) } } } @@ -2661,7 +2600,7 @@ export default function CompanyProfilePage() { console.error('Failed to save company profile to backend:', err) } - goToNextStep() + setCurrentStep(99) // Show summary } const handleBack = () => { @@ -2741,6 +2680,114 @@ export default function CompanyProfilePage() { const isLastStep = currentStep === lastStep || (currentStep === 6 && !showMachineBuilderStep) + // ========================================================================= + // SUMMARY VIEW (Step 99) — shown after profile completion + // ========================================================================= + if (currentStep === 99) { + const summaryItems = [ + { label: 'Firmenname', value: formData.companyName }, + { label: 'Rechtsform', value: formData.legalForm ? LEGAL_FORM_LABELS[formData.legalForm] : undefined }, + { label: 'Branche', value: formData.industry?.join(', ') }, + { label: 'Geschaeftsmodell', value: formData.businessModel ? BUSINESS_MODEL_LABELS[formData.businessModel]?.short : undefined }, + { label: 'Unternehmensgroesse', value: formData.companySize ? COMPANY_SIZE_LABELS[formData.companySize] : undefined }, + { label: 'Mitarbeiter', value: formData.employeeCount }, + { label: 'Hauptsitz', value: [formData.headquartersZip, formData.headquartersCity, formData.headquartersCountry === 'DE' ? 'Deutschland' : formData.headquartersCountry].filter(Boolean).join(', ') }, + { label: 'Zielmaerkte', value: formData.targetMarkets?.map(m => TARGET_MARKET_LABELS[m] || m).join(', ') }, + { label: 'Verantwortlicher', value: formData.isDataController ? 'Ja' : 'Nein' }, + { label: 'Auftragsverarbeiter', value: formData.isDataProcessor ? 'Ja' : 'Nein' }, + { label: 'DSB', value: formData.dpoName || 'Nicht angegeben' }, + ].filter(item => item.value && item.value.length > 0) + + const missingFields: string[] = [] + if (!formData.companyName) missingFields.push('Firmenname') + if (!formData.legalForm) missingFields.push('Rechtsform') + if (!formData.industry || formData.industry.length === 0) missingFields.push('Branche') + if (!formData.businessModel) missingFields.push('Geschaeftsmodell') + if (!formData.companySize) missingFields.push('Unternehmensgroesse') + + return ( +
+
+
+

Unternehmensprofil

+
+ + {/* Success Banner */} +
+
+
+ {formData.isComplete ? '\u2713' : '!'} +
+
+

+ {formData.isComplete + ? 'Profil erfolgreich abgeschlossen' + : 'Profil unvollstaendig' + } +

+

+ {formData.isComplete + ? 'Alle Angaben wurden gespeichert. Sie koennen jetzt mit der Scope-Analyse fortfahren.' + : `Es fehlen noch Angaben: ${missingFields.join(', ')}.` + } +

+
+
+
+ + {/* Profile Summary */} +
+

Zusammenfassung

+
+ {summaryItems.map(item => ( +
+ {item.label} + {item.value} +
+ ))} +
+
+ + {/* Actions */} +
+ + + {formData.isComplete ? ( + + ) : ( + + )} +
+
+
+ ) + } + + // ========================================================================= + // WIZARD VIEW (Steps 1-7) + // ========================================================================= + return (
@@ -2855,16 +2902,6 @@ export default function CompanyProfilePage() {
- {/* Generate Documents CTA (only when profile is complete) */} - {formData.isComplete && ( -
-

Dokumente generieren

-

- Basierend auf Ihrem Profil können DSFA, VVT, TOM, Löschfristen und Pflichten automatisch als Entwürfe generiert werden. -

- -
- )}
diff --git a/admin-compliance/app/sdk/use-cases/new/page.tsx b/admin-compliance/app/sdk/use-cases/new/page.tsx index 147de79..02c238d 100644 --- a/admin-compliance/app/sdk/use-cases/new/page.tsx +++ b/admin-compliance/app/sdk/use-cases/new/page.tsx @@ -2,6 +2,7 @@ import React, { useState, useEffect, Suspense } from 'react' import { useRouter, useSearchParams } from 'next/navigation' +import { useSDK } from '@/lib/sdk' import { AssessmentResultCard } from '@/components/sdk/use-case-assessment/AssessmentResultCard' // ============================================================================= @@ -11,7 +12,7 @@ import { AssessmentResultCard } from '@/components/sdk/use-case-assessment/Asses const WIZARD_STEPS = [ { id: 1, title: 'Grundlegendes', description: 'Titel und Beschreibung' }, { id: 2, title: 'Datenkategorien', description: 'Welche Daten werden verarbeitet?' }, - { id: 3, title: 'Verarbeitungszweck', description: 'Rechtsgrundlage und Zweck' }, + { id: 3, title: 'Verarbeitungszweck', description: 'Zweck der Datenverarbeitung' }, { id: 4, title: 'Automatisierung', description: 'Grad der Automatisierung' }, { id: 5, title: 'Hosting & Modell', description: 'Technische Details' }, { id: 6, title: 'Datentransfer', description: 'Internationaler Datentransfer' }, @@ -19,21 +20,279 @@ const WIZARD_STEPS = [ { id: 8, title: 'Vertraege', description: 'Compliance und Vereinbarungen' }, ] -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' }, +// KI-Anwendungskategorien als Auswahlkacheln +const AI_USE_CATEGORIES = [ + { value: 'content_generation', label: 'Content-Erstellung', icon: '✍️', desc: 'Texte, Berichte, E-Mails, Dokumentation automatisch erstellen' }, + { value: 'image_generation', label: 'Bilder erstellen', icon: '🎨', desc: 'KI-generierte Bilder, Grafiken, Produktfotos' }, + { value: 'marketing_material', label: 'Marketingmaterial', icon: '📢', desc: 'Werbetexte, Social Media Posts, Newsletter generieren' }, + { value: 'customer_service', label: 'Kundenservice / Chatbot', icon: '💬', desc: 'Automatisierte Kundenanfragen, FAQ-Bots, Support-Tickets' }, + { value: 'crm_analytics', label: 'CRM & Kundenanalyse', icon: '👥', desc: 'Kundensegmentierung, Churn-Vorhersage, Lead-Scoring' }, + { value: 'hr_recruiting', label: 'Bewerberauswahl / HR', icon: '🧑‍💼', desc: 'CV-Screening, Matching, Mitarbeiteranalysen' }, + { value: 'financial_analysis', label: 'Finanzdaten analysieren', icon: '📊', desc: 'Buchhaltung, Forecasting, Betrugs­erkennung, Risikobewertung' }, + { value: 'predictive_maintenance', label: 'Predictive Maintenance', icon: '🔧', desc: 'Vorausschauende Wartung, Ausfallvorhersage, IoT-Sensoranalyse' }, + { value: 'production_analytics', label: 'Produktionsdaten­auswertung', icon: '🏭', desc: 'Qualitaetskontrolle, Prozess­optimierung, OEE-Analyse' }, + { value: 'document_analysis', label: 'Dokumentenanalyse', icon: '📄', desc: 'Vertraege, Rechnungen, PDFs automatisch auswerten und klassifizieren' }, + { value: 'code_development', label: 'Softwareentwicklung', icon: '💻', desc: 'Code-Generierung, Code-Review, Test-Erstellung, Dokumentation' }, + { value: 'translation', label: 'Uebersetzung', icon: '🌍', desc: 'Automatische Uebersetzung von Texten, Dokumenten, Webinhalten' }, + { value: 'search_knowledge', label: 'Wissensmanagement / Suche', icon: '🔍', desc: 'Interne Wissensdatenbank, RAG-basierte Suche, FAQ-Systeme' }, + { value: 'data_extraction', label: 'Datenextraktion', icon: '⛏️', desc: 'OCR, Formularerkennung, strukturierte Daten aus Freitext' }, + { value: 'risk_compliance', label: 'Risiko & Compliance', icon: '⚖️', desc: 'Compliance-Pruefung, Risikobewertung, Audit-Unterstuetzung' }, + { value: 'supply_chain', label: 'Lieferkette & Logistik', icon: '🚛', desc: 'Bedarfsprognose, Routenoptimierung, Bestandsmanagement' }, + { value: 'medical_health', label: 'Medizin & Gesundheit', icon: '🏥', desc: 'Diagnoseunterstuetzung, Bildanalyse, Patientendaten' }, + { value: 'security_monitoring', label: 'Sicherheit & Monitoring', icon: '🛡️', desc: 'Anomalieerkennung, Bedrohungsanalyse, Zugriffskontrolle' }, + { value: 'personalization', label: 'Personalisierung', icon: '🎯', desc: 'Produktempfehlungen, dynamische Preisgestaltung, A/B-Testing' }, + { value: 'voice_speech', label: 'Sprache & Audio', icon: '🎙️', desc: 'Spracherkennung, Text-to-Speech, Meeting-Transkription' }, + { value: 'other', label: 'Sonstiges', icon: '➕', desc: 'Anderer KI-Anwendungsfall' }, ] +// Map Profil-Branche to domain value for backend compatibility +function industryToDomain(industries: string[]): string { + if (!industries || industries.length === 0) return 'general' + const first = industries[0].toLowerCase() + if (first.includes('gesundheit') || first.includes('pharma')) return 'healthcare' + if (first.includes('finanz') || first.includes('versicherung')) return 'finance' + if (first.includes('bildung')) return 'education' + if (first.includes('handel') || first.includes('commerce')) return 'retail' + if (first.includes('it') || first.includes('technologie')) return 'it_services' + if (first.includes('beratung') || first.includes('consulting')) return 'consulting' + if (first.includes('produktion') || first.includes('industrie') || first.includes('maschinenbau')) return 'manufacturing' + if (first.includes('marketing') || first.includes('agentur')) return 'marketing' + if (first.includes('recht')) return 'legal' + return 'general' +} + +// ============================================================================= +// DATA CATEGORIES (Step 2) — grouped tile selection +// ============================================================================= + +const DATA_CATEGORY_GROUPS = [ + { + group: 'Stamm- & Kontaktdaten', + items: [ + { value: 'basic_identity', label: 'Name & Identitaet', icon: '👤', desc: 'Vor-/Nachname, Geburtsdatum, Geschlecht' }, + { value: 'contact_data', label: 'Kontaktdaten', icon: '📧', desc: 'E-Mail, Telefon, Fax' }, + { value: 'address_data', label: 'Adressdaten', icon: '🏠', desc: 'Wohn-/Meldeadresse, PLZ, Lieferadresse' }, + { value: 'government_ids', label: 'Ausweisdaten', icon: '🪪', desc: 'Personalausweis-Nr., Reisepass, Fuehrerschein' }, + { value: 'customer_ids', label: 'Kundennummern', icon: '🏷️', desc: 'Kunden-ID, Vertrags-Nr., Mitgliedsnummer' }, + ], + }, + { + group: 'Besondere Kategorien (Art. 9 DSGVO)', + art9: true, + items: [ + { value: 'health_data', label: 'Gesundheitsdaten', icon: '🏥', desc: 'Diagnosen, Medikation, AU, Pflegegrad' }, + { value: 'biometric_data', label: 'Biometrische Daten', icon: '🔐', desc: 'Fingerabdruck, Gesichtserkennung, Iris-Scan' }, + { value: 'genetic_data', label: 'Genetische Daten', icon: '🧬', desc: 'DNA-Profil, Genomsequenzen, Erbkrankheitstests' }, + { value: 'racial_ethnic', label: 'Ethnische Herkunft', icon: '🌍', desc: 'Rassische/ethnische Zugehoerigkeit' }, + { value: 'political_opinions', label: 'Politische Meinungen', icon: '🗳️', desc: 'Politische Ueberzeugungen, Parteizugehoerigkeit' }, + { value: 'religious_beliefs', label: 'Religion', icon: '🕊️', desc: 'Religionszugehoerigkeit, Weltanschauung' }, + { value: 'trade_union', label: 'Gewerkschaft', icon: '🤝', desc: 'Gewerkschaftsmitgliedschaft' }, + { value: 'sexual_orientation', label: 'Sexuelle Orientierung', icon: '🏳️‍🌈', desc: 'Sexualleben und Orientierung' }, + ], + }, + { + group: 'Finanz- & Steuerdaten', + items: [ + { value: 'bank_account', label: 'Bankverbindung', icon: '🏦', desc: 'IBAN, BIC, Kontonummer' }, + { value: 'payment_card', label: 'Zahlungskarten', icon: '💳', desc: 'Kreditkarten-Nr., CVV (PCI-DSS)' }, + { value: 'transaction_data', label: 'Transaktionsdaten', icon: '🧾', desc: 'Zahlungshistorie, Ueberweisungen, Kaufhistorie' }, + { value: 'credit_score', label: 'Bonitaet / Schufa', icon: '📈', desc: 'Kreditwuerdigkeit, Schuldenhistorie' }, + { value: 'income_salary', label: 'Einkommen & Gehalt', icon: '💰', desc: 'Bruttogehalt, Nettolohn, Boni' }, + { value: 'tax_ids', label: 'Steuer-IDs', icon: '📋', desc: 'Steuer-ID, Steuernummer, USt-IdNr.' }, + { value: 'insurance_data', label: 'Versicherungsdaten', icon: '☂️', desc: 'Versicherungsnummern, Policen, Schadenmeldungen' }, + ], + }, + { + group: 'Fahrzeug- & Mobilitaetsdaten', + items: [ + { value: 'vehicle_ids', label: 'Fahrzeug-IDs (VIN)', icon: '🚗', desc: 'Fahrgestellnummer (VIN/FIN), Fahrzeugschein' }, + { value: 'license_plates', label: 'Kennzeichen', icon: '🔢', desc: 'Amtliches Kennzeichen, Wunschkennzeichen' }, + { value: 'gps_tracking', label: 'GPS & Routen', icon: '📍', desc: 'Echtzeitposition, Fahrtenprotokolle' }, + { value: 'telematics', label: 'Telematikdaten', icon: '📡', desc: 'Fahrverhalten, Geschwindigkeit, Motordiagnose' }, + { value: 'fleet_data', label: 'Fuhrpark / Logistik', icon: '🚛', desc: 'Einsatzzeiten, Kilometerstand, Fahrerzuweisung' }, + ], + }, + { + group: 'Technische Identifikatoren', + items: [ + { value: 'ip_address', label: 'IP-Adresse', icon: '🌐', desc: 'IPv4/IPv6 (EuGH: personenbezogen)' }, + { value: 'device_ids', label: 'Geraete-IDs', icon: '📱', desc: 'IMEI, UUID, Advertising-ID, Seriennummer' }, + { value: 'cookies_tracking', label: 'Cookies & Tracking', icon: '🍪', desc: 'Session-/Persistent Cookies, Pixel-Tags' }, + { value: 'browser_fingerprint', label: 'Browser-Fingerprint', icon: '🔎', desc: 'Browser-Typ, OS, Plugins, Canvas-Fingerprint' }, + { value: 'mac_address', label: 'MAC-Adresse', icon: '📶', desc: 'Netzwerkadapter-Kennung, WLAN-Praesenz' }, + ], + }, + { + group: 'Verhaltens- & Nutzungsdaten', + items: [ + { value: 'clickstream', label: 'Klick- & Nutzungspfade', icon: '🖱️', desc: 'Klickpfade, Scrolltiefe, Verweildauer, Heatmaps' }, + { value: 'purchase_history', label: 'Kaufverhalten', icon: '🛒', desc: 'Bestellhistorie, Warenkorb, Wunschlisten' }, + { value: 'app_usage', label: 'App-Nutzung', icon: '📲', desc: 'Genutzte Apps, Nutzungsdauer, In-App-Aktivitaeten' }, + { value: 'profiling_scores', label: 'Profiling / Scoring', icon: '📊', desc: 'KI-generierte Profile, Segmente, Affinitaetsscores' }, + ], + }, + { + group: 'Kommunikation & Medien', + items: [ + { value: 'email_content', label: 'E-Mail-Inhalte', icon: '✉️', desc: 'E-Mail-Texte, Anhaenge, Metadaten' }, + { value: 'chat_messages', label: 'Chat & Messaging', icon: '💬', desc: 'Textnachrichten, Messenger, Teams, Slack' }, + { value: 'call_recordings', label: 'Telefonaufzeichnungen', icon: '📞', desc: 'Gespraeche, Transkripte, Anrufmetadaten' }, + { value: 'video_conference', label: 'Videokonferenzen', icon: '📹', desc: 'Meeting-Aufzeichnungen, Teilnehmerlisten' }, + { value: 'photographs', label: 'Fotos & Bilder', icon: '📷', desc: 'Portraitfotos, Profilbilder, Produktfotos' }, + { value: 'cctv_surveillance', label: 'Videoueberwachung', icon: '📹', desc: 'CCTV-Aufnahmen, Zutrittskontrolle' }, + { value: 'voice_recordings', label: 'Sprachaufnahmen', icon: '🎙️', desc: 'Voicemails, Sprachmemos, Diktate' }, + ], + }, + { + group: 'HR & Beschaeftigung', + items: [ + { value: 'employment_data', label: 'Beschaeftigungsdaten', icon: '💼', desc: 'Arbeitgeber, Berufsbezeichnung, Vertragsart' }, + { value: 'performance_data', label: 'Leistungsbeurteilungen', icon: '🏆', desc: 'Zielerreichung, Feedback, Abmahnungen' }, + { value: 'work_time', label: 'Arbeitszeit', icon: '⏰', desc: 'Zeiterfassung, Ueberstunden, Schichtplaene' }, + { value: 'candidate_data', label: 'Bewerberdaten', icon: '📝', desc: 'Lebenslaeufe, Interviews, Assessment-Ergebnisse' }, + { value: 'social_security', label: 'Sozialversicherungs-Nr.', icon: '🛡️', desc: 'RVNR (Art. 9 — kodiert Geburtsdatum/Geschlecht)' }, + ], + }, + { + group: 'IoT & Sensordaten', + items: [ + { value: 'industrial_sensor', label: 'Industriesensoren', icon: '🏭', desc: 'Maschinendaten, Fehlerprotokolle, Produktionsmesswerte' }, + { value: 'wearable_data', label: 'Wearable-Daten', icon: '⌚', desc: 'Herzfrequenz, Schritte, Schlaf (Art. 9 — Gesundheit)' }, + { value: 'smart_home', label: 'Smart-Home', icon: '🏡', desc: 'Heizung, Licht, Bewegungsmelder, Nutzungszeiten' }, + { value: 'energy_data', label: 'Energieverbrauch', icon: '🔌', desc: 'Smart-Meter, Verbrauchsprofil (enthuellt Verhalten)' }, + ], + }, + { + group: 'Sonstige Kategorien', + items: [ + { value: 'children_data', label: 'Kinderdaten (unter 16)', icon: '👶', desc: 'Besonderer Schutz, Eltern-Einwilligung erforderlich' }, + { value: 'criminal_data', label: 'Strafrechtliche Daten', icon: '⚖️', desc: 'Vorstrafen, Ermittlungsverfahren (Art. 10 DSGVO)' }, + { value: 'location_data', label: 'Standortdaten', icon: '📍', desc: 'GPS, Mobilfunk, WLAN-Ortung, Bewegungsprofile' }, + { value: 'social_media', label: 'Social-Media-Daten', icon: '📱', desc: 'Profile, Posts, Follower, Interaktionen' }, + { value: 'auth_credentials', label: 'Login & Zugangsdaten', icon: '🔑', desc: 'Passwoerter, 2FA, Session-Tokens, Zugriffsprotokolle' }, + ], + }, +] + +// ============================================================================= +// PROCESSING PURPOSES (Step 3) — tile selection +// ============================================================================= + +const PURPOSE_TILES = [ + { value: 'service_delivery', label: 'Serviceerbringung', icon: '⚙️', desc: 'Kernfunktion des Produkts oder Services' }, + { value: 'analytics', label: 'Analyse & BI', icon: '📊', desc: 'Statistische Auswertung, Business Intelligence, Reporting' }, + { value: 'marketing', label: 'Marketing & Werbung', icon: '📢', desc: 'Werbung, Personalisierung, Targeting, Newsletter' }, + { value: 'profiling', label: 'Profiling', icon: '🎯', desc: 'Automatisierte Analyse personenbezogener Aspekte' }, + { value: 'automated_decision', label: 'Automatisierte Entscheidung', icon: '🤖', desc: 'Art. 22 DSGVO — Entscheidung ohne menschliches Zutun' }, + { value: 'customer_support', label: 'Kundensupport', icon: '🎧', desc: 'Anfragenbearbeitung, Ticketsystem, Chatbot' }, + { value: 'quality_control', label: 'Qualitaetskontrolle', icon: '✅', desc: 'Produktpruefung, Fehleranalyse, Prozessoptimierung' }, + { value: 'hr_management', label: 'Personalverwaltung', icon: '👥', desc: 'Recruiting, Onboarding, Mitarbeiterentwicklung' }, + { value: 'fraud_detection', label: 'Betrugserkennung', icon: '🕵️', desc: 'Anomalieerkennung, Transaktionsueberwachung' }, + { value: 'research', label: 'Forschung & Entwicklung', icon: '🔬', desc: 'Wissenschaftliche Auswertung, Produktentwicklung' }, + { value: 'compliance_audit', label: 'Compliance & Audit', icon: '📜', desc: 'Regulatorische Pruefung, Dokumentation, Audit-Trail' }, + { value: 'communication', label: 'Kommunikation', icon: '💬', desc: 'Interne/externe Kommunikation, Uebersetzung' }, + { value: 'content_creation', label: 'Content-Erstellung', icon: '✍️', desc: 'Text-, Bild-, Video-Generierung' }, + { value: 'predictive', label: 'Vorhersage & Prognose', icon: '🔮', desc: 'Demand Forecasting, Predictive Analytics, Wartungsvorhersage' }, + { value: 'security', label: 'IT-Sicherheit', icon: '🛡️', desc: 'Bedrohungserkennung, Zugriffskontrolle, Monitoring' }, + { value: 'archiving', label: 'Archivierung', icon: '🗄️', desc: 'Gesetzliche Aufbewahrung, Dokumentenarchiv' }, +] + +// ============================================================================= +// AUTOMATION LEVELS (Step 4) — single-select tiles +// ============================================================================= + +const AUTOMATION_TILES = [ + { value: 'assistive', label: 'Assistiv (Mensch entscheidet)', icon: '🧑‍💻', desc: 'KI liefert Vorschlaege, Mensch trifft Entscheidung', examples: 'Rechtschreibkorrektur, Suchvorschlaege, Zusammenfassungen' }, + { value: 'semi_automated', label: 'Teilautomatisiert (Mensch prueft)', icon: '🤝', desc: 'KI erstellt Ergebnisse, Mensch prueft und bestaetigt', examples: 'E-Mail-Entwuerfe mit Freigabe, KI-Vertraege mit juristischer Pruefung' }, + { value: 'fully_automated', label: 'Vollautomatisiert (KI entscheidet)', icon: '🤖', desc: 'KI trifft Entscheidungen eigenstaendig', examples: 'Automatische Kreditentscheidungen, autonome Chatbot-Antworten' }, +] + +// ============================================================================= +// HOSTING & MODEL (Step 5) — tiles +// ============================================================================= + +const HOSTING_PROVIDER_TILES = [ + { value: 'self_hosted', label: 'Eigenes Hosting', icon: '🏢', desc: 'On-Premise oder eigene Server' }, + { value: 'hetzner', label: 'Hetzner (DE)', icon: '🇩🇪', desc: 'Deutsche Cloud-Infrastruktur' }, + { value: 'aws', label: 'AWS', icon: '☁️', desc: 'Amazon Web Services' }, + { value: 'azure', label: 'Microsoft Azure', icon: '🔷', desc: 'Microsoft Cloud' }, + { value: 'gcp', label: 'Google Cloud', icon: '🔵', desc: 'Google Cloud Platform' }, + { value: 'other', label: 'Anderer Anbieter', icon: '🌐', desc: 'Sonstiger Cloud-Anbieter' }, +] + +const HOSTING_REGION_TILES = [ + { value: 'de', label: 'Deutschland', icon: '🇩🇪', desc: 'Rechenzentrum in Deutschland' }, + { value: 'eu', label: 'EU / EWR', icon: '🇪🇺', desc: 'Innerhalb der Europaeischen Union' }, + { value: 'us', label: 'USA', icon: '🇺🇸', desc: 'Vereinigte Staaten' }, + { value: 'other', label: 'Andere Region', icon: '🌍', desc: 'Drittland ausserhalb EU/USA' }, +] + +const MODEL_USAGE_TILES = [ + { value: 'inference', label: 'Inferenz', icon: '⚡', desc: 'Fertiges Modell direkt nutzen (z.B. ChatGPT, Claude, DeepL)' }, + { value: 'rag', label: 'RAG', icon: '📚', desc: 'Modell erhaelt Kontext aus eigenen Dokumenten' }, + { value: 'finetune', label: 'Fine-Tuning', icon: '🎛️', desc: 'Bestehendes Modell mit eigenen Daten nachtrainieren' }, + { value: 'training', label: 'Eigenes Modell trainieren', icon: '🧠', desc: 'Komplett eigenes KI-Modell von Grund auf' }, +] + +// ============================================================================= +// DATA TRANSFER (Step 6) — tiles +// ============================================================================= + +const TRANSFER_TARGET_TILES = [ + { value: 'no_transfer', label: 'Kein Drittlandtransfer', icon: '🇪🇺', desc: 'Daten verbleiben in der EU/EWR' }, + { value: 'usa', label: 'USA', icon: '🇺🇸', desc: 'Datentransfer in die USA' }, + { value: 'uk', label: 'Grossbritannien', icon: '🇬🇧', desc: 'Datentransfer nach UK (Angemessenheitsbeschluss)' }, + { value: 'switzerland', label: 'Schweiz', icon: '🇨🇭', desc: 'Datentransfer in die Schweiz (Angemessenheitsbeschluss)' }, + { value: 'other_adequate', label: 'Anderes Land (Angemessenheit)', icon: '✅', desc: 'Land mit Angemessenheitsbeschluss der EU' }, + { value: 'other_third', label: 'Sonstiges Drittland', icon: '🌍', desc: 'Land ohne Angemessenheitsbeschluss' }, +] + +const TRANSFER_MECHANISM_TILES = [ + { value: 'not_needed', label: 'Nicht erforderlich', icon: '✅', desc: 'Kein Drittlandtransfer oder Angemessenheit' }, + { value: 'scc', label: 'Standardvertragsklauseln', icon: '📝', desc: 'SCC nach Art. 46 Abs. 2c DSGVO' }, + { value: 'bcr', label: 'Binding Corporate Rules', icon: '🏛️', desc: 'BCR nach Art. 47 DSGVO' }, + { value: 'adequacy', label: 'Angemessenheitsbeschluss', icon: '🤝', desc: 'EU-Kommissionsbeschluss (z.B. EU-US DPF)' }, + { value: 'derogation', label: 'Ausnahme (Art. 49)', icon: '⚠️', desc: 'Einwilligung oder zwingende Interessen' }, +] + +// ============================================================================= +// RETENTION (Step 7) — tiles +// ============================================================================= + +const RETENTION_TILES = [ + { value: 'session', label: 'Nur waehrend Session', icon: '⏱️', desc: 'Daten werden nach Sitzungsende geloescht' }, + { value: '30_days', label: '30 Tage', icon: '📅', desc: 'Kurzfristige Aufbewahrung' }, + { value: '90_days', label: '90 Tage', icon: '📅', desc: 'Standardaufbewahrung' }, + { value: '1_year', label: '1 Jahr', icon: '📆', desc: 'Jaehrliche Aufbewahrung' }, + { value: '3_years', label: '3 Jahre', icon: '📆', desc: 'Mittelfristige Aufbewahrung' }, + { value: '6_years', label: '6 Jahre', icon: '📆', desc: 'Handelsrechtliche Aufbewahrungsfrist' }, + { value: '10_years', label: '10 Jahre', icon: '📆', desc: 'Steuerrechtliche Aufbewahrungsfrist' }, + { value: 'indefinite', label: 'Unbefristet', icon: '♾️', desc: 'Keine zeitliche Begrenzung' }, +] + +// ============================================================================= +// CONTRACTS (Step 8) — tiles +// ============================================================================= + +const CONTRACT_TILES = [ + { value: 'has_dpa', label: 'AVV / DPA vorhanden', icon: '📄', desc: 'Auftragsverarbeitungsvertrag nach Art. 28 DSGVO' }, + { value: 'has_aia_doc', label: 'AI Act Dokumentation', icon: '🤖', desc: 'Risikoklassifizierung und technische Doku nach EU AI Act' }, + { value: 'has_dsfa', label: 'DSFA durchgefuehrt', icon: '📋', desc: 'Datenschutz-Folgenabschaetzung nach Art. 35 DSGVO' }, + { value: 'has_tia', label: 'TIA durchgefuehrt', icon: '🌍', desc: 'Transfer Impact Assessment fuer Drittlandtransfers' }, + { value: 'has_tom', label: 'TOM dokumentiert', icon: '🔒', desc: 'Technisch-organisatorische Massnahmen nach Art. 32 DSGVO' }, + { value: 'has_vvt', label: 'Im VVT erfasst', icon: '📚', desc: 'Im Verzeichnis von Verarbeitungstaetigkeiten eingetragen' }, + { value: 'has_consent', label: 'Einwilligungen eingeholt', icon: '✅', desc: 'Nutzereinwilligungen vorhanden und dokumentiert' }, + { value: 'none', label: 'Noch keine Dokumente', icon: '⚠️', desc: 'Compliance-Dokumentation steht noch aus' }, +] + +// ============================================================================= +// SHARED TILE TOGGLE HELPER +// ============================================================================= + +function toggleInArray(arr: string[], value: string): string[] { + return arr.includes(value) ? arr.filter(v => v !== value) : [...arr, value] +} + // ============================================================================= // MAIN COMPONENT // ============================================================================= @@ -41,6 +300,7 @@ const DOMAINS = [ function NewUseCasePageInner() { const router = useRouter() const searchParams = useSearchParams() + const { state: sdkState } = useSDK() const editId = searchParams.get('edit') const isEditMode = !!editId @@ -50,48 +310,39 @@ function NewUseCasePageInner() { const [result, setResult] = useState(null) const [error, setError] = useState(null) - // Form state + // Derive domain from company profile industry + const profileIndustry = sdkState.companyProfile?.industry + const derivedDomain = industryToDomain( + Array.isArray(profileIndustry) ? profileIndustry : profileIndustry ? [profileIndustry] : [] + ) + + // Form state — tile-based multi-select via arrays const [form, setForm] = useState({ title: '', use_case_text: '', domain: 'general', - // Data Types - personal_data: false, - special_categories: false, - minors_data: false, - health_data: false, - biometric_data: false, - financial_data: false, + category: '' as string, + // Data categories (multi-select tiles) + data_categories: [] as string[], custom_data_types: [] as string[], - // Purpose - purpose_profiling: false, - purpose_automated_decision: false, - purpose_marketing: false, - purpose_analytics: false, - purpose_service_delivery: false, - // Automation - automation: 'assistive' as 'assistive' | 'semi_automated' | 'fully_automated', - // Hosting - hosting_provider: 'self_hosted', - hosting_region: 'eu', - // Model Usage - model_rag: false, - model_finetune: false, - model_training: false, - model_inference: true, - // Legal Basis (Step 3) - legal_basis: 'consent' as 'consent' | 'contract' | 'legitimate_interest' | 'legal_obligation' | 'vital_interest' | 'public_interest', - // Data Transfer (Step 6) - international_transfer: false, + // Purpose (multi-select tiles) + purposes: [] as string[], + // Automation (single-select tile) + automation: '' as string, + // Hosting (single-select tile) + hosting_provider: '' as string, + hosting_region: '' as string, + // Model Usage (multi-select tiles) + model_usage: [] as string[], + // Data Transfer (Step 6 — tiles) + transfer_targets: [] as string[], transfer_countries: [] as string[], - transfer_mechanism: 'none' as 'none' | 'scc' | 'bcr' | 'adequacy' | 'derogation', + transfer_mechanism: '' as string, // Retention (Step 7) - retention_days: 90, + retention_period: '' as string, retention_purpose: '', - // Contracts (Step 8) - has_dpa: false, - has_aia_documentation: false, - has_risk_assessment: false, + // Contracts (Step 8 — multi-select tiles) + contracts: [] as string[], subprocessors: '', }) @@ -99,6 +350,14 @@ function NewUseCasePageInner() { setForm(prev => ({ ...prev, ...updates })) } + // Auto-set domain from profile + useEffect(() => { + if (!isEditMode && derivedDomain !== 'general') { + updateForm({ domain: derivedDomain }) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [derivedDomain]) + // Pre-fill form when in edit mode useEffect(() => { if (!editId) return @@ -111,35 +370,21 @@ function NewUseCasePageInner() { title: data.title || '', use_case_text: intake.use_case_text || '', domain: data.domain || 'general', - personal_data: intake.data_types?.personal_data || false, - special_categories: intake.data_types?.article_9_data || false, - minors_data: intake.data_types?.minor_data || false, - health_data: intake.data_types?.health_data || false, - biometric_data: intake.data_types?.biometric_data || false, - financial_data: intake.data_types?.financial_data || false, - custom_data_types: intake.data_types?.custom_data_types || [], - purpose_profiling: intake.purpose?.profiling || false, - purpose_automated_decision: intake.purpose?.automated_decision || intake.purpose?.decision_making || false, - purpose_marketing: intake.purpose?.marketing || false, - purpose_analytics: intake.purpose?.analytics || false, - purpose_service_delivery: intake.purpose?.service_delivery || intake.purpose?.customer_support || false, - automation: intake.automation || 'assistive', - hosting_provider: intake.hosting?.provider || 'self_hosted', - hosting_region: intake.hosting?.region || 'eu', - model_rag: intake.model_usage?.rag || false, - model_finetune: intake.model_usage?.finetune || false, - model_training: intake.model_usage?.training || false, - model_inference: intake.model_usage?.inference ?? true, - legal_basis: intake.legal_basis || 'consent', - international_transfer: intake.international_transfer?.enabled || false, - transfer_countries: intake.international_transfer?.countries || [], - transfer_mechanism: intake.international_transfer?.mechanism || 'none', - retention_days: intake.retention?.days || 90, - retention_purpose: intake.retention?.purpose || '', - has_dpa: intake.contracts?.has_dpa || false, - has_aia_documentation: intake.contracts?.has_aia_documentation || false, - has_risk_assessment: intake.contracts?.has_risk_assessment || false, - subprocessors: intake.contracts?.subprocessors || '', + category: data.category || intake.category || '', + data_categories: intake.data_categories || [], + custom_data_types: intake.data_types?.custom_data_types || intake.custom_data_types || [], + purposes: intake.purposes || [], + automation: intake.automation || '', + hosting_provider: intake.hosting?.provider || '', + hosting_region: intake.hosting?.region || '', + model_usage: intake.model_usage_list || [], + transfer_targets: intake.transfer_targets || [], + transfer_countries: intake.international_transfer?.countries || intake.transfer_countries || [], + transfer_mechanism: intake.transfer_mechanism || intake.international_transfer?.mechanism || '', + retention_period: intake.retention_period || '', + retention_purpose: intake.retention?.purpose || intake.retention_purpose || '', + contracts: intake.contracts_list || [], + subprocessors: intake.contracts?.subprocessors || intake.subprocessors || '', }) }) .catch(() => {}) @@ -154,49 +399,23 @@ function NewUseCasePageInner() { title: form.title, use_case_text: form.use_case_text, domain: form.domain, - data_types: { - personal_data: form.personal_data, - special_categories: form.special_categories, - minors_data: form.minors_data, - health_data: form.health_data, - biometric_data: form.biometric_data, - financial_data: form.financial_data, - custom_data_types: form.custom_data_types.filter(s => s.trim()), - }, - purpose: { - profiling: form.purpose_profiling, - automated_decision: form.purpose_automated_decision, - marketing: form.purpose_marketing, - analytics: form.purpose_analytics, - service_delivery: form.purpose_service_delivery, - }, + category: form.category, + data_categories: form.data_categories, + custom_data_types: form.custom_data_types.filter(s => s.trim()), + purposes: form.purposes, automation: form.automation, hosting: { provider: form.hosting_provider, region: form.hosting_region, }, - model_usage: { - rag: form.model_rag, - finetune: form.model_finetune, - training: form.model_training, - inference: form.model_inference, - }, - legal_basis: form.legal_basis, - international_transfer: { - enabled: form.international_transfer, - countries: form.transfer_countries, - mechanism: form.transfer_mechanism, - }, - retention: { - days: form.retention_days, - purpose: form.retention_purpose, - }, - contracts: { - has_dpa: form.has_dpa, - has_aia_documentation: form.has_aia_documentation, - has_risk_assessment: form.has_risk_assessment, - subprocessors: form.subprocessors, - }, + model_usage_list: form.model_usage, + transfer_targets: form.transfer_targets, + transfer_countries: form.transfer_countries, + transfer_mechanism: form.transfer_mechanism, + retention_period: form.retention_period, + retention_purpose: form.retention_purpose, + contracts_list: form.contracts, + subprocessors: form.subprocessors, store_raw_text: true, } @@ -315,10 +534,21 @@ function NewUseCasePageInner() {
{/* Step 1: Grundlegendes */} {currentStep === 1 && ( -
+

Grundlegende Informationen

+ + {/* Branche aus Profil (nur Anzeige) */} + {profileIndustry && (Array.isArray(profileIndustry) ? profileIndustry.length > 0 : true) && ( +
+ Branche (aus Unternehmensprofil) +

+ {Array.isArray(profileIndustry) ? profileIndustry.join(', ') : profileIndustry} +

+
+ )} +
- +
+ + {/* KI-Anwendungskategorie als Kacheln */}
- - +
)} {/* Step 2: Datenkategorien */} {currentStep === 2 && ( -
+

Welche Daten werden verarbeitet?

- {[ - { key: 'personal_data', label: 'Personenbezogene Daten', desc: 'Name, E-Mail, Adresse etc.' }, - { key: 'special_categories', label: 'Besondere Kategorien (Art. 9)', desc: 'Religion, Gesundheit, politische Meinung' }, - { key: 'health_data', label: 'Gesundheitsdaten', desc: 'Diagnosen, Medikation, Fitness' }, - { key: 'biometric_data', label: 'Biometrische Daten', desc: 'Gesichtserkennung, Fingerabdruck, Stimme' }, - { key: 'minors_data', label: 'Daten von Minderjaehrigen', desc: 'Unter 16 Jahren' }, - { key: 'financial_data', label: 'Finanzdaten', desc: 'Kontodaten, Transaktionen, Kreditwuerdigkeit' }, - ].map(item => ( -