1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
/**
* GET /api/events
*
* Query params:
* date_from YYYY-MM-DD (default: today)
* date_to YYYY-MM-DD
* venue_id string
* keyword string (title or artist partial match)
* capacity_range small | medium | large
* area string
* limit 1–100 (default 60)
* offset integer (default 0)
*/
import type { Route } from "./+types/api.events._index";
import { queryEvents } from "~/lib/db.server";
export async function loader({ request }: Route.LoaderArgs) {
const url = new URL(request.url);
const p = url.searchParams;
const rawLimit = parseInt(p.get("limit") ?? "60", 10);
const limit = Number.isNaN(rawLimit) ? 60 : Math.min(Math.max(rawLimit, 1), 100);
const rawOffset = parseInt(p.get("offset") ?? "0", 10);
const offset = Number.isNaN(rawOffset) ? 0 : Math.max(rawOffset, 0);
const capacityRaw = p.get("capacity_range");
const capacity_range =
capacityRaw === "small" || capacityRaw === "medium" || capacityRaw === "large"
? capacityRaw
: undefined;
const events = queryEvents({
date_from: p.get("date_from") ?? undefined,
date_to: p.get("date_to") ?? undefined,
venue_id: p.get("venue_id") ?? undefined,
keyword: p.get("keyword") ?? undefined,
area: p.get("area") ?? undefined,
capacity_range,
limit,
offset,
});
return Response.json(
{ events, meta: { limit, offset, count: events.length } },
{ headers: { "Cache-Control": "public, max-age=300" } }
);
}
|