'use client' import { useState, useEffect, useCallback, useMemo } from 'react' import type { Obligation, ObligationComplianceCheckResult } from '@/lib/sdk/obligations-compliance' import { buildObligationDocumentHtml, createDefaultObligationDocumentOrgHeader, type ObligationDocumentOrgHeader, type ObligationDocumentRevision, } from '@/lib/sdk/obligations-document' // ============================================================================= // TYPES // ============================================================================= interface ObligationDocumentTabProps { obligations: Obligation[] complianceResult: ObligationComplianceCheckResult | null } // ============================================================================= // COMPONENT // ============================================================================= function ObligationDocumentTab({ obligations, complianceResult }: ObligationDocumentTabProps) { // --------------------------------------------------------------------------- // State // --------------------------------------------------------------------------- const [orgHeader, setOrgHeader] = useState(() => { if (typeof window !== 'undefined') { const saved = localStorage.getItem('bp_obligation_document_orgheader') if (saved) { try { return JSON.parse(saved) } catch { /* ignore */ } } } return createDefaultObligationDocumentOrgHeader() }) const [revisions, setRevisions] = useState(() => { if (typeof window !== 'undefined') { const saved = localStorage.getItem('bp_obligation_document_revisions') if (saved) { try { return JSON.parse(saved) } catch { /* ignore */ } } } return [] }) // --------------------------------------------------------------------------- // localStorage persistence // --------------------------------------------------------------------------- useEffect(() => { localStorage.setItem('bp_obligation_document_orgheader', JSON.stringify(orgHeader)) }, [orgHeader]) useEffect(() => { localStorage.setItem('bp_obligation_document_revisions', JSON.stringify(revisions)) }, [revisions]) // --------------------------------------------------------------------------- // Computed values // --------------------------------------------------------------------------- const obligationCount = obligations.length const completedCount = useMemo(() => { return obligations.filter(o => o.status === 'completed').length }, [obligations]) const distinctSources = useMemo(() => { const sources = new Set(obligations.map(o => o.source || 'Sonstig')) return sources.size }, [obligations]) // --------------------------------------------------------------------------- // Handlers // --------------------------------------------------------------------------- const handlePrintDocument = useCallback(() => { const html = buildObligationDocumentHtml( obligations, orgHeader, complianceResult, revisions, ) const printWindow = window.open('', '_blank') if (printWindow) { printWindow.document.write(html) printWindow.document.close() setTimeout(() => printWindow.print(), 300) } }, [obligations, orgHeader, complianceResult, revisions]) const handleDownloadDocumentHtml = useCallback(() => { const html = buildObligationDocumentHtml( obligations, orgHeader, complianceResult, revisions, ) const blob = new Blob([html], { type: 'text/html;charset=utf-8' }) const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = `Pflichtenregister-${orgHeader.organizationName || 'Organisation'}-${new Date().toISOString().split('T')[0]}.html` document.body.appendChild(a) a.click() document.body.removeChild(a) URL.revokeObjectURL(url) }, [obligations, orgHeader, complianceResult, revisions]) const handleAddRevision = useCallback(() => { setRevisions(prev => [...prev, { version: String(prev.length + 1) + '.0', date: new Date().toISOString().split('T')[0], author: '', changes: '', }]) }, []) const handleUpdateRevision = useCallback((index: number, field: keyof ObligationDocumentRevision, value: string) => { setRevisions(prev => prev.map((r, i) => i === index ? { ...r, [field]: value } : r)) }, []) const handleRemoveRevision = useCallback((index: number) => { setRevisions(prev => prev.filter((_, i) => i !== index)) }, []) const updateOrgHeader = useCallback((field: keyof ObligationDocumentOrgHeader, value: string) => { setOrgHeader(prev => ({ ...prev, [field]: value })) }, []) // --------------------------------------------------------------------------- // Render // --------------------------------------------------------------------------- return (
{/* 1. Action Bar */}

Pflichtenregister

Auditfaehiges Dokument mit {obligationCount} Pflichten generieren

{/* 2. Org Header Form */}

Organisationsdaten

updateOrgHeader('organizationName', e.target.value)} className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-purple-500 focus:ring-1 focus:ring-purple-500 outline-none" />
updateOrgHeader('industry', e.target.value)} className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-purple-500 focus:ring-1 focus:ring-purple-500 outline-none" />
updateOrgHeader('dpoName', e.target.value)} className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-purple-500 focus:ring-1 focus:ring-purple-500 outline-none" />
updateOrgHeader('dpoContact', e.target.value)} className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-purple-500 focus:ring-1 focus:ring-purple-500 outline-none" />
updateOrgHeader('responsiblePerson', e.target.value)} className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-purple-500 focus:ring-1 focus:ring-purple-500 outline-none" />
updateOrgHeader('legalDepartment', e.target.value)} className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-purple-500 focus:ring-1 focus:ring-purple-500 outline-none" />
updateOrgHeader('documentVersion', e.target.value)} className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-purple-500 focus:ring-1 focus:ring-purple-500 outline-none" />
updateOrgHeader('reviewInterval', e.target.value)} className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-purple-500 focus:ring-1 focus:ring-purple-500 outline-none" />
updateOrgHeader('lastReviewDate', e.target.value)} className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-purple-500 focus:ring-1 focus:ring-purple-500 outline-none" />
updateOrgHeader('nextReviewDate', e.target.value)} className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-purple-500 focus:ring-1 focus:ring-purple-500 outline-none" />
{/* 3. Revisions Manager */}

Aenderungshistorie

{revisions.length > 0 ? ( {revisions.map((revision, index) => ( ))}
Version Datum Autor Aenderungen
handleUpdateRevision(index, 'version', e.target.value)} className="w-full rounded-lg border border-gray-300 px-3 py-1.5 text-sm focus:border-purple-500 focus:ring-1 focus:ring-purple-500 outline-none" /> handleUpdateRevision(index, 'date', e.target.value)} className="w-full rounded-lg border border-gray-300 px-3 py-1.5 text-sm focus:border-purple-500 focus:ring-1 focus:ring-purple-500 outline-none" /> handleUpdateRevision(index, 'author', e.target.value)} placeholder="Name" className="w-full rounded-lg border border-gray-300 px-3 py-1.5 text-sm focus:border-purple-500 focus:ring-1 focus:ring-purple-500 outline-none" /> handleUpdateRevision(index, 'changes', e.target.value)} placeholder="Beschreibung der Aenderungen" className="w-full rounded-lg border border-gray-300 px-3 py-1.5 text-sm focus:border-purple-500 focus:ring-1 focus:ring-purple-500 outline-none" />
) : (

Noch keine Revisionen. Die erste Version wird automatisch im Dokument eingetragen.

)}
{/* 4. Document Preview */}

Dokument-Vorschau

{obligationCount === 0 ? (

Erfassen Sie Pflichten, um das Pflichtenregister zu generieren.

) : (
{/* Cover preview */}

Pflichtenregister

Regulatorische Pflichten — {orgHeader.organizationName || 'Organisation'}

Version {orgHeader.documentVersion} | Stand: {new Date().toLocaleDateString('de-DE')}

{/* Stats */}

{obligationCount}

Pflichten

{completedCount}

Abgeschlossen

{distinctSources}

Regulierungen

12

Sektionen

{complianceResult ? complianceResult.score : '—'}

Compliance-Score

{/* 12 Sections list */}

12 Dokument-Sektionen:

  1. Ziel und Zweck
  2. Geltungsbereich
  3. Methodik
  4. Regulatorische Grundlagen
  5. Pflichtenuebersicht
  6. Detaillierte Pflichten
  7. Verantwortlichkeiten
  8. Fristen und Termine
  9. Nachweisverzeichnis
  10. Compliance-Status
  11. Aenderungshistorie
)}
) } export { ObligationDocumentTab }