95 lines
2.9 KiB
TypeScript
95 lines
2.9 KiB
TypeScript
// app/api/options/lens/route.ts
|
||
import { NextResponse } from "next/server";
|
||
import { directusFetch } from "@/lib/directus";
|
||
|
||
/**
|
||
* Lens options:
|
||
* - Fiber / UV / CO2 Galvo -> laser_scan_lens (field_size, focal_length)
|
||
* - CO2 Gantry -> laser_focus_lens (focal_length)
|
||
* Returns [{ id, label }] using submission_id if present, otherwise id.
|
||
*/
|
||
|
||
function collectionForTarget(
|
||
target?: string
|
||
): "laser_scan_lens" | "laser_focus_lens" | null {
|
||
switch (target) {
|
||
case "settings_fiber":
|
||
case "settings_uv":
|
||
case "settings_co2gal":
|
||
return "laser_scan_lens";
|
||
case "settings_co2gan":
|
||
return "laser_focus_lens";
|
||
default:
|
||
return null;
|
||
}
|
||
}
|
||
|
||
export async function GET(req: Request) {
|
||
try {
|
||
const { searchParams } = new URL(req.url);
|
||
const target = searchParams.get("target") || undefined;
|
||
const q = (searchParams.get("q") || "").toLowerCase().trim();
|
||
const limit = Number(searchParams.get("limit") || "500");
|
||
|
||
const coll = collectionForTarget(target);
|
||
if (!coll) return NextResponse.json({ data: [] });
|
||
|
||
// Important: don't request fields that don't exist.
|
||
const fields =
|
||
coll === "laser_scan_lens"
|
||
? "submission_id,id,field_size,focal_length"
|
||
: "submission_id,id,focal_length";
|
||
|
||
const url = `/items/${coll}?fields=${encodeURIComponent(
|
||
fields
|
||
)}&limit=${limit}`;
|
||
|
||
const { data } = await directusFetch<{ data: any[] }>(url);
|
||
const list = Array.isArray(data) ? data : [];
|
||
|
||
const items = list.map((x) => {
|
||
const id = String(x?.submission_id ?? x?.id);
|
||
|
||
const fieldSize =
|
||
x?.field_size !== null && x?.field_size !== undefined
|
||
? String(x.field_size).trim()
|
||
: "";
|
||
|
||
const fnum = Number(x?.focal_length);
|
||
const focalTxt = Number.isFinite(fnum) ? `F${fnum} mm` : "";
|
||
|
||
// Label: field_size first, then focal length (requested order).
|
||
let label = [fieldSize, focalTxt].filter(Boolean).join(" — ");
|
||
if (!label) label = id;
|
||
|
||
// Sort numerically by focal length when available, else alpha by label.
|
||
const sortKey: number | string = Number.isFinite(fnum)
|
||
? fnum
|
||
: label.toLowerCase();
|
||
|
||
return {
|
||
id,
|
||
label,
|
||
sortKey,
|
||
_search: `${id} ${label} ${fieldSize} ${x?.focal_length ?? ""}`.toLowerCase(),
|
||
};
|
||
});
|
||
|
||
const filtered = q ? items.filter((m) => m._search.includes(q)) : items;
|
||
|
||
filtered.sort((a, b) => {
|
||
if (typeof a.sortKey === "number" && typeof b.sortKey === "number") {
|
||
return a.sortKey - b.sortKey;
|
||
}
|
||
return String(a.sortKey).localeCompare(String(b.sortKey));
|
||
});
|
||
|
||
return NextResponse.json({
|
||
data: filtered.map(({ id, label }) => ({ id, label })),
|
||
});
|
||
} catch (e: any) {
|
||
console.error("[options/lens] error:", e?.message || e);
|
||
// Fail-soft so the UI doesn’t hang
|
||
return NextResponse.json({ data: [] });
|
||
}
|
||
}
|