"use client"; import Link from "next/link"; import { useActionState, useId, useState } from "react"; import { FormErrorBanner } from "@/components/admin/Flash"; import { FormTabs } from "@/components/admin/FormTabs"; import { RichTextEditor } from "@/components/admin/RichTextEditor"; import { SubmitButton } from "@/components/admin/SubmitButton"; import { ErrorText, HelpText, Input, Label, Select } from "@/components/ui"; import type { Page } from "@/db/schema"; import { type FormState, firstFieldError, initialFormState } from "@/lib/forms"; import { slugify } from "@/lib/slug"; type Props = { page?: Page; action: (prev: FormState, formData: FormData) => Promise; }; const SETTINGS_FIELDS = ["title", "slug"]; /** Same tabbed layout as PostForm: full-height canvas + settings panel. */ export function PageForm({ page, action }: Props) { const [state, formAction] = useActionState(action, initialFormState); const ids = useId(); // See PostForm: explicit tab clicks win until the next action result, // which routes to the tab containing validation errors. const [tabChoice, setTabChoice] = useState<{ tab: "content" | "settings"; forState: FormState; }>({ tab: "content", forState: initialFormState }); const [title, setTitle] = useState(page?.title ?? ""); const [slug, setSlug] = useState(page?.slug ?? ""); const [slugTouched, setSlugTouched] = useState(page !== undefined); const [status, setStatus] = useState(page?.status ?? "draft"); const err = (field: string) => firstFieldError(state, field); const errorKeys = Object.keys(state.fieldErrors ?? {}); const settingsHasError = errorKeys.some((key) => SETTINGS_FIELDS.includes(key)); const contentHasError = errorKeys.includes("body"); const tab = tabChoice.forState === state ? tabChoice.tab : settingsHasError ? "settings" : contentHasError ? "content" : tabChoice.tab; const setTab = (next: "content" | "settings") => setTabChoice({ tab: next, forState: state }); return (
setTab(id as typeof tab)} tabs={[ { id: "content", label: "Content", hasError: contentHasError }, { id: "settings", label: "Page settings", hasError: settingsHasError }, ]} />
Save page Cancel
{state.formError}
); }