Files
cup26/src/components/GroupTable.tsx
T
NilsBriggen 4faedd60c4 Surrounding screens refresh: live hero, row-style match cards, form bars, unified bracket
Design handoff steps 4-5:
- LivePage: headline live-match hero (gradient card, live ring, smallcaps
  stage/venue + minute, big mono score, 3-segment in-play win-prob bar);
  favorite team's live match takes the hero slot
- MatchCard: played matches as stacked team rows with the beaten side
  dimmed; scheduled matches as a centered 'vs' pairing (model hint and
  venue stay)
- GroupTable: Form column — tiny W/D/L bars (accent/gold/loss) computed
  from finished group matches
- BracketPage: one round-selector layout on every screen size (cards in
  a 2-col grid, losers dimmed), gold 'Projected champion' banner on the
  Final view; what-if mode, advance bars, R32 and the third-place
  play-off all unchanged
- Predict title race: leader bar, rank and percentage in gold

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 11:37:06 +02:00

87 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Link } from '@tanstack/react-router';
import { cn } from '@/lib/cn';
import { teamFlag } from '@/lib/teams';
import { fmt, useT } from '@/lib/i18n';
import type { StandingRow } from '@/lib/types';
export type FormLetter = 'W' | 'D' | 'L';
/** Tiny result bars, oldest → newest: W accent · D gold · L loss. */
function FormBars({ form }: { form: FormLetter[] }) {
const t = useT();
if (!form.length) return <span className="text-faint"></span>;
return (
<span className="inline-flex items-end gap-[3px]" role="img" aria-label={form.join(' ')}>
{form.map((r, i) => (
<span
key={i}
title={t.groups.formLetter[r]}
className={cn(
'inline-block w-1.5 rounded-[2px]',
r === 'W' && 'h-3.5 bg-accent',
r === 'D' && 'h-2.5 bg-gold',
r === 'L' && 'h-2.5 bg-loss',
)}
/>
))}
</span>
);
}
/** One group's standings. Top 2 qualify directly; 3rd may advance as a best-third. */
export function GroupTable({ group, rows, form }: { group: string; rows: StandingRow[]; form?: Record<string, FormLetter[]> }) {
const t = useT();
return (
<div className="overflow-hidden rounded-xl border border-line bg-panel">
<div className="flex items-center justify-between border-b border-line px-3 py-2">
<span className="font-display text-sm font-bold text-ink">{fmt(t.common.group, { group })}</span>
<span className="smallcaps">{t.groups.tableHeaderPldPts}</span>
</div>
<table className="w-full border-collapse text-sm">
<thead>
<tr className="text-[11px] uppercase tracking-wide text-faint">
<th className="px-3 py-1.5 text-left font-semibold">{t.groups.colTeam}</th>
<th className="w-8 py-1.5 text-center font-semibold">{t.groups.colPlayed}</th>
<th className="w-8 py-1.5 text-center font-semibold">{t.groups.colGoalDiff}</th>
<th className="w-9 py-1.5 text-center font-semibold">{t.groups.colPoints}</th>
{form && <th className="w-10 py-1.5 pr-3 text-center font-semibold">{t.groups.colForm}</th>}
</tr>
</thead>
<tbody>
{rows.map((r) => (
<tr
key={r.team}
className={cn(
'border-t border-line/60',
r.rank <= 2 && 'bg-accent-glow',
r.rank === 3 && 'bg-gold/5',
)}
>
<td className="px-3 py-1.5">
<Link to="/team/$name" params={{ name: r.team }} className="flex items-center gap-2 hover:text-accent">
<span
className={cn(
'w-4 text-center text-[11px] font-bold tabular-nums',
r.rank <= 2 ? 'text-accent' : r.rank === 3 ? 'text-gold' : 'text-faint',
)}
>
{r.rank}
</span>
<span aria-hidden className="text-base leading-none">{teamFlag(r.team)}</span>
<span className="truncate text-ink">{r.team}</span>
</Link>
</td>
<td className="py-1.5 text-center tabular-nums text-muted">{r.played}</td>
<td className="py-1.5 text-center tabular-nums text-muted">
{r.gd > 0 ? `+${r.gd}` : r.gd}
</td>
<td className="py-1.5 text-center font-bold tabular-nums text-ink">{r.points}</td>
{form && <td className="py-1.5 pr-3 text-center"><FormBars form={form[r.team] ?? []} /></td>}
</tr>
))}
</tbody>
</table>
</div>
);
}