import { useState, useEffect } from "preact/hooks"; import type { Trip, Day, DayStop } from "./types"; export interface TripTimeState { now: Date; todayIdx: number; currentStopIdx: number; nextStopIdx: number; today: Day | null; currentStop: DayStop | null; nextStop: DayStop | null; tripStarted: boolean; tripEnded: boolean; } function parseTime(timeStr: string, dateStr: string): Date | null { const m = timeStr.replace(/^~\s*/, "").match(/^(\d{1,2}):(\d{2})\s*(AM|PM)$/i); if (!m) return null; let hours = parseInt(m[1]); const mins = parseInt(m[2]); const ampm = m[3].toUpperCase(); if (ampm === "PM" && hours !== 12) hours += 12; if (ampm === "AM" && hours === 12) hours = 0; const d = new Date(dateStr + "T00:00:00"); d.setHours(hours, mins, 0, 0); return d; } function parseTimeRange(str: string, dateStr: string): { start: Date; end: Date } | null { const parts = str.match(/^(\d{1,2}:\d{2}\s*(?:AM|PM))\s*[-–]\s*(\d{1,2}:\d{2}\s*(?:AM|PM))$/i); if (parts) { const start = parseTime(parts[1].trim(), dateStr); const end = parseTime(parts[2].trim(), dateStr); if (start && end) return { start, end }; } return null; } export function useTripTime(trip: Trip): TripTimeState { const [now, setNow] = useState(new Date()); useEffect(() => { const id = setInterval(() => setNow(new Date()), 30000); return () => clearInterval(id); }, []); const todayStr = now.toLocaleDateString("en-CA"); const todayIdx = trip.days.findIndex(d => d.date === todayStr); const today = todayIdx >= 0 ? trip.days[todayIdx] : null; const firstDate = trip.meta.dates[0]; const lastDate = trip.meta.dates[trip.meta.dates.length - 1]; const tripStarted = todayStr >= firstDate; const tripEnded = todayStr > lastDate; let currentStopIdx = -1; let nextStopIdx = -1; if (today) { for (let i = today.stops.length - 1; i >= 0; i--) { const stop = today.stops[i]; const timeRef = stop.arrival || stop.departure; if (!timeRef) continue; const range = parseTimeRange(timeRef, today.date); if (range) { if (now >= range.start && now <= range.end) { currentStopIdx = i; nextStopIdx = i + 1 < today.stops.length ? i + 1 : -1; break; } if (now > range.end) { nextStopIdx = i + 1 < today.stops.length ? i + 1 : -1; break; } continue; } const t = parseTime(timeRef, today.date); if (t && now >= t) { currentStopIdx = i; nextStopIdx = i + 1 < today.stops.length ? i + 1 : -1; break; } } if (currentStopIdx === -1 && nextStopIdx === -1 && today.stops.length > 0) { for (let i = 0; i < today.stops.length; i++) { const ref = today.stops[i].arrival || today.stops[i].departure; if (!ref) continue; const range = parseTimeRange(ref, today.date); const t = range ? range.start : parseTime(ref, today.date); if (t && now < t) { nextStopIdx = i; } break; } } } return { now, todayIdx, currentStopIdx, nextStopIdx, today, currentStop: today && currentStopIdx >= 0 ? today.stops[currentStopIdx] : null, nextStop: today && nextStopIdx >= 0 ? today.stops[nextStopIdx] : null, tripStarted, tripEnded, }; }