From 9a04e25c20f0f29514816783bf09311c2c88da30 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 17 Jun 2026 16:57:40 +0000 Subject: [PATCH] Also fetch group stage match times for sport-season event schedule The previous fix only queried playoffMatchGames.scheduledAt for bracket events. FIFA World Cup group stage matches live in groupStageMatches (linked via tournamentGroups), not playoffMatchGames. Now getUpcomingScoringEvents fetches both tables in parallel and uses the earliest scheduledAt from either source as earliestGameTime, matching what UpcomingCalendarPanel already shows on the Upcoming Events page. Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01KiVGo8gSBXe3WuRniVNKsd --- app/models/scoring-event.ts | 65 ++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/app/models/scoring-event.ts b/app/models/scoring-event.ts index d1abd32..26e31e9 100644 --- a/app/models/scoring-event.ts +++ b/app/models/scoring-event.ts @@ -310,33 +310,54 @@ export async function getUpcomingScoringEvents( if (events.length === 0) return []; - // Find earliest upcoming game time per event from bracket match games. + // Find earliest upcoming game time per event from both bracket match games + // and group stage matches (FIFA World Cup style). const eventIds = events.map((e) => e.id); const now = new Date(); - const gameTimeRows = await db - .select({ - eventId: schema.scoringEvents.id, - scheduledAt: schema.playoffMatchGames.scheduledAt, - }) - .from(schema.scoringEvents) - .innerJoin( - schema.playoffMatches, - eq(schema.playoffMatches.scoringEventId, schema.scoringEvents.id) - ) - .innerJoin( - schema.playoffMatchGames, - eq(schema.playoffMatchGames.playoffMatchId, schema.playoffMatches.id) - ) - .where( - and( - inArray(schema.scoringEvents.id, eventIds), - isNotNull(schema.playoffMatchGames.scheduledAt), - gte(schema.playoffMatchGames.scheduledAt, now) + + const [gameTimeRows, groupStageTimeRows] = await Promise.all([ + db + .select({ + eventId: schema.scoringEvents.id, + scheduledAt: schema.playoffMatchGames.scheduledAt, + }) + .from(schema.scoringEvents) + .innerJoin( + schema.playoffMatches, + eq(schema.playoffMatches.scoringEventId, schema.scoringEvents.id) ) - ); + .innerJoin( + schema.playoffMatchGames, + eq(schema.playoffMatchGames.playoffMatchId, schema.playoffMatches.id) + ) + .where( + and( + inArray(schema.scoringEvents.id, eventIds), + isNotNull(schema.playoffMatchGames.scheduledAt), + gte(schema.playoffMatchGames.scheduledAt, now) + ) + ), + db + .select({ + eventId: schema.tournamentGroups.scoringEventId, + scheduledAt: schema.groupStageMatches.scheduledAt, + }) + .from(schema.groupStageMatches) + .innerJoin( + schema.tournamentGroups, + eq(schema.groupStageMatches.tournamentGroupId, schema.tournamentGroups.id) + ) + .where( + and( + inArray(schema.tournamentGroups.scoringEventId, eventIds), + isNotNull(schema.groupStageMatches.scheduledAt), + gte(schema.groupStageMatches.scheduledAt, now) + ) + ), + ]); const earliestGameById = new Map(); - for (const row of gameTimeRows) { + for (const row of [...gameTimeRows, ...groupStageTimeRows]) { if (!row.scheduledAt) continue; const prev = earliestGameById.get(row.eventId); if (!prev || row.scheduledAt < prev) {