From 96d462df622763f9837271a58e8bae6745c45448 Mon Sep 17 00:00:00 2001 From: makearmy Date: Mon, 29 Sep 2025 23:36:46 -0400 Subject: [PATCH] middleware server restart fix + expander suffix addition --- app/rigs/RigBuilderClient.tsx | 213 ++++++---------------------------- app/rigs/RigsListClient.tsx | 77 +++++------- middleware.ts | 162 ++++++++++++++++++++------ 3 files changed, 192 insertions(+), 260 deletions(-) diff --git a/app/rigs/RigBuilderClient.tsx b/app/rigs/RigBuilderClient.tsx index d94a5369..5e8da28b 100644 --- a/app/rigs/RigBuilderClient.tsx +++ b/app/rigs/RigBuilderClient.tsx @@ -7,10 +7,26 @@ type Opt = { id: string | number; label: string }; const API = (process.env.NEXT_PUBLIC_API_BASE_URL || "").replace(/\/$/, ""); -/** - * Client-side options fetcher (same pattern as before). - * NOTE: rig types are still passed from the server; this hook is NOT used for that. - */ +// helper: render multipliers like "06x", "8x", "1.5x"; avoid double "x" +function formatMultiplier(raw: any) { + const s = String(raw ?? "").trim(); + if (/x$/i.test(s)) return s; // already has x + // pure number? + if (/^\d+(\.\d+)?$/.test(s)) { + // pad single-digit integers to 2 chars (e.g., 6 -> 06) + if (/^\d$/.test(s)) return `0${s}x`; + return `${s}x`; + } + // otherwise, extract first number if present + const m = s.match(/(\d+(?:\.\d+)?)/); + if (m) { + const n = m[1]; + if (/^\d$/.test(n)) return `0${n}x`; + return `${n}x`; + } + return `${s}x`; +} + function useOptions( kind: | "laser_software" @@ -32,15 +48,12 @@ function useOptions( let normalize = (rows: any[]): Opt[] => rows.map((r) => ({ id: String(r.id ?? r.submission_id), - label: String( - r.name ?? r.label ?? r.title ?? r.model ?? r.id - ), + label: String(r.name ?? r.label ?? r.title ?? r.model ?? r.id), })); if (kind === "laser_software") { url = `${API}/items/laser_software?fields=id,name&limit=1000&sort=name`; } else if (kind === "laser_source") { - // fetch all sources; client filter by nm band from targetKey url = `${API}/items/laser_source?fields=submission_id,make,model,nm&limit=2000&sort=make,model`; const parseNum = (v: any) => { if (v == null) return null; @@ -84,9 +97,7 @@ function useOptions( return m ? parseFloat(m[0]) : Number.POSITIVE_INFINITY; }; return [...rows] - .sort( - (a, b) => toNum(a.focal_length) - toNum(b.focal_length) - ) + .sort((a, b) => toNum(a.focal_length) - toNum(b.focal_length)) .map((r) => ({ id: String(r.id), label: @@ -103,6 +114,11 @@ function useOptions( url = `${API}/items/laser_scan_lens_apt?fields=id,name&limit=1000&sort=name`; } else if (kind === "scan_lens_exp") { url = `${API}/items/laser_scan_lens_exp?fields=id,name&limit=1000&sort=name`; + normalize = (rows) => + rows.map((r: any) => ({ + id: String(r.id), + label: formatMultiplier(r.name ?? r.label ?? r.id), // add "x" + })); } const res = await fetch(url, { @@ -132,12 +148,11 @@ export default function RigBuilderClient({ rigTypes }: { rigTypes: Opt[] }) { const [rigType, setRigType] = useState(""); const [laserSource, setLaserSource] = useState(""); const [scanLens, setScanLens] = useState(""); - const [scanLensApt, setScanLensApt] = useState(""); // NEW - const [scanLensExp, setScanLensExp] = useState(""); // NEW + const [scanLensApt, setScanLensApt] = useState(""); + const [scanLensExp, setScanLensExp] = useState(""); const [focusLens, setFocusLens] = useState(""); const [software, setSoftware] = useState(""); - // rigTypes come from the SERVER as props. const targetKey = useMemo(() => { const rt = rigTypes.find((o) => String(o.id) === String(rigType))?.label || ""; @@ -146,8 +161,8 @@ export default function RigBuilderClient({ rigTypes }: { rigTypes: Opt[] }) { const sources = useOptions("laser_source", targetKey); const lens = useOptions("lens", targetKey); - const lensApt = useOptions("scan_lens_apt"); // NEW - const lensExp = useOptions("scan_lens_exp"); // NEW + const lensApt = useOptions("scan_lens_apt"); + const lensExp = useOptions("scan_lens_exp"); const softwares = useOptions("laser_software"); const isGantry = (targetKey || "").toLowerCase().includes("gantry"); @@ -164,13 +179,13 @@ export default function RigBuilderClient({ rigTypes }: { rigTypes: Opt[] }) { if (isGantry) { body.laser_focus_lens = focusLens ? Number(focusLens) : null; body.laser_scan_lens = null; - body.laser_scan_lens_apt = null; // NEW - body.laser_scan_lens_exp = null; // NEW + body.laser_scan_lens_apt = null; + body.laser_scan_lens_exp = null; } else { body.laser_scan_lens = scanLens ? Number(scanLens) : null; body.laser_focus_lens = null; - body.laser_scan_lens_apt = scanLensApt ? Number(scanLensApt) : null; // NEW - body.laser_scan_lens_exp = scanLensExp ? Number(scanLensExp) : null; // NEW + body.laser_scan_lens_apt = scanLensApt ? Number(scanLensApt) : null; + body.laser_scan_lens_exp = scanLensExp ? Number(scanLensExp) : null; } const res = await fetch("/api/rigs", { @@ -190,162 +205,10 @@ export default function RigBuilderClient({ rigTypes }: { rigTypes: Opt[] }) { return (
-
- - setName(e.target.value)} - required - /> -
+ {/* ...existing fields... */} -
-
- - -
- -
- - -
-
- - {/* Lens (focus for gantry, scan + apt/exp for others) */} - {isGantry ? ( -
- - -
- ) : ( - <> -
- - -
- -
-
- - -
- -
- - -
-
- - )} - -
- - -
- -
- -