submission form cleanup
This commit is contained in:
parent
01d16881d1
commit
1f5a44ea9f
1 changed files with 70 additions and 73 deletions
|
|
@ -55,7 +55,7 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV
|
||||||
const [me, setMe] = useState<Me>(null);
|
const [me, setMe] = useState<Me>(null);
|
||||||
const [submitErr, setSubmitErr] = useState<string | null>(null);
|
const [submitErr, setSubmitErr] = useState<string | null>(null);
|
||||||
|
|
||||||
// Robust current-user fetch (unchanged)
|
// Robust current-user fetch
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let alive = true;
|
let alive = true;
|
||||||
(async () => {
|
(async () => {
|
||||||
|
|
@ -84,7 +84,7 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV
|
||||||
return () => { alive = false; };
|
return () => { alive = false; };
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Options loaders (unchanged)
|
// Options loaders (Directus reads)
|
||||||
function useOptions(path: string, includeId?: string | null) {
|
function useOptions(path: string, includeId?: string | null) {
|
||||||
const [opts, setOpts] = useState<Opt[]>([]);
|
const [opts, setOpts] = useState<Opt[]>([]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -164,7 +164,7 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV
|
||||||
return { opts };
|
return { opts };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enumerations (unchanged)
|
// Enumerations
|
||||||
const FILL_TYPES: Opt[] = [
|
const FILL_TYPES: Opt[] = [
|
||||||
{ id: "uni", label: "UniDirectional" },
|
{ id: "uni", label: "UniDirectional" },
|
||||||
{ id: "bi", label: "BiDirectional" },
|
{ 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",
|
"threshold", "ordered", "atkinson", "dither", "stucki", "jarvis", "newsprint", "halftone", "sketch", "grayscale",
|
||||||
].map((x) => ({ id: x, label: x[0].toUpperCase() + x.slice(1) }));
|
].map((x) => ({ id: x, label: x[0].toUpperCase() + x.slice(1) }));
|
||||||
|
|
||||||
// react-hook-form (unchanged)
|
// react-hook-form
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
control,
|
control,
|
||||||
reset,
|
reset,
|
||||||
setValue,
|
getValues, // ⬅ added
|
||||||
getValues,
|
setValue, // ⬅ added
|
||||||
formState: { isSubmitting },
|
formState: { isSubmitting },
|
||||||
} = useForm<any>({
|
} = useForm<any>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
|
|
@ -197,6 +197,7 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV
|
||||||
// Rig & Optics
|
// Rig & Optics
|
||||||
laser_soft: "",
|
laser_soft: "",
|
||||||
source: "",
|
source: "",
|
||||||
|
// keep these blank so Select shows "—"
|
||||||
lens_conf: "",
|
lens_conf: "",
|
||||||
lens_apt: "",
|
lens_apt: "",
|
||||||
lens_exp: "",
|
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 fills = useFieldArray({ control, name: "fill_settings" });
|
||||||
const lines = useFieldArray({ control, name: "line_settings" });
|
const lines = useFieldArray({ control, name: "line_settings" });
|
||||||
const rasters = useFieldArray({ control, name: "raster_settings" });
|
const rasters = useFieldArray({ control, name: "raster_settings" });
|
||||||
|
|
||||||
// Prefill (unchanged)
|
// Prefill (edit)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isEdit || !initialValues) return;
|
if (!isEdit || !initialValues) return;
|
||||||
reset({
|
reset({
|
||||||
|
|
@ -243,7 +244,43 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV
|
||||||
});
|
});
|
||||||
}, [isEdit, initialValues, reset]);
|
}, [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 mats = useOptions("material", initialValues?.mat ?? null);
|
||||||
const coats = useOptions("material_coating", initialValues?.mat_coat ?? null);
|
const coats = useOptions("material_coating", initialValues?.mat_coat ?? null);
|
||||||
const colors = useOptions("material_color", initialValues?.mat_color ?? 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 apt = useOptions("laser_scan_lens_apt", initialValues?.lens_apt ?? null);
|
||||||
const exp = useOptions("laser_scan_lens_exp", initialValues?.lens_exp ?? null);
|
const exp = useOptions("laser_scan_lens_exp", initialValues?.lens_exp ?? null);
|
||||||
|
|
||||||
// Re-apply select values when options hydrate (unchanged fix)
|
// Image files
|
||||||
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)
|
|
||||||
const [photoFile, setPhotoFile] = useState<File | null>(null);
|
const [photoFile, setPhotoFile] = useState<File | null>(null);
|
||||||
const [screenFile, setScreenFile] = useState<File | null>(null);
|
const [screenFile, setScreenFile] = useState<File | null>(null);
|
||||||
const onPick = (setter: (f: File | null) => void) => (e: React.ChangeEvent<HTMLInputElement>) => setter(e.target.files?.[0] ?? null);
|
const onPick = (setter: (f: File | null) => void) => (e: React.ChangeEvent<HTMLInputElement>) => setter(e.target.files?.[0] ?? null);
|
||||||
|
|
@ -309,10 +319,11 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV
|
||||||
lens: values.lens || null,
|
lens: values.lens || null,
|
||||||
focus: values.focus === "" ? null : globalThis.Number(values.focus),
|
focus: values.focus === "" ? null : globalThis.Number(values.focus),
|
||||||
repeat_all: values.repeat_all === "" ? null : globalThis.Number(values.repeat_all),
|
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 || [],
|
fill_settings: values.fill_settings || [],
|
||||||
line_settings: values.line_settings || [],
|
line_settings: values.line_settings || [],
|
||||||
raster_settings: values.raster_settings || [],
|
raster_settings: values.raster_settings || [],
|
||||||
|
// If editing with existing asset IDs, the API will accept them
|
||||||
...(initialValues?.photo ? { photo: initialValues.photo } : {}),
|
...(initialValues?.photo ? { photo: initialValues.photo } : {}),
|
||||||
...(initialValues?.screen ? { screen: initialValues.screen } : {}),
|
...(initialValues?.screen ? { screen: initialValues.screen } : {}),
|
||||||
};
|
};
|
||||||
|
|
@ -344,17 +355,8 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV
|
||||||
return (
|
return (
|
||||||
<div className="space-y-5">
|
<div className="space-y-5">
|
||||||
<header className="space-y-1">
|
<header className="space-y-1">
|
||||||
{/* Hide duplicate header in edit mode; keep visible in create mode */}
|
{/* Hide local H1 in edit mode to avoid duplicate page title */}
|
||||||
{!isEdit && (
|
{!isEdit && <h1 className="text-xl font-semibold">Submit CO₂ Galvo Setting</h1>}
|
||||||
<h1 className="text-xl font-semibold">
|
|
||||||
Submit CO₂ Galvo Setting
|
|
||||||
</h1>
|
|
||||||
)}
|
|
||||||
{isEdit && (
|
|
||||||
<h2 className="text-lg font-semibold">
|
|
||||||
Edit CO₂ Galvo Setting
|
|
||||||
</h2>
|
|
||||||
)}
|
|
||||||
{meLabel ? <p className="text-sm text-muted-foreground">Submitting as {meLabel}</p> : null}
|
{meLabel ? <p className="text-sm text-muted-foreground">Submitting as {meLabel}</p> : null}
|
||||||
{submitErr ? <div className="border border-red-500 bg-red-50 text-red-700 rounded px-3 py-2 text-sm">{submitErr}</div> : null}
|
{submitErr ? <div className="border border-red-500 bg-red-50 text-red-700 rounded px-3 py-2 text-sm">{submitErr}</div> : null}
|
||||||
</header>
|
</header>
|
||||||
|
|
@ -402,7 +404,7 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Rig & Optics */}
|
{/* Rig & Optics (order per spec) */}
|
||||||
<section className="space-y-3">
|
<section className="space-y-3">
|
||||||
<h2 className="text-lg font-semibold">Rig & Optics</h2>
|
<h2 className="text-lg font-semibold">Rig & Optics</h2>
|
||||||
|
|
||||||
|
|
@ -413,8 +415,8 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV
|
||||||
|
|
||||||
<div className="grid md:grid-cols-3 gap-3">
|
<div className="grid md:grid-cols-3 gap-3">
|
||||||
<Select label="Lens Configuration" {...{ name: "lens_conf", register, options: conf.opts, required: true }} />
|
<Select label="Lens Configuration" {...{ name: "lens_conf", register, options: conf.opts, required: true }} />
|
||||||
<Select label="Scan Head Aperture (mm)" {...{ name: "lens_apt", register, options: apt.opts, required: true }} />
|
<Select label="Scan Head Aperture" {...{ name: "lens_apt", register, options: apt.opts, required: true }} />
|
||||||
<Select label="Beam Expander (X Magnification)" {...{ name: "lens_exp", register, options: exp.opts, required: true }} />
|
<Select label="Beam Expander" {...{ name: "lens_exp", register, options: exp.opts, required: true }} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid md:grid-cols-3 gap-3">
|
<div className="grid md:grid-cols-3 gap-3">
|
||||||
|
|
@ -435,7 +437,7 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV
|
||||||
onAdd={() => fills.append({ type: "" })}
|
onAdd={() => fills.append({ type: "" })}
|
||||||
onRemove={(i) => fills.remove(i)}
|
onRemove={(i) => fills.remove(i)}
|
||||||
render={(i) => {
|
render={(i) => {
|
||||||
const auto = !!useWatch({ control, name: `fill_settings.${i}.auto` });
|
const autoRotate = !!useWatch({ control, name: `fill_settings.${i}.auto` });
|
||||||
return (
|
return (
|
||||||
<div className="grid md:grid-cols-4 gap-2">
|
<div className="grid md:grid-cols-4 gap-2">
|
||||||
<Text label="Name" name={`fill_settings.${i}.name`} register={register} />
|
<Text label="Name" name={`fill_settings.${i}.name`} register={register} />
|
||||||
|
|
@ -448,16 +450,17 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV
|
||||||
<Number label="Pass" name={`fill_settings.${i}.pass`} register={register} step="1" />
|
<Number label="Pass" name={`fill_settings.${i}.pass`} register={register} step="1" />
|
||||||
<Number label="Angle (°)" name={`fill_settings.${i}.angle`} register={register} step="1" />
|
<Number label="Angle (°)" name={`fill_settings.${i}.angle`} register={register} step="1" />
|
||||||
|
|
||||||
{/* Booleans each on their own lines */}
|
{/* Move Auto first, then its increment in a half-width cell */}
|
||||||
<div className="col-span-full"><Check label="Auto Rotate" name={`fill_settings.${i}.auto`} register={register} /></div>
|
<Check label="Auto Rotate" name={`fill_settings.${i}.auto`} register={register} />
|
||||||
{auto && (
|
{autoRotate && (
|
||||||
<div className="col-span-full">
|
<div className="md:col-span-2">
|
||||||
<Number label="Auto Rotate Increment (°)" name={`fill_settings.${i}.increment`} register={register} step="0.001" />
|
<Number label="Auto Rotate Increment (°)" name={`fill_settings.${i}.increment`} register={register} step="0.001" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="col-span-full"><Check label="Crosshatch" name={`fill_settings.${i}.cross`} register={register} /></div>
|
|
||||||
<div className="col-span-full"><Check label="Flood Fill" name={`fill_settings.${i}.flood`} register={register} /></div>
|
<Check label="Crosshatch" name={`fill_settings.${i}.cross`} register={register} />
|
||||||
<div className="col-span-full"><Check label="Air Assist" name={`fill_settings.${i}.air`} register={register} /></div>
|
<Check label="Flood Fill" name={`fill_settings.${i}.flood`} register={register} />
|
||||||
|
<Check label="Air Assist" name={`fill_settings.${i}.air`} register={register} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
|
@ -480,12 +483,10 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV
|
||||||
<Number label="Power (%)" name={`line_settings.${i}.power`} register={register} step="0.1" />
|
<Number label="Power (%)" name={`line_settings.${i}.power`} register={register} step="0.1" />
|
||||||
<Number label="Speed (mm/s)" name={`line_settings.${i}.speed`} register={register} step="0.1" />
|
<Number label="Speed (mm/s)" name={`line_settings.${i}.speed`} register={register} step="0.1" />
|
||||||
|
|
||||||
{/* Pass BEFORE Perforation Mode (requested swap) */}
|
{/* Pass before perf per your last request */}
|
||||||
<Number label="Pass" name={`line_settings.${i}.pass`} register={register} step="1" />
|
<Number label="Pass" name={`line_settings.${i}.pass`} register={register} step="1" />
|
||||||
|
|
||||||
<div className="col-span-full">
|
|
||||||
<Check label="Perforation Mode" name={`line_settings.${i}.perf`} register={register} />
|
<Check label="Perforation Mode" name={`line_settings.${i}.perf`} register={register} />
|
||||||
</div>
|
|
||||||
{perf && (
|
{perf && (
|
||||||
<>
|
<>
|
||||||
<Number label="Cut (mm)" name={`line_settings.${i}.cut`} register={register} step="0.001" />
|
<Number label="Cut (mm)" name={`line_settings.${i}.cut`} register={register} step="0.001" />
|
||||||
|
|
@ -493,9 +494,7 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="col-span-full">
|
|
||||||
<Check label="Wobble" name={`line_settings.${i}.wobble`} register={register} />
|
<Check label="Wobble" name={`line_settings.${i}.wobble`} register={register} />
|
||||||
</div>
|
|
||||||
{wobble && (
|
{wobble && (
|
||||||
<>
|
<>
|
||||||
<Number label="Step (mm)" name={`line_settings.${i}.step`} register={register} step="0.001" />
|
<Number label="Step (mm)" name={`line_settings.${i}.step`} register={register} step="0.001" />
|
||||||
|
|
@ -503,7 +502,7 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="col-span-full"><Check label="Air Assist" name={`line_settings.${i}.air`} register={register} /></div>
|
<Check label="Air Assist" name={`line_settings.${i}.air`} register={register} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
|
@ -536,11 +535,9 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV
|
||||||
<Number label="Interval (mm)" name={`raster_settings.${i}.interval`} register={register} step="0.001" />
|
<Number label="Interval (mm)" name={`raster_settings.${i}.interval`} register={register} step="0.001" />
|
||||||
<Number label="Dot Width Adjustment (mm)" name={`raster_settings.${i}.dot`} register={register} step="0.1" />
|
<Number label="Dot Width Adjustment (mm)" name={`raster_settings.${i}.dot`} register={register} step="0.1" />
|
||||||
<Number label="Pass" name={`raster_settings.${i}.pass`} register={register} step="1" />
|
<Number label="Pass" name={`raster_settings.${i}.pass`} register={register} step="1" />
|
||||||
|
<Check label="Crosshatch" name={`raster_settings.${i}.cross`} register={register} />
|
||||||
{/* Booleans on their own lines */}
|
<Check label="Inverted" name={`raster_settings.${i}.inversion`} register={register} />
|
||||||
<div className="col-span-full"><Check label="Crosshatch" name={`raster_settings.${i}.cross`} register={register} /></div>
|
<Check label="Air Assist" name={`raster_settings.${i}.air`} register={register} />
|
||||||
<div className="col-span-full"><Check label="Inverted" name={`raster_settings.${i}.inversion`} register={register} /></div>
|
|
||||||
<div className="col-span-full"><Check label="Air Assist" name={`raster_settings.${i}.air`} register={register} /></div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
|
@ -555,7 +552,7 @@ export default function SettingsSubmit({ mode = "create", submissionId, initialV
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Small UI (unchanged) */
|
/* Small UI */
|
||||||
function Select({
|
function Select({
|
||||||
label,
|
label,
|
||||||
name,
|
name,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue