From 4b416b01e7e618137fd7954ec6193b02bb34a7f3 Mon Sep 17 00:00:00 2001 From: makearmy Date: Tue, 30 Sep 2025 00:20:56 -0400 Subject: [PATCH] build error fix --- app/lasers/[id]/LaserDetailsClient.tsx | 162 ++++--------------------- 1 file changed, 24 insertions(+), 138 deletions(-) diff --git a/app/lasers/[id]/LaserDetailsClient.tsx b/app/lasers/[id]/LaserDetailsClient.tsx index f2beb2d0..10e3b4e7 100644 --- a/app/lasers/[id]/LaserDetailsClient.tsx +++ b/app/lasers/[id]/LaserDetailsClient.tsx @@ -1,161 +1,47 @@ -'use client'; +// app/lasers/[id]/LaserDetailsClient.tsx +"use client"; -import { useEffect, useMemo, useState } from 'react'; -import { useParams } from 'next/navigation'; -import Link from 'next/link'; +import Link from "next/link"; +type Group = { title: string; fields: Record }; type Laser = Record; -const API = (process.env.NEXT_PUBLIC_API_BASE_URL || '').replace(/\/$/, ''); - -// Human labels for select-ish fields we render. -// Extend this as needed if you add more enums to the UI. const CHOICE_LABELS: Record> = { - op: { - pm: 'MOPA', - pq: 'Q-Switch', - }, - cooling: { - aa: 'Air, Active', - ap: 'Air, Passive', - w: 'Water', - }, + op: { pm: "MOPA", pq: "Q-Switch" }, + cooling: { aa: "Air, Active", ap: "Air, Passive", w: "Water" }, }; -// The exact fields this page uses; keeps payloads lean. -const FIELD_GROUPS = [ - { - title: 'General Information', - fields: { - make: 'Make', - model: 'Model', - op: 'Pulse Operation Mode', - notes: 'Notes', - }, - }, -{ - title: 'Optical Specifications', - fields: { - w: 'Laser Wattage (W)', - mj: 'milliJoule Max (mJ)', - nm: 'Wavelength (nm)', - k_hz: 'Pulse Repetition Rate (kHz)', - ns: 'Pulse Width (ns)', - d: 'Beam Diameter (mm)', - m2: 'M² - Quality', - instability: 'Instability', - polarization: 'Polarization', - band: 'Band (nm)', - anti: 'Anti-Reflection Coating', - mw: 'Red Dot Wattage (mW)', - }, -}, -{ - title: 'Electrical & Timing', - fields: { - v: 'Operating Voltage (V)', - temp_op: 'Operating Temperature (°C)', - temp_store: 'Storage Temperature (°C)', - l_on: 'l_on', - l_off: 'l_off', - mj_c: 'mj_c', - ns_c: 'ns_c', - d_c: 'd_c', - on_c: 'on_c', - off_c: 'off_c', - }, -}, -{ - title: 'Integration & Physical', - fields: { - cable: 'Cable Length (m)', - cooling: 'Cooling Method', - weight: 'Weight (kg)', - dimensions: 'Dimensions (cm)', - }, -}, -] as const; - -const FIELD_KEYS = Array.from( - new Set([ - 'make', - 'model', - ...FIELD_GROUPS.flatMap((g) => Object.keys(g.fields)), - ]), -); - -export default function LaserSourceDetailsPage() { - const params = useParams(); - const id = Array.isArray(params?.id) ? params.id[0] : (params?.id as string | undefined); - - const [laser, setLaser] = useState(null); - const [error, setError] = useState(null); - - // Precompute the Directus fields query - const fieldsQuery = useMemo( - () => encodeURIComponent(FIELD_KEYS.join(',')), - [], - ); - - useEffect(() => { - if (!id) return; - let abort = false; - - (async () => { - try { - setError(null); - setLaser(null); - - const res = await fetch( - `${API}/items/laser_source/${encodeURIComponent(String(id))}?fields=${fieldsQuery}`, - { cache: 'no-store' }, - ); - if (!res.ok) throw new Error(`Fetch ${res.status}`); - const json = await res.json().catch(() => ({})); - if (!abort) setLaser(json?.data ?? null); - } catch (e: any) { - if (!abort) setError(e?.message || 'Failed to load'); - } - })(); - - return () => { - abort = true; - }; - }, [id, fieldsQuery]); - - if (error) return
Error: {error}
; - if (!laser) return
Loading...
; - - const resolveLabel = (field: string, value: any) => { - if (value == null || value === '') return '—'; - // enum-ish fields - const map = CHOICE_LABELS[field]; - if (map && typeof value === 'string' && map[value]) return map[value]; - - // smart-ish formatting for primitives - if (typeof value === 'boolean') return value ? 'Yes' : 'No'; - if (typeof value === 'number') return Number.isFinite(value) ? String(value) : '—'; - - return String(value); - }; +function resolveLabel(field: string, value: any) { + if (value == null || value === "") return "—"; + const map = CHOICE_LABELS[field]; + if (map && typeof value === "string" && map[value]) return map[value]; + if (typeof value === "boolean") return value ? "Yes" : "No"; + if (typeof value === "number") return Number.isFinite(value) ? String(value) : "—"; + return String(value); +} +export default function LaserDetailsClient({ + laser, + fieldGroups, +}: { + laser: Laser; + fieldGroups: Group[]; +}) { return (

- {(laser.make as string) || '—'} {laser.model || ''} + {(laser.make as string) || "—"} {laser.model || ""}

- {FIELD_GROUPS.map(({ title, fields }) => ( + {fieldGroups.map(({ title, fields }) => (

{title}

{Object.entries(fields).map(([key, label]) => (
{label}
-
- {resolveLabel(key, (laser as any)[key])} -
+
{resolveLabel(key, laser[key])}
))}