diff --git a/admin-compliance/app/sdk/vvt/_components/FormPrimitives.tsx b/admin-compliance/app/sdk/vvt/_components/FormPrimitives.tsx new file mode 100644 index 0000000..7ad6b11 --- /dev/null +++ b/admin-compliance/app/sdk/vvt/_components/FormPrimitives.tsx @@ -0,0 +1,96 @@ +'use client' + +import { useState } from 'react' + +export function FormSection({ title, children }: { title: string; children: React.ReactNode }) { + return ( +
+

{title}

+ {children} +
+ ) +} + +export function FormField({ label, children }: { label: string; children: React.ReactNode }) { + return ( +
+ + {children} +
+ ) +} + +export function MultiTextInput({ values, onChange, placeholder }: { values: string[]; onChange: (v: string[]) => void; placeholder?: string }) { + const [input, setInput] = useState('') + + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === 'Enter' && input.trim()) { + e.preventDefault() + onChange([...values, input.trim()]) + setInput('') + } + } + + return ( +
+
+ {values.map((v, i) => ( + + {v} + + + ))} +
+ setInput(e.target.value)} + onKeyDown={handleKeyDown} + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent" + placeholder={placeholder} + /> +
+ ) +} + +export function CheckboxGrid({ options, selected, onChange }: { + options: { value: string; label: string; highlight?: boolean }[] + selected: string[] + onChange: (v: string[]) => void +}) { + const toggle = (value: string) => { + if (selected.includes(value)) { + onChange(selected.filter(v => v !== value)) + } else { + onChange([...selected, value]) + } + } + + return ( +
+ {options.map(opt => ( + + ))} +
+ ) +} diff --git a/admin-compliance/app/sdk/vvt/_components/TabEditor.tsx b/admin-compliance/app/sdk/vvt/_components/TabEditor.tsx new file mode 100644 index 0000000..cace8b8 --- /dev/null +++ b/admin-compliance/app/sdk/vvt/_components/TabEditor.tsx @@ -0,0 +1,402 @@ +'use client' + +import { useState, useEffect } from 'react' +import { + DATA_SUBJECT_CATEGORY_META, + PERSONAL_DATA_CATEGORY_META, + LEGAL_BASIS_META, + TRANSFER_MECHANISM_META, + ART9_CATEGORIES, + BUSINESS_FUNCTION_LABELS, + STATUS_LABELS, + STATUS_COLORS, + PROTECTION_LEVEL_LABELS, + DEPLOYMENT_LABELS, +} from '@/lib/sdk/vvt-types' +import type { VVTActivity, BusinessFunction } from '@/lib/sdk/vvt-types' +import { FormSection, FormField, MultiTextInput, CheckboxGrid } from './FormPrimitives' + +export function TabEditor({ + activity, activities, onSave, onBack, onSelectActivity, +}: { + activity: VVTActivity | null | undefined + activities: VVTActivity[] + onSave: (updated: VVTActivity) => void + onBack: () => void + onSelectActivity: (id: string) => void +}) { + const [local, setLocal] = useState(null) + const [showAdvanced, setShowAdvanced] = useState(false) + + useEffect(() => { + setLocal(activity ? { ...activity } : null) + }, [activity]) + + if (!local) { + return ( +
+
+

Keine Verarbeitung ausgewaehlt

+

Waehlen Sie eine Verarbeitung aus dem Verzeichnis oder erstellen Sie eine neue.

+ +
+ {activities.length > 0 && ( +
+

Verarbeitungen zum Bearbeiten:

+
+ {activities.map(a => ( + + ))} +
+
+ )} +
+ ) + } + + const update = (patch: Partial) => setLocal(prev => prev ? { ...prev, ...patch } : prev) + + const handleSave = () => { + if (local) onSave(local) + } + + return ( +
+ {/* Header */} +
+
+ +
+ {local.vvtId} +

{local.name || 'Neue Verarbeitung'}

+
+
+
+ + +
+
+ + {/* Form */} +
+ {/* Bezeichnung + Beschreibung */} + + + update({ name: e.target.value })} + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent" + placeholder="z.B. Mitarbeiterverwaltung" /> + + +