diff --git a/admin-compliance/app/sdk/loeschfristen/page.tsx b/admin-compliance/app/sdk/loeschfristen/page.tsx index 3e82ce9..a9ab327 100644 --- a/admin-compliance/app/sdk/loeschfristen/page.tsx +++ b/admin-compliance/app/sdk/loeschfristen/page.tsx @@ -136,6 +136,9 @@ export default function LoeschfristenPage() { // ---- VVT data ---- const [vvtActivities, setVvtActivities] = useState([]) + // ---- Vendor data ---- + const [vendorList, setVendorList] = useState>([]) + // ---- Loeschkonzept document state ---- const [orgHeader, setOrgHeader] = useState(createDefaultLoeschkonzeptOrgHeader()) const [revisions, setRevisions] = useState([]) @@ -194,6 +197,7 @@ export default function LoeschfristenPage() { responsiblePerson: raw.responsible_person || '', releaseProcess: raw.release_process || '', linkedVVTActivityIds: raw.linked_vvt_activity_ids || [], + linkedVendorIds: raw.linked_vendor_ids || [], status: raw.status || 'DRAFT', lastReviewDate: raw.last_review_date || base.lastReviewDate, nextReviewDate: raw.next_review_date || base.nextReviewDate, @@ -228,6 +232,7 @@ export default function LoeschfristenPage() { responsible_person: p.responsiblePerson, release_process: p.releaseProcess, linked_vvt_activity_ids: p.linkedVVTActivityIds, + linked_vendor_ids: p.linkedVendorIds, status: p.status, last_review_date: p.lastReviewDate || null, next_review_date: p.nextReviewDate || null, @@ -257,6 +262,17 @@ export default function LoeschfristenPage() { }) }, [tab, editingId]) + // Load vendor list from API + useEffect(() => { + fetch('/api/sdk/v1/vendor-compliance/vendors?limit=500') + .then(r => r.ok ? r.json() : null) + .then(data => { + const items = data?.data?.items || [] + setVendorList(items.map((v: any) => ({ id: v.id, name: v.name }))) + }) + .catch(() => {}) + }, []) + // Load Loeschkonzept org header from VVT organization data + revisions from localStorage useEffect(() => { // Load revisions from localStorage @@ -1408,13 +1424,13 @@ export default function LoeschfristenPage() { Verarbeitungstaetigkeit aus Ihrem VVT.

- {policy.linkedVvtIds && policy.linkedVvtIds.length > 0 && ( + {policy.linkedVVTActivityIds && policy.linkedVVTActivityIds.length > 0 && (
- {policy.linkedVvtIds.map((vvtId: string) => { + {policy.linkedVVTActivityIds.map((vvtId: string) => { const activity = vvtActivities.find( (a: any) => a.id === vvtId, ) @@ -1429,8 +1445,8 @@ export default function LoeschfristenPage() { onClick={() => updatePolicy(pid, (p) => ({ ...p, - linkedVvtIds: ( - p.linkedVvtIds || [] + linkedVVTActivityIds: ( + p.linkedVVTActivityIds || [] ).filter((id: string) => id !== vvtId), })) } @@ -1449,11 +1465,11 @@ export default function LoeschfristenPage() { const val = e.target.value if ( val && - !(policy.linkedVvtIds || []).includes(val) + !(policy.linkedVVTActivityIds || []).includes(val) ) { updatePolicy(pid, (p) => ({ ...p, - linkedVvtIds: [...(p.linkedVvtIds || []), val], + linkedVVTActivityIds: [...(p.linkedVVTActivityIds || []), val], })) } e.target.value = '' @@ -1466,7 +1482,7 @@ export default function LoeschfristenPage() { {vvtActivities .filter( (a: any) => - !(policy.linkedVvtIds || []).includes(a.id), + !(policy.linkedVVTActivityIds || []).includes(a.id), ) .map((a: any) => (
+ {/* Sektion 5b: Auftragsverarbeiter-Verknuepfung */} +
+

+ 5b. Verknuepfte Auftragsverarbeiter +

+ + {vendorList.length > 0 ? ( +
+

+ Verknuepfen Sie diese Loeschfrist mit relevanten Auftragsverarbeitern. +

+
+ {policy.linkedVendorIds && policy.linkedVendorIds.length > 0 && ( +
+ +
+ {policy.linkedVendorIds.map((vendorId: string) => { + const vendor = vendorList.find( + (v) => v.id === vendorId, + ) + return ( + + {vendor?.name || vendorId} + + + ) + })} +
+
+ )} + +
+
+ ) : ( +

+ Keine Auftragsverarbeiter gefunden. Erstellen Sie zuerst + Auftragsverarbeiter im Vendor-Compliance-Modul, um hier Verknuepfungen + herstellen zu koennen. +

+ )} +
+ {/* Sektion 6: Review-Einstellungen */}

@@ -2608,19 +2713,20 @@ export default function LoeschfristenPage() { {/* Section list */}
-
11 Sektionen
+
12 Sektionen
1. Ziel und Zweck
-
7. Legal Hold Verfahren
+
7. Auftragsverarbeiter
2. Geltungsbereich
-
8. Verantwortlichkeiten
+
8. Legal Hold Verfahren
3. Grundprinzipien
-
9. Pruef-/Revisionszyklus
+
9. Verantwortlichkeiten
4. Loeschregeln-Uebersicht
-
10. Compliance-Status
+
10. Pruef-/Revisionszyklus
5. Detaillierte Loeschregeln
-
11. Aenderungshistorie
+
11. Compliance-Status
6. VVT-Verknuepfung
+
12. Aenderungshistorie
@@ -2628,6 +2734,7 @@ export default function LoeschfristenPage() {
{activePolicies.length} Loeschregeln {policies.filter(p => p.linkedVVTActivityIds.length > 0).length} VVT-Verknuepfungen + {policies.filter(p => p.linkedVendorIds.length > 0).length} Vendor-Verknuepfungen {revisions.length} Revisionen {complianceResult && ( Compliance-Score: = 75 ? 'text-green-600' : complianceResult.score >= 50 ? 'text-yellow-600' : 'text-red-600'}>{complianceResult.score}/100 diff --git a/admin-compliance/app/sdk/obligations/page.tsx b/admin-compliance/app/sdk/obligations/page.tsx index 251a383..0f6d2d6 100644 --- a/admin-compliance/app/sdk/obligations/page.tsx +++ b/admin-compliance/app/sdk/obligations/page.tsx @@ -1,35 +1,20 @@ 'use client' -import React, { useState, useEffect, useCallback } from 'react' +import React, { useState, useEffect, useCallback, useMemo } from 'react' import { StepHeader, STEP_EXPLANATIONS } from '@/components/sdk/StepHeader' import TOMControlPanel from '@/components/sdk/obligations/TOMControlPanel' import GapAnalysisView from '@/components/sdk/obligations/GapAnalysisView' +import { ObligationDocumentTab } from '@/components/sdk/obligations/ObligationDocumentTab' import { useSDK } from '@/lib/sdk' import { buildAssessmentPayload } from '@/lib/sdk/scope-to-facts' import type { ApplicableRegulation } from '@/lib/sdk/compliance-scope-types' +import type { Obligation, ObligationComplianceCheckResult } from '@/lib/sdk/obligations-compliance' +import { runObligationComplianceCheck } from '@/lib/sdk/obligations-compliance' // ============================================================================= -// Types +// Types (local only — Obligation imported from obligations-compliance.ts) // ============================================================================= -interface Obligation { - id: string - title: string - description: string - source: string - source_article: string - deadline: string | null - status: 'pending' | 'in-progress' | 'completed' | 'overdue' - priority: 'critical' | 'high' | 'medium' | 'low' - responsible: string - linked_systems: string[] - assessment_id?: string - rule_code?: string - notes?: string - created_at?: string - updated_at?: string -} - interface ObligationStats { pending: number in_progress: number @@ -50,6 +35,7 @@ interface ObligationFormData { priority: string responsible: string linked_systems: string + linked_vendor_ids: string notes: string } @@ -63,11 +49,26 @@ const EMPTY_FORM: ObligationFormData = { priority: 'medium', responsible: '', linked_systems: '', + linked_vendor_ids: '', notes: '', } const API = '/api/sdk/v1/compliance/obligations' +// ============================================================================= +// Tab definitions +// ============================================================================= + +type Tab = 'uebersicht' | 'editor' | 'profiling' | 'gap-analyse' | 'pflichtenregister' + +const TABS: { key: Tab; label: string }[] = [ + { key: 'uebersicht', label: 'Uebersicht' }, + { key: 'editor', label: 'Detail-Editor' }, + { key: 'profiling', label: 'Profiling' }, + { key: 'gap-analyse', label: 'Gap-Analyse' }, + { key: 'pflichtenregister', label: 'Pflichtenregister' }, +] + // ============================================================================= // Status helpers // ============================================================================= @@ -262,6 +263,18 @@ function ObligationModal({ />
+
+ + update('linked_vendor_ids', e.target.value)} + className="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-purple-500" + placeholder="Kommagetrennt: Vendor-ID-1, Vendor-ID-2" + /> +

IDs der Auftragsverarbeiter aus dem Vendor Register

+
+