prefilled settings edits
This commit is contained in:
parent
7e9b5adfa8
commit
494f5525af
2 changed files with 259 additions and 227 deletions
|
|
@ -167,10 +167,12 @@ function useOptions(path: string) {
|
|||
}));
|
||||
};
|
||||
} else if (rawPath === "lens") {
|
||||
// CO2 gantry uses focus lenses; all others use scan lenses
|
||||
if (target === "co2-gantry") {
|
||||
url = `${API}/items/laser_focus_lens?fields=id,name&limit=1000`;
|
||||
normalize = (rows) => rows.map((r) => ({ id: String(r.id), label: String(r.name ?? r.id) }));
|
||||
} else {
|
||||
// SCAN LENSES (fiber, uv, co2-galvo): sort numerically by focal_length
|
||||
url = `${API}/items/laser_scan_lens?fields=id,field_size,focal_length&limit=1000`;
|
||||
normalize = (rows) => {
|
||||
const toNum = (v: any) => {
|
||||
|
|
@ -187,6 +189,7 @@ function useOptions(path: string) {
|
|||
};
|
||||
}
|
||||
} else {
|
||||
// unknown path → empty
|
||||
setOpts([]);
|
||||
setLoading(false);
|
||||
return;
|
||||
|
|
@ -198,6 +201,7 @@ function useOptions(path: string) {
|
|||
const rows = json?.data ?? [];
|
||||
const mapped = normalize(rows);
|
||||
|
||||
// client-side text filter
|
||||
const needle = (q || "").trim().toLowerCase();
|
||||
const filtered = needle ? mapped.filter((o) => o.label.toLowerCase().includes(needle)) : mapped;
|
||||
|
||||
|
|
@ -281,6 +285,43 @@ function BoolBox({ label, name, register }: { label: string; name: string; regis
|
|||
);
|
||||
}
|
||||
|
||||
function LabeledInput({
|
||||
label,
|
||||
name,
|
||||
type = "text",
|
||||
step,
|
||||
register,
|
||||
required = false,
|
||||
min,
|
||||
max,
|
||||
}: {
|
||||
label: string;
|
||||
name: string;
|
||||
type?: "text" | "number";
|
||||
step?: string | number;
|
||||
register: UseFormRegister<any>;
|
||||
required?: boolean;
|
||||
min?: number;
|
||||
max?: number;
|
||||
}) {
|
||||
return (
|
||||
<div>
|
||||
<label className="block text-xs mb-1">
|
||||
{label}
|
||||
{required ? " *" : ""}
|
||||
</label>
|
||||
<input
|
||||
type={type}
|
||||
step={step}
|
||||
min={min}
|
||||
max={max}
|
||||
className="w-full border rounded px-2 py-1"
|
||||
{...register(name, { required })}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// Component
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
|
|
@ -289,11 +330,12 @@ export default function SettingsSubmit(props: CreateProps | EditProps) {
|
|||
const sp = useSearchParams();
|
||||
|
||||
const isEdit = isEditProps(props);
|
||||
const edit = isEdit ? props : null;
|
||||
const edit = isEdit ? props : null; // strongly-typed local when edit
|
||||
|
||||
const initialFromQuery = (sp.get("target") as Target) || props.initialTarget || "settings_fiber";
|
||||
const [target, setTarget] = useState<Target>(initialFromQuery);
|
||||
|
||||
// Map collection -> slug used by options selectors
|
||||
const typeForOptions = useMemo(() => {
|
||||
switch (target) {
|
||||
case "settings_fiber":
|
||||
|
|
@ -325,6 +367,7 @@ export default function SettingsSubmit(props: CreateProps | EditProps) {
|
|||
useEffect(() => {
|
||||
let alive = true;
|
||||
|
||||
// use our bearer-only API
|
||||
fetch(`/api/me`, { cache: "no-store", credentials: "include" })
|
||||
.then((r) => (r.ok ? r.json() : Promise.reject(r)))
|
||||
.then((j) => {
|
||||
|
|
@ -347,12 +390,13 @@ export default function SettingsSubmit(props: CreateProps | EditProps) {
|
|||
const coats = useOptions("material_coating");
|
||||
const colors = useOptions("material_color");
|
||||
const opacs = useOptions("material_opacity");
|
||||
const soft = useOptions("laser_software");
|
||||
const soft = useOptions("laser_software"); // required for ALL targets
|
||||
|
||||
// these two need ?target=
|
||||
const srcs = useOptions(`laser_source?target=${typeForOptions}`);
|
||||
const lens = useOptions(`lens?target=${typeForOptions}`);
|
||||
|
||||
// Repeater choice options (LOCAL)
|
||||
// Repeater choice options (LOCAL now, no network)
|
||||
const fillType = { opts: toOpts(FILL_TYPE_OPTIONS), loading: false, setQ: (_: string) => {} };
|
||||
const rasterType = { opts: toOpts(RASTER_TYPE_OPTIONS), loading: false, setQ: (_: string) => {} };
|
||||
const rasterDither = { opts: toOpts(RASTER_DITHER_OPTIONS), loading: false, setQ: (_: string) => {} };
|
||||
|
|
@ -376,7 +420,7 @@ export default function SettingsSubmit(props: CreateProps | EditProps) {
|
|||
lens: "",
|
||||
focus: "",
|
||||
laser_soft: "",
|
||||
repeat_all: "",
|
||||
repeat_all: "", // on all targets
|
||||
fill_settings: [],
|
||||
line_settings: [],
|
||||
raster_settings: [],
|
||||
|
|
@ -387,30 +431,29 @@ export default function SettingsSubmit(props: CreateProps | EditProps) {
|
|||
const lines = useFieldArray({ control, name: "line_settings" });
|
||||
const rasters = useFieldArray({ control, name: "raster_settings" });
|
||||
|
||||
// ✅ Prefill when editing
|
||||
// Prefill the form in edit mode
|
||||
useEffect(() => {
|
||||
if (!isEdit || !edit?.initialValues) return;
|
||||
|
||||
const S = (v: any) => (v == null ? "" : String(v));
|
||||
|
||||
reset({
|
||||
setting_title: edit.initialValues.setting_title ?? "",
|
||||
setting_notes: edit.initialValues.setting_notes ?? "",
|
||||
mat: S(edit.initialValues.mat),
|
||||
mat_coat: S(edit.initialValues.mat_coat),
|
||||
mat_color: S(edit.initialValues.mat_color),
|
||||
mat_opacity: S(edit.initialValues.mat_opacity),
|
||||
mat_thickness: edit.initialValues.mat_thickness ?? "",
|
||||
source: S(edit.initialValues.source),
|
||||
lens: S(edit.initialValues.lens),
|
||||
focus: edit.initialValues.focus ?? "",
|
||||
laser_soft: S(edit.initialValues.laser_soft),
|
||||
repeat_all: edit.initialValues.repeat_all ?? "",
|
||||
fill_settings: edit.initialValues.fill_settings ?? [],
|
||||
line_settings: edit.initialValues.line_settings ?? [],
|
||||
raster_settings: edit.initialValues.raster_settings ?? [],
|
||||
});
|
||||
// we keep previews empty; “Current: <id>” is shown below file inputs
|
||||
if (isEdit && edit?.initialValues) {
|
||||
reset({
|
||||
setting_title: edit.initialValues.setting_title ?? "",
|
||||
setting_notes: edit.initialValues.setting_notes ?? "",
|
||||
photo: edit.initialValues.photo ?? null,
|
||||
screen: edit.initialValues.screen ?? null,
|
||||
mat: edit.initialValues.mat ?? "",
|
||||
mat_coat: edit.initialValues.mat_coat ?? "",
|
||||
mat_color: edit.initialValues.mat_color ?? "",
|
||||
mat_opacity: edit.initialValues.mat_opacity ?? "",
|
||||
mat_thickness: edit.initialValues.mat_thickness ?? "",
|
||||
source: edit.initialValues.source ?? "",
|
||||
lens: edit.initialValues.lens ?? "",
|
||||
focus: edit.initialValues.focus ?? "",
|
||||
laser_soft: edit.initialValues.laser_soft ?? "",
|
||||
repeat_all: edit.initialValues.repeat_all ?? "",
|
||||
fill_settings: edit.initialValues.fill_settings ?? [],
|
||||
line_settings: edit.initialValues.line_settings ?? [],
|
||||
raster_settings: edit.initialValues.raster_settings ?? [],
|
||||
});
|
||||
}
|
||||
}, [isEdit, edit?.initialValues, reset]);
|
||||
|
||||
function num(v: any) {
|
||||
|
|
@ -421,10 +464,10 @@ export default function SettingsSubmit(props: CreateProps | EditProps) {
|
|||
async function onSubmit(values: any) {
|
||||
setSubmitErr(null);
|
||||
|
||||
// In edit mode, allow keeping the existing photo (no new file) if one exists.
|
||||
const hasExistingPhotoId =
|
||||
!!(isEdit && typeof edit?.initialValues?.photo === "string" && edit?.initialValues?.photo);
|
||||
|
||||
if (!photoFile && !hasExistingPhotoId) {
|
||||
!!(isEdit && typeof edit!.initialValues?.photo === "string" && edit!.initialValues.photo);
|
||||
if (!photoFile && !hasExistingPhotoId && !isEdit) {
|
||||
(document.querySelector('input[type="file"][data-role="photo"]') as HTMLInputElement | null)?.focus();
|
||||
return;
|
||||
}
|
||||
|
|
@ -441,8 +484,8 @@ export default function SettingsSubmit(props: CreateProps | EditProps) {
|
|||
source: values.source || null,
|
||||
lens: values.lens || null,
|
||||
focus: num(values.focus),
|
||||
laser_soft: values.laser_soft || null,
|
||||
repeat_all: num(values.repeat_all),
|
||||
laser_soft: values.laser_soft || null, // all targets
|
||||
repeat_all: num(values.repeat_all), // all targets
|
||||
fill_settings: (values.fill_settings || []).map((r: any) => ({
|
||||
name: r.name || "",
|
||||
power: num(r.power),
|
||||
|
|
@ -493,10 +536,10 @@ export default function SettingsSubmit(props: CreateProps | EditProps) {
|
|||
})),
|
||||
};
|
||||
|
||||
// ✅ Tell the API we're editing and which record to patch
|
||||
if (isEdit) {
|
||||
// Ensure EDIT gets routed as a PATCH via the API
|
||||
if (isEdit && edit?.submissionId != null) {
|
||||
payload.mode = "edit";
|
||||
payload.submission_id = edit!.submissionId;
|
||||
payload.submission_id = edit.submissionId;
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -520,11 +563,12 @@ export default function SettingsSubmit(props: CreateProps | EditProps) {
|
|||
const data = await res.json().catch(() => ({}));
|
||||
if (!res.ok) {
|
||||
if (res.status === 401 || res.status === 403) throw new Error("You must be signed in to submit settings.");
|
||||
throw new Error(data?.error || "Submission failed");
|
||||
throw new Error((data as any)?.error || "Submission failed");
|
||||
}
|
||||
|
||||
// Reset only on create; for edit, keep values visible
|
||||
// Success
|
||||
if (!isEdit) {
|
||||
// reset only on create
|
||||
reset();
|
||||
setPhotoFile(null);
|
||||
setScreenFile(null);
|
||||
|
|
@ -532,11 +576,16 @@ export default function SettingsSubmit(props: CreateProps | EditProps) {
|
|||
setScreenPreview("");
|
||||
}
|
||||
|
||||
const id = data?.id ? String(data.id) : String(edit?.submissionId ?? "");
|
||||
const next = isEdit
|
||||
? `/submit/settings/success?target=${encodeURIComponent(target)}&id=${encodeURIComponent(id)}`
|
||||
: `/submit/settings/success?target=${encodeURIComponent(target)}&id=${encodeURIComponent(id)}`;
|
||||
router.push(next);
|
||||
const id = (data as any)?.id ? String((data as any).id) : String(edit?.submissionId ?? "");
|
||||
// back to success (create) or view (edit)
|
||||
if (isEdit) {
|
||||
// remove ?edit=1
|
||||
const q = new URLSearchParams(sp.toString());
|
||||
q.delete("edit");
|
||||
router.replace(`/portal/laser-settings?${q.toString()}`);
|
||||
} else {
|
||||
router.push(`/submit/settings/success?target=${encodeURIComponent(target)}&id=${encodeURIComponent(id)}`);
|
||||
}
|
||||
} catch (e: any) {
|
||||
setSubmitErr(e?.message || "Submission failed");
|
||||
}
|
||||
|
|
@ -553,14 +602,15 @@ export default function SettingsSubmit(props: CreateProps | EditProps) {
|
|||
reader.readAsDataURL(file);
|
||||
}
|
||||
|
||||
// Convenience strings for “Current:” (edit mode)
|
||||
const currentPhotoId =
|
||||
isEdit && typeof edit?.initialValues?.photo === "string" ? edit!.initialValues!.photo : null;
|
||||
isEdit && typeof edit.initialValues?.photo === "string" ? (edit.initialValues.photo as string) : null;
|
||||
const currentScreenId =
|
||||
isEdit && typeof edit?.initialValues?.screen === "string" ? edit!.initialValues!.screen : null;
|
||||
isEdit && typeof edit.initialValues?.screen === "string" ? (edit.initialValues.screen as string) : null;
|
||||
|
||||
return (
|
||||
<div className="max-w-3xl mx-auto space-y-4">
|
||||
{/* Target + Software */}
|
||||
{/* Target + Software (Software required for ALL targets) */}
|
||||
<div className="flex flex-wrap gap-3 items-end">
|
||||
<div>
|
||||
<label className="block text-sm mb-1">Target</label>
|
||||
|
|
@ -619,7 +669,7 @@ export default function SettingsSubmit(props: CreateProps | EditProps) {
|
|||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm mb-1">
|
||||
Result Photo <span className="text-red-600">*</span>
|
||||
Result Photo {isEdit ? null : <span className="text-red-600">*</span>}
|
||||
</label>
|
||||
|
||||
{currentPhotoId && (
|
||||
|
|
@ -632,14 +682,12 @@ export default function SettingsSubmit(props: CreateProps | EditProps) {
|
|||
type="file"
|
||||
accept="image/*"
|
||||
data-role="photo"
|
||||
required={!currentPhotoId}
|
||||
required={!isEdit && !currentPhotoId}
|
||||
onChange={(e) => onPick(e.target.files?.[0] ?? null, setPhotoFile, setPhotoPreview)}
|
||||
/>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
{photoFile ? (
|
||||
<>
|
||||
Selected: <span className="font-mono">{photoFile.name}</span>
|
||||
</>
|
||||
<>Selected: <span className="font-mono">{photoFile.name}</span></>
|
||||
) : (
|
||||
"Max 25 MB. JPG/PNG/WebP recommended."
|
||||
)}
|
||||
|
|
@ -663,9 +711,7 @@ export default function SettingsSubmit(props: CreateProps | EditProps) {
|
|||
/>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
{screenFile ? (
|
||||
<>
|
||||
Selected: <span className="font-mono">{screenFile.name}</span>
|
||||
</>
|
||||
<>Selected: <span className="font-mono">{screenFile.name}</span></>
|
||||
) : (
|
||||
"Max 25 MB. JPG/PNG/WebP recommended."
|
||||
)}
|
||||
|
|
@ -740,49 +786,23 @@ export default function SettingsSubmit(props: CreateProps | EditProps) {
|
|||
|
||||
{/* Focus, thickness, repeat_all */}
|
||||
<div className="grid md:grid-cols-3 gap-3">
|
||||
<div>
|
||||
<label className="block text-sm mb-1">Material Thickness (mm)</label>
|
||||
<input type="number" step="0.01" className="w-full border rounded px-2 py-1" {...register("mat_thickness")} />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm mb-1">
|
||||
Focus (mm) <span className="text-red-600">*</span>
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
min={-10}
|
||||
max={10}
|
||||
step="1"
|
||||
className="w-full border rounded px-2 py-1"
|
||||
{...register("focus", { required: true })}
|
||||
/>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
0 = in focus. Negative = focus closer. Positive = focus further.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm mb-1">
|
||||
Repeat All <span className="text-red-600">*</span>
|
||||
</label>
|
||||
<input type="number" step="1" className="w-full border rounded px-2 py-1" {...register("repeat_all", { required: true })} />
|
||||
</div>
|
||||
<LabeledInput label="Material Thickness (mm)" name="mat_thickness" type="number" step="0.01" register={register} />
|
||||
<LabeledInput label="Focus (mm)" name="focus" type="number" min={-10} max={10} step="1" register={register} required />
|
||||
<LabeledInput label="Repeat All" name="repeat_all" type="number" step="1" register={register} required />
|
||||
<p className="text-xs text-muted-foreground md:col-span-3">0 = in focus. Negative = focus closer. Positive = focus further.</p>
|
||||
</div>
|
||||
|
||||
{/* FILL */}
|
||||
<fieldset className="border rounded p-3 space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<legend className="font-semibold">Fill Settings</legend>
|
||||
<button
|
||||
type="button"
|
||||
className="px-2 py-1 border rounded"
|
||||
onClick={() => fills.append({ type: "uni" })}
|
||||
>
|
||||
<button type="button" className="px-2 py-1 border rounded" onClick={() => fills.append({ type: "uni" })}>
|
||||
+ Add
|
||||
</button>
|
||||
</div>
|
||||
{fills.fields.map((f, i) => (
|
||||
<div key={f.id} className="grid md:grid-cols-4 gap-2">
|
||||
<input placeholder="Name" className="border rounded px-2 py-1 md:col-span-2" {...register(`fill_settings.${i}.name`)} />
|
||||
<LabeledInput label="Name" name={`fill_settings.${i}.name`} register={register} />
|
||||
<FilterableSelect
|
||||
label="Type"
|
||||
name={`fill_settings.${i}.type`}
|
||||
|
|
@ -792,14 +812,14 @@ export default function SettingsSubmit(props: CreateProps | EditProps) {
|
|||
onQuery={() => {}}
|
||||
placeholder="Select type"
|
||||
/>
|
||||
<input placeholder="Frequency (kHz)" type="number" step="0.1" className="border rounded px-2 py-1" {...register(`fill_settings.${i}.frequency`)} />
|
||||
<input placeholder="Pulse (ns)" type="number" step="0.1" className="border rounded px-2 py-1" {...register(`fill_settings.${i}.pulse`)} />
|
||||
<input placeholder="Power (%)" type="number" step="0.1" className="border rounded px-2 py-1" {...register(`fill_settings.${i}.power`)} />
|
||||
<input placeholder="Speed (mm/s)" type="number" step="0.1" className="border rounded px-2 py-1" {...register(`fill_settings.${i}.speed`)} />
|
||||
<input placeholder="Interval (mm)" type="number" step="0.001" className="border rounded px-2 py-1" {...register(`fill_settings.${i}.interval`)} />
|
||||
<input placeholder="Pass" type="number" step="1" className="border rounded px-2 py-1" {...register(`fill_settings.${i}.pass`)} />
|
||||
<input placeholder="Angle (°)" type="number" step="1" className="border rounded px-2 py-1" {...register(`fill_settings.${i}.angle`)} />
|
||||
<input placeholder="Increment" type="number" step="0.001" className="border rounded px-2 py-1" {...register(`fill_settings.${i}.increment`)} />
|
||||
<LabeledInput label="Frequency (kHz)" name={`fill_settings.${i}.frequency`} type="number" step="0.1" register={register} />
|
||||
<LabeledInput label="Pulse (ns)" name={`fill_settings.${i}.pulse`} type="number" step="0.1" register={register} />
|
||||
<LabeledInput label="Power (%)" name={`fill_settings.${i}.power`} type="number" step="0.1" register={register} />
|
||||
<LabeledInput label="Speed (mm/s)" name={`fill_settings.${i}.speed`} type="number" step="0.1" register={register} />
|
||||
<LabeledInput label="Interval (mm)" name={`fill_settings.${i}.interval`} type="number" step="0.001" register={register} />
|
||||
<LabeledInput label="Pass" name={`fill_settings.${i}.pass`} type="number" step="1" register={register} />
|
||||
<LabeledInput label="Angle (°)" name={`fill_settings.${i}.angle`} type="number" step="1" register={register} />
|
||||
<LabeledInput label="Increment" name={`fill_settings.${i}.increment`} type="number" step="0.001" register={register} />
|
||||
<div className="flex items-center gap-3">
|
||||
<BoolBox label="Auto" name={`fill_settings.${i}.auto`} register={register} />
|
||||
<BoolBox label="Cross" name={`fill_settings.${i}.cross`} register={register} />
|
||||
|
|
@ -826,17 +846,17 @@ export default function SettingsSubmit(props: CreateProps | EditProps) {
|
|||
</div>
|
||||
{lines.fields.map((f, i) => (
|
||||
<div key={f.id} className="grid md:grid-cols-4 gap-2">
|
||||
<input placeholder="Name" className="border rounded px-2 py-1 md:col-span-2" {...register(`line_settings.${i}.name`)} />
|
||||
<input placeholder="Frequency (kHz)" type="number" step="0.1" className="border rounded px-2 py-1" {...register(`line_settings.${i}.frequency`)} />
|
||||
<input placeholder="Pulse (ns)" type="number" step="0.1" className="border rounded px-2 py-1" {...register(`line_settings.${i}.pulse`)} />
|
||||
<input placeholder="Power (%)" type="number" step="0.1" className="border rounded px-2 py-1" {...register(`line_settings.${i}.power`)} />
|
||||
<input placeholder="Speed (mm/s)" type="number" step="0.1" className="border rounded px-2 py-1" {...register(`line_settings.${i}.speed`)} />
|
||||
<input placeholder="Perf" className="border rounded px-2 py-1" {...register(`line_settings.${i}.perf`)} />
|
||||
<input placeholder="Cut" className="border rounded px-2 py-1" {...register(`line_settings.${i}.cut`)} />
|
||||
<input placeholder="Skip" className="border rounded px-2 py-1" {...register(`line_settings.${i}.skip`)} />
|
||||
<input placeholder="Pass" type="number" step="1" className="border rounded px-2 py-1" {...register(`line_settings.${i}.pass`)} />
|
||||
<input placeholder="Step" type="number" step="0.001" className="border rounded px-2 py-1" {...register(`line_settings.${i}.step`)} />
|
||||
<input placeholder="Size" type="number" step="0.001" className="border rounded px-2 py-1" {...register(`line_settings.${i}.size`)} />
|
||||
<LabeledInput label="Name" name={`line_settings.${i}.name`} register={register} />
|
||||
<LabeledInput label="Frequency (kHz)" name={`line_settings.${i}.frequency`} type="number" step="0.1" register={register} />
|
||||
<LabeledInput label="Pulse (ns)" name={`line_settings.${i}.pulse`} type="number" step="0.1" register={register} />
|
||||
<LabeledInput label="Power (%)" name={`line_settings.${i}.power`} type="number" step="0.1" register={register} />
|
||||
<LabeledInput label="Speed (mm/s)" name={`line_settings.${i}.speed`} type="number" step="0.1" register={register} />
|
||||
<LabeledInput label="Perf" name={`line_settings.${i}.perf`} register={register} />
|
||||
<LabeledInput label="Cut" name={`line_settings.${i}.cut`} register={register} />
|
||||
<LabeledInput label="Skip" name={`line_settings.${i}.skip`} register={register} />
|
||||
<LabeledInput label="Pass" name={`line_settings.${i}.pass`} type="number" step="1" register={register} />
|
||||
<LabeledInput label="Step" name={`line_settings.${i}.step`} type="number" step="0.001" register={register} />
|
||||
<LabeledInput label="Size" name={`line_settings.${i}.size`} type="number" step="0.001" register={register} />
|
||||
<BoolBox label="Wobble" name={`line_settings.${i}.wobble`} register={register} />
|
||||
<BoolBox label="Air" name={`line_settings.${i}.air`} register={register} />
|
||||
|
||||
|
|
@ -861,9 +881,9 @@ export default function SettingsSubmit(props: CreateProps | EditProps) {
|
|||
</div>
|
||||
{rasters.fields.map((f, i) => (
|
||||
<div key={f.id} className="grid md:grid-cols-4 gap-2">
|
||||
<input placeholder="Name" className="border rounded px-2 py-1 md:col-span-2" {...register(`raster_settings.${i}.name`)} />
|
||||
<input placeholder="Frequency (kHz)" type="number" step="0.1" className="border rounded px-2 py-1" {...register(`raster_settings.${i}.frequency`)} />
|
||||
<input placeholder="Pulse (ns)" type="number" step="0.1" className="border rounded px-2 py-1" {...register(`raster_settings.${i}.pulse`)} />
|
||||
<LabeledInput label="Name" name={`raster_settings.${i}.name`} register={register} />
|
||||
<LabeledInput label="Frequency (kHz)" name={`raster_settings.${i}.frequency`} type="number" step="0.1" register={register} />
|
||||
<LabeledInput label="Pulse (ns)" name={`raster_settings.${i}.pulse`} type="number" step="0.1" register={register} />
|
||||
<FilterableSelect
|
||||
label="Type"
|
||||
name={`raster_settings.${i}.type`}
|
||||
|
|
@ -882,13 +902,13 @@ export default function SettingsSubmit(props: CreateProps | EditProps) {
|
|||
onQuery={() => {}}
|
||||
placeholder="Select dither"
|
||||
/>
|
||||
<input placeholder="Power (%)" type="number" step="0.1" className="border rounded px-2 py-1" {...register(`raster_settings.${i}.power`)} />
|
||||
<input placeholder="Speed (mm/s)" type="number" step="0.1" className="border rounded px-2 py-1" {...register(`raster_settings.${i}.speed`)} />
|
||||
<input placeholder="Halftone Cell" type="number" step="1" className="border rounded px-2 py-1" {...register(`raster_settings.${i}.halftone_cell`)} />
|
||||
<input placeholder="Halftone Angle" type="number" step="1" className="border rounded px-2 py-1" {...register(`raster_settings.${i}.halftone_angle`)} />
|
||||
<input placeholder="Interval (mm)" type="number" step="0.001" className="border rounded px-2 py-1" {...register(`raster_settings.${i}.interval`)} />
|
||||
<input placeholder="Dot" type="number" step="0.1" className="border rounded px-2 py-1" {...register(`raster_settings.${i}.dot`)} />
|
||||
<input placeholder="Pass" type="number" step="1" className="border rounded px-2 py-1" {...register(`raster_settings.${i}.pass`)} />
|
||||
<LabeledInput label="Power (%)" name={`raster_settings.${i}.power`} type="number" step="0.1" register={register} />
|
||||
<LabeledInput label="Speed (mm/s)" name={`raster_settings.${i}.speed`} type="number" step="0.1" register={register} />
|
||||
<LabeledInput label="Halftone Cell" name={`raster_settings.${i}.halftone_cell`} type="number" step="1" register={register} />
|
||||
<LabeledInput label="Halftone Angle" name={`raster_settings.${i}.halftone_angle`} type="number" step="1" register={register} />
|
||||
<LabeledInput label="Interval (mm)" name={`raster_settings.${i}.interval`} type="number" step="0.001" register={register} />
|
||||
<LabeledInput label="Dot" name={`raster_settings.${i}.dot`} type="number" step="0.1" register={register} />
|
||||
<LabeledInput label="Pass" name={`raster_settings.${i}.pass`} type="number" step="1" register={register} />
|
||||
<BoolBox label="Cross" name={`raster_settings.${i}.cross`} register={register} />
|
||||
<div className="flex items-center gap-3">
|
||||
<BoolBox label="Inversion" name={`raster_settings.${i}.inversion`} register={register} />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue