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

101 lines
3.6 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 { NextRequest, NextResponse } from "next/server";
import { directusFetch } from "@/lib/directus";
/**
* Parse "110x110", "110×110", "110 X 110", etc. -> [110, 110]
* Returns null if we can't find two numbers.
*/
function parseFieldSize(s: unknown): [number, number] | null {
if (!s) return null;
const nums = String(s).match(/\d+(\.\d+)?/g)?.map((n) => Number(n)) ?? [];
if (nums.length >= 2 && Number.isFinite(nums[0]) && Number.isFinite(nums[1])) {
return [nums[0], nums[1]];
}
return null;
}
/** Pull a clean integer from a value like "F160", "160", "160mm" */
function parseFocalLength(v: unknown): number | null {
if (v == null) return null;
const m = String(v).match(/\d+(\.\d+)?/);
if (!m) return null;
const n = Number(m[0]);
return Number.isFinite(n) ? Math.round(n) : null;
}
/** Natural-ish compare for scan lens sizes: sort by width then height */
function sizeCompare(a: string, b: string): number {
const as = parseFieldSize(a);
const bs = parseFieldSize(b);
if (!as && !bs) return String(a).localeCompare(String(b));
if (!as) return 1;
if (!bs) return -1;
// width, then height
if (as[0] !== bs[0]) return as[0] - bs[0];
if (as[1] !== bs[1]) return as[1] - bs[1];
return 0;
}
export async function GET(req: NextRequest) {
try {
const { searchParams } = new URL(req.url);
const target = searchParams.get("target") || "";
const q = (searchParams.get("q") || "").trim().toLowerCase();
const limit = Number(searchParams.get("limit") || "500");
const isGantry = target === "settings_co2gan";
if (isGantry) {
// CO2 Gantry -> FOCUS lenses
const url = `/items/laser_focus_lens?fields=id,name&limit=${limit}`;
const { data } = await directusFetch<{ data: Array<{ id: string | number; name?: string }> }>(url);
let rows = (data ?? []).map((r) => ({
id: String(r.id),
label: r.name?.trim() || String(r.id),
_key: r.name?.toLowerCase() ?? "",
}));
if (q) rows = rows.filter((r) => r.label.toLowerCase().includes(q));
rows.sort((a, b) => a.label.localeCompare(b.label));
return NextResponse.json({ data: rows.map(({ id, label }) => ({ id, label })) });
}
// Galvo/UV/Fiber -> SCAN lenses with field_size + focal_length
const url = `/items/laser_scan_lens?fields=id,field_size,focal_length&limit=${limit}`;
const { data } = await directusFetch<{
data: Array<{ id: string | number; field_size?: string; focal_length?: string | number }>;
}>(url);
let rows = (data ?? []).map((r) => {
const sizeTxt = (r.field_size ?? "").toString().trim(); // e.g. "110x110"
const fmm = parseFocalLength(r.focal_length); // e.g. 160
// Build label: "110x110mm (F160)" or "110x110mm" if focal length missing
const label =
sizeTxt
? `${sizeTxt}mm${fmm != null ? ` (F${fmm})` : ""}`
: `${r.id}`;
return {
id: String(r.id),
label,
_size: sizeTxt,
};
});
if (q) {
const qq = q.toLowerCase();
rows = rows.filter((r) => r.label.toLowerCase().includes(qq));
}
rows.sort((a, b) => {
const c = sizeCompare(a._size, b._size);
return c !== 0 ? c : a.label.localeCompare(b.label);
});
return NextResponse.json({ data: rows.map(({ id, label }) => ({ id, label })) });
} catch (e: any) {
console.error("[options/lens] error:", e?.message || e);
return NextResponse.json({ error: e?.message || "Internal error" }, { status: 500 });
}
}