feat: coaster filter toggle on homepage
All checks were successful
Build and Deploy / Build & Push (push) Successful in 1m14s
All checks were successful
Build and Deploy / Build & Push (push) Successful in 1m14s
- 🎢 Coasters button in nav bar (URL-driven: ?coasters=1) - When active, swaps ride counts for coaster counts per park - Label switches between "X rides operating" / "X coasters operating" - Arrow key navigation preserves coaster filter state - Only shown when coaster data exists in park-meta Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
33
app/page.tsx
33
app/page.tsx
@@ -8,9 +8,10 @@ import { openDb, getDateRange } from "@/lib/db";
|
||||
import { getTodayLocal, isWithinOperatingWindow } from "@/lib/env";
|
||||
import { fetchLiveRides } from "@/lib/scrapers/queuetimes";
|
||||
import { QUEUE_TIMES_IDS } from "@/lib/queue-times-map";
|
||||
import { readParkMeta, getCoasterSet } from "@/lib/park-meta";
|
||||
|
||||
interface PageProps {
|
||||
searchParams: Promise<{ week?: string }>;
|
||||
searchParams: Promise<{ week?: string; coasters?: string }>;
|
||||
}
|
||||
|
||||
function getWeekStart(param: string | undefined): string {
|
||||
@@ -45,6 +46,7 @@ function getCurrentWeekStart(): string {
|
||||
export default async function HomePage({ searchParams }: PageProps) {
|
||||
const params = await searchParams;
|
||||
const weekStart = getWeekStart(params.week);
|
||||
const coastersOnly = params.coasters === "1";
|
||||
const weekDates = getWeekDates(weekStart);
|
||||
const endDate = weekDates[6];
|
||||
const today = getTodayLocal();
|
||||
@@ -61,7 +63,11 @@ export default async function HomePage({ searchParams }: PageProps) {
|
||||
|
||||
// Fetch live ride counts for parks open today (cached 5 min via Queue-Times).
|
||||
// Only shown when the current time is within 1h before open to 1h after close.
|
||||
const parkMeta = readParkMeta();
|
||||
const hasCoasterData = PARKS.some((p) => (parkMeta[p.id]?.coasters.length ?? 0) > 0);
|
||||
|
||||
let rideCounts: Record<string, number> = {};
|
||||
let coasterCounts: Record<string, number> = {};
|
||||
if (weekDates.includes(today)) {
|
||||
const openTodayParks = PARKS.filter((p) => {
|
||||
const dayData = data[p.id]?.[today];
|
||||
@@ -70,14 +76,23 @@ export default async function HomePage({ searchParams }: PageProps) {
|
||||
});
|
||||
const results = await Promise.all(
|
||||
openTodayParks.map(async (p) => {
|
||||
const result = await fetchLiveRides(QUEUE_TIMES_IDS[p.id], null, 300);
|
||||
const count = result ? result.rides.filter((r) => r.isOpen).length : 0;
|
||||
return [p.id, count] as [string, number];
|
||||
const coasterSet = getCoasterSet(p.id, parkMeta);
|
||||
const result = await fetchLiveRides(QUEUE_TIMES_IDS[p.id], coasterSet, 300);
|
||||
const rideCount = result ? result.rides.filter((r) => r.isOpen).length : 0;
|
||||
const coasterCount = result ? result.rides.filter((r) => r.isOpen && r.isCoaster).length : 0;
|
||||
return { id: p.id, rideCount, coasterCount };
|
||||
})
|
||||
);
|
||||
rideCounts = Object.fromEntries(results.filter(([, count]) => count > 0));
|
||||
rideCounts = Object.fromEntries(
|
||||
results.filter(({ rideCount }) => rideCount > 0).map(({ id, rideCount }) => [id, rideCount])
|
||||
);
|
||||
coasterCounts = Object.fromEntries(
|
||||
results.filter(({ coasterCount }) => coasterCount > 0).map(({ id, coasterCount }) => [id, coasterCount])
|
||||
);
|
||||
}
|
||||
|
||||
const activeCounts = coastersOnly ? coasterCounts : rideCounts;
|
||||
|
||||
const visibleParks = PARKS.filter((park) =>
|
||||
weekDates.some((date) => data[park.id]?.[date]?.isOpen)
|
||||
);
|
||||
@@ -137,6 +152,8 @@ export default async function HomePage({ searchParams }: PageProps) {
|
||||
weekStart={weekStart}
|
||||
weekDates={weekDates}
|
||||
isCurrentWeek={isCurrentWeek}
|
||||
coastersOnly={coastersOnly}
|
||||
hasCoasterData={hasCoasterData}
|
||||
/>
|
||||
<div className="hidden sm:flex">
|
||||
<Legend />
|
||||
@@ -157,7 +174,8 @@ export default async function HomePage({ searchParams }: PageProps) {
|
||||
weekDates={weekDates}
|
||||
data={data}
|
||||
today={today}
|
||||
rideCounts={rideCounts}
|
||||
rideCounts={activeCounts}
|
||||
coastersOnly={coastersOnly}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -168,7 +186,8 @@ export default async function HomePage({ searchParams }: PageProps) {
|
||||
weekDates={weekDates}
|
||||
data={data}
|
||||
grouped={grouped}
|
||||
rideCounts={rideCounts}
|
||||
rideCounts={activeCounts}
|
||||
coastersOnly={coastersOnly}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user