shinkan-jinkendo/frontend/src/components/LegalDocumentPreview.jsx

112 lines
3.3 KiB
React
Raw Normal View History

import { useEffect } from 'react'
import LegalDocumentBody from './LegalDocumentBody'
import { legalSectionNumber } from '../utils/legalPdfExport'
/** Inhalt wie auf der öffentlichen Rechtstextseite (inkl. §-Nummerierung). */
export function LegalDocumentPublicPreviewContent({
title,
sections,
showDraftNotice = true,
metaLine,
}) {
const safeTitle = (title || '').trim() || 'Ohne Titel'
return (
<div className="legal-admin-preview-inner">
{showDraftNotice && (
<div
className="card"
style={{
marginBottom: '1.25rem',
borderLeft: '4px solid var(--warn)',
background: 'var(--surface)',
}}
>
<strong style={{ color: 'var(--text1)' }}>Vorschau</strong>
<p style={{ margin: '0.35rem 0 0', fontSize: '0.88rem', color: 'var(--text2)' }}>
So erscheint der Text für Besucher nach Veröffentlichung (Markdown wird gerendert, §-Nummern wie online).
</p>
</div>
)}
{metaLine && (
<p style={{ fontSize: '0.85rem', color: 'var(--text3)', margin: '0 0 1rem' }}>{metaLine}</p>
)}
<h1 style={{ margin: '0 0 1.5rem', color: 'var(--text1)', fontSize: '1.5rem' }}>{safeTitle}</h1>
{(sections || []).map((section, i) => (
<div key={i} style={{ marginBottom: '1.75rem' }}>
<h2 style={{ fontSize: '1.05rem', marginBottom: '0.4rem', color: 'var(--text1)' }}>
{section.heading?.trim()
? `${legalSectionNumber(i)} ${section.heading}`
: legalSectionNumber(i)}
</h2>
<LegalDocumentBody content={section.content} />
</div>
))}
{sections?.length === 0 && (
<p style={{ color: 'var(--text3)', fontSize: '0.9rem' }}>Noch keine Abschnitte.</p>
)}
</div>
)
}
/**
* Modal: gerenderte Rechtstext-Vorschau (Editor oder gespeicherte Version).
*/
export function LegalPreviewModal({
open,
onClose,
title,
sections,
metaLine,
loading,
showDraftNotice = true,
}) {
useEffect(() => {
if (!open) return
const onKey = (e) => {
if (e.key === 'Escape') onClose()
}
window.addEventListener('keydown', onKey)
return () => window.removeEventListener('keydown', onKey)
}, [open, onClose])
if (!open) return null
return (
<div
className="legal-preview-modal-backdrop"
role="presentation"
onClick={onClose}
>
<div
className="legal-preview-modal"
role="dialog"
aria-modal="true"
aria-labelledby="legal-preview-modal-title"
onClick={(e) => e.stopPropagation()}
>
<div className="legal-preview-modal__header">
<h3 id="legal-preview-modal-title" style={{ margin: 0, fontSize: '1.05rem' }}>
Öffentliche Darstellung
</h3>
<button type="button" className="btn btn-secondary" onClick={onClose}>
Schließen
</button>
</div>
<div className="legal-preview-modal__body">
{loading ? (
<div className="spinner" style={{ margin: '2rem auto' }} />
) : (
<LegalDocumentPublicPreviewContent
title={title}
sections={sections}
metaLine={metaLine}
showDraftNotice={showDraftNotice}
/>
)}
</div>
</div>
</div>
)
}