feat(sdk): Replace mock data with real API calls in consent, DSR, and consent-management

- /sdk/consent: Replace hardcoded mockDocuments with GET /api/admin/consent/documents
- /sdk/dsr: Replace createMockDSRList with fetchSDKDSRList via /api/sdk/v1/dsgvo/dsr
- /sdk/dsr/new: Replace console.log mock with real POST to create DSR requests
- /sdk/dsr/[requestId]: Replace mock lookup with real GET/PUT for DSR details and status updates
- /sdk/consent-management: Add real stats, GDPR process counts, and email template editor
- lib/sdk/dsr/api.ts: Add transformBackendDSR adapter (flat backend → nested frontend types)

Prepares for removal of /dsgvo and /compliance pages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-02-10 11:53:35 +01:00
parent 8c77df494b
commit 4ed290ccf3
6 changed files with 613 additions and 123 deletions

View File

@@ -1,6 +1,6 @@
'use client'
import React, { useState } from 'react'
import React, { useState, useEffect } from 'react'
import { useSDK } from '@/lib/sdk'
import { StepHeader, STEP_EXPLANATIONS } from '@/components/sdk/StepHeader'
@@ -21,84 +21,47 @@ interface LegalDocument {
changes: string[]
}
// =============================================================================
// MOCK DATA
// =============================================================================
interface ApiDocument {
id: string
type: string
name: string
description: string
mandatory: boolean
created_at: string
updated_at: string
}
const mockDocuments: LegalDocument[] = [
{
id: 'doc-1',
type: 'privacy-policy',
name: 'Datenschutzerklaerung',
version: '2.3',
// Map API document type to UI type
function mapDocumentType(apiType: string): LegalDocument['type'] {
const mapping: Record<string, LegalDocument['type']> = {
'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('2024-01-15'),
publishedAt: new Date('2024-01-15'),
author: 'DSB Mueller',
changes: ['KI-Verarbeitungen ergaenzt', 'Cookie-Abschnitt aktualisiert'],
},
{
id: 'doc-2',
type: 'terms',
name: 'Allgemeine Geschaeftsbedingungen',
version: '1.8',
language: 'de',
status: 'active',
lastUpdated: new Date('2023-12-01'),
publishedAt: new Date('2023-12-01'),
author: 'Rechtsabteilung',
changes: ['Widerrufsrecht angepasst'],
},
{
id: 'doc-3',
type: 'cookie-policy',
name: 'Cookie-Richtlinie',
version: '1.5',
language: 'de',
status: 'active',
lastUpdated: new Date('2024-01-10'),
publishedAt: new Date('2024-01-10'),
author: 'DSB Mueller',
changes: ['Analytics-Cookies aktualisiert', 'Neue Cookie-Kategorien'],
},
{
id: 'doc-4',
type: 'privacy-policy',
name: 'Privacy Policy (EN)',
version: '2.3',
language: 'en',
status: 'draft',
lastUpdated: new Date('2024-01-20'),
publishedAt: null,
author: 'DSB Mueller',
changes: ['Uebersetzung der deutschen Version'],
},
{
id: 'doc-5',
type: 'dpa',
name: 'Auftragsverarbeitungsvertrag (AVV)',
version: '1.2',
language: 'de',
status: 'active',
lastUpdated: new Date('2024-01-05'),
publishedAt: new Date('2024-01-05'),
author: 'Rechtsabteilung',
changes: ['Subunternehmer aktualisiert', 'TOMs ergaenzt'],
},
{
id: 'doc-6',
type: 'imprint',
name: 'Impressum',
version: '1.1',
language: 'de',
status: 'active',
lastUpdated: new Date('2023-11-01'),
publishedAt: new Date('2023-11-01'),
author: 'Admin',
changes: ['Neue Geschaeftsadresse'],
},
]
lastUpdated: new Date(doc.updated_at),
publishedAt: new Date(doc.created_at),
author: 'System',
changes: doc.description ? [doc.description] : [],
}
}
// =============================================================================
// COMPONENTS
@@ -198,9 +161,37 @@ function DocumentCard({ document }: { document: LegalDocument }) {
export default function ConsentPage() {
const { state } = useSDK()
const [documents] = useState<LegalDocument[]>(mockDocuments)
const [documents, setDocuments] = useState<LegalDocument[]>([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
const [filter, setFilter] = useState<string>('all')
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)
}
}
const filteredDocuments = filter === 'all'
? documents
: documents.filter(d => d.type === filter || d.status === filter)
@@ -250,6 +241,16 @@ export default function ConsentPage() {
</div>
</div>
{/* Loading / Error */}
{loading && (
<div className="text-center py-8 text-gray-500">Lade Dokumente...</div>
)}
{error && (
<div className="bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded-lg">
{error}
</div>
)}
{/* Quick Actions */}
<div className="bg-gradient-to-r from-purple-50 to-blue-50 rounded-xl border border-purple-200 p-6">
<h3 className="font-semibold text-gray-900 mb-4">Schnellaktionen</h3>