import { useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { useFieldDefinitions } from "../api/queries"; import { FieldInput } from "./field-input"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; export type ObjectCore = { object_number: string; object_name: string; number_of_objects: number; brief_description: string | null; current_location: string | null; current_owner: string | null; recorder: string | null; recording_date: string | null; }; export type ObjectFormValues = { core: ObjectCore; visibility?: "draft" | "internal"; fields: Record; }; type FormShape = { core: ObjectCore; visibility: "draft" | "internal"; fields: Record; } & Record; const EMPTY_CORE: ObjectCore = { object_number: "", object_name: "", number_of_objects: 1, brief_description: null, current_location: null, current_owner: null, recorder: null, recording_date: null, }; export function ObjectForm({ mode, defaults, onSubmit, onCancel, formError, }: { mode: "create" | "edit"; defaults?: { core: ObjectCore; fields: Record }; onSubmit: (values: ObjectFormValues) => void; onCancel: () => void; formError?: string | null; }) { const { t } = useTranslation(); const { data: definitions } = useFieldDefinitions(); const form = useForm({ defaultValues: { core: defaults?.core ?? EMPTY_CORE, visibility: "draft", fields: defaults?.fields ?? {}, }, }); const { register, handleSubmit, formState: { errors } } = form; const submit = handleSubmit((data) => { const fields = pruneFields(data.fields); onSubmit( mode === "create" ? { core: data.core, visibility: data.visibility, fields } : { core: data.core, fields }, ); }); const coreField = ( key: keyof ObjectCore, labelKey: string, opts?: { type?: string; required?: boolean }, ) => (
{errors.core?.[key] && (

{t("form.required")}

)}
); return (
{formError && (

{formError}

)} {coreField("object_number", "objectNumber", { required: true })} {coreField("object_name", "objectName", { required: true })} {coreField("number_of_objects", "count", { type: "number", required: true })} {coreField("brief_description", "briefDescription")} {coreField("current_location", "currentLocation")} {coreField("current_owner", "currentOwner")} {coreField("recorder", "recorder")} {coreField("recording_date", "recordingDate", { type: "date" })} {mode === "create" && (
)} {definitions && definitions.length > 0 && (
{t("form.flexibleHeading")} {definitions.map((def) => (
{errors.fields?.[def.key] && (

{t("form.required")}

)}
))}
)}
); } function pruneFields(fields: Record): Record { const out: Record = {}; for (const [key, value] of Object.entries(fields)) { if (value === undefined || value === null || value === "") continue; if (typeof value === "object" && !Array.isArray(value)) { const inner = Object.fromEntries( Object.entries(value as Record).filter( ([, v]) => v !== undefined && v !== null && v !== "", ), ); if (Object.keys(inner).length > 0) out[key] = inner; continue; } out[key] = value; } return out; }