diff --git a/app/api/rigs/route.ts b/app/api/rigs/route.ts index 62d22c97..bbf86787 100644 --- a/app/api/rigs/route.ts +++ b/app/api/rigs/route.ts @@ -9,6 +9,14 @@ function bad(msg: string, code = 400) { return NextResponse.json({ error: msg }, { status: code }); } +// tiny helper so we handle either `dxGET` shape +async function dxArray(path: string, bearer: string): Promise { + const res = await dxGET(path, bearer); + if (Array.isArray(res)) return res as T[]; + if (res?.data && Array.isArray(res.data)) return res.data as T[]; + return []; +} + export async function GET(req: Request) { try { const bearer = requireBearer(req); @@ -16,7 +24,7 @@ export async function GET(req: Request) { const q = new URL(req.url).searchParams; const limit = Math.min(parseInt(q.get("limit") || "50", 10), 100); - const debug = q.get("debug") === "1"; + const wantDebug = q.get("debug") === "1"; const fields = [ "id", @@ -36,132 +44,62 @@ export async function GET(req: Request) { "laser_software.name", "date_created", "date_updated", - // Add owner.id in case we need to inspect it in debug payloads - "owner.id" ].join(","); - const base = - `/items/user_rigs` + - `?fields=${encodeURIComponent(fields)}` + - `&sort=-date_updated` + - `&limit=${limit}`; + const base = `/items/user_rigs?fields=${encodeURIComponent( + fields + )}&sort=-date_updated&limit=${limit}`; - const attempts = [ - { label: "owner.id", path: `${base}&filter[owner][id][_eq]=${encodeURIComponent(me.id)}` }, - { label: "owner", path: `${base}&filter[owner][_eq]=${encodeURIComponent(me.id)}` }, - ]; + // Attempt A: filter by owner + const byOwnerPath = `${base}&filter[owner][_eq]=${encodeURIComponent( + me.id + )}`; + const rowsOwner = await dxArray(byOwnerPath, bearer); - let picked: { label: string; path: string } | null = null; - let rows: any[] = []; + // If nothing, Attempt B: fall back to user_created + let picked = "owner"; + let rows = rowsOwner; + if (!rowsOwner.length) { + const byCreatedPath = `${base}&filter[user_created][_eq]=${encodeURIComponent( + me.id + )}`; + const rowsCreated = await dxArray(byCreatedPath, bearer); - for (const a of attempts) { - try { - const r = await dxGET(a.path, bearer); // dxGET returns unwrapped `data` - if (Array.isArray(r) && r.length > 0) { - picked = a; - rows = r; - break; - } - // Keep the emptiest result in case both return [], so we can still respond - if (!picked) { - picked = a; - rows = Array.isArray(r) ? r : []; - } - } catch { - // ignore and try next attempt + // Prefer created if owner == 0, otherwise merge (dedupe by id) + if (rowsCreated.length) { + picked = "user_created"; + const map = new Map(); + for (const r of [...rowsOwner, ...rowsCreated]) map.set(r.id, r); + rows = Array.from(map.values()); } } - if (debug) { - // In debug mode, include meta so you can see what's happening directly in the browser + if (wantDebug) { + // also fetch counts for the debug panel + const ownerCount = rowsOwner.length; + // Re-run created count only if needed + let createdCount = 0; + if (picked === "user_created") { + const createdCountPath = `${base}&filter[user_created][_eq]=${encodeURIComponent( + me.id + )}&limit=1`; + const createdProbe = await dxArray(createdCountPath, bearer); + createdCount = createdProbe.length ? rows.length : 0; + } return NextResponse.json({ meta: { - me: me.id, - picked: picked?.label, - attempts: await Promise.all( - attempts.map(async (a) => { - try { - const r = await dxGET(a.path, bearer); - return { label: a.label, count: Array.isArray(r) ? r.length : 0 }; - } catch (e: any) { - return { label: a.label, error: String(e?.message || e) }; - } - }) - ), + picked, + attempts: [ + { label: "owner", count: ownerCount }, + { label: "user_created", count: picked === "user_created" ? rows.length : 0 }, + ], }, data: rows, }); } - return NextResponse.json(rows ?? []); + return NextResponse.json(rows); } catch (e: any) { return bad(e?.message || "Failed to load rigs", e?.status || 500); } } - -export async function POST(req: Request) { - try { - const bearer = requireBearer(req); - const body = await req.json().catch(() => ({})); - - const name = (body?.name || "").trim(); - const rig_type = body?.rig_type; // id - 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_software = body?.laser_software || null; - const notes = (body?.notes || "").trim(); - - if (!name) return bad("Missing: name"); - if (!rig_type) return bad("Missing: rig_type"); - if (!laser_source) return bad("Missing: laser_source"); - - // set owner from the authenticated user - const me = await dxGET<{ id: string }>("/users/me?fields=id", bearer); - - const payload: any = { - owner: me.id, - name, - rig_type, - laser_source, - laser_scan_lens, - laser_focus_lens, - laser_software, - notes, - }; - - const res = await dxPOST<{ data: { id: string } }>( - "/items/user_rigs", - bearer, - payload - ); - - return NextResponse.json({ ok: true, id: String(res?.data?.id) }); - } catch (e: any) { - return bad(e?.message || "Failed to create rig", e?.status || 500); - } -} - -export async function DELETE(req: Request) { - try { - const bearer = requireBearer(req); - const url = new URL(req.url); - const id = url.searchParams.get("id"); - if (!id) return bad("Missing: id"); - - // Ensure the rig belongs to the current user (owner.id for precision) - const me = await dxGET<{ id: string }>("/users/me?fields=id", bearer); - const rig = await dxGET<{ id: string; owner?: { id?: string } }>( - `/items/user_rigs/${encodeURIComponent(id)}?fields=id,owner.id`, - bearer - ); - if (!rig || String(rig.owner?.id) !== String(me.id)) { - return bad("Not your rig", 403); - } - - await dxDELETE(`/items/user_rigs/${encodeURIComponent(id)}`, bearer); - return NextResponse.json({ ok: true }); - } catch (e: any) { - return bad(e?.message || "Failed to delete rig", e?.status || 500); - } -}