diff --git a/README.md b/README.md index ddb9199..f03512f 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,7 @@ The backend starts on port 3001, initializes the database, and begins the cron s npm run dev ``` -Open [http://localhost:3000](http://localhost:3000). Navigate weeks with the `←` / `→` buttons, or pass `?week=YYYY-MM-DD` directly. Click any park name to open its detail page. +Open [http://localhost:3000](http://localhost:3000). Navigate weeks with the `←` / `→` buttons (or arrow keys); your selected week persists across visits via the `tcWeek` cookie. Click any park name to open its detail page. ### Debug a specific park + date diff --git a/app/actions/week.ts b/app/actions/week.ts new file mode 100644 index 0000000..42784ce --- /dev/null +++ b/app/actions/week.ts @@ -0,0 +1,29 @@ +"use server"; + +import { cookies } from "next/headers"; +import { revalidatePath } from "next/cache"; + +const WEEK_COOKIE = "tcWeek"; +const MAX_AGE = 60 * 60 * 24 * 30; // 30 days + +/** + * Persist the selected week start (YYYY-MM-DD) in a server-readable cookie + * and revalidate the home page so the new week renders. + */ +export async function setWeek(weekStart: string): Promise { + if (!/^\d{4}-\d{2}-\d{2}$/.test(weekStart)) return; + const cookieStore = await cookies(); + cookieStore.set(WEEK_COOKIE, weekStart, { + path: "/", + maxAge: MAX_AGE, + sameSite: "lax", + }); + revalidatePath("/"); +} + +/** Clear the saved week — used by the "Today" button to jump back to current. */ +export async function clearWeek(): Promise { + const cookieStore = await cookies(); + cookieStore.delete(WEEK_COOKIE); + revalidatePath("/"); +} diff --git a/app/page.tsx b/app/page.tsx index 14d7545..423b82c 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,15 +1,14 @@ +import { cookies } from "next/headers"; import { HomePageClient } from "@/components/HomePageClient"; import { getTodayLocal, formatDateLocal } from "@/lib/env"; const BACKEND_URL = process.env.BACKEND_URL ?? "http://localhost:3001"; -interface PageProps { - searchParams: Promise<{ week?: string }>; -} +const WEEK_COOKIE = "tcWeek"; -function getWeekStart(param: string | undefined): string { - if (param && /^\d{4}-\d{2}-\d{2}$/.test(param)) { - const d = new Date(param + "T00:00:00"); +function getWeekStart(saved: string | undefined): string { + if (saved && /^\d{4}-\d{2}-\d{2}$/.test(saved)) { + const d = new Date(saved + "T00:00:00"); if (!isNaN(d.getTime())) { d.setDate(d.getDate() - d.getDay()); return formatDateLocal(d); @@ -21,9 +20,9 @@ function getWeekStart(param: string | undefined): string { return formatDateLocal(d); } -export default async function HomePage({ searchParams }: PageProps) { - const params = await searchParams; - const weekStart = getWeekStart(params.week); +export default async function HomePage() { + const saved = (await cookies()).get(WEEK_COOKIE)?.value; + const weekStart = getWeekStart(saved); const data = await fetch( `${BACKEND_URL}/api/calendar/week?start=${weekStart}`, diff --git a/components/BackToCalendarLink.tsx b/components/BackToCalendarLink.tsx index 5fe3d03..557927b 100644 --- a/components/BackToCalendarLink.tsx +++ b/components/BackToCalendarLink.tsx @@ -1,19 +1,12 @@ -"use client"; - -import { useState, useEffect } from "react"; import Link from "next/link"; export function BackToCalendarLink() { - const [href, setHref] = useState("/"); - - useEffect(() => { - const saved = localStorage.getItem("lastWeek"); - if (saved) setHref(`/?week=${saved}`); - }, []); - + // The selected week is stored in a server-readable cookie (tcWeek), so the + // home page already renders the right week without us needing to pass it + // through the URL. return ( timeouts.forEach(clearTimeout); }, [isCurrentWeek, today, data, router]); - // Remember the current week so the park page back button returns here. - useEffect(() => { - localStorage.setItem("lastWeek", weekStart); - }, [weekStart]); - const toggle = () => { const next = !coastersOnly; setCoastersOnly(next); diff --git a/components/WeekNav.tsx b/components/WeekNav.tsx index 7437658..1fe192b 100644 --- a/components/WeekNav.tsx +++ b/components/WeekNav.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect } from "react"; -import { useRouter } from "next/navigation"; +import { setWeek, clearWeek } from "@/app/actions/week"; interface WeekNavProps { weekStart: string; // YYYY-MM-DD (Sunday) @@ -39,9 +39,11 @@ function shiftWeek(weekStart: string, delta: number): string { } export function WeekNav({ weekStart, weekDates, isCurrentWeek }: WeekNavProps) { - const router = useRouter(); const nav = (delta: number) => { - router.push(`/?week=${shiftWeek(weekStart, delta)}`); + void setWeek(shiftWeek(weekStart, delta)); + }; + const jumpToToday = () => { + void clearWeek(); }; useEffect(() => { @@ -68,7 +70,7 @@ export function WeekNav({ weekStart, weekDates, isCurrentWeek }: WeekNavProps) { {!isCurrentWeek && (