'use client' import { DATA_SUBJECT_CATEGORY_META, PERSONAL_DATA_CATEGORY_META, ART9_CATEGORIES, STATUS_LABELS, REVIEW_INTERVAL_LABELS, } from '@/lib/sdk/vvt-types' import type { VVTActivity, VVTOrganizationHeader } from '@/lib/sdk/vvt-types' import { FormField } from './FormPrimitives' export function TabExport({ activities, orgHeader, onUpdateOrgHeader, }: { activities: VVTActivity[] orgHeader: VVTOrganizationHeader onUpdateOrgHeader: (org: VVTOrganizationHeader) => void }) { // Compliance check const issues: { activityId: string; vvtId: string; name: string; issues: string[] }[] = [] for (const a of activities) { const actIssues: string[] = [] if (!a.name) actIssues.push('Bezeichnung fehlt') if (a.purposes.length === 0) actIssues.push('Zweck(e) fehlen') if (a.legalBases.length === 0) actIssues.push('Rechtsgrundlage fehlt') if (a.dataSubjectCategories.length === 0) actIssues.push('Betroffenenkategorien fehlen') if (a.personalDataCategories.length === 0) actIssues.push('Datenkategorien fehlen') if (!a.retentionPeriod.description) actIssues.push('Aufbewahrungsfrist fehlt') if (!a.tomDescription && a.structuredToms.accessControl.length === 0) actIssues.push('TOM-Beschreibung fehlt') // Art. 9 without Art. 9 legal basis const hasArt9Data = a.personalDataCategories.some(c => ART9_CATEGORIES.includes(c)) const hasArt9Basis = a.legalBases.some(lb => lb.type.startsWith('ART9_')) if (hasArt9Data && !hasArt9Basis) actIssues.push('Art.-9-Daten ohne Art.-9-Rechtsgrundlage') // Third country without mechanism for (const tc of a.thirdCountryTransfers) { if (!tc.transferMechanism) actIssues.push(`Drittland ${tc.country}: Transfer-Mechanismus fehlt`) } if (actIssues.length > 0) { issues.push({ activityId: a.id, vvtId: a.vvtId, name: a.name || '(Ohne Namen)', issues: actIssues }) } } const compliantCount = activities.length - issues.length const compliancePercent = activities.length > 0 ? Math.round((compliantCount / activities.length) * 100) : 0 const handleExportJSON = () => { const data = { version: '1.0', exportDate: new Date().toISOString(), organization: orgHeader, activities: activities, } const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }) const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = `vvt-export-${new Date().toISOString().split('T')[0]}.json` a.click() URL.revokeObjectURL(url) } const handleExportCSV = () => { const headers = ['VVT-ID', 'Name', 'Beschreibung', 'Zwecke', 'Rechtsgrundlagen', 'Betroffene', 'Datenkategorien', 'Empfaenger', 'Drittlandtransfers', 'Aufbewahrungsfrist', 'TOM', 'Status', 'Verantwortlich'] const rows = activities.map(a => [ a.vvtId, a.name, a.description, a.purposes.join('; '), a.legalBases.map(lb => `${lb.type}${lb.reference ? ' (' + lb.reference + ')' : ''}`).join('; '), a.dataSubjectCategories.map(c => DATA_SUBJECT_CATEGORY_META[c as keyof typeof DATA_SUBJECT_CATEGORY_META]?.de || c).join('; '), a.personalDataCategories.map(c => PERSONAL_DATA_CATEGORY_META[c as keyof typeof PERSONAL_DATA_CATEGORY_META]?.label?.de || c).join('; '), a.recipientCategories.map(r => `${r.name} (${r.type})`).join('; '), a.thirdCountryTransfers.map(t => `${t.country}: ${t.recipient}`).join('; '), a.retentionPeriod.description, a.tomDescription, STATUS_LABELS[a.status], a.responsible, ]) const csvContent = [headers, ...rows].map(row => row.map(cell => `"${String(cell || '').replace(/"/g, '""')}"`).join(',') ).join('\n') const blob = new Blob(['\ufeff' + csvContent], { type: 'text/csv;charset=utf-8' }) const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = `vvt-export-${new Date().toISOString().split('T')[0]}.csv` a.click() URL.revokeObjectURL(url) } return (
Der Export enthaelt alle {activities.length} Verarbeitungstaetigkeiten inkl. Organisations-Metadaten.