fix(sdk): Fix compliance scope wizard — missing labels, broken prefill, invisible helpText

- Rename `label` to `question` in profiling data (35 questions) to match
  ScopeProfilingQuestion type — fixes missing question headings
- Sync ScopeWizardTab props with page.tsx (onEvaluate/canEvaluate/isEvaluating
  instead of onComplete/companyProfile/currentLevel)
- Load companyProfile from SDK context instead of expecting it as prop
- Auto-prefill from company profile on mount when answers are empty
- Add "Aus Profil" badge for prefilled questions
- Replace title-only helpText tooltip with click-to-expand visible info box
- Fix ScopeQuestionBlockId to match actual block IDs in data
- Add `order` field to ScopeQuestionBlock type
- Fix completionStats to count against total required questions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-02-10 13:42:31 +01:00
parent 81536d9738
commit b3e9604d72
4 changed files with 243 additions and 193 deletions

View File

@@ -19,7 +19,7 @@ const BLOCK_1_ORGANISATION: ScopeQuestionBlock = {
{
id: 'org_employee_count',
type: 'number',
label: 'Wie viele Mitarbeiter hat Ihre Organisation?',
question: 'Wie viele Mitarbeiter hat Ihre Organisation?',
helpText: 'Geben Sie die Gesamtzahl aller Beschäftigten an (inkl. Teilzeit, Minijobs)',
required: true,
scoreWeights: { risk: 5, complexity: 8, assurance: 6 },
@@ -28,7 +28,7 @@ const BLOCK_1_ORGANISATION: ScopeQuestionBlock = {
{
id: 'org_customer_count',
type: 'single',
label: 'Wie viele Kunden/Nutzer betreuen Sie?',
question: 'Wie viele Kunden/Nutzer betreuen Sie?',
helpText: 'Schätzen Sie die Anzahl aktiver Kunden oder Nutzer',
required: true,
options: [
@@ -43,7 +43,7 @@ const BLOCK_1_ORGANISATION: ScopeQuestionBlock = {
{
id: 'org_annual_revenue',
type: 'single',
label: 'Wie hoch ist Ihr jährlicher Umsatz?',
question: 'Wie hoch ist Ihr jährlicher Umsatz?',
helpText: 'Wählen Sie die zutreffende Umsatzklasse',
required: true,
options: [
@@ -58,7 +58,7 @@ const BLOCK_1_ORGANISATION: ScopeQuestionBlock = {
{
id: 'org_cert_target',
type: 'multi',
label: 'Welche Zertifizierungen streben Sie an oder besitzen Sie bereits?',
question: 'Welche Zertifizierungen streben Sie an oder besitzen Sie bereits?',
helpText: 'Mehrfachauswahl möglich. Zertifizierungen erhöhen den Assurance-Bedarf',
required: false,
options: [
@@ -74,7 +74,7 @@ const BLOCK_1_ORGANISATION: ScopeQuestionBlock = {
{
id: 'org_industry',
type: 'single',
label: 'In welcher Branche sind Sie tätig?',
question: 'In welcher Branche sind Sie tätig?',
helpText: 'Ihre Branche beeinflusst Risikobewertung und regulatorische Anforderungen',
required: true,
options: [
@@ -96,7 +96,7 @@ const BLOCK_1_ORGANISATION: ScopeQuestionBlock = {
{
id: 'org_business_model',
type: 'single',
label: 'Was ist Ihr primäres Geschäftsmodell?',
question: 'Was ist Ihr primäres Geschäftsmodell?',
helpText: 'B2C-Modelle haben höhere Datenschutzanforderungen',
required: true,
options: [
@@ -113,7 +113,7 @@ const BLOCK_1_ORGANISATION: ScopeQuestionBlock = {
{
id: 'org_has_dsb',
type: 'boolean',
label: 'Haben Sie einen Datenschutzbeauftragten bestellt?',
question: 'Haben Sie einen Datenschutzbeauftragten bestellt?',
helpText: 'Ein DSB ist bei mehr als 20 Personen mit regelmäßiger Datenverarbeitung Pflicht',
required: true,
scoreWeights: { risk: 5, complexity: 3, assurance: 6 },
@@ -133,7 +133,7 @@ const BLOCK_2_DATA: ScopeQuestionBlock = {
{
id: 'data_minors',
type: 'boolean',
label: 'Verarbeiten Sie Daten von Minderjährigen?',
question: 'Verarbeiten Sie Daten von Minderjährigen?',
helpText: 'Besondere Schutzpflichten für unter 16-Jährige (bzw. 13-Jährige bei Online-Diensten)',
required: true,
scoreWeights: { risk: 10, complexity: 5, assurance: 7 },
@@ -142,7 +142,7 @@ const BLOCK_2_DATA: ScopeQuestionBlock = {
{
id: 'data_art9',
type: 'multi',
label: 'Verarbeiten Sie besondere Kategorien personenbezogener Daten (Art. 9 DSGVO)?',
question: 'Verarbeiten Sie besondere Kategorien personenbezogener Daten (Art. 9 DSGVO)?',
helpText: 'Diese Daten unterliegen erhöhten Schutzanforderungen',
required: true,
options: [
@@ -162,7 +162,7 @@ const BLOCK_2_DATA: ScopeQuestionBlock = {
{
id: 'data_hr',
type: 'boolean',
label: 'Verarbeiten Sie Personaldaten (HR)?',
question: 'Verarbeiten Sie Personaldaten (HR)?',
helpText: 'Bewerberdaten, Gehälter, Leistungsbeurteilungen etc.',
required: true,
scoreWeights: { risk: 6, complexity: 4, assurance: 5 },
@@ -172,7 +172,7 @@ const BLOCK_2_DATA: ScopeQuestionBlock = {
{
id: 'data_communication',
type: 'boolean',
label: 'Verarbeiten Sie Kommunikationsdaten (E-Mail, Chat, Telefonie)?',
question: 'Verarbeiten Sie Kommunikationsdaten (E-Mail, Chat, Telefonie)?',
helpText: 'Inhalte oder Metadaten von Kommunikationsvorgängen',
required: true,
scoreWeights: { risk: 7, complexity: 5, assurance: 6 },
@@ -180,7 +180,7 @@ const BLOCK_2_DATA: ScopeQuestionBlock = {
{
id: 'data_financial',
type: 'boolean',
label: 'Verarbeiten Sie Finanzdaten (Konten, Zahlungen)?',
question: 'Verarbeiten Sie Finanzdaten (Konten, Zahlungen)?',
helpText: 'Bankdaten, Kreditkartendaten, Buchhaltungsdaten',
required: true,
scoreWeights: { risk: 8, complexity: 6, assurance: 7 },
@@ -190,7 +190,7 @@ const BLOCK_2_DATA: ScopeQuestionBlock = {
{
id: 'data_volume',
type: 'single',
label: 'Wie viele Personendatensätze verarbeiten Sie insgesamt?',
question: 'Wie viele Personendatensätze verarbeiten Sie insgesamt?',
helpText: 'Schätzen Sie die Gesamtzahl betroffener Personen',
required: true,
options: [
@@ -217,7 +217,7 @@ const BLOCK_3_PROCESSING: ScopeQuestionBlock = {
{
id: 'proc_tracking',
type: 'boolean',
label: 'Setzen Sie Tracking oder Profiling ein?',
question: 'Setzen Sie Tracking oder Profiling ein?',
helpText: 'Web-Analytics, Werbe-Tracking, Nutzungsprofile etc.',
required: true,
scoreWeights: { risk: 7, complexity: 6, assurance: 6 },
@@ -225,7 +225,7 @@ const BLOCK_3_PROCESSING: ScopeQuestionBlock = {
{
id: 'proc_adm_scoring',
type: 'boolean',
label: 'Treffen Sie automatisierte Entscheidungen (Art. 22 DSGVO)?',
question: 'Treffen Sie automatisierte Entscheidungen (Art. 22 DSGVO)?',
helpText: 'Scoring, Bonitätsprüfung, automatische Ablehnung ohne menschliche Beteiligung',
required: true,
scoreWeights: { risk: 9, complexity: 8, assurance: 8 },
@@ -233,7 +233,7 @@ const BLOCK_3_PROCESSING: ScopeQuestionBlock = {
{
id: 'proc_ai_usage',
type: 'multi',
label: 'Setzen Sie KI-Systeme ein?',
question: 'Setzen Sie KI-Systeme ein?',
helpText: 'KI-Einsatz kann zusätzliche Anforderungen (EU AI Act) auslösen',
required: true,
options: [
@@ -249,7 +249,7 @@ const BLOCK_3_PROCESSING: ScopeQuestionBlock = {
{
id: 'proc_data_combination',
type: 'boolean',
label: 'Führen Sie Daten aus verschiedenen Quellen zusammen?',
question: 'Führen Sie Daten aus verschiedenen Quellen zusammen?',
helpText: 'Data Matching, Anreicherung aus externen Quellen',
required: true,
scoreWeights: { risk: 7, complexity: 7, assurance: 6 },
@@ -257,7 +257,7 @@ const BLOCK_3_PROCESSING: ScopeQuestionBlock = {
{
id: 'proc_employee_monitoring',
type: 'boolean',
label: 'Überwachen Sie Mitarbeiter (Zeiterfassung, Standort, IT-Nutzung)?',
question: 'Überwachen Sie Mitarbeiter (Zeiterfassung, Standort, IT-Nutzung)?',
helpText: 'Beschäftigtendatenschutz nach § 26 BDSG',
required: true,
scoreWeights: { risk: 8, complexity: 6, assurance: 7 },
@@ -265,7 +265,7 @@ const BLOCK_3_PROCESSING: ScopeQuestionBlock = {
{
id: 'proc_video_surveillance',
type: 'boolean',
label: 'Setzen Sie Videoüberwachung ein?',
question: 'Setzen Sie Videoüberwachung ein?',
helpText: 'Kameras in Büros, Produktionsstätten, Verkaufsräumen etc.',
required: true,
scoreWeights: { risk: 8, complexity: 5, assurance: 7 },
@@ -287,7 +287,7 @@ const BLOCK_4_TECH: ScopeQuestionBlock = {
{
id: 'tech_hosting_location',
type: 'single',
label: 'Wo werden Ihre Daten primär gehostet?',
question: 'Wo werden Ihre Daten primär gehostet?',
helpText: 'Standort bestimmt anwendbares Datenschutzrecht',
required: true,
options: [
@@ -302,7 +302,7 @@ const BLOCK_4_TECH: ScopeQuestionBlock = {
{
id: 'tech_subprocessors',
type: 'boolean',
label: 'Nutzen Sie Auftragsverarbeiter (externe Dienstleister)?',
question: 'Nutzen Sie Auftragsverarbeiter (externe Dienstleister)?',
helpText: 'Cloud-Anbieter, Hosting, E-Mail-Service, CRM etc. erfordert AVV nach Art. 28 DSGVO',
required: true,
scoreWeights: { risk: 6, complexity: 7, assurance: 7 },
@@ -310,7 +310,7 @@ const BLOCK_4_TECH: ScopeQuestionBlock = {
{
id: 'tech_third_country',
type: 'boolean',
label: 'Übermitteln Sie Daten in Drittländer?',
question: 'Übermitteln Sie Daten in Drittländer?',
helpText: 'Transfer außerhalb EU/EWR erfordert Schutzmaßnahmen (SCC, BCR etc.)',
required: true,
scoreWeights: { risk: 9, complexity: 8, assurance: 8 },
@@ -319,7 +319,7 @@ const BLOCK_4_TECH: ScopeQuestionBlock = {
{
id: 'tech_encryption_rest',
type: 'boolean',
label: 'Sind Daten im Ruhezustand verschlüsselt (at rest)?',
question: 'Sind Daten im Ruhezustand verschlüsselt (at rest)?',
helpText: 'Datenbank-, Dateisystem- oder Volume-Verschlüsselung',
required: true,
scoreWeights: { risk: -5, complexity: 3, assurance: 7 },
@@ -327,7 +327,7 @@ const BLOCK_4_TECH: ScopeQuestionBlock = {
{
id: 'tech_encryption_transit',
type: 'boolean',
label: 'Sind Daten bei Übertragung verschlüsselt (in transit)?',
question: 'Sind Daten bei Übertragung verschlüsselt (in transit)?',
helpText: 'TLS/SSL für alle Verbindungen',
required: true,
scoreWeights: { risk: -5, complexity: 2, assurance: 7 },
@@ -335,7 +335,7 @@ const BLOCK_4_TECH: ScopeQuestionBlock = {
{
id: 'tech_cloud_providers',
type: 'multi',
label: 'Welche Cloud-Anbieter nutzen Sie?',
question: 'Welche Cloud-Anbieter nutzen Sie?',
helpText: 'Mehrfachauswahl möglich',
required: false,
options: [
@@ -365,7 +365,7 @@ const BLOCK_5_PROCESSES: ScopeQuestionBlock = {
{
id: 'proc_dsar_process',
type: 'boolean',
label: 'Haben Sie einen Prozess für Betroffenenrechte (DSAR)?',
question: 'Haben Sie einen Prozess für Betroffenenrechte (DSAR)?',
helpText: 'Auskunft, Löschung, Berichtigung, Widerspruch etc. Art. 15-22 DSGVO',
required: true,
scoreWeights: { risk: 6, complexity: 5, assurance: 8 },
@@ -373,7 +373,7 @@ const BLOCK_5_PROCESSES: ScopeQuestionBlock = {
{
id: 'proc_deletion_concept',
type: 'boolean',
label: 'Haben Sie ein Löschkonzept?',
question: 'Haben Sie ein Löschkonzept?',
helpText: 'Definierte Löschfristen und automatisierte Löschroutinen',
required: true,
scoreWeights: { risk: 7, complexity: 6, assurance: 8 },
@@ -381,7 +381,7 @@ const BLOCK_5_PROCESSES: ScopeQuestionBlock = {
{
id: 'proc_incident_response',
type: 'boolean',
label: 'Haben Sie einen Notfallplan für Datenschutzvorfälle?',
question: 'Haben Sie einen Notfallplan für Datenschutzvorfälle?',
helpText: 'Incident Response Plan, 72h-Meldepflicht an Aufsichtsbehörde (Art. 33 DSGVO)',
required: true,
scoreWeights: { risk: 8, complexity: 6, assurance: 9 },
@@ -389,7 +389,7 @@ const BLOCK_5_PROCESSES: ScopeQuestionBlock = {
{
id: 'proc_regular_audits',
type: 'boolean',
label: 'Führen Sie regelmäßige Datenschutz-Audits durch?',
question: 'Führen Sie regelmäßige Datenschutz-Audits durch?',
helpText: 'Interne oder externe Prüfungen mindestens jährlich',
required: true,
scoreWeights: { risk: 5, complexity: 4, assurance: 9 },
@@ -397,7 +397,7 @@ const BLOCK_5_PROCESSES: ScopeQuestionBlock = {
{
id: 'proc_training',
type: 'boolean',
label: 'Schulen Sie Ihre Mitarbeiter im Datenschutz?',
question: 'Schulen Sie Ihre Mitarbeiter im Datenschutz?',
helpText: 'Awareness-Trainings, Onboarding, jährliche Auffrischung',
required: true,
scoreWeights: { risk: 6, complexity: 3, assurance: 7 },
@@ -417,7 +417,7 @@ const BLOCK_6_PRODUCT: ScopeQuestionBlock = {
{
id: 'prod_type',
type: 'multi',
label: 'Welche Art von Produkten/Services bieten Sie an?',
question: 'Welche Art von Produkten/Services bieten Sie an?',
helpText: 'Mehrfachauswahl möglich',
required: true,
options: [
@@ -435,7 +435,7 @@ const BLOCK_6_PRODUCT: ScopeQuestionBlock = {
{
id: 'prod_cookies_consent',
type: 'boolean',
label: 'Benötigen Sie Cookie-Consent (Tracking-Cookies)?',
question: 'Benötigen Sie Cookie-Consent (Tracking-Cookies)?',
helpText: 'Nicht-essenzielle Cookies erfordern opt-in Einwilligung',
required: true,
scoreWeights: { risk: 5, complexity: 4, assurance: 6 },
@@ -443,7 +443,7 @@ const BLOCK_6_PRODUCT: ScopeQuestionBlock = {
{
id: 'prod_webshop',
type: 'boolean',
label: 'Betreiben Sie einen Online-Shop?',
question: 'Betreiben Sie einen Online-Shop?',
helpText: 'E-Commerce mit Zahlungsabwicklung, Bestellverwaltung',
required: true,
scoreWeights: { risk: 7, complexity: 6, assurance: 6 },
@@ -451,7 +451,7 @@ const BLOCK_6_PRODUCT: ScopeQuestionBlock = {
{
id: 'prod_api_external',
type: 'boolean',
label: 'Bieten Sie externe APIs an (Daten-Weitergabe an Dritte)?',
question: 'Bieten Sie externe APIs an (Daten-Weitergabe an Dritte)?',
helpText: 'Programmierschnittstellen für Partner, Entwickler etc.',
required: true,
scoreWeights: { risk: 7, complexity: 7, assurance: 7 },
@@ -459,7 +459,7 @@ const BLOCK_6_PRODUCT: ScopeQuestionBlock = {
{
id: 'prod_data_broker',
type: 'boolean',
label: 'Handeln Sie mit Daten (Data Brokerage, Adresshandel)?',
question: 'Handeln Sie mit Daten (Data Brokerage, Adresshandel)?',
helpText: 'Verkauf oder Vermittlung personenbezogener Daten',
required: true,
scoreWeights: { risk: 10, complexity: 8, assurance: 9 },

View File

@@ -42,12 +42,12 @@ export interface ComplianceScores {
* IDs der Fragenblöcke für das Scope-Profiling
*/
export type ScopeQuestionBlockId =
| 'org_reife' // Organisatorische Reife
| 'daten_betroffene' // Daten & Betroffene
| 'verarbeitung_zweck' // Verarbeitung & Zweck
| 'technik_hosting' // Technik & Hosting
| 'rechte_prozesse' // Rechte & Prozesse
| 'produktkontext'; // Produktkontext
| 'organisation' // Organisation & Reife
| 'data' // Daten & Betroffene
| 'processing' // Verarbeitung & Zweck
| 'tech' // Technik & Hosting
| 'processes' // Rechte & Prozesse
| 'product'; // Produktkontext
/**
* Eine einzelne Frage im Scope-Profiling
@@ -55,8 +55,6 @@ export type ScopeQuestionBlockId =
export interface ScopeProfilingQuestion {
/** Eindeutige ID der Frage */
id: string;
/** Zugehöriger Block */
block: ScopeQuestionBlockId;
/** Fragetext */
question: string;
/** Optional: Hilfetext/Erklärung */
@@ -103,6 +101,8 @@ export interface ScopeQuestionBlock {
title: string;
/** Block-Beschreibung */
description: string;
/** Reihenfolge des Blocks */
order: number;
/** Fragen in diesem Block */
questions: ScopeProfilingQuestion[];
}