Files
Lageplan/src/components/legal/legal-page.tsx
Pepe Ziberi 5f360480ae
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 53m24s
feat(legal): FKS-Quellenangabe, Auslandtransfer-Doku, Journal-Warnung, Region-Fix (v1.9.1)
Compliance-Runde 2 (ohne Doppelstrukturen; baut auf v1.7–v1.9 auf):

FKS/FEUKOS (dokumentierte schriftliche Genehmigung 17.02.2026):
- legal.ts: fksAttribution (exakte Quellenangabe, Genehmigungsdatum, Nutzungshinweis) + operatorType
- Neue Seite /quellen-und-lizenzen (+ Footer/Sitemap-Link)
- FKS-Abschnitt in Nutzungsbedingungen (§10a); Quellenangabe im Symbol-Panel und in PDF/PNG-Export
- Terminologie entschärft: "offizielle FKS/BABS-Signaturen" -> "FEUKOS-Symbole der FKS"
  (keine Partnerschaft/Zertifizierung/Empfehlung suggeriert)
- FKS_ATTRIBUTION als Dokumenttyp (Migration-Seed, LegalDocumentType), Kontexte erweitert
- licenses-and-attributions.md aktualisiert; .gitignore: private-legal-evidence/

Datenschutz/Transparenz:
- [REGION]-Platzhalter in der Subprozessorenliste durch öffentlich bekannte Firmensitze ersetzt
  (keine Platzhalter mehr öffentlich sichtbar)
- Journal-Freitext-Warnung (keine schutzwürdigen Daten)

Docs: current-state-audit, international-data-transfers, backup-and-restore,
privacy-risk-assessment, manual-action-checklist

Tests: Krypto-Round-Trip (crypto-secret); legal-config-Test aktualisiert; 17 grün. tsc+build ok.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-31 13:52:38 +02:00

94 lines
4.0 KiB
TypeScript

'use client'
import Link from 'next/link'
import { ArrowLeft, Printer } from 'lucide-react'
import { legal } from '@/config/legal'
/** Pflicht-Links, die im Footer jeder öffentlichen (Rechts-)Seite erscheinen. */
export const LEGAL_LINKS: { href: string; label: string }[] = [
{ href: '/impressum', label: 'Impressum' },
{ href: '/datenschutz', label: 'Datenschutz' },
{ href: '/nutzungsbedingungen', label: 'Nutzungsbedingungen' },
{ href: '/verantwortungsvolle-nutzung', label: 'Verantwortungsvolle Nutzung' },
{ href: '/sicherheit', label: 'Sicherheit' },
{ href: '/quellen-und-lizenzen', label: 'Quellen & Lizenzen' },
{ href: '/organisationen/datenschutzvereinbarung', label: 'Datenschutzvereinbarung (Org.)' },
{ href: '/unterstuetzen', label: 'Unterstützen' },
]
export function LegalFooterLinks() {
return (
<nav aria-label="Rechtliche Seiten" className="mt-10 border-t border-border pt-6 print:hidden">
<ul className="flex flex-wrap gap-x-4 gap-y-2 text-sm text-muted-foreground">
{LEGAL_LINKS.map(l => (
<li key={l.href}>
<Link href={l.href} className="hover:text-foreground underline underline-offset-2">{l.label}</Link>
</li>
))}
</ul>
</nav>
)
}
interface LegalPageProps {
title: string
/** Versionsangabe, z.B. legal.documents.terms.version */
version?: string
/** Veröffentlichungsdatum ISO */
publishedAt?: string
/** Optionaler Warnhinweis (Standard: aus — Texte sind final). */
draft?: boolean
/** Kurzer Einleitungssatz unter dem Titel */
intro?: string
children: React.ReactNode
}
/**
* Einheitliche, responsive, druckbare Hülle für alle öffentlichen Rechtsseiten.
* Enthält Zurück-Link, Drucken-Button, Version/Datum, Entwurfshinweis und die Pflicht-Footer-Links.
*/
export function LegalPage({ title, version, publishedAt, draft = false, intro, children }: LegalPageProps) {
return (
<div className="min-h-screen bg-background px-4 py-10 print:py-0 print:bg-white">
<div className="max-w-3xl mx-auto">
<div className="flex items-center justify-between mb-6 print:hidden">
<Link href="/" className="text-sm text-muted-foreground hover:text-foreground inline-flex items-center gap-1">
<ArrowLeft className="w-3.5 h-3.5" /> Zur Startseite
</Link>
<button
onClick={() => window.print()}
className="text-sm text-muted-foreground hover:text-foreground inline-flex items-center gap-1"
>
<Printer className="w-3.5 h-3.5" /> Drucken
</button>
</div>
<article className="bg-card rounded-xl border border-border shadow-sm p-6 md:p-10 print:border-0 print:shadow-none print:p-0">
<h1 className="text-3xl font-bold text-foreground">{title}</h1>
<div className="mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground">
{version && <span>Version {version}</span>}
{publishedAt && <span>· Stand: {publishedAt}</span>}
<span>· {legal.projectName} ({legal.siteDomain})</span>
</div>
{intro && <p className="mt-4 text-sm text-muted-foreground leading-relaxed">{intro}</p>}
{draft && (
<div className="mt-4 rounded-lg border border-amber-300 bg-amber-50 dark:bg-amber-950/30 dark:border-amber-800 px-4 py-3 text-sm text-amber-800 dark:text-amber-300">
{legal.draftNotice}
</div>
)}
<div className="legal-prose mt-6 space-y-6 text-sm leading-relaxed text-muted-foreground [&_h2]:text-lg [&_h2]:font-semibold [&_h2]:text-foreground [&_h2]:mb-2 [&_h2]:mt-2 [&_h3]:font-semibold [&_h3]:text-foreground [&_strong]:text-foreground [&_a]:text-red-600 [&_a]:underline [&_ul]:list-disc [&_ul]:pl-5 [&_ul]:space-y-1 [&_ol]:list-decimal [&_ol]:pl-5 [&_ol]:space-y-1">
{children}
</div>
<LegalFooterLinks />
<p className="mt-4 text-xs text-muted-foreground/70">{legal.draftNotice}</p>
</article>
</div>
</div>
)
}