From 7dccdf4695fb4407b6c3765ec220455c5bff3e1c Mon Sep 17 00:00:00 2001 From: Benjamin Admin Date: Mon, 27 Apr 2026 23:52:40 +0200 Subject: [PATCH] feat: Consent Document Approval Workflow im Frontend aktivieren MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VersionsTab zeigt jetzt kontextabhaengige Workflow-Buttons: - Entwurf → "Zur Pruefung" (Submit for Review) - In Pruefung → "Genehmigen" / "Ablehnen" (Approve/Reject) - Genehmigt → "Publizieren" (Publish) Backend-Endpoints (legal_document_routes.py) existierten bereits, wurden aber vom Frontend nicht genutzt. Status-Badges erweitert: draft, review, approved, published, archived, rejected. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../_components/VersionsTab.tsx | 122 +++++++++--------- .../_hooks/useConsentData.ts | 40 ++++++ .../app/sdk/consent-management/page.tsx | 5 + 3 files changed, 109 insertions(+), 58 deletions(-) diff --git a/admin-compliance/app/sdk/consent-management/_components/VersionsTab.tsx b/admin-compliance/app/sdk/consent-management/_components/VersionsTab.tsx index 51e9c10..1d385be 100644 --- a/admin-compliance/app/sdk/consent-management/_components/VersionsTab.tsx +++ b/admin-compliance/app/sdk/consent-management/_components/VersionsTab.tsx @@ -2,18 +2,28 @@ import type { Document, Version } from '../_types' +const STATUS_STYLES: Record = { + draft: { label: 'Entwurf', color: 'bg-gray-100 text-gray-700' }, + review: { label: 'Pruefung', color: 'bg-yellow-100 text-yellow-700' }, + approved: { label: 'Genehmigt', color: 'bg-blue-100 text-blue-700' }, + published: { label: 'Publiziert', color: 'bg-green-100 text-green-700' }, + archived: { label: 'Archiviert', color: 'bg-gray-100 text-gray-400' }, + rejected: { label: 'Abgelehnt', color: 'bg-red-100 text-red-700' }, +} + export function VersionsTab({ - loading, - documents, - versions, - selectedDocument, - setSelectedDocument, + loading, documents, versions, selectedDocument, setSelectedDocument, + onSubmitReview, onApprove, onReject, onPublish, }: { loading: boolean documents: Document[] versions: Version[] selectedDocument: string setSelectedDocument: (id: string) => void + onSubmitReview?: (versionId: string) => void + onApprove?: (versionId: string) => void + onReject?: (versionId: string, comment: string) => void + onPublish?: (versionId: string) => void }) { return (
@@ -27,73 +37,69 @@ export function VersionsTab({ > {documents.map((doc) => ( - + ))}
- {selectedDocument && ( - - )} {!selectedDocument ? ( -
- Bitte waehlen Sie ein Dokument aus -
+
Bitte waehlen Sie ein Dokument aus
) : loading ? (
Lade Versionen...
) : versions.length === 0 ? ( -
- Keine Versionen vorhanden -
+
Keine Versionen vorhanden
) : (
- {versions.map((version) => ( -
-
-
-
- v{version.version} - - {version.language.toUpperCase()} - - - {version.status} - + {versions.map((version) => { + const style = STATUS_STYLES[version.status] || STATUS_STYLES.draft + return ( +
+
+
+
+ v{version.version} + + {version.language.toUpperCase()} + + {style.label} +
+

{version.title}

+

+ Erstellt: {new Date(version.created_at).toLocaleDateString('de-DE')} + {version.published_at && ` | Publiziert: ${new Date(version.published_at).toLocaleDateString('de-DE')}`} +

+
+
+ {version.status === 'draft' && onSubmitReview && ( + + )} + {version.status === 'review' && onApprove && ( + + )} + {version.status === 'review' && onReject && ( + + )} + {version.status === 'approved' && onPublish && ( + + )}
-

{version.title}

-

- Erstellt: {new Date(version.created_at).toLocaleDateString('de-DE')} -

-
-
- - {version.status === 'draft' && ( - - )}
-
- ))} + ) + })}
)}
diff --git a/admin-compliance/app/sdk/consent-management/_hooks/useConsentData.ts b/admin-compliance/app/sdk/consent-management/_hooks/useConsentData.ts index 8115d9c..f8977fe 100644 --- a/admin-compliance/app/sdk/consent-management/_hooks/useConsentData.ts +++ b/admin-compliance/app/sdk/consent-management/_hooks/useConsentData.ts @@ -277,6 +277,45 @@ export function useConsentData(activeTab: Tab, selectedDocument: string) { localStorage.setItem('sdk-email-templates', JSON.stringify(updated)) } + // Document version workflow actions (via admin consent proxy → legal-documents backend) + async function submitVersionForReview(versionId: string) { + try { + const res = await fetch(`${API_BASE}/versions/${versionId}/submit-review`, { + method: 'POST', headers: authToken ? { 'Authorization': `Bearer ${authToken}` } : {}, + }) + if (res.ok && selectedDocument) await loadVersions(selectedDocument) + } catch (err) { console.error('Submit failed:', err) } + } + + async function approveVersion(versionId: string) { + try { + const res = await fetch(`${API_BASE}/versions/${versionId}/approve`, { + method: 'POST', headers: authToken ? { 'Authorization': `Bearer ${authToken}` } : {}, + }) + if (res.ok && selectedDocument) await loadVersions(selectedDocument) + } catch (err) { console.error('Approve failed:', err) } + } + + async function rejectVersion(versionId: string, comment: string) { + try { + const res = await fetch(`${API_BASE}/versions/${versionId}/reject`, { + method: 'POST', + headers: { 'Content-Type': 'application/json', ...(authToken ? { 'Authorization': `Bearer ${authToken}` } : {}) }, + body: JSON.stringify({ comment }), + }) + if (res.ok && selectedDocument) await loadVersions(selectedDocument) + } catch (err) { console.error('Reject failed:', err) } + } + + async function publishVersion(versionId: string) { + try { + const res = await fetch(`${API_BASE}/versions/${versionId}/publish`, { + method: 'POST', headers: authToken ? { 'Authorization': `Bearer ${authToken}` } : {}, + }) + if (res.ok) { if (selectedDocument) await loadVersions(selectedDocument); await loadDocuments() } + } catch (err) { console.error('Publish failed:', err) } + } + return { documents, versions, loading, error, setError, consentStats, dsrCounts, dsrOverview, @@ -286,6 +325,7 @@ export function useConsentData(activeTab: Tab, selectedDocument: string) { savingTemplateId, savingProcessId, saveApiEmailTemplate, saveApiGdprProcess, loadApiEmailTemplates, + submitVersionForReview, approveVersion, rejectVersion, publishVersion, authToken, setAuthToken, } } diff --git a/admin-compliance/app/sdk/consent-management/page.tsx b/admin-compliance/app/sdk/consent-management/page.tsx index 1ac5dfe..6ab3e02 100644 --- a/admin-compliance/app/sdk/consent-management/page.tsx +++ b/admin-compliance/app/sdk/consent-management/page.tsx @@ -45,6 +45,7 @@ export default function ConsentManagementPage() { savingTemplateId, savingProcessId, saveApiEmailTemplate, saveApiGdprProcess, loadApiEmailTemplates, + submitVersionForReview, approveVersion, rejectVersion, publishVersion, authToken, setAuthToken, } = useConsentData(activeTab, selectedDocument) @@ -128,6 +129,10 @@ export default function ConsentManagementPage() { versions={versions} selectedDocument={selectedDocument} setSelectedDocument={setSelectedDocument} + onSubmitReview={submitVersionForReview} + onApprove={approveVersion} + onReject={rejectVersion} + onPublish={publishVersion} /> )}