added exp and apt to rigs.

This commit is contained in:
makearmy 2025-09-29 23:17:20 -04:00
parent d142ba464a
commit 9390b52aae
3 changed files with 91 additions and 15 deletions

View file

@ -30,19 +30,21 @@ export async function GET(req: Request) {
"laser_scan_lens.focal_length", "laser_scan_lens.focal_length",
"laser_focus_lens.id", "laser_focus_lens.id",
"laser_focus_lens.name", "laser_focus_lens.name",
"laser_scan_lens_apt.id", // NEW
"laser_scan_lens_apt.name", // NEW
"laser_scan_lens_exp.id", // NEW
"laser_scan_lens_exp.name", // NEW
"laser_software.id", "laser_software.id",
"laser_software.name", "laser_software.name",
"date_created", "date_created",
"date_updated", "date_updated",
].join(","); ].join(",");
// Rely entirely on Directus role rules to scope results ("My Rigs")
const path = const path =
`/items/user_rigs?fields=${encodeURIComponent(fields)}` + `/items/user_rigs?fields=${encodeURIComponent(fields)}` +
`&sort=-date_updated` + `&sort=-date_updated` +
`&limit=${limit}`; `&limit=${limit}`;
// dxGET returns the unwrapped `data` array
const rows = await dxGET<any[]>(path, bearer); const rows = await dxGET<any[]>(path, bearer);
return NextResponse.json(rows ?? []); return NextResponse.json(rows ?? []);
} catch (e: any) { } catch (e: any) {
@ -60,6 +62,8 @@ export async function POST(req: Request) {
const laser_source = body?.laser_source; // submission_id const laser_source = body?.laser_source; // submission_id
const laser_scan_lens = body?.laser_scan_lens || null; const laser_scan_lens = body?.laser_scan_lens || null;
const laser_focus_lens = body?.laser_focus_lens || null; const laser_focus_lens = body?.laser_focus_lens || null;
const laser_scan_lens_apt = body?.laser_scan_lens_apt || null; // NEW
const laser_scan_lens_exp = body?.laser_scan_lens_exp || null; // NEW
const laser_software = body?.laser_software || null; const laser_software = body?.laser_software || null;
const notes = (body?.notes || "").trim(); const notes = (body?.notes || "").trim();
@ -67,7 +71,6 @@ export async function POST(req: Request) {
if (!rig_type) return bad("Missing: rig_type"); if (!rig_type) return bad("Missing: rig_type");
if (!laser_source) return bad("Missing: laser_source"); if (!laser_source) return bad("Missing: laser_source");
// derive owner from the authenticated user
const me = await dxGET<{ id: string }>("/users/me?fields=id", bearer); const me = await dxGET<{ id: string }>("/users/me?fields=id", bearer);
const payload: any = { const payload: any = {
@ -77,6 +80,8 @@ export async function POST(req: Request) {
laser_source, laser_source,
laser_scan_lens, laser_scan_lens,
laser_focus_lens, laser_focus_lens,
laser_scan_lens_apt, // NEW
laser_scan_lens_exp, // NEW
laser_software, laser_software,
notes, notes,
}; };
@ -100,7 +105,6 @@ export async function DELETE(req: Request) {
const id = url.searchParams.get("id"); const id = url.searchParams.get("id");
if (!id) return bad("Missing: id"); if (!id) return bad("Missing: id");
// ensure the rig belongs to the current user
const me = await dxGET<{ id: string }>("/users/me?fields=id", bearer); const me = await dxGET<{ id: string }>("/users/me?fields=id", bearer);
const rig = await dxGET<any>( const rig = await dxGET<any>(
`/items/user_rigs/${encodeURIComponent(id)}?fields=id,owner`, `/items/user_rigs/${encodeURIComponent(id)}?fields=id,owner`,

View file

@ -8,11 +8,16 @@ type Opt = { id: string | number; label: string };
const API = (process.env.NEXT_PUBLIC_API_BASE_URL || "").replace(/\/$/, ""); const API = (process.env.NEXT_PUBLIC_API_BASE_URL || "").replace(/\/$/, "");
/** /**
* Note: we are ONLY using this hook for kinds OTHER THAN "user_rig_type". * Client-side options fetcher (same pattern as before).
* Rig types now arrive from the server via props. * NOTE: rig types are still passed from the server; this hook is NOT used for that.
*/ */
function useOptions( function useOptions(
kind: "laser_software" | "laser_source" | "lens", kind:
| "laser_software"
| "laser_source"
| "lens"
| "scan_lens_apt"
| "scan_lens_exp",
targetKey?: string targetKey?: string
) { ) {
const [opts, setOpts] = useState<Opt[]>([]); const [opts, setOpts] = useState<Opt[]>([]);
@ -94,6 +99,10 @@ function useOptions(
})); }));
}; };
} }
} else if (kind === "scan_lens_apt") {
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`;
} }
const res = await fetch(url, { const res = await fetch(url, {
@ -123,10 +132,12 @@ export default function RigBuilderClient({ rigTypes }: { rigTypes: Opt[] }) {
const [rigType, setRigType] = useState<string>(""); const [rigType, setRigType] = useState<string>("");
const [laserSource, setLaserSource] = useState<string>(""); const [laserSource, setLaserSource] = useState<string>("");
const [scanLens, setScanLens] = useState<string>(""); const [scanLens, setScanLens] = useState<string>("");
const [scanLensApt, setScanLensApt] = useState<string>(""); // NEW
const [scanLensExp, setScanLensExp] = useState<string>(""); // NEW
const [focusLens, setFocusLens] = useState<string>(""); const [focusLens, setFocusLens] = useState<string>("");
const [software, setSoftware] = useState<string>(""); const [software, setSoftware] = useState<string>("");
// rigTypes now come from the SERVER, authenticated, as props. // rigTypes come from the SERVER as props.
const targetKey = useMemo(() => { const targetKey = useMemo(() => {
const rt = const rt =
rigTypes.find((o) => String(o.id) === String(rigType))?.label || ""; rigTypes.find((o) => String(o.id) === String(rigType))?.label || "";
@ -135,6 +146,8 @@ export default function RigBuilderClient({ rigTypes }: { rigTypes: Opt[] }) {
const sources = useOptions("laser_source", targetKey); const sources = useOptions("laser_source", targetKey);
const lens = useOptions("lens", targetKey); const lens = useOptions("lens", targetKey);
const lensApt = useOptions("scan_lens_apt"); // NEW
const lensExp = useOptions("scan_lens_exp"); // NEW
const softwares = useOptions("laser_software"); const softwares = useOptions("laser_software");
const isGantry = (targetKey || "").toLowerCase().includes("gantry"); const isGantry = (targetKey || "").toLowerCase().includes("gantry");
@ -151,9 +164,13 @@ export default function RigBuilderClient({ rigTypes }: { rigTypes: Opt[] }) {
if (isGantry) { if (isGantry) {
body.laser_focus_lens = focusLens ? Number(focusLens) : null; body.laser_focus_lens = focusLens ? Number(focusLens) : null;
body.laser_scan_lens = null; body.laser_scan_lens = null;
body.laser_scan_lens_apt = null; // NEW
body.laser_scan_lens_exp = null; // NEW
} else { } else {
body.laser_scan_lens = scanLens ? Number(scanLens) : null; body.laser_scan_lens = scanLens ? Number(scanLens) : null;
body.laser_focus_lens = 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
} }
const res = await fetch("/api/rigs", { const res = await fetch("/api/rigs", {
@ -167,7 +184,6 @@ export default function RigBuilderClient({ rigTypes }: { rigTypes: Opt[] }) {
alert(j?.error || "Failed to create rig"); alert(j?.error || "Failed to create rig");
return; return;
} }
// Go back to list tab
router.replace("/portal/rigs?t=my", { scroll: false }); router.replace("/portal/rigs?t=my", { scroll: false });
router.refresh(); router.refresh();
} }
@ -226,7 +242,7 @@ export default function RigBuilderClient({ rigTypes }: { rigTypes: Opt[] }) {
</div> </div>
</div> </div>
{/* Lens (focus for gantry, scan for others) */} {/* Lens (focus for gantry, scan + apt/exp for others) */}
{isGantry ? ( {isGantry ? (
<div> <div>
<label className="block text-sm mb-1">Focus Lens</label> <label className="block text-sm mb-1">Focus Lens</label>
@ -244,6 +260,7 @@ export default function RigBuilderClient({ rigTypes }: { rigTypes: Opt[] }) {
</select> </select>
</div> </div>
) : ( ) : (
<>
<div> <div>
<label className="block text-sm mb-1">Scan Lens</label> <label className="block text-sm mb-1">Scan Lens</label>
<select <select
@ -259,6 +276,45 @@ export default function RigBuilderClient({ rigTypes }: { rigTypes: Opt[] }) {
))} ))}
</select> </select>
</div> </div>
<div className="grid sm:grid-cols-2 gap-3">
<div>
<label className="block text-sm mb-1">Scan Lens Apt</label>
<select
className="w-full border rounded px-2 py-1"
value={scanLensApt}
onChange={(e) => setScanLensApt(e.target.value)}
>
<option value="">
{lensApt.loading ? "Loading…" : "—"}
</option>
{lensApt.opts.map((o) => (
<option key={o.id} value={o.id}>
{o.label}
</option>
))}
</select>
</div>
<div>
<label className="block text-sm mb-1">Scan Lens Exp</label>
<select
className="w-full border rounded px-2 py-1"
value={scanLensExp}
onChange={(e) => setScanLensExp(e.target.value)}
>
<option value="">
{lensExp.loading ? "Loading…" : "—"}
</option>
{lensExp.opts.map((o) => (
<option key={o.id} value={o.id}>
{o.label}
</option>
))}
</select>
</div>
</div>
</>
)} )}
<div> <div>

View file

@ -10,6 +10,8 @@ type Rig = {
laser_source?: { submission_id: number; make?: string; model?: string }; laser_source?: { submission_id: number; make?: string; model?: string };
laser_scan_lens?: { id: number; field_size?: string; focal_length?: string }; laser_scan_lens?: { id: number; field_size?: string; focal_length?: string };
laser_focus_lens?: { id: number; name?: string }; laser_focus_lens?: { id: number; name?: string };
laser_scan_lens_apt?: { id: number; name?: string }; // NEW
laser_scan_lens_exp?: { id: number; name?: string }; // NEW
laser_software?: { id: number; name?: string }; laser_software?: { id: number; name?: string };
}; };
@ -73,18 +75,32 @@ export default function RigsListClient() {
.{" "} .{" "}
</> </>
) : null} ) : null}
{r.laser_focus_lens?.name ? <>Focus Lens: {r.laser_focus_lens.name}. </> : null} {r.laser_focus_lens?.name ? (
<>Focus Lens: {r.laser_focus_lens.name}. </>
) : null}
{r.laser_scan_lens ? ( {r.laser_scan_lens ? (
<> <>
Scan Lens:{" "} Scan Lens:{" "}
{[ {[
r.laser_scan_lens.field_size && `${r.laser_scan_lens.field_size}mm`, r.laser_scan_lens.field_size &&
r.laser_scan_lens.focal_length && `${r.laser_scan_lens.focal_length}mm`, `${r.laser_scan_lens.field_size}mm`,
].filter(Boolean).join(" / ")} r.laser_scan_lens.focal_length &&
`${r.laser_scan_lens.focal_length}mm`,
]
.filter(Boolean)
.join(" / ")}
.{" "} .{" "}
</> </>
) : null} ) : null}
{r.laser_software?.name ? <>Software: {r.laser_software.name}. </> : null} {r.laser_scan_lens_apt?.name ? (
<>Scan Lens Apt: {r.laser_scan_lens_apt.name}. </>
) : null}
{r.laser_scan_lens_exp?.name ? (
<>Scan Lens Exp: {r.laser_scan_lens_exp.name}. </>
) : null}
{r.laser_software?.name ? (
<>Software: {r.laser_software.name}. </>
) : null}
</div> </div>
{r.notes ? <div className="text-sm mt-2">{r.notes}</div> : null} {r.notes ? <div className="text-sm mt-2">{r.notes}</div> : null}
</div> </div>