From a1d14fb6baedcc68782b826daec2c15b56aad8a2 Mon Sep 17 00:00:00 2001 From: makearmy Date: Fri, 26 Sep 2025 18:30:40 -0400 Subject: [PATCH] build failure fixes --- app/my/rigs/RigBuilderClient.tsx | 369 ++++++++++++++++++++++++++++++ app/my/rigs/page.tsx | 372 +------------------------------ 2 files changed, 374 insertions(+), 367 deletions(-) create mode 100644 app/my/rigs/RigBuilderClient.tsx diff --git a/app/my/rigs/RigBuilderClient.tsx b/app/my/rigs/RigBuilderClient.tsx new file mode 100644 index 00000000..df01e4af --- /dev/null +++ b/app/my/rigs/RigBuilderClient.tsx @@ -0,0 +1,369 @@ +// app/my/rigs/RigBuilderClient.tsx +"use client"; + +import { useEffect, useMemo, useState } from "react"; +import { z } from "zod"; +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; + +import { useToast } from "@/hooks/use-toast"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { + Select, + SelectTrigger, + SelectContent, + SelectItem, + SelectValue, +} from "@/components/ui/select"; +import { Textarea } from "@/components/ui/textarea"; +import { Badge } from "@/components/ui/badge"; + +type RigType = { id: number | string; name: string }; +export default function RigBuilderClient({ rigTypes }: { rigTypes: RigType[] }) { + const { toast } = useToast(); + + const FormSchema = z.object({ + name: z.string().min(2, "Please enter a name"), + rig_type: z.string().min(1, "Choose a rig type"), + laser_source: z.string().optional().nullable(), + laser_focus_lens: z.string().optional().nullable(), + laser_scan_lens: z.string().optional().nullable(), + laser_scan_lens_apt: z.string().optional().nullable(), + laser_scan_lens_exp: z.string().optional().nullable(), + laser_software: z.string().optional().nullable(), + notes: z.string().optional().nullable(), + }); + type FormValues = z.infer; + + const form = useForm({ + resolver: zodResolver(FormSchema), + defaultValues: { + name: "", + rig_type: "", + notes: "", + }, + }); + + const selectedTypeName = useMemo(() => { + const v = form.watch("rig_type"); + return rigTypes.find((r) => String(r.id) === String(v))?.name ?? ""; + }, [form, rigTypes]); + + // Option lists (pulled from your existing endpoints) + const [laserSources, setLaserSources] = useState<{ id: string; label: string }[]>([]); + const [scanLenses, setScanLenses] = useState<{ id: string; label: string }[]>([]); + const [focusLenses, setFocusLenses] = useState<{ id: string; label: string }[]>([]); + const [softwares, setSoftwares] = useState<{ id: string; label: string }[]>([]); + + useEffect(() => { + (async () => { + try { + const ls = await fetch("/api/options/laser_source").then((r) => r.json()); + setLaserSources(ls?.data ?? []); + } catch {} + try { + const sl = await fetch("/api/options/lens?target=settings_fiber").then((r) => r.json()); + setScanLenses(sl?.data ?? []); + } catch {} + try { + const fl = await fetch("/api/options/repeater-choices?key=laser_focus_lens").then((r) => + r.json() + ); + setFocusLenses(fl?.data ?? []); + } catch {} + try { + const sw = await fetch("/api/options/repeater-choices?key=laser_software").then((r) => + r.json() + ); + setSoftwares(sw?.data ?? []); + } catch {} + })(); + }, []); + + const coerceId = (v: unknown) => { + if (typeof v === "number") return v; + if (typeof v === "string" && v !== "") { + const n = Number(v); + return Number.isFinite(n) ? n : v; + } + return v ?? null; + }; + + async function onSubmit(values: FormValues) { + try { + const payload = { + name: values.name, + rig_type: coerceId(values.rig_type), // IMPORTANT: send ID + laser_source: values.laser_source ? coerceId(values.laser_source) : null, + laser_focus_lens: + selectedTypeName === "co2_gantry" && values.laser_focus_lens + ? coerceId(values.laser_focus_lens) + : null, + laser_scan_lens: + selectedTypeName !== "co2_gantry" && values.laser_scan_lens + ? coerceId(values.laser_scan_lens) + : null, + laser_scan_lens_apt: + selectedTypeName !== "co2_gantry" && values.laser_scan_lens_apt + ? values.laser_scan_lens_apt + : null, + laser_scan_lens_exp: + selectedTypeName !== "co2_gantry" && values.laser_scan_lens_exp + ? values.laser_scan_lens_exp + : null, + laser_software: values.laser_software ? coerceId(values.laser_software) : null, + notes: values.notes ?? null, + }; + + const res = await fetch("/api/my/rigs", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(payload), + }); + + const json = await res.json().catch(() => ({})); + if (!res.ok) { + throw new Error(json?.error || json?.errors?.[0]?.message || res.statusText); + } + + toast({ title: "Saved!", description: `Rig created (id: ${json?.data?.id ?? "?"}).` }); + form.reset({ name: "", rig_type: "", notes: "" }); + document.dispatchEvent(new CustomEvent("rigs:refresh")); + } catch (err: any) { + toast({ + title: "Failed to save rig", + description: String(err?.message || err), + variant: "destructive", + }); + } + } + + return ( + <> +
+
+

New Rig

+ {selectedTypeName ? {selectedTypeName} : null} +
+ +
+ {/* Name */} +
+ + + {form.formState.errors.name ? ( +

{form.formState.errors.name.message}

+ ) : null} +
+ + {/* Rig Type (ID values) */} +
+ + + {form.formState.errors.rig_type ? ( +

{form.formState.errors.rig_type.message}

+ ) : null} +
+ + {/* Source */} +
+ + +
+ + {/* Software */} +
+ + +
+ + {/* Focus lens – only for co2_gantry */} + {selectedTypeName === "co2_gantry" && ( +
+ + +
+ )} + + {/* Scan lens fields – for fiber/uv/co2_galvo */} + {selectedTypeName && selectedTypeName !== "co2_gantry" && ( + <> +
+ + +
+ +
+ + +
+ +
+ + +
+ + )} + +
+ +