makearmy-app/app/api/options/[collection]/route.ts

91 lines
3.5 KiB
TypeScript

// app/api/options/[collection]/route.ts
import { NextResponse } from "next/server";
import { directusFetch } from "@/lib/directus";
// Parse "nm" that may be stored as a string (e.g., "1064", "1064nm", "1,064")
function parseNm(v: any): number | null {
const s = String(v ?? "").replace(/[^0-9.]/g, "");
if (!s) return null;
const n = Number(s);
return Number.isFinite(n) ? n : null;
}
// target → wavelength range (nm)
function nmRangeForTarget(t?: string): [number, number] | null {
switch (t) {
case "settings_fiber": return [1000, 1100];
case "settings_uv": return [300, 400];
case "settings_co2gan":
case "settings_co2gal": return [10000, 11000];
default: return null;
}
}
// generic collections we expose here
const GENERIC_MAP: Record<string, { coll: string }> = {
material: { coll: "material" },
material_coating: { coll: "material_coating" },
material_color: { coll: "material_color" },
material_opacity: { coll: "material_opacity" },
laser_software: { coll: "laser_software" },
};
function bestLabel(it: any): string {
// prefer common fields; fall back gracefully
const cand = [it.name, it.label, it.title, it.value, it.opacity, it.color, it.coating];
const label = cand.find((x) => x != null && String(x).trim().length) ?? it.id ?? it.submission_id;
return String(label);
}
export async function GET(req: Request, ctx: { params: { collection: string } }) {
try {
const { searchParams } = new URL(req.url);
const q = searchParams.get("q")?.trim() || "";
const limit = Number(searchParams.get("limit") || "500");
const target = searchParams.get("target") || undefined;
const key = ctx.params.collection;
// laser_source: wavelength filtered by target, and pk may be 'submission_id'
if (key === "laser_source") {
const range = nmRangeForTarget(target);
if (!range) return NextResponse.json({ error: "missing/invalid target for laser_source" }, { status: 400 });
const url = `/items/laser_source?limit=${limit}${q ? `&search=${encodeURIComponent(q)}` : ""}`;
const { data } = await directusFetch<{ data: any[] }>(url);
const [lo, hi] = range;
const filtered = (data || []).filter((x) => {
const nm = parseNm(x?.nm);
return nm !== null && nm >= lo && nm <= hi;
});
const out = filtered
.map((x) => {
const id = String(x.submission_id ?? x.id);
const label = [x.make, x.model].filter(Boolean).join(" ").trim() || id;
const sortKey = [x.make ?? "", x.model ?? ""].join(" ").toLowerCase();
return { id, label, sortKey };
})
.sort((a, b) => a.sortKey.localeCompare(b.sortKey))
.map(({ id, label }) => ({ id, label }));
return NextResponse.json({ data: out });
}
// generic collections
const cfg = GENERIC_MAP[key];
if (!cfg) return NextResponse.json({ error: "unsupported collection" }, { status: 400 });
const url = `/items/${cfg.coll}?limit=${limit}${q ? `&search=${encodeURIComponent(q)}` : ""}`;
const { data } = await directusFetch<{ data: any[] }>(url);
const mapped = (data || []).map((it) => ({
id: String(it.submission_id ?? it.id),
label: bestLabel(it),
}));
mapped.sort((a, b) => a.label.localeCompare(b.label));
return NextResponse.json({ data: mapped });
} catch (e: any) {
return NextResponse.json({ error: e?.message || "options error" }, { status: 500 });
}
}