feat: add per-ride history charts with wait time and uptime tracking
Build and Deploy / Build & Push (push) Successful in 3m7s

Adds a cron-driven sampler that snapshots Queue-Times waits and Six Flags
Fast Lane data every 5 minutes into a new ride_wait_samples table, and a
clickable per-ride detail page at /park/[id]/ride/[slug] with Today / 7d /
30d Recharts views plus a 30d uptime pill. Rides are keyed by Queue-Times'
stable qt_ride_id so renames don't fragment history. Samples store
pre-bucketed local_date and local_time in the park's IANA timezone so
aggregations are pure SQL and DST-safe.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-29 23:35:27 -04:00
parent bfe099322f
commit 4f838d99c1
25 changed files with 2052 additions and 18 deletions
+6
View File
@@ -19,6 +19,8 @@ const HEADERS = {
};
export interface LiveRide {
/** Stable Queue-Times ride ID — survives renames, used as the history key. */
qtRideId: number;
name: string;
isOpen: boolean;
waitMinutes: number;
@@ -30,6 +32,8 @@ export interface LiveRide {
hasFastLane?: boolean;
/** Current Fast Lane wait in minutes; null = no data / walk-on. Set by the rides route. */
fastLaneMinutes?: number | null;
/** URL-safe slug derived from name. Set by the rides route. */
slug?: string;
}
export interface LiveRidesResult {
@@ -95,6 +99,7 @@ export async function fetchLiveRides(
for (const r of land.rides ?? []) {
if (!r.name) continue;
rides.push({
qtRideId: r.id,
name: r.name,
isOpen: r.is_open,
waitMinutes: r.wait_time ?? 0,
@@ -108,6 +113,7 @@ export async function fetchLiveRides(
for (const r of json.rides ?? []) {
if (!r.name) continue;
rides.push({
qtRideId: r.id,
name: r.name,
isOpen: r.is_open,
waitMinutes: r.wait_time ?? 0,