'use client' import { useMemo } from 'react' import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '@/components/ui/card' import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from '@/components/ui/accordion' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { ScrollArea } from '@/components/ui/scroll-area' import { Separator } from '@/components/ui/separator' import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from '@/components/ui/tooltip' import { Database, FileText, List, Table, AlertTriangle, Shield, Clock, Users, Globe, } from 'lucide-react' import { DataPoint, DataPointCategory, CATEGORY_METADATA, RISK_LEVEL_STYLING, RiskLevel, } from '@/lib/sdk/einwilligungen/types' interface DataPointsPreviewProps { dataPoints: DataPoint[] onInsertPlaceholder: (placeholder: string) => void language?: 'de' | 'en' } /** * Platzhalter-Definitionen mit Beschreibungen */ const PLACEHOLDERS = [ { placeholder: '[DATENPUNKTE_TABLE]', label: { de: 'Tabelle', en: 'Table' }, description: { de: 'Fügt eine Markdown-Tabelle mit allen Datenpunkten ein', en: 'Inserts a markdown table with all data points' }, icon: Table, }, { placeholder: '[DATENPUNKTE_LIST]', label: { de: 'Liste', en: 'List' }, description: { de: 'Kommaseparierte Liste der Datenpunkt-Namen', en: 'Comma-separated list of data point names' }, icon: List, }, { placeholder: '[VERARBEITUNGSZWECKE]', label: { de: 'Zwecke', en: 'Purposes' }, description: { de: 'Alle Verarbeitungszwecke (dedupliziert)', en: 'All processing purposes (deduplicated)' }, icon: FileText, }, { placeholder: '[RECHTSGRUNDLAGEN]', label: { de: 'Rechtsgrundlagen', en: 'Legal Bases' }, description: { de: 'Verwendete DSGVO-Artikel', en: 'Used GDPR articles' }, icon: Shield, }, { placeholder: '[SPEICHERFRISTEN]', label: { de: 'Speicherfristen', en: 'Retention' }, description: { de: 'Fristen gruppiert nach Kategorie', en: 'Periods grouped by category' }, icon: Clock, }, { placeholder: '[EMPFAENGER]', label: { de: 'Empfänger', en: 'Recipients' }, description: { de: 'Liste aller Drittparteien', en: 'List of all third parties' }, icon: Users, }, { placeholder: '[BESONDERE_KATEGORIEN]', label: { de: 'Art. 9 Abschnitt', en: 'Art. 9 Section' }, description: { de: 'DSGVO-konformer Abschnitt für sensible Daten', en: 'GDPR-compliant section for sensitive data' }, icon: AlertTriangle, }, { placeholder: '[DRITTLAND_TRANSFERS]', label: { de: 'Drittländer', en: 'Third Countries' }, description: { de: 'Abschnitt zu Datenübermittlung außerhalb EU', en: 'Section about data transfers outside EU' }, icon: Globe, }, ] /** * Risiko-Badge Varianten mapping */ function getRiskBadgeVariant(riskLevel: RiskLevel): 'default' | 'secondary' | 'destructive' | 'outline' { switch (riskLevel) { case 'HIGH': return 'destructive' case 'MEDIUM': return 'secondary' case 'LOW': default: return 'outline' } } /** * DataPointsPreview Komponente * * Zeigt eine Vorschau der ausgewählten Einwilligungen-Datenpunkte im Dokumentengenerator. * Ermöglicht das schnelle Einfügen von Platzhaltern. */ export function DataPointsPreview({ dataPoints, onInsertPlaceholder, language = 'de', }: DataPointsPreviewProps) { // Gruppiere Datenpunkte nach Kategorie const byCategory = useMemo(() => { return dataPoints.reduce((acc, dp) => { if (!acc[dp.category]) { acc[dp.category] = [] } acc[dp.category].push(dp) return acc }, {} as Record) }, [dataPoints]) // Statistiken berechnen const stats = useMemo(() => { const riskCounts: Record = { LOW: 0, MEDIUM: 0, HIGH: 0 } let specialCategoryCount = 0 let explicitConsentCount = 0 const recipients = new Set() dataPoints.forEach(dp => { riskCounts[dp.riskLevel]++ if (dp.isSpecialCategory) specialCategoryCount++ if (dp.requiresExplicitConsent) explicitConsentCount++ dp.thirdPartyRecipients?.forEach(r => recipients.add(r)) }) return { riskCounts, specialCategoryCount, explicitConsentCount, recipientCount: recipients.size, categoryCount: Object.keys(byCategory).length, } }, [dataPoints, byCategory]) // Sortierte Kategorien (nach Code) const sortedCategories = useMemo(() => { return Object.entries(byCategory).sort((a, b) => { const codeA = CATEGORY_METADATA[a[0] as DataPointCategory]?.code || 'Z' const codeB = CATEGORY_METADATA[b[0] as DataPointCategory]?.code || 'Z' return codeA.localeCompare(codeB) }) }, [byCategory]) if (dataPoints.length === 0) { return ( {language === 'de' ? 'Einwilligungen' : 'Consents'}

{language === 'de' ? 'Keine Datenpunkte ausgewählt. Wählen Sie Datenpunkte im Einwilligungs-Schritt aus, um sie hier zu sehen.' : 'No data points selected. Select data points in the consent step to see them here.'}

) } return ( {language === 'de' ? 'Einwilligungen' : 'Consents'} {dataPoints.length} {language === 'de' ? 'Datenpunkte aus' : 'data points from'}{' '} {stats.categoryCount} {language === 'de' ? 'Kategorien' : 'categories'} {/* Statistik-Badges */}
{stats.riskCounts.HIGH > 0 && ( {stats.riskCounts.HIGH} {language === 'de' ? 'Hoch' : 'High'} )} {stats.riskCounts.MEDIUM > 0 && ( {stats.riskCounts.MEDIUM} {language === 'de' ? 'Mittel' : 'Medium'} )} {stats.riskCounts.LOW > 0 && ( {stats.riskCounts.LOW} {language === 'de' ? 'Niedrig' : 'Low'} )} {stats.specialCategoryCount > 0 && ( {stats.specialCategoryCount} Art. 9 )}
{/* Datenpunkte nach Kategorie */} {sortedCategories.map(([category, points]) => { const metadata = CATEGORY_METADATA[category as DataPointCategory] if (!metadata) return null return (
{metadata.code} {language === 'de' ? metadata.name.de : metadata.name.en} {points.length}
    {points.map(dp => (
  • {language === 'de' ? dp.name.de : dp.name.en}
    {dp.isSpecialCategory && ( {language === 'de' ? 'Besondere Kategorie (Art. 9 DSGVO)' : 'Special Category (Art. 9 GDPR)'} )} {RISK_LEVEL_STYLING[dp.riskLevel].label[language]}
  • ))}
) })}
{/* Schnell-Einfügen Buttons */}

{language === 'de' ? 'Platzhalter einfügen:' : 'Insert placeholder:'}

{PLACEHOLDERS.slice(0, 4).map(({ placeholder, label, description, icon: Icon }) => (

{language === 'de' ? description.de : description.en}

{placeholder}

))}
{PLACEHOLDERS.slice(4).map(({ placeholder, label, description, icon: Icon }) => (

{language === 'de' ? description.de : description.en}

{placeholder}

))}
) } export default DataPointsPreview