"use client"; import { GROUP_IDS, GroupId, Match, Team, teamName } from "@/lib/types"; import { computeGroupTables } from "@/lib/standings"; import { Dictionary } from "@/lib/i18n"; import Flag from "./Flag"; function teamById(teams: Team[], id: string | null) { return id ? teams.find((t) => t.id === id) : undefined; } function tzLabel(locale: string): string { try { const parts = new Intl.DateTimeFormat(locale === "en" ? "en-US" : "de-DE", { timeZoneName: "short" }) .formatToParts(new Date()); return parts.find((p) => p.type === "timeZoneName")?.value ?? ""; } catch { return ""; } } function fmtDate(iso: string, locale: string): string { const d = new Date(iso); const s = d.toLocaleString(locale === "en" ? "en-US" : "de-DE", { weekday: "short", day: "2-digit", month: "2-digit", hour: "2-digit", minute: "2-digit", }); const tz = tzLabel(locale); return tz ? `${s} ${tz}` : s; } function statusText(m: Match, dict: Dictionary): { text: string; live: boolean } { switch (m.status) { case "LIVE": case "IN_PLAY": return { text: m.minute != null ? `${m.minute}'` : dict.status.running, live: true }; case "PAUSED": return { text: dict.status.halftime, live: true }; case "FINISHED": return { text: dict.status.finished, live: false }; default: return { text: "", live: false }; } } // Mitte: Ergebnis (wenn vorhanden) oder ein schlichtes "–" bei ungespielten // Spielen. Datum/Uhrzeit steht bereits links im Status und wird hier NICHT // wiederholt. function ScoreCell({ m, dict }: { m: Match; dict: Dictionary }) { const hasScore = m.homeScore != null && m.awayScore != null; const st = statusText(m, dict); if (hasScore) { return ( {m.homeScore} : {m.awayScore} ); } return ; } function GroupStandings({ group, teams, matches, dict, }: { group: GroupId; teams: Team[]; matches: Match[]; dict: Dictionary }) { // Live-Tabelle: laufende Spiele werden mit Zwischenstand eingerechnet. const table = computeGroupTables(teams, matches, true).find((t) => t.group === group); if (!table) return null; // Teams, die gerade ein laufendes Spiel haben -> Zeile markieren. const liveTeamIds = new Set(); let hasLive = false; for (const m of matches) { if (m.group !== group) continue; if (m.status === "LIVE" || m.status === "IN_PLAY" || m.status === "PAUSED") { hasLive = true; if (m.homeTeamId) liveTeamIds.add(m.homeTeamId); if (m.awayTeamId) liveTeamIds.add(m.awayTeamId); } } return (
{dict.fixtures.standingsTitle(group)} {hasLive && {dict.label.liveIndicator}}
{table.rows.map((r) => { const team = teamById(teams, r.teamId); const cls = r.rank <= 2 ? `q${r.rank}` : r.rank === 3 ? "q3" : ""; const isLive = liveTeamIds.has(r.teamId); return ( ); })}
{dict.table.team} {dict.table.matches}{dict.table.won}{dict.table.drawn}{dict.table.lost} {dict.table.goals}{dict.table.goalDiff}{dict.table.points}
{r.rank} {teamName(team, "de")} {isLive && } {r.played} {r.won} {r.drawn} {r.lost} {r.goalsFor}:{r.goalsAgainst} {r.goalDiff > 0 ? `+${r.goalDiff}` : r.goalDiff} {r.points}
); } export default function Fixtures({ group, teams, matches, onSelectGroup, dict, locale, }: { group: GroupId; teams: Team[]; matches: Match[]; onSelectGroup: (g: GroupId) => void; dict: Dictionary; locale: string; }) { const intlLocale = locale === "en" ? "en-US" : "de-DE"; const list = matches .filter((m) => m.group === group) .sort((a, b) => +new Date(a.utcDate) - +new Date(b.utcDate)); return (
{GROUP_IDS.map((g) => ( ))}
{list.length === 0 ? (
{dict.fixtures.noMatches(group)}
) : (
{list.map((m) => { const home = teamById(teams, m.homeTeamId); const away = teamById(teams, m.awayTeamId); const st = statusText(m, dict); const displayText = st.text || fmtDate(m.utcDate, locale); const homeWin = m.homeScore != null && m.awayScore != null && m.homeScore > m.awayScore; const awayWin = m.homeScore != null && m.awayScore != null && m.awayScore > m.homeScore; return (
{st.live && } {displayText}
{teamName(home, locale)}
{teamName(away, locale)}
{(() => { const stadium = [m.stadiumName, m.stadiumCity].filter(Boolean).join(", "); const crowd = m.attendance != null ? m.attendance.toLocaleString(intlLocale) : ""; const sep = stadium && crowd ? " · " : ""; const text = stadium + sep + crowd; return text ? {text} : null; })()}
); })}
)} {list.length > 0 && ( )}
); }