import { useEffect, useMemo, useState } from "react"; import type { PageDetail } from "@ledger/shared"; import { api } from "../lib/api"; import { MarkdownComposerHint } from "./MarkdownComposerHint"; const emptyPage = { spaceId: "", title: "", slug: "", bodyMarkdown: "", excerpt: "", visibility: "internal", state: "draft", tagNames: [] as string[] }; function normalizeMarkdownForEmptyState(value: string) { return value .replace(/\u200B/g, "") .replace(/\r\n/g, "\n") .trim(); } function hasMeaningfulMarkdown(value: string) { const normalized = normalizeMarkdownForEmptyState(value); if (!normalized) { return false; } return normalized !== "# New page\n\nStart writing..." && normalized !== "Start writing..."; } export function PageEditor({ spaces, initialPage, mode = "create", variant = "panel", onSaved, onCancel }: { spaces: Array<{ id: string; name: string; key: string }>; initialPage?: (Pick & { parentPageId?: string | null; }) | null; mode?: "create" | "edit"; variant?: "panel" | "dialog" | "page"; onSaved?: (slug: string) => void; onCancel?: () => void; }) { const createEmptyForm = () => ({ ...emptyPage, spaceId: initialPage?.spaceId ?? spaces[0]?.id ?? "", title: initialPage?.title ?? "", slug: initialPage?.slug ?? "", bodyMarkdown: initialPage?.bodyMarkdown ?? "", excerpt: initialPage?.excerpt ?? "", visibility: initialPage?.visibility ?? "internal", state: initialPage?.state ?? "draft", tagNames: initialPage?.tags ?? [], parentPageId: initialPage?.parentPageId ?? null }); const [form, setForm] = useState(createEmptyForm); const [tagInput, setTagInput] = useState((initialPage?.tags ?? []).join(", ")); const [status, setStatus] = useState(null); const isDialog = variant === "dialog"; const isPage = variant === "page"; const showMarkdownHelper = useMemo(() => !hasMeaningfulMarkdown(form.bodyMarkdown), [form.bodyMarkdown]); const canPublish = form.state === "published"; useEffect(() => { setForm(createEmptyForm()); setTagInput((initialPage?.tags ?? []).join(", ")); }, [initialPage, spaces]); async function submit(nextState?: "draft" | "published") { try { const payload = { ...form, state: nextState ?? form.state, tagNames: form.tagNames, allowedRoleKeys: form.visibility === "restricted" ? ["viewer"] : [] }; const result = mode === "edit" && initialPage ? await api.put<{ slug: string }>(`/api/pages/${initialPage.id}`, payload) : await api.post<{ slug: string }>("/api/pages", payload); setStatus(mode === "edit" ? "Document saved." : `Saved page ${result.slug}`); if (mode === "create") { setForm({ ...emptyPage, spaceId: spaces[0]?.id ?? "" }); setTagInput(""); } onSaved?.(result.slug); } catch (error) { setStatus(error instanceof Error ? error.message : "Could not save page"); } } return (

{mode === "edit" ? "Editor" : "Publishing"}

{mode === "edit" ? "Edit document" : isDialog ? "New document" : isPage ? "New document" : "Create a new page"}

{mode === "edit" ? "Draft editor" : "Editor"} {onCancel ? ( ) : null}