/**
* WEB-0b: Seiten-Editor der öffentlichen Webseite.
* - Kopf: Titel, SEO-Beschreibung, Status (Entwurf/Veröffentlicht).
* - Geordneter Block-Editor: Blöcke hinzufügen, bearbeiten, verschieben, löschen.
*
* Reihenfolge/Anlegen/Löschen rufen das Backend auf und laden danach neu; der
* Editor wird über `key` neu montiert, sodass der lokale Zustand frisch aus den
* geladenen Daten initialisiert wird (keine Prop→State-Synchronisation per Effekt).
*/
import { useState } from 'react'
import { Link, useParams } from 'react-router-dom'
import { de } from '../strings/de'
import {
ADDABLE_BLOCK_TYPES,
addBlock,
defaultBlockData,
deleteBlock,
getPage,
reorderBlocks,
updateBlock,
updatePage,
type Block,
type BlockData,
type BlockType,
type GalleryImage,
type Page,
type PageStatus,
} from '../api/pages'
import { useApi, useMutation } from '../hooks/useApi'
import './webseite.css'
const asStr = (v: unknown): string => (typeof v === 'string' ? v : '')
export default function WebseiteEditorPage() {
const { slug = '' } = useParams<{ slug: string }>()
const page = useApi(() => getPage(slug), [slug])
if (page.loading) return
{de.common.loading}
if (page.error || !page.data) {
return (
{de.pages.webseite.title}
{page.error}
)
}
// Signatur der Blöcke -> erzwingt Neu-Montage nach Reload (frische Init).
const signature = page.data.blocks.map((b) => `${b.id}:${b.order}`).join('|')
return
}
function PageEditor({ page, reload }: { page: Page; reload: () => void }) {
const t = de.pages.webseite
const [title, setTitle] = useState(page.title)
const [seo, setSeo] = useState(page.seoDescription ?? '')
const [status, setStatus] = useState(page.status)
const [savedHead, setSavedHead] = useState(false)
const saveHead = useMutation(() =>
updatePage(page.id, {
slug: page.slug,
title,
seoDescription: seo.trim() === '' ? null : seo,
status,
}),
)
async function onSaveHead() {
const r = await saveHead.run()
if (r.ok) {
setSavedHead(true)
reload()
}
}
const blocks = [...page.blocks].sort((a, b) => a.order - b.order)
const adder = useMutation((type: BlockType) =>
addBlock(page.id, { type, data: defaultBlockData(type) }),
)
async function onAdd(type: BlockType) {
const r = await adder.run(type)
if (r.ok) reload()
}
const remover = useMutation((id: string) => deleteBlock(id))
async function onDelete(id: string) {
if (!window.confirm(t.blocks.confirmDelete)) return
const r = await remover.run(id)
if (r.ok) reload()
}
const reorder = useMutation((ids: string[]) => reorderBlocks(page.id, ids))
async function onMove(index: number, dir: -1 | 1) {
const target = index + dir
if (target < 0 || target >= blocks.length) return
const ids = blocks.map((b) => b.id)
;[ids[index], ids[target]] = [ids[target], ids[index]]
const r = await reorder.run(ids)
if (r.ok) reload()
}
const busy = adder.pending || remover.pending || reorder.pending
return (