Files
robertoandClaude Sonnet 5 ddd2db2a52 Initial commit: Tina Barcelona trip picker
Static Cloudflare Pages site + KV-backed Pages Function for jointly
planning Tina's Barcelona visit (7 Jul - 18 Aug 2026). List and calendar
views share one client state; dated evening events are radio groups to
prevent double-booking, multi-night shows live once in TRIP_DATA.spanning
instead of being duplicated per day, and undated collections get
optionally date-tagged when picked from the calendar view.

Includes a client-side-only password gate and an instructions page.
Live at https://summeroffun.hortal.me.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 22:58:15 +02:00

40 lines
1.2 KiB
JavaScript

// GET /api/selections -> { picks: { [groupId]: string | string[] } }
// POST /api/selections { groupId, value } -> merges value into stored picks, returns updated state.
//
// Single shared document in KV under key "picks" — no auth, no per-user accounts.
// Good enough for a private link shared between two people; anyone with the URL can edit.
const KEY = "picks";
export async function onRequestGet({ env }) {
const raw = await env.PICKS.get(KEY);
const picks = raw ? JSON.parse(raw) : {};
return Response.json({ picks });
}
export async function onRequestPost({ request, env }) {
let body;
try {
body = await request.json();
} catch {
return new Response("Invalid JSON body", { status: 400 });
}
const { groupId, value } = body;
if (!groupId || typeof groupId !== "string") {
return new Response("groupId is required", { status: 400 });
}
const raw = await env.PICKS.get(KEY);
const picks = raw ? JSON.parse(raw) : {};
if (value === "" || value == null) {
delete picks[groupId];
} else {
picks[groupId] = value; // string for day radio picks, string[] for collection checkboxes
}
await env.PICKS.put(KEY, JSON.stringify(picks));
return Response.json({ picks });
}