feat: initial project scaffold with CI/CD and Docker deployment
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>
This commit is contained in:
59
app/api/parks/route.ts
Normal file
59
app/api/parks/route.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
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",
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user