Part 1 — CS2 playoff matches now appear in upcoming schedule:
getUpcomingEventsForDraftedParticipants (all-compete path) now also
picks up events with upcoming playoff_match_games.scheduledAt, so CS2
Champions Stage bracket games set via the admin bracket UI surface on
both /upcoming-events and the sport_season EventSchedule panel.
getUpcomingScoringEvents is updated to sort by earliest bracket game
time when eventDate/eventStartsAt are absent or past.
Part 2 — Auto floor-score CS2 Champions Stage qualifiers:
assignCs2EliminationQP now writes provisional floor event_result rows
(placement=5, QP = tie-split of slots 5–8) for the 8 Champions Stage
advancing teams once all Stage-3 exits are known. The bracket admin's
result entry overwrites these via onConflictDoUpdate.
Part 3 — Public event detail view:
New route /leagues/:leagueId/sports-seasons/:sportsSeasonId/events/:eventId
shows CS2 Swiss stage progress (W-L table + matches per stage) and the
Champions Stage bracket, bracket events (tennis/golf bracket + groups),
and results tables for QP/racing events. EventSchedule and
UpcomingCalendarPanel event rows now link to this detail page.
https://claude.ai/code/session_01RYK7NCjcaah545979wupcM
## Summary
- **Group stage match list**: Removed MD 1/2/3 headings; matches now listed chronologically under date separators (e.g. "Jun 14"). Kick-off time appears below the team names instead of between them.
- **Sort order**: \`findMatchesByGroupIds\` / \`findMatchesByEventId\` now order by \`scheduledAt ASC NULLS LAST\` so unscheduled matches always trail scheduled ones.
- **Groups/Bracket toggle**: When both group stage and knockout bracket exist, a toggle appears (mirroring the NBA/AFL standings toggle). Sports with both regular-season standings and a group stage get all views available.
- **Upcoming events**: \`getUpcomingEventsForDraftedParticipants\` now also queries \`groupStageMatches\`, so World Cup group fixtures appear on the home page calendar sorted by kick-off time with a label like "Group A — France vs Germany".
- **\`isAllCompete\` fix**: \`UpcomingEventsCard\` and \`UpcomingCalendarPanel\` now treat \`group_stage_match\` as a bracket-style event, showing team badges instead of "N of your picks".
Fixes#53
## Test plan
- [ ] Navigate to a World Cup sports season page — groups should be listed chronologically under date headers with no MD labels; kick-off time should appear below each match row
- [ ] Once the knockout bracket has matches, confirm the Groups/Bracket toggle appears and both views render correctly
- [ ] On the home page, a user with drafted World Cup participants should see upcoming group fixtures in the calendar panel with individual team badges (not a participant count)
- [ ] NBA/AFL/NHL pages unaffected — their standings/playoffs/finished toggle still works normally
- [ ] \`npm run typecheck\` and \`npm run test:run\` pass
Co-authored-by: Chris Parsons <chrisparsons1127@gmail.com>
Reviewed-on: #55
- Fix UTC midnight rollover bug: server now queries from yesterday UTC
as a buffer; UpcomingCalendarPanel filters to local-today client-side
via useEffect + Intl.DateTimeFormat, removing the need for any
cookie or server-side timezone detection
- Cap homepage and league page panels at 6 events with a "View all" link
- Add /upcoming-events page (60-day view across all leagues)
- Add /leagues/:leagueId/upcoming-events page (60-day per-league view)
- Add emptyMessage prop to UpcomingCalendarPanel for context-specific copy
- Change getUpcomingEventsForDraftedParticipants to accept pre-computed
date strings instead of Date objects
fixes#213
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>