'use client' import React, { useState, useEffect, useCallback, useRef, useMemo } from 'react' import { useSDK } from '@/lib/sdk' import { useEinwilligungen, EinwilligungenProvider } from '@/lib/sdk/einwilligungen/context' import { StepHeader, STEP_EXPLANATIONS } from '@/components/sdk/StepHeader' import { LegalTemplateResult, TemplateType, LicenseType, TEMPLATE_TYPE_LABELS, LICENSE_TYPE_LABELS, } from '@/lib/sdk/types' import { DataPointsPreview } from './components/DataPointsPreview' import { DocumentValidation } from './components/DocumentValidation' import { generateAllPlaceholders } from '@/lib/sdk/document-generator/datapoint-helpers' import { loadAllTemplates, searchTemplates } from './searchTemplates' // ============================================================================= // CATEGORY CONFIG // ============================================================================= const CATEGORIES: { key: string; label: string; types: string[] | null }[] = [ { key: 'all', label: 'Alle', types: null }, { key: 'privacy_policy', label: 'Datenschutz', types: ['privacy_policy'] }, { key: 'terms', label: 'AGB', types: ['terms_of_service', 'agb', 'clause'] }, { key: 'impressum', label: 'Impressum', types: ['impressum'] }, { key: 'dpa', label: 'AVV/DPA', types: ['dpa'] }, { key: 'nda', label: 'NDA', types: ['nda'] }, { key: 'sla', label: 'SLA', types: ['sla'] }, { key: 'acceptable_use', label: 'AUP', types: ['acceptable_use'] }, { key: 'widerruf', label: 'Widerruf', types: ['widerruf'] }, { key: 'cookie', label: 'Cookie', types: ['cookie_policy', 'cookie_banner'] }, { key: 'cloud', label: 'Cloud', types: ['cloud_service_agreement'] }, { key: 'misc', label: 'Weitere', types: ['community_guidelines', 'copyright_policy', 'data_usage_clause'] }, ] // ============================================================================= // SMALL COMPONENTS // ============================================================================= function LicenseBadge({ licenseId, small = false }: { licenseId: LicenseType | null; small?: boolean }) { if (!licenseId) return null const colors: Partial> = { public_domain: 'bg-green-100 text-green-700 border-green-200', cc0: 'bg-green-100 text-green-700 border-green-200', unlicense: 'bg-green-100 text-green-700 border-green-200', mit: 'bg-blue-100 text-blue-700 border-blue-200', cc_by_4: 'bg-purple-100 text-purple-700 border-purple-200', reuse_notice: 'bg-orange-100 text-orange-700 border-orange-200', } return ( {LICENSE_TYPE_LABELS[licenseId] || licenseId} ) } // ============================================================================= // LIBRARY CARD // ============================================================================= function LibraryCard({ template, expanded, onTogglePreview, onUse, }: { template: LegalTemplateResult expanded: boolean onTogglePreview: () => void onUse: () => void }) { const typeLabel = template.templateType ? (TEMPLATE_TYPE_LABELS[template.templateType as TemplateType] || template.templateType) : null const placeholderCount = template.placeholders?.length ?? 0 return (
{/* Card header */}

{template.documentTitle || 'Vorlage'}

{template.language}
{typeLabel && ( {typeLabel} )} {placeholderCount > 0 && ( {placeholderCount} Platzh. )}
{/* Inline preview */} {expanded && (
            {template.text.slice(0, 1500)}{template.text.length > 1500 ? '\n…' : ''}
          
)}
) } // ============================================================================= // GENERATOR SECTION // ============================================================================= function GeneratorSection({ template, placeholderValues, onPlaceholderChange, onClose, }: { template: LegalTemplateResult placeholderValues: Record onPlaceholderChange: (key: string, value: string) => void onClose: () => void }) { const [activeTab, setActiveTab] = useState<'placeholders' | 'preview'>('placeholders') const renderedContent = useMemo(() => { let content = template.text for (const [key, value] of Object.entries(placeholderValues)) { if (value) { content = content.replace(new RegExp(key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), value) } } return content }, [template.text, placeholderValues]) const handleCopy = () => navigator.clipboard.writeText(renderedContent) const handleExportMarkdown = () => { const blob = new Blob([renderedContent], { type: 'text/markdown' }) const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = `${(template.documentTitle || 'dokument').replace(/\s+/g, '-').toLowerCase()}.md` a.click() URL.revokeObjectURL(url) } const handlePrint = () => window.print() const placeholders = template.placeholders || [] return (
{/* Generator header */}
Generator
{template.documentTitle}
{/* Tab bar */}
{(['placeholders', 'preview'] as const).map((tab) => ( ))}
{/* Tab content */}
{activeTab === 'placeholders' && (
{placeholders.length === 0 ? (
Keine Platzhalter — Vorlage kann direkt verwendet werden.
) : ( <>
{placeholders.map((placeholder) => (
onPlaceholderChange(placeholder, e.target.value)} placeholder={`Wert für ${placeholder}`} className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-purple-400" />
))}
)}
)} {activeTab === 'preview' && (
{placeholders.length > 0 && Object.values(placeholderValues).filter(Boolean).length < placeholders.length && ( ⚠ {placeholders.length - Object.values(placeholderValues).filter(Boolean).length} Platzhalter noch nicht ausgefüllt )}
                {renderedContent}
              
{template.attributionRequired && template.attributionText && (
Attribution erforderlich: {template.attributionText}
)}
)}
) } // ============================================================================= // MAIN PAGE // ============================================================================= function DocumentGeneratorPageInner() { const { state } = useSDK() const { selectedDataPointsData } = useEinwilligungen() // Library state const [allTemplates, setAllTemplates] = useState([]) const [isLoadingLibrary, setIsLoadingLibrary] = useState(true) const [activeCategory, setActiveCategory] = useState('all') const [activeLanguage, setActiveLanguage] = useState<'all' | 'de' | 'en'>('all') const [librarySearch, setLibrarySearch] = useState('') const [expandedPreviewId, setExpandedPreviewId] = useState(null) // Generator state const [activeTemplate, setActiveTemplate] = useState(null) const [placeholderValues, setPlaceholderValues] = useState>({}) const generatorRef = useRef(null) // Status const [totalCount, setTotalCount] = useState(0) // Load all templates on mount useEffect(() => { setIsLoadingLibrary(true) loadAllTemplates(200).then((templates) => { setAllTemplates(templates) setTotalCount(templates.length) setIsLoadingLibrary(false) }) }, []) // Pre-fill placeholders from company profile useEffect(() => { if (state?.companyProfile) { const profile = state.companyProfile setPlaceholderValues((prev) => ({ ...prev, '{{COMPANY_NAME}}': profile.companyName || '', '{{FIRMENNAME}}': profile.companyName || '', '{{CONTACT_EMAIL}}': profile.dpoEmail || '', '{{DSB_EMAIL}}': profile.dpoEmail || '', '{{DPO_NAME}}': profile.dpoName || '', '{{DSB_NAME}}': profile.dpoName || '', })) } }, [state?.companyProfile]) // Pre-fill from Einwilligungen data points useEffect(() => { if (selectedDataPointsData && selectedDataPointsData.length > 0) { const generated = generateAllPlaceholders(selectedDataPointsData, 'de') setPlaceholderValues((prev) => ({ ...prev, ...generated })) } }, [selectedDataPointsData]) // Filtered templates (computed) const filteredTemplates = useMemo(() => { const category = CATEGORIES.find((c) => c.key === activeCategory) return allTemplates.filter((t) => { if (category && category.types !== null) { if (!category.types.includes(t.templateType || '')) return false } if (activeLanguage !== 'all' && t.language !== activeLanguage) return false if (librarySearch.trim()) { const q = librarySearch.toLowerCase() const title = (t.documentTitle || '').toLowerCase() const type = (t.templateType || '').toLowerCase() if (!title.includes(q) && !type.includes(q)) return false } return true }) }, [allTemplates, activeCategory, activeLanguage, librarySearch]) const handleUseTemplate = useCallback((t: LegalTemplateResult) => { setActiveTemplate(t) setExpandedPreviewId(null) // Scroll to generator setTimeout(() => { generatorRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' }) }, 100) }, []) const handleInsertPlaceholder = useCallback((placeholder: string) => { if (!placeholderValues[placeholder]) { const generated = generateAllPlaceholders(selectedDataPointsData || [], 'de') if (generated[placeholder as keyof typeof generated]) { setPlaceholderValues((prev) => ({ ...prev, [placeholder]: generated[placeholder as keyof typeof generated], })) } } }, [placeholderValues, selectedDataPointsData]) const stepInfo = STEP_EXPLANATIONS['document-generator'] || { title: 'Dokumentengenerator', description: 'Generieren Sie rechtliche Dokumente aus lizenzkonformen Vorlagen', explanation: 'Der Dokumentengenerator nutzt frei lizenzierte Textbausteine um Datenschutzerklaerungen, AGB und andere rechtliche Dokumente zu erstellen.', tips: ['Wählen Sie eine Vorlage aus der Bibliothek aus', 'Füllen Sie die Platzhalter mit Ihren Unternehmensdaten'], } return (
{/* Step Header */} {/* Status bar */}
Vorlagen gesamt
{totalCount}
Angezeigt
{filteredTemplates.length}
Aktive Vorlage
{activeTemplate ? activeTemplate.documentTitle : '—'}
{/* ================================================================= */} {/* SECTION 1: TEMPLATE-BIBLIOTHEK */} {/* ================================================================= */}
{/* Library header */}

Template-Bibliothek

{/* Language toggle */}
{(['all', 'de', 'en'] as const).map((lang) => ( ))}
{/* Category pills */}
{CATEGORIES.map((cat) => { const count = cat.types === null ? allTemplates.filter(t => activeLanguage === 'all' || t.language === activeLanguage).length : allTemplates.filter(t => cat.types!.includes(t.templateType || '') && (activeLanguage === 'all' || t.language === activeLanguage) ).length return ( ) })}
{/* Search */}
setLibrarySearch(e.target.value)} placeholder="Vorlage suchen... (optional)" className="w-full pl-9 pr-4 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-purple-400" /> {librarySearch && ( )}
{/* Template grid */}
{isLoadingLibrary ? (
) : filteredTemplates.length === 0 ? (
📄

Keine Vorlagen für diese Auswahl

) : (
{filteredTemplates.map((template) => ( setExpandedPreviewId((prev) => (prev === template.id ? null : template.id)) } onUse={() => handleUseTemplate(template)} /> ))}
)}
{/* ================================================================= */} {/* SECTION 2: GENERATOR (visible only when activeTemplate is set) */} {/* ================================================================= */} {activeTemplate && (
setPlaceholderValues((prev) => ({ ...prev, [key]: value })) } onClose={() => setActiveTemplate(null)} /> {/* Einwilligungen DataPoints sidebar (shown below generator on small screens, side on large) */} {selectedDataPointsData && selectedDataPointsData.length > 0 && (
)}
)}
) } export default function DocumentGeneratorPage() { return ( ) }