import { useState, useEffect } from 'react' import { Link } from 'react-router-dom' import LegalDocumentBody from '../components/LegalDocumentBody' import { generateLegalPdf, legalSectionNumber } from '../utils/legalPdfExport' import api from '../utils/api' // document_type values used in the DB / API const TYPE_MAP = { impressum: 'impressum', datenschutz: 'privacy_policy', nutzungsbedingungen: 'terms_of_use', medienrichtlinie: 'media_policy', } const PAGES = { impressum: { title: 'Impressum', sections: [ { heading: 'Betreiber / Verantwortlicher', placeholder: '[Name und Rechtsform des Betreibers — vom Betreiber einzutragen]', }, { heading: 'Anschrift', placeholder: '[Straße, Hausnummer, PLZ, Ort — vom Betreiber einzutragen]', }, { heading: 'Vertretungsberechtigte Person', placeholder: '[Name der vertretungsberechtigten Person — vom Betreiber einzutragen]', }, { heading: 'Kontakt', placeholder: '[E-Mail-Adresse, ggf. Telefonnummer — vom Betreiber einzutragen]', }, { heading: 'Registerangaben (falls relevant)', placeholder: '[Vereinsregister, Handelsregister o. ä. — vom Rechtsanwalt prüfen lassen]', }, ], }, datenschutz: { title: 'Datenschutzerklärung', sections: [ { heading: 'Verantwortlicher', placeholder: '[Name, Anschrift und Kontakt des Verantwortlichen — vom Betreiber einzutragen]', }, { heading: 'Zwecke der Verarbeitung', placeholder: '[Welche Daten werden zu welchem Zweck verarbeitet? — vom Rechtsanwalt zu formulieren]', }, { heading: 'Rechtsgrundlagen', placeholder: '[Art. 6 DSGVO: Einwilligung, Vertrag, berechtigtes Interesse — vom Rechtsanwalt zu bestimmen]', }, { heading: 'Empfänger und Dienstleister', placeholder: '[SMTP-Anbieter, Hosting, ggf. weitere — vom Rechtsanwalt und Betreiber zu listen]', }, { heading: 'Speicherdauern', placeholder: '[Wie lange werden welche Daten gespeichert? — vom Rechtsanwalt zu bestimmen]', }, { heading: 'Betroffenenrechte', placeholder: '[Auskunft, Berichtigung, Löschung, Widerspruch, Datenübertragbarkeit — vom Rechtsanwalt zu formulieren]', }, { heading: 'Browser-Speicher (localStorage, sessionStorage)', placeholder: '[Technisch notwendige Speicherung des Auth-Tokens und Sitzungsdaten. Nach TDDDG §25 ggf. ohne Einwilligung zulässig — vom Rechtsanwalt zu prüfen]', }, { heading: 'Kontakt für Datenschutzanfragen', placeholder: '[E-Mail oder Kontaktweg für Datenschutzanfragen — vom Betreiber einzutragen]', }, { heading: 'Zuständige Aufsichtsbehörde', placeholder: '[Zuständige Datenschutzbehörde je nach Bundesland — vom Rechtsanwalt zu bestimmen]', }, ], }, nutzungsbedingungen: { title: 'Nutzungsbedingungen', sections: [ { heading: 'Nutzungsumfang', placeholder: '[Für welche Nutzergruppen und Zwecke darf die Plattform genutzt werden? — vom Rechtsanwalt zu formulieren]', }, { heading: 'Registrierung', placeholder: '[Voraussetzungen für die Registrierung, Wahrheitspflicht der Angaben — vom Rechtsanwalt zu formulieren]', }, { heading: 'Zulässige und unzulässige Inhalte', placeholder: '[Was darf hochgeladen und veröffentlicht werden? Was ist verboten? — vom Rechtsanwalt zu formulieren]', }, { heading: 'Verantwortlichkeit der Nutzer', placeholder: '[Nutzer sind für ihre hochgeladenen Inhalte selbst verantwortlich — vom Rechtsanwalt zu formulieren]', }, { heading: 'Sperrung und Löschung', placeholder: '[Unter welchen Bedingungen können Konten oder Inhalte gesperrt oder gelöscht werden? — vom Rechtsanwalt zu formulieren]', }, { heading: 'Haftungshinweise', placeholder: '[Haftungsausschluss für Nutzerinhalte, externe Links, Systemausfälle — vom Rechtsanwalt zu formulieren]', }, { heading: 'Geltungsbereich und anwendbares Recht', placeholder: '[Welches Recht ist anwendbar? Welcher Gerichtsstand gilt? — vom Rechtsanwalt zu bestimmen]', }, ], }, medienrichtlinie: { title: 'Medienrichtlinie', sections: [ { heading: 'Urheberrechte', placeholder: '[Nur eigene oder ausdrücklich lizenzierte Inhalte hochladen — vom Rechtsanwalt zu formulieren]', }, { heading: 'Rechte am eigenen Bild (§ 22 KUG)', placeholder: '[Erkennbare Personen müssen eingewilligt haben; besondere Regeln für Minderjährige — juristisch zu prüfen und zu formulieren]', }, { heading: 'Minderjährige', placeholder: '[Besondere Schutzpflichten bei Aufnahmen von Minderjährigen — vom Rechtsanwalt zu formulieren]', }, { heading: 'Musik und sonstige Fremdinhalte', placeholder: '[Keine Hintergrundmusik oder andere Fremdinhalte ohne gültige Lizenz — vom Rechtsanwalt zu formulieren]', }, { heading: 'Sichtbarkeitsstufen', placeholder: '[Erläuterung der Stufen: privat, vereinsintern, öffentlich — vom Betreiber zu beschreiben]', }, { heading: 'Meldewege für rechtsverletzende Inhalte', placeholder: '[Wie können Inhalte gemeldet werden? — wird nach Umsetzung von P-13 (Content-Melde-Backend) ergänzt]', }, { heading: 'Lösch- und Sperrlogik', placeholder: '[Wann und wie werden gemeldete Inhalte entfernt oder gesperrt? — wird nach Umsetzung von P-11 und P-13 ergänzt]', }, ], }, } const LEGAL_LINKS = [ { to: '/impressum', label: 'Impressum' }, { to: '/datenschutz', label: 'Datenschutz' }, { to: '/nutzungsbedingungen', label: 'Nutzungsbedingungen' }, { to: '/medienrichtlinie', label: 'Medienrichtlinie' }, ] function LegalPage({ type }) { const fallback = PAGES[type] const [apiDoc, setApiDoc] = useState(undefined) // undefined = loading, null = not found const [loading, setLoading] = useState(true) const documentType = TYPE_MAP[type] useEffect(() => { if (!documentType) { setLoading(false) return } api.getPublishedLegalDocument(documentType) .then(doc => setApiDoc(doc)) .catch(() => setApiDoc(null)) .finally(() => setLoading(false)) }, [documentType]) if (!fallback) return null const isPlaceholder = !apiDoc const title = apiDoc ? apiDoc.title : fallback.title const sections = apiDoc ? (apiDoc.content_sections || []) : fallback.sections.map(s => ({ heading: s.heading, content: s.placeholder })) return (
← Zurück zur Anmeldung
{loading ? (
) : ( <> {isPlaceholder && (
⚠ MUSTER / PLATZHALTER

Inhalt wird vor Produktivbetrieb juristisch geprüft und durch den Betreiber ergänzt. Diese Seite hat keinen rechtlich verbindlichen Charakter.

)}

{title}

{apiDoc && ( )}
{sections.map((section, i) => (

{section.heading ? `${legalSectionNumber(i)} ${section.heading}` : legalSectionNumber(i)}

))} )}
{LEGAL_LINKS.map((l) => ( {l.label} ))}
) } export default LegalPage