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_focus_lens.id",
"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.name",
"date_created",
"date_updated",
].join(",");
// Rely entirely on Directus role rules to scope results ("My Rigs")
const path =
`/items/user_rigs?fields=${encodeURIComponent(fields)}` +
`&sort=-date_updated` +
`&limit=${limit}`;
// dxGET returns the unwrapped `data` array
const rows = await dxGET<any[]>(path, bearer);
return NextResponse.json(rows ?? []);
} catch (e: any) {
@ -60,6 +62,8 @@ export async function POST(req: Request) {
const laser_source = body?.laser_source; // submission_id
const laser_scan_lens = body?.laser_scan_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 notes = (body?.notes || "").trim();
@ -67,7 +71,6 @@ export async function POST(req: Request) {
if (!rig_type) return bad("Missing: rig_type");
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 payload: any = {
@ -77,6 +80,8 @@ export async function POST(req: Request) {
laser_source,
laser_scan_lens,
laser_focus_lens,
laser_scan_lens_apt, // NEW
laser_scan_lens_exp, // NEW
laser_software,
notes,
};
@ -100,7 +105,6 @@ export async function DELETE(req: Request) {
const id = url.searchParams.get("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 rig = await dxGET<any>(
`/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(/\/$/, "");
/**
* Note: we are ONLY using this hook for kinds OTHER THAN "user_rig_type".
* Rig types now arrive from the server via props.
* Client-side options fetcher (same pattern as before).
* NOTE: rig types are still passed from the server; this hook is NOT used for that.
*/
function useOptions(
kind: "laser_software" | "laser_source" | "lens",
kind:
| "laser_software"
| "laser_source"
| "lens"
| "scan_lens_apt"
| "scan_lens_exp",
targetKey?: string
) {
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, {
@ -123,10 +132,12 @@ export default function RigBuilderClient({ rigTypes }: { rigTypes: Opt[] }) {
const [rigType, setRigType] = useState<string>("");
const [laserSource, setLaserSource] = 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 [software, setSoftware] = useState<string>("");
// rigTypes now come from the SERVER, authenticated, as props.
// rigTypes come from the SERVER as props.
const targetKey = useMemo(() => {
const rt =
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 lens = useOptions("lens", targetKey);
const lensApt = useOptions("scan_lens_apt"); // NEW
const lensExp = useOptions("scan_lens_exp"); // NEW
const softwares = useOptions("laser_software");
const isGantry = (targetKey || "").toLowerCase().includes("gantry");
@ -151,9 +164,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
} 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
}
const res = await fetch("/api/rigs", {
@ -167,7 +184,6 @@ export default function RigBuilderClient({ rigTypes }: { rigTypes: Opt[] }) {
alert(j?.error || "Failed to create rig");
return;
}
// Go back to list tab
router.replace("/portal/rigs?t=my", { scroll: false });
router.refresh();
}
@ -226,7 +242,7 @@ export default function RigBuilderClient({ rigTypes }: { rigTypes: Opt[] }) {
</div>
</div>
{/* Lens (focus for gantry, scan for others) */}
{/* Lens (focus for gantry, scan + apt/exp for others) */}
{isGantry ? (
<div>
<label className="block text-sm mb-1">Focus Lens</label>
@ -244,6 +260,7 @@ export default function RigBuilderClient({ rigTypes }: { rigTypes: Opt[] }) {
</select>
</div>
) : (
<>
<div>
<label className="block text-sm mb-1">Scan Lens</label>
<select
@ -259,6 +276,45 @@ export default function RigBuilderClient({ rigTypes }: { rigTypes: Opt[] }) {
))}
</select>
</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>

View file

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