'use client' import React, { useState, useEffect } from 'react' import { useRouter } from 'next/navigation' import { useSDK } from '@/lib/sdk' import { StepHeader, STEP_EXPLANATIONS } from '@/components/sdk/StepHeader' // ============================================================================= // TYPES // ============================================================================= interface LegalDocument { id: string type: 'privacy-policy' | 'terms' | 'cookie-policy' | 'imprint' | 'dpa' name: string version: string language: string status: 'draft' | 'active' | 'archived' lastUpdated: Date publishedAt: Date | null author: string changes: string[] } interface ApiDocument { id: string type: string name: string description: string mandatory: boolean created_at: string updated_at: string } // Map API document type to UI type function mapDocumentType(apiType: string): LegalDocument['type'] { const mapping: Record = { 'privacy_policy': 'privacy-policy', 'privacy-policy': 'privacy-policy', 'terms': 'terms', 'terms_of_service': 'terms', 'cookie_policy': 'cookie-policy', 'cookie-policy': 'cookie-policy', 'imprint': 'imprint', 'dpa': 'dpa', 'avv': 'dpa', } return mapping[apiType] || 'terms' } // Transform API response to UI format function transformApiDocument(doc: ApiDocument): LegalDocument { return { id: doc.id, type: mapDocumentType(doc.type), name: doc.name, version: '1.0', language: 'de', status: 'active', lastUpdated: new Date(doc.updated_at), publishedAt: new Date(doc.created_at), author: 'System', changes: doc.description ? [doc.description] : [], } } // ============================================================================= // COMPONENTS // ============================================================================= function DocumentCard({ document, onDelete, onEdit, onPreview, }: { document: LegalDocument onDelete: (id: string) => void onEdit: (id: string) => void onPreview: (doc: LegalDocument) => void }) { const typeColors = { 'privacy-policy': 'bg-blue-100 text-blue-700', terms: 'bg-green-100 text-green-700', 'cookie-policy': 'bg-yellow-100 text-yellow-700', imprint: 'bg-gray-100 text-gray-700', dpa: 'bg-purple-100 text-purple-700', } const typeLabels = { 'privacy-policy': 'Datenschutz', terms: 'AGB', 'cookie-policy': 'Cookie-Richtlinie', imprint: 'Impressum', dpa: 'AVV', } const statusColors = { draft: 'bg-yellow-100 text-yellow-700', active: 'bg-green-100 text-green-700', archived: 'bg-gray-100 text-gray-500', } const statusLabels = { draft: 'Entwurf', active: 'Aktiv', archived: 'Archiviert', } return (
{typeLabels[document.type]} {statusLabels[document.status]} {document.language} v{document.version}

{document.name}

{document.changes.length > 0 && (
Letzte Aenderungen:
    {document.changes.slice(0, 2).map((change, i) => (
  • {change}
  • ))}
)}
Autor: {document.author} | Aktualisiert: {document.lastUpdated.toLocaleDateString('de-DE')}
{document.status === 'draft' && ( )}
) } // ============================================================================= // MAIN PAGE // ============================================================================= export default function ConsentPage() { const { state } = useSDK() const router = useRouter() const [documents, setDocuments] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [filter, setFilter] = useState('all') const [showCreateModal, setShowCreateModal] = useState(false) const [newDocForm, setNewDocForm] = useState({ type: 'privacy_policy', name: '', description: '', content: '' }) const [creating, setCreating] = useState(false) const [previewDoc, setPreviewDoc] = useState<{ name: string; content: string } | null>(null) useEffect(() => { loadDocuments() }, []) async function loadDocuments() { setLoading(true) setError(null) try { const token = localStorage.getItem('bp_admin_token') const res = await fetch('/api/admin/consent/documents', { headers: token ? { 'Authorization': `Bearer ${token}` } : {} }) if (res.ok) { const data = await res.json() const apiDocs: ApiDocument[] = data.documents || [] setDocuments(apiDocs.map(transformApiDocument)) } else { setError('Fehler beim Laden der Dokumente') } } catch { setError('Verbindungsfehler zum Server') } finally { setLoading(false) } } async function handleRagSuggest() { const docType = newDocForm.type || newDocForm.name || 'Datenschutzerklärung' try { const res = await fetch('/api/sdk/v1/rag/search', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: `${docType} DSGVO Vorlage`, limit: 1 }), }) if (res.ok) { const data = await res.json() const first = data.results?.[0] if (first?.text) setNewDocForm(d => ({ ...d, content: first.text })) } } catch { /* silently ignore */ } } async function handleCreateDocument() { if (!newDocForm.name.trim()) return setCreating(true) try { const token = localStorage.getItem('bp_admin_token') const res = await fetch('/api/admin/consent/documents', { method: 'POST', headers: { 'Content-Type': 'application/json', ...(token ? { 'Authorization': `Bearer ${token}` } : {}), }, body: JSON.stringify(newDocForm), }) if (res.ok) { setShowCreateModal(false) setNewDocForm({ type: 'privacy_policy', name: '', description: '', content: '' }) await loadDocuments() } else { setError('Fehler beim Erstellen des Dokuments') } } catch { setError('Verbindungsfehler beim Erstellen') } finally { setCreating(false) } } async function handleDeleteDocument(id: string) { if (!confirm('Dokument wirklich löschen?')) return try { const token = localStorage.getItem('bp_admin_token') const res = await fetch(`/api/admin/consent/documents/${id}`, { method: 'DELETE', headers: token ? { 'Authorization': `Bearer ${token}` } : {}, }) if (res.ok || res.status === 204) { setDocuments(prev => prev.filter(d => d.id !== id)) } else { setError('Fehler beim Löschen des Dokuments') } } catch { setError('Verbindungsfehler beim Löschen') } } function handleEdit(id: string) { router.push('/sdk/workflow') } async function handlePreview(doc: LegalDocument) { try { const token = localStorage.getItem('bp_admin_token') const res = await fetch(`/api/admin/consent/documents/${doc.id}/versions`, { headers: token ? { 'Authorization': `Bearer ${token}` } : {} }) if (res.ok) { const data = await res.json() const versions = Array.isArray(data) ? data : (data.versions || []) const published = versions.find((v: { status: string; content?: string }) => v.status === 'published') const latest = published || versions[0] setPreviewDoc({ name: doc.name, content: latest?.content || '

Kein Inhalt verfügbar.

' }) } else { setPreviewDoc({ name: doc.name, content: '

Vorschau nicht verfügbar.

' }) } } catch { setPreviewDoc({ name: doc.name, content: '

Fehler beim Laden der Vorschau.

' }) } } const filteredDocuments = filter === 'all' ? documents : documents.filter(d => d.type === filter || d.status === filter) const activeCount = documents.filter(d => d.status === 'active').length const draftCount = documents.filter(d => d.status === 'draft').length const stepInfo = STEP_EXPLANATIONS['consent'] return (
{/* Step Header */} {/* Stats */}
Gesamt
{documents.length}
Aktiv
{activeCount}
Entwuerfe
{draftCount}
Sprachen
{[...new Set(documents.map(d => d.language))].length}
{/* Loading / Error */} {loading && (
Lade Dokumente...
)} {error && (
{error}
)} {/* Quick Actions */}

Schnellaktionen

{/* Filter */}
Filter: {['all', 'privacy-policy', 'terms', 'cookie-policy', 'dpa', 'active', 'draft'].map(f => ( ))}
{/* Documents List */}
{filteredDocuments.map(document => ( ))}
{filteredDocuments.length === 0 && (

Keine Dokumente gefunden

Passen Sie den Filter an oder erstellen Sie ein neues Dokument.

)} {/* Preview Modal */} {previewDoc && (

{previewDoc.name}

)} {/* Create Document Modal */} {showCreateModal && (

Neues Dokument erstellen

setNewDocForm({ ...newDocForm, name: e.target.value })} placeholder="z.B. Datenschutzerklärung Website" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500" />