feat: show all groups including unplayed, add upcoming matches per group

sync.ts: after computing standings from played matches, seed 0-0-0-0 rows
for every team in any group match, so all 12 groups always appear.

/groups: fetch all 2026 matches alongside standings; each group card now
shows results (score), live badge, and upcoming fixtures with local
kickoff time, sorted by UTC kickoff.

/tournaments/[year]: derive group list from union of standings + match
group names, so groups with no played matches still render with their
fixtures.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-15 19:47:52 +02:00
parent 76425e7f76
commit 71e7e47aca
3 changed files with 139 additions and 5 deletions
+12 -2
View File
@@ -100,7 +100,12 @@ export default function TournamentPage({ params }: { params: Promise<{ year: str
return acc
}, {})
const groupRounds = Object.entries(byGroup).sort(([a], [b]) => a.localeCompare(b))
// Union of groups from standings + groups from match data (handles groups with no played matches yet)
const groupNames = new Set([
...Object.keys(byGroup),
...allMatches.filter(m => m.group).map(m => m.group!),
])
const groupRounds = [...groupNames].sort().map(g => [g, byGroup[g] ?? []] as [string, Standing[]])
const koRounds = allMatches.filter(m => !m.group && !m.isQualiPlayoff)
const koByRound = koRounds.reduce<Record<string, MatchData[]>>((acc, m) => {
acc[m.round] = [...(acc[m.round] ?? []), m]
@@ -177,7 +182,12 @@ export default function TournamentPage({ params }: { params: Promise<{ year: str
<h2 className="font-['Bebas_Neue'] text-2xl text-green mb-5">Group Stage</h2>
{groupRounds.map(([groupName, rows]) => {
const sorted = [...rows].sort((a, b) => b.pts - a.pts || b.goalDiff - a.goalDiff)
const groupMatches = (byRound[groupName] ?? []).sort((a, b) => (a.date ?? '') < (b.date ?? '') ? -1 : 1)
const groupMatches = (byRound[groupName] ?? []).sort((a, b) => {
if (!a.date) return 1; if (!b.date) return -1
const cmp = a.date.localeCompare(b.date)
if (cmp !== 0) return cmp
return (a.time ?? '').localeCompare(b.time ?? '')
})
return (
<div key={groupName} className="mb-8">
<h3 className="text-[13px] font-bold text-green tracking-wide uppercase mb-3">{groupName}</h3>