Commit graph

7 commits

Author SHA1 Message Date
Chris Parsons
0397da22fb Fix lint: move pad helper to module scope in date-utils
All checks were successful
🚀 Deploy / 🧪 Test (pull_request) Successful in 2m58s
🚀 Deploy / ʦ🔍 Typecheck & Lint (pull_request) Successful in 1m25s
🚀 Deploy / 🐳 Build (pull_request) Has been skipped
🚀 Deploy / 🚀 Deploy (pull_request) Has been skipped
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 18:58:03 -07:00
Claude
74f117f1c1
Fix group-stage match times being stored as local-wall-time-as-UTC
The admin group-stage schedule form submitted the raw datetime-local
string, which the server parsed with new Date() in the server's timezone
(UTC), so an admin's local wall-clock time was stored as if it were UTC.
Downstream displays then correctly converted UTC->local, shifting times
by the admin's UTC offset (e.g. 7 PM PDT showed as 12 PM).

Mirror the existing playoff "add-game" form: convert local->UTC on the
client via localDateTimeToUtcIso into a hidden field on submit, and
render the stored UTC value back into the input in the browser's local
timezone via a client-only effect (avoids SSR hydration mismatch).

Adds utcIsoToLocalDateTime helper (inverse of localDateTimeToUtcIso)
with unit tests covering nullish/invalid input and a tz-independent
round-trip.

Note: matches saved before this fix must be re-saved once in admin to
correct their stored values.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0125nZohVD2Cpoq3Q9f4jeds
2026-06-17 20:42:49 +00:00
08ae2bb88a Fix SSR/hydration timezone flip in event date and time display (#95)
All checks were successful
🚀 Deploy / ʦ🔍 Typecheck & Lint (push) Successful in 1m38s
🚀 Deploy / 🧪 Test (push) Successful in 3m30s
🚀 Deploy / 🐳 Build (push) Successful in 1m9s
🚀 Deploy / 🚀 Deploy (push) Successful in 11s
## Summary

- Adds `useHasMounted` hook (using `useSyncExternalStore` — no extra render cycle) to gate UTC timestamp formatting to client-only
- Fixes the visible time-flip in `EventSchedule` and `UpcomingCalendarPanel` where SSR rendered UTC time (e.g. "9:00 PM") and the client re-rendered with local time (e.g. "2:00 PM PDT") after hydration, with `suppressHydrationWarning` silently hiding the mismatch
- Fixes `formatEventDate` in `date-utils.ts` (and `EventSchedule`'s private copy) to parse `YYYY-MM-DD` strings as local midnight instead of UTC midnight, correcting an off-by-one day bug for UTC-negative users across all callers

## Test plan

- [ ] Navigate to a sports season page — confirm event times show in local timezone with no flash/flip on load
- [ ] Hard-reload the page — confirm no brief UTC time visible before settling on local time
- [ ] Check the home page `UpcomingCalendarPanel` — confirm same behavior
- [ ] Verify dates display correctly (e.g. no "Jun 17" showing for a "Jun 18" event near midnight UTC)

Co-authored-by: Chris Parsons <chrisparsons1127@gmail.com>
Reviewed-on: #95
2026-06-17 06:09:29 +00:00
Chris Parsons
84787c9a4b
Consolidate F1/IndyCar simulators into shared AutoRacingSimulator class (#151)
Replaces the duplicated F1Simulator (which was copy-pasted for IndyCar) with a
single AutoRacingSimulator that accepts a race points table at construction time.
Registry entries for f1_standings and indycar_standings remain separate, each
wired to the correct scoring system (F1: top-10, IndyCar: top-26 positions).

Also imports SIMULATOR_TYPES from registry into the admin route to eliminate the
duplicate hardcoded array, and updates stale comments mentioning F1/IndyCar.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 12:22:08 -07:00
Chris Parsons
dc13d99f39
Add event_starts_at timestamp to scoring events for sub-day ordering (#146)
- New `event_starts_at timestamptz` column on `scoring_events`; backfilled
  from `event_date` (midnight UTC) via migration for all existing rows
- Admin create/edit forms consolidated from separate Date + Time inputs into
  a single `datetime-local` field; server derives `eventDate` from the UTC
  date portion of `eventStartsAt` so calendar-window queries continue to work
- Edit form pre-fill computed client-side via useEffect to avoid server-timezone
  mismatch for non-UTC admins
- Sort fix: replaced `eventDate ?? earliestGameTime.split("T")[0]` with
  `toEventSortKey` helper that prefers `earliestGameTime ?? eventDate` so
  bracket events with only per-game timestamps sort in the correct calendar position
- DB sort queries updated to use `eventStartsAt` as a tiebreaker after `eventDate`
- F1/IndyCar/golf events now populate `earliestGameTime` from `eventStartsAt`,
  giving time display in `UpcomingCalendarPanel`
- Bulk import gains optional `HH:MM` (UTC) third column
- New unit tests for `toEventSortKey` and `eventStartsAt` model behavior

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 10:22:42 -07:00
Chris Parsons
4fe76b6845
Display upcoming matches (#141) 2026-03-12 10:12:38 -07:00
Chris Parsons
ed4e99b40e
Fix datetime-local to UTC conversion for game scheduling (#138)
* fix: use hidden input for UTC date value in add-game form

The onSubmit handler was setting the datetime-local input's value to an
ISO UTC string (e.g. "2026-03-11T17:00:00.000Z"). datetime-local inputs
only accept the format "YYYY-MM-DDTHH:MM" — values with a 'Z' timezone
suffix are invalid and the browser silently clears the field to "". This
caused the form to submit an empty scheduledAt, which the server treated
as null, so games were always saved without a date.

Fix by keeping the datetime-local input for user interaction (renamed
scheduledAtLocal, not submitted) and writing the converted UTC ISO string
into a separate hidden input named scheduledAt in the onSubmit handler.

Also adds app/lib/date-utils.ts with a localDateTimeToUtcIso helper and
matching tests to document and verify the datetime-local ↔ ISO conversion
behaviour.

https://claude.ai/code/session_0148fgZiXpyvGX8ZX3BFRGCs

* refactor: use localDateTimeToUtcIso in component and clean up tests

- Import and call localDateTimeToUtcIso in the add-game onSubmit handler
  instead of duplicating the conversion inline; also applies the null/
  invalid-date safety from the utility to the component
- Remove the redundant "incompatible with datetime-local" test case (its
  intent is better expressed as a code comment than a test assertion)
- Move the datetime-local incompatibility explanation into a NOTE comment
  on the utility function's JSDoc

https://claude.ai/code/session_0148fgZiXpyvGX8ZX3BFRGCs

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-11 16:22:29 -07:00