feat: show open dot based on hours, Weather Delay when queue-times shows 0 rides
All checks were successful
Build and Deploy / Build & Push (push) Successful in 49s

Park open indicator now derives from scheduled hours, not ride counts.
Parks with queue-times coverage but 0 open rides (e.g. storm) show a
"⛈ Weather Delay" notice instead of a ride count on both desktop and mobile.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Josh Wright
2026-04-05 14:56:54 -04:00
parent d84a15ad64
commit 32f0d05038
5 changed files with 61 additions and 10 deletions

View File

@@ -63,12 +63,16 @@ export default async function HomePage({ searchParams }: PageProps) {
let rideCounts: Record<string, number> = {};
let coasterCounts: Record<string, number> = {};
let closingParkIds: string[] = [];
let openParkIds: string[] = [];
let weatherDelayParkIds: string[] = [];
if (weekDates.includes(today)) {
// Parks within operating hours right now (for open dot — independent of ride counts)
const openTodayParks = PARKS.filter((p) => {
const dayData = data[p.id]?.[today];
if (!dayData?.isOpen || !QUEUE_TIMES_IDS[p.id] || !dayData.hoursLabel) return false;
if (!dayData?.isOpen || !dayData.hoursLabel) return false;
return isWithinOperatingWindow(dayData.hoursLabel, p.timezone);
});
openParkIds = openTodayParks.map((p) => p.id);
closingParkIds = openTodayParks
.filter((p) => {
const dayData = data[p.id]?.[today];
@@ -77,17 +81,23 @@ export default async function HomePage({ searchParams }: PageProps) {
: false;
})
.map((p) => p.id);
// Only fetch ride counts for parks that have queue-times coverage
const trackedParks = openTodayParks.filter((p) => QUEUE_TIMES_IDS[p.id]);
const results = await Promise.all(
openTodayParks.map(async (p) => {
trackedParks.map(async (p) => {
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 rideCount = result ? result.rides.filter((r) => r.isOpen).length : null;
const coasterCount = result ? result.rides.filter((r) => r.isOpen && r.isCoaster).length : 0;
return { id: p.id, rideCount, coasterCount };
})
);
// Parks with queue-times coverage but 0 open rides = likely weather delay
weatherDelayParkIds = results
.filter(({ rideCount }) => rideCount === 0)
.map(({ id }) => id);
rideCounts = Object.fromEntries(
results.filter(({ rideCount }) => rideCount > 0).map(({ id, rideCount }) => [id, rideCount])
results.filter(({ rideCount }) => rideCount != null && rideCount > 0).map(({ id, rideCount }) => [id, rideCount!])
);
coasterCounts = Object.fromEntries(
results.filter(({ coasterCount }) => coasterCount > 0).map(({ id, coasterCount }) => [id, coasterCount])
@@ -103,7 +113,9 @@ export default async function HomePage({ searchParams }: PageProps) {
data={data}
rideCounts={rideCounts}
coasterCounts={coasterCounts}
openParkIds={openParkIds}
closingParkIds={closingParkIds}
weatherDelayParkIds={weatherDelayParkIds}
hasCoasterData={hasCoasterData}
scrapedCount={scrapedCount}
/>