feat: Package 4 Rechtliche Texte — DB-Persistenz fuer Legal Documents, Einwilligungen und Cookie Banner
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 46s
CI / test-python-backend-compliance (push) Successful in 32s
CI / test-python-document-crawler (push) Successful in 22s
CI / test-python-dsms-gateway (push) Successful in 17s

- Migration 007: compliance_legal_documents, _versions, _approvals (Approval-Workflow)
- Migration 008: compliance_einwilligungen_catalog, _company, _cookies, _consents
- Backend: legal_document_routes.py (11 Endpoints + draft→review→approved→published Workflow)
- Backend: einwilligungen_routes.py (10 Endpoints inkl. Stats, Pagination, Revoke)
- Frontend: /api/admin/consent/[[...path]] Catch-All-Proxy fuer Legal Documents
- Frontend: catalog/consent/cookie-banner routes von In-Memory auf DB-Proxy umgestellt
- Frontend: einwilligungen/page.tsx + cookie-banner/page.tsx laden jetzt via API (kein Mock)
- Tests: 44/44 pass (test_legal_document_routes.py + test_einwilligungen_routes.py)
- Deploy-Scripts: apply_legal_docs_migration.sh + apply_einwilligungen_migration.sh

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-03 08:25:13 +01:00
parent 799668e472
commit 113ecdfa77
17 changed files with 2501 additions and 664 deletions

View File

@@ -219,13 +219,63 @@ function CategoryCard({
export default function CookieBannerPage() {
const { state } = useSDK()
const [categories, setCategories] = useState<CookieCategory[]>(mockCategories)
const [categories, setCategories] = useState<CookieCategory[]>([])
const [config, setConfig] = useState<BannerConfig>(defaultConfig)
const [isSaving, setIsSaving] = useState(false)
const handleCategoryToggle = (categoryId: string, enabled: boolean) => {
React.useEffect(() => {
const loadConfig = async () => {
try {
const response = await fetch('/api/sdk/v1/einwilligungen/cookie-banner/config')
if (response.ok) {
const data = await response.json()
if (data.categories && data.categories.length > 0) {
setCategories(data.categories)
} else {
// Fall back to mock data for initial display
setCategories(mockCategories)
}
if (data.config && Object.keys(data.config).length > 0) {
setConfig(prev => ({ ...prev, ...data.config }))
}
} else {
setCategories(mockCategories)
}
} catch {
setCategories(mockCategories)
}
}
loadConfig()
}, [])
const handleCategoryToggle = async (categoryId: string, enabled: boolean) => {
setCategories(prev =>
prev.map(cat => cat.id === categoryId ? { ...cat, enabled } : cat)
)
try {
await fetch('/api/sdk/v1/einwilligungen/cookie-banner/config', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ categoryId, enabled }),
})
} catch {
// Silently ignore — local state already updated
}
}
const handleSaveConfig = async () => {
setIsSaving(true)
try {
await fetch('/api/sdk/v1/einwilligungen/cookie-banner/config', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ categories, config }),
})
} catch {
// Silently ignore
} finally {
setIsSaving(false)
}
}
const totalCookies = categories.reduce((sum, cat) => sum + cat.cookies.length, 0)
@@ -250,8 +300,12 @@ export default function CookieBannerPage() {
<button className="px-4 py-2 text-gray-600 hover:bg-gray-100 rounded-lg transition-colors">
Code exportieren
</button>
<button className="flex items-center gap-2 px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors">
Veroeffentlichen
<button
onClick={handleSaveConfig}
disabled={isSaving}
className="flex items-center gap-2 px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors disabled:opacity-50"
>
{isSaving ? 'Speichern...' : 'Veroeffentlichen'}
</button>
</div>
</StepHeader>