From 3570dd10ea30f8789391baa3e60d84e0d2287960 Mon Sep 17 00:00:00 2001 From: Benjamin Admin Date: Tue, 3 Mar 2026 09:29:58 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20Package=204=20Phase=202=20=E2=80=94=20F?= =?UTF-8?q?rontend-Fixes=20und=20Backend-Endpoints=20vervollst=C3=A4ndigt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - document-generator: STEP_EXPLANATIONS Key 'consent' → 'document-generator' - Proxy: Content-Type nicht mehr hardcoded; forwarded vom Client (Fix für DOCX-Upload + multipart/arrayBuffer) - Backend: GET /documents/{id}, DELETE /documents/{id}, GET /versions/{id} ergänzt - Backend-Tests: 4 neue Tests für die neuen Endpoints - consent/page.tsx: Create-Modal + handleCreateDocument() + DELETE-Handler verdrahtet - einwilligungen/page.tsx: odentifier→identifier, ip_address, user_agent, history aus API gemappt; source nullable - cookie-banner/page.tsx: handleExportCode() + Toast für 'Code exportieren' Button - workflow/page.tsx: 'Neues Dokument' Button + createDocument() + Modal Co-Authored-By: Claude Sonnet 4.6 --- .../app/(sdk)/sdk/consent/page.tsx | 125 +++++++++++++++++- .../app/(sdk)/sdk/cookie-banner/page.tsx | 32 ++++- .../app/(sdk)/sdk/document-generator/page.tsx | 4 +- .../app/(sdk)/sdk/einwilligungen/page.tsx | 37 +++--- .../app/(sdk)/sdk/workflow/page.tsx | 97 ++++++++++++++ .../api/admin/consent/[[...path]]/route.ts | 20 ++- .../compliance/api/legal_document_routes.py | 28 ++++ .../tests/test_legal_document_routes.py | 58 ++++++++ 8 files changed, 372 insertions(+), 29 deletions(-) diff --git a/admin-compliance/app/(sdk)/sdk/consent/page.tsx b/admin-compliance/app/(sdk)/sdk/consent/page.tsx index 2b38182..59947bc 100644 --- a/admin-compliance/app/(sdk)/sdk/consent/page.tsx +++ b/admin-compliance/app/(sdk)/sdk/consent/page.tsx @@ -67,7 +67,7 @@ function transformApiDocument(doc: ApiDocument): LegalDocument { // COMPONENTS // ============================================================================= -function DocumentCard({ document }: { document: LegalDocument }) { +function DocumentCard({ document, onDelete }: { document: LegalDocument; onDelete: (id: string) => void }) { const typeColors = { 'privacy-policy': 'bg-blue-100 text-blue-700', terms: 'bg-green-100 text-green-700', @@ -149,6 +149,12 @@ function DocumentCard({ document }: { document: LegalDocument }) { Veroeffentlichen )} + @@ -165,6 +171,9 @@ export default function ConsentPage() { 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: '' }) + const [creating, setCreating] = useState(false) useEffect(() => { loadDocuments() @@ -192,6 +201,51 @@ export default function ConsentPage() { } } + 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: '' }) + 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') + } + } + const filteredDocuments = filter === 'all' ? documents : documents.filter(d => d.type === filter || d.status === filter) @@ -211,7 +265,10 @@ export default function ConsentPage() { explanation={stepInfo.explanation} tips={stepInfo.tips} > -