makearmy-app/app/api/options/lens/route.ts

117 lines
4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// app/api/options/lens/route.ts
import { NextResponse } from "next/server";
import { directusFetch } from "@/lib/directus";
type Target =
| "settings_fiber"
| "settings_uv"
| "settings_co2gal"
| "settings_co2gan";
/** Map target -> Directus collection */
function collectionForTarget(t?: string) {
switch ((t ?? "") as Target) {
case "settings_fiber":
case "settings_uv":
case "settings_co2gal":
return "laser_scan_lens" as const; // has field_size + focal_length
case "settings_co2gan":
return "laser_focus_lens" as const; // has name (no focal_length)
default:
return null;
}
}
/** Parse "110x110", "110×110", "110 x 110", or single "110" => {w,h} */
function parseFieldSize(raw: unknown): { w: number; h: number } | null {
if (raw == null) return null;
const s = String(raw).trim();
const m = s.match(/(\d+(?:\.\d+)?)(?:\s*[x×]\s*(\d+(?:\.\d+)?))?/i);
if (!m) return null;
const w = Number(m[1]);
const h = m[2] ? Number(m[2]) : w;
if (!Number.isFinite(w) || !Number.isFinite(h)) return null;
return { w, h };
}
const fmtNum = (n: number) =>
Number.isInteger(n) ? String(n) : String(n).replace(/\.0+$/, "");
const dimsText = (d: { w: number; h: number }) => `${fmtNum(d.w)}x${fmtNum(d.h)}`;
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: [] });
if (coll === "laser_scan_lens") {
// fiber / uv / co2gal → scan lenses have field_size + focal_length
const { data } = await directusFetch<{ data: any[] }>(
`/items/${coll}?fields=id,field_size,focal_length&limit=${encodeURIComponent(
String(limit)
)}`
);
const rows = (data ?? []).map((r) => {
const dim = parseFieldSize(r.field_size);
const fnumRaw = r.focal_length;
const label =
dim && fnumRaw != null && fnumRaw !== ""
? `${dimsText(dim)} (F${fmtNum(Number(fnumRaw))})`
: dim
? dimsText(dim)
: String(r.field_size ?? r.id);
const area =
dim && Number.isFinite(dim.w) && Number.isFinite(dim.h)
? dim.w * dim.h
: Number.POSITIVE_INFINITY;
return {
id: String(r.id),
label,
_sort: { area, w: dim?.w ?? Number.POSITIVE_INFINITY, h: dim?.h ?? Number.POSITIVE_INFINITY },
_search: `${r.field_size ?? ""} ${r.focal_length ?? ""} ${label}`.toLowerCase(),
};
});
const filtered = q ? rows.filter((r) => r._search.includes(q)) : rows;
filtered.sort((a, b) => {
if (a._sort.area !== b._sort.area) return a._sort.area - b._sort.area;
if (a._sort.w !== b._sort.w) return a._sort.w - b._sort.w;
if (a._sort.h !== b._sort.h) return a._sort.h - b._sort.h;
return a.label.localeCompare(b.label);
});
return NextResponse.json({
data: filtered.map(({ id, label }) => ({ id, label })),
});
}
// CO2 Gantry → focus lenses only have "name"
const { data } = await directusFetch<{ data: any[] }>(
`/items/${coll}?fields=id,name&limit=${encodeURIComponent(String(limit))}`
);
const rows = (data ?? []).map((r) => ({
id: String(r.id),
label: String(r.name ?? r.id),
_search: String(r.name ?? r.id).toLowerCase(),
}));
const filtered = q ? rows.filter((r) => r._search.includes(q)) : rows;
filtered.sort((a, b) => a.label.localeCompare(b.label));
return NextResponse.json({
data: filtered.map(({ id, label }) => ({ id, label })),
});
} catch (err: any) {
console.error("[options/lens] error:", err?.message || err);
return NextResponse.json({ data: [] }, { status: 200 });
}
}