From e5f4c7040eeae9ef6bb6fc95451a5bb2f0e70902 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Sun, 15 Feb 2026 09:25:15 -0700 Subject: [PATCH] Fix proxy endpoints and demo data mapping for live cross-service data - rVote proxy: use space-scoped /api/s/{slug}/api/proposals instead of top-level - rNotes proxy: fetch all notebooks and filter by slug server-side - rCart demo: map carts array directly (each cart = one gear item) Co-Authored-By: Claude Opus 4.6 --- src/app/api/proxy/rnotes/route.ts | 43 ++++++++++++++++++------------- src/app/api/proxy/rvote/route.ts | 2 +- src/app/demo/demo-content.tsx | 25 +++++++++--------- 3 files changed, 39 insertions(+), 31 deletions(-) diff --git a/src/app/api/proxy/rnotes/route.ts b/src/app/api/proxy/rnotes/route.ts index ad831a0..752f32e 100644 --- a/src/app/api/proxy/rnotes/route.ts +++ b/src/app/api/proxy/rnotes/route.ts @@ -12,27 +12,34 @@ export async function GET(req: NextRequest) { return NextResponse.json({ error: 'Missing endpoint param' }, { status: 400 }); } - let targetUrl: string; - - if (endpoint === 'notebook' && slug) { - // Get notebook by slug — use search with slug filter - targetUrl = `${RNOTES_BASE}/api/notebooks?slug=${encodeURIComponent(slug)}`; - } else if (endpoint === 'notes' && notebookId) { - targetUrl = `${RNOTES_BASE}/api/notebooks/${encodeURIComponent(notebookId)}/notes`; - } else { - return NextResponse.json({ error: 'Invalid endpoint or missing params' }, { status: 400 }); - } - try { - const res = await fetch(targetUrl, { next: { revalidate: 30 } }); - if (!res.ok) { - return NextResponse.json( - { error: `Upstream error: ${res.status}` }, - { status: res.status } + if (endpoint === 'notebook' && slug) { + // Fetch all notebooks and filter by slug (rNotes API doesn't support slug filter) + const res = await fetch(`${RNOTES_BASE}/api/notebooks`, { next: { revalidate: 30 } }); + if (!res.ok) { + return NextResponse.json({ error: `Upstream error: ${res.status}` }, { status: res.status }); + } + const notebooks = await res.json(); + const notebook = Array.isArray(notebooks) + ? notebooks.find((nb: { slug: string }) => nb.slug === slug) + : null; + if (!notebook) { + return NextResponse.json({ error: 'Notebook not found' }, { status: 404 }); + } + return NextResponse.json(notebook); + } else if (endpoint === 'notes' && notebookId) { + const res = await fetch( + `${RNOTES_BASE}/api/notebooks/${encodeURIComponent(notebookId)}/notes`, + { next: { revalidate: 30 } } ); + if (!res.ok) { + return NextResponse.json({ error: `Upstream error: ${res.status}` }, { status: res.status }); + } + const data = await res.json(); + return NextResponse.json(data); + } else { + return NextResponse.json({ error: 'Invalid endpoint or missing params' }, { status: 400 }); } - const data = await res.json(); - return NextResponse.json(data); } catch (e) { return NextResponse.json( { error: e instanceof Error ? e.message : 'Fetch failed' }, diff --git a/src/app/api/proxy/rvote/route.ts b/src/app/api/proxy/rvote/route.ts index 9926081..db8c15e 100644 --- a/src/app/api/proxy/rvote/route.ts +++ b/src/app/api/proxy/rvote/route.ts @@ -17,7 +17,7 @@ export async function GET(req: NextRequest) { targetUrl = `${RVOTE_BASE}/api/spaces/${encodeURIComponent(slug)}`; } else if (endpoint === 'proposals') { const status = searchParams.get('status') || 'RANKING'; - targetUrl = `${RVOTE_BASE}/api/proposals?spaceSlug=${encodeURIComponent(slug)}&status=${status}&limit=10`; + targetUrl = `${RVOTE_BASE}/api/s/${encodeURIComponent(slug)}/api/proposals?status=${status}&limit=10`; } else { return NextResponse.json({ error: 'Invalid endpoint' }, { status: 400 }); } diff --git a/src/app/demo/demo-content.tsx b/src/app/demo/demo-content.tsx index a882399..e6f618f 100644 --- a/src/app/demo/demo-content.tsx +++ b/src/app/demo/demo-content.tsx @@ -676,18 +676,19 @@ export default function DemoContent() { }) .then((data) => { if (Array.isArray(data) && data.length > 0) { - const cart = data[0] - if (cart.items?.length > 0) { - setCartData( - cart.items.map((item: Record) => ({ - item: item.name as string, - target: (item.targetAmount as number) || 100, - funded: (item.fundedAmount as number) || 0, - status: ((item.fundedAmount as number) || 0) >= ((item.targetAmount as number) || 100) ? 'Purchased' : 'Funding', - })) - ) - setLiveFlags((f) => ({ ...f, cart: true })) - } + setCartData( + data.map((cart: Record) => { + const target = Number(cart.targetAmount) || 100 + const funded = Number(cart.fundedAmount) || 0 + return { + item: cart.name as string, + target, + funded, + status: (funded >= target ? 'Purchased' : 'Funding') as 'Purchased' | 'Funding', + } + }) + ) + setLiveFlags((f) => ({ ...f, cart: true })) } }) .catch(() => {