diff --git a/components/forms/SettingsSubmit.tsx b/components/forms/SettingsSubmit.tsx index 0ff3f16d..b1f8450d 100644 --- a/components/forms/SettingsSubmit.tsx +++ b/components/forms/SettingsSubmit.tsx @@ -55,7 +55,7 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV const [me, setMe] = useState(null); const [submitErr, setSubmitErr] = useState(null); - // Robust current-user fetch (unchanged) + // Robust current-user fetch useEffect(() => { let alive = true; (async () => { @@ -84,7 +84,7 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV return () => { alive = false; }; }, []); - // Options loaders (unchanged) + // Options loaders (Directus reads) function useOptions(path: string, includeId?: string | null) { const [opts, setOpts] = useState([]); useEffect(() => { @@ -164,7 +164,7 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV return { opts }; } - // Enumerations (unchanged) + // Enumerations const FILL_TYPES: Opt[] = [ { id: "uni", label: "UniDirectional" }, { id: "bi", label: "BiDirectional" }, @@ -175,14 +175,14 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV "threshold", "ordered", "atkinson", "dither", "stucki", "jarvis", "newsprint", "halftone", "sketch", "grayscale", ].map((x) => ({ id: x, label: x[0].toUpperCase() + x.slice(1) })); - // react-hook-form (unchanged) + // react-hook-form const { register, handleSubmit, control, reset, - setValue, - getValues, + getValues, // ⬅ added + setValue, // ⬅ added formState: { isSubmitting }, } = useForm({ defaultValues: { @@ -197,6 +197,7 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV // Rig & Optics laser_soft: "", source: "", + // keep these blank so Select shows "—" lens_conf: "", lens_apt: "", lens_exp: "", @@ -210,12 +211,12 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV }, }); - // Repeaters (unchanged) + // Repeaters const fills = useFieldArray({ control, name: "fill_settings" }); const lines = useFieldArray({ control, name: "line_settings" }); const rasters = useFieldArray({ control, name: "raster_settings" }); - // Prefill (unchanged) + // Prefill (edit) useEffect(() => { if (!isEdit || !initialValues) return; reset({ @@ -243,7 +244,43 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV }); }, [isEdit, initialValues, reset]); - // Options (unchanged) + // Re-apply select values when options hydrate (fixes stubborn placeholder issue) + useEffect(() => { + if (!isEdit || !initialValues) return; + + const ensure = (name: string, currentId: string | null | undefined, opts: Opt[]) => { + if (!currentId) return; + const cur = getValues(name as any); + const curStr = cur == null ? "" : String(cur); + if (!curStr || !opts.some((o) => String(o.id) === curStr)) { + setValue(name as any, String(currentId), { shouldDirty: false, shouldValidate: false }); + } + }; + + ensure("mat", initialValues.mat, mats.opts); + ensure("mat_coat", initialValues.mat_coat, coats.opts); + ensure("mat_color", initialValues.mat_color, colors.opts); + ensure("mat_opacity", initialValues.mat_opacity, opacs.opts); + + ensure("laser_soft", initialValues.laser_soft, soft.opts); + ensure("source", initialValues.source, srcs.opts); + + ensure("lens_conf", initialValues.lens_conf, conf.opts); + ensure("lens_apt", initialValues.lens_apt, apt.opts); + ensure("lens_exp", initialValues.lens_exp, exp.opts); + + ensure("lens", initialValues.lens, lens.opts); + }, [ + isEdit, + initialValues, + mats.opts, coats.opts, colors.opts, opacs.opts, + soft.opts, srcs.opts, + conf.opts, apt.opts, exp.opts, + lens.opts, + getValues, setValue, + ]); + + // Option lists (include current IDs to guarantee a visible option) const mats = useOptions("material", initialValues?.mat ?? null); const coats = useOptions("material_coating", initialValues?.mat_coat ?? null); const colors = useOptions("material_color", initialValues?.mat_color ?? null); @@ -255,34 +292,7 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV const apt = useOptions("laser_scan_lens_apt", initialValues?.lens_apt ?? null); const exp = useOptions("laser_scan_lens_exp", initialValues?.lens_exp ?? null); - // Re-apply select values when options hydrate (unchanged fix) - useEffect(() => { - const pairs: Array<[keyof any, string | null | undefined, Opt[]]> = [ - ["mat", initialValues?.mat, mats.opts], - ["mat_coat", initialValues?.mat_coat, coats.opts], - ["mat_color", initialValues?.mat_color, colors.opts], - ["mat_opacity", initialValues?.mat_opacity, opacs.opts], - ["laser_soft", initialValues?.laser_soft, soft.opts], - ["source", initialValues?.source, srcs.opts], - ["lens_conf", initialValues?.lens_conf, conf.opts], - ["lens_apt", initialValues?.lens_apt, apt.opts], - ["lens_exp", initialValues?.lens_exp, exp.opts], - ["lens", initialValues?.lens, lens.opts], - ]; - pairs.forEach(([name, id, opts]) => { - if (!id || !opts.length) return; - const current = getValues(String(name)); - if (!current) { - setValue(String(name), String(id), { shouldDirty: false, shouldValidate: false }); - } - }); - }, [ - mats.opts, coats.opts, colors.opts, opacs.opts, soft.opts, - srcs.opts, conf.opts, apt.opts, exp.opts, lens.opts, - initialValues, getValues, setValue - ]); - - // Files (unchanged) + // Image files const [photoFile, setPhotoFile] = useState(null); const [screenFile, setScreenFile] = useState(null); const onPick = (setter: (f: File | null) => void) => (e: React.ChangeEvent) => setter(e.target.files?.[0] ?? null); @@ -309,10 +319,11 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV lens: values.lens || null, focus: values.focus === "" ? null : globalThis.Number(values.focus), repeat_all: values.repeat_all === "" ? null : globalThis.Number(values.repeat_all), - // Repeaters + // Repeaters (raw pass-through; api will normalize nums/bools) fill_settings: values.fill_settings || [], line_settings: values.line_settings || [], raster_settings: values.raster_settings || [], + // If editing with existing asset IDs, the API will accept them ...(initialValues?.photo ? { photo: initialValues.photo } : {}), ...(initialValues?.screen ? { screen: initialValues.screen } : {}), }; @@ -344,17 +355,8 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV return (
- {/* Hide duplicate header in edit mode; keep visible in create mode */} - {!isEdit && ( -

- Submit CO₂ Galvo Setting -

- )} - {isEdit && ( -

- Edit CO₂ Galvo Setting -

- )} + {/* Hide local H1 in edit mode to avoid duplicate page title */} + {!isEdit &&

Submit CO₂ Galvo Setting

} {meLabel ?

Submitting as {meLabel}

: null} {submitErr ?
{submitErr}
: null}
@@ -402,7 +404,7 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV
- {/* Rig & Optics */} + {/* Rig & Optics (order per spec) */}

Rig & Optics

@@ -413,8 +415,8 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV
- +