Next.js 15 + Tailwind CSS v4 week calendar showing Six Flags park hours. Scrapes the internal CloudFront API, stores results in SQLite. Includes Dockerfile (Debian/Playwright-compatible), docker-compose, and Gitea Actions pipeline that builds and pushes to the container registry. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
60 lines
1.6 KiB
TypeScript
60 lines
1.6 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { PARKS } from "@/lib/parks";
|
|
import { openDb, getMonthCalendar } from "@/lib/db";
|
|
import type { Park } from "@/lib/scrapers/types";
|
|
|
|
export interface ParksApiResponse {
|
|
parks: Park[];
|
|
calendar: Record<string, boolean[]>;
|
|
month: string;
|
|
daysInMonth: number;
|
|
}
|
|
|
|
function getDaysInMonth(year: number, month: number): number {
|
|
return new Date(year, month, 0).getDate();
|
|
}
|
|
|
|
function parseMonthParam(
|
|
monthParam: string | null
|
|
): { year: number; month: number } | null {
|
|
if (!monthParam) return null;
|
|
const match = monthParam.match(/^(\d{4})-(\d{2})$/);
|
|
if (!match) return null;
|
|
const year = parseInt(match[1], 10);
|
|
const month = parseInt(match[2], 10);
|
|
if (month < 1 || month > 12) return null;
|
|
return { year, month };
|
|
}
|
|
|
|
export async function GET(request: NextRequest): Promise<NextResponse> {
|
|
const monthParam = request.nextUrl.searchParams.get("month");
|
|
const parsed = parseMonthParam(monthParam);
|
|
|
|
if (!parsed) {
|
|
return NextResponse.json(
|
|
{ error: "Invalid or missing ?month=YYYY-MM parameter" },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
const { year, month } = parsed;
|
|
const daysInMonth = getDaysInMonth(year, month);
|
|
|
|
const db = openDb();
|
|
const calendar = getMonthCalendar(db, year, month);
|
|
db.close();
|
|
|
|
const response: ParksApiResponse = {
|
|
parks: PARKS,
|
|
calendar,
|
|
month: `${year}-${String(month).padStart(2, "0")}`,
|
|
daysInMonth,
|
|
};
|
|
|
|
return NextResponse.json(response, {
|
|
headers: {
|
|
"Cache-Control": "public, s-maxage=3600, stale-while-revalidate=86400",
|
|
},
|
|
});
|
|
}
|