2e284ec49e
For shootout games the FT score (e.g. 2–2) was the main display, which was misleading. Now the penalty score is the headline (4–2) with "2–2 a.e.t." below it. Winner highlighting also uses the penalty score. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
110 lines
4.9 KiB
TypeScript
110 lines
4.9 KiB
TypeScript
import Link from 'next/link'
|
||
import { TeamFlag } from './team-flag'
|
||
import { LiveBadge } from './live-badge'
|
||
|
||
interface Team { name: string; iso2?: string | null }
|
||
interface Match {
|
||
id: number
|
||
year: number
|
||
round: string
|
||
group?: string | null
|
||
date?: string | null
|
||
time?: string | null
|
||
team1: Team
|
||
team2: Team
|
||
scoreFt?: number[] | null
|
||
scoreEt?: number[] | null
|
||
scoreP?: number[] | null
|
||
isLive: boolean
|
||
}
|
||
|
||
function formatDate(d: string) {
|
||
return new Date(d).toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' })
|
||
}
|
||
|
||
export function MatchCard({ match, compact = false }: { match: Match; compact?: boolean }) {
|
||
const ft = match.scoreFt
|
||
const hasScore = ft != null
|
||
// Penalty score determines the winner when present
|
||
const decisive = match.scoreP ?? ft
|
||
const winner = decisive ? (decisive[0] > decisive[1] ? 'home' : decisive[0] < decisive[1] ? 'away' : 'draw') : null
|
||
|
||
if (compact) {
|
||
return (
|
||
<Link href={`/tournaments/${match.year}#match-${match.id}`} className="block">
|
||
<div className="bg-[#0a1810] border border-[rgba(34,197,94,0.08)] rounded-xl p-3.5 hover:border-[rgba(34,197,94,0.22)] transition-colors">
|
||
<div className="text-[9px] text-[#2a5c35] tracking-[0.1em] uppercase mb-2.5">
|
||
{match.round}{match.group ? ` · ${match.group}` : ''} · {match.date ? formatDate(match.date) : ''}
|
||
</div>
|
||
<div className="flex items-center gap-2">
|
||
<div className="flex-1 flex items-center gap-2 overflow-hidden">
|
||
<TeamFlag name={match.team1.name} iso2={match.team1.iso2} size="sm" />
|
||
<span className={`text-sm font-medium truncate ${winner === 'home' ? 'text-[#dff5e8]' : 'text-[#4a7a55]'}`}>
|
||
{match.team1.name}
|
||
</span>
|
||
</div>
|
||
<div className="flex-shrink-0 min-w-[52px] text-center">
|
||
<div className="font-['Bebas_Neue'] text-xl text-[#22c55e]">
|
||
{hasScore
|
||
? match.scoreP
|
||
? `${match.scoreP[0]} – ${match.scoreP[1]}`
|
||
: `${ft![0]} – ${ft![1]}`
|
||
: match.isLive ? <LiveBadge label="•" /> : '–'}
|
||
</div>
|
||
{match.scoreP && (
|
||
<div className="text-[8px] text-[#2a5c35] leading-none">
|
||
{ft![0]}–{ft![1]} a.e.t.
|
||
</div>
|
||
)}
|
||
</div>
|
||
<div className="flex-1 flex items-center justify-end gap-2 overflow-hidden">
|
||
<span className={`text-sm font-medium truncate ${winner === 'away' ? 'text-[#dff5e8]' : 'text-[#4a7a55]'}`}>
|
||
{match.team2.name}
|
||
</span>
|
||
<TeamFlag name={match.team2.name} iso2={match.team2.iso2} size="sm" />
|
||
</div>
|
||
</div>
|
||
{match.scoreEt && !match.scoreP && (
|
||
<div className="text-[9px] text-[#2a5c35] mt-1 text-center">a.e.t.</div>
|
||
)}
|
||
</div>
|
||
</Link>
|
||
)
|
||
}
|
||
|
||
return (
|
||
<Link href={`/tournaments/${match.year}#match-${match.id}`} className="block">
|
||
<div className="bg-gradient-to-br from-[#0d2016] to-[#102a1c] border border-[rgba(34,197,94,0.28)] rounded-2xl p-9 hover:border-[rgba(34,197,94,0.45)] transition-colors">
|
||
{match.isLive && <div className="mb-4"><LiveBadge label="Live Now" /></div>}
|
||
<div className="flex items-center justify-center gap-8 flex-wrap">
|
||
<div className="text-center flex-1 min-w-[100px]">
|
||
<TeamFlag name={match.team1.name} iso2={match.team1.iso2} size="xl" className="mb-2.5" />
|
||
<div className="font-['Bebas_Neue'] text-xl tracking-[0.07em] text-[#dff5e8]">{match.team1.name}</div>
|
||
</div>
|
||
<div className="text-center flex-shrink-0">
|
||
<div className="font-['Bebas_Neue'] text-[76px] text-[#22c55e] leading-none">
|
||
{hasScore
|
||
? match.scoreP
|
||
? `${match.scoreP[0]} – ${match.scoreP[1]}`
|
||
: `${ft![0]} – ${ft![1]}`
|
||
: '? – ?'}
|
||
</div>
|
||
{match.scoreP && (
|
||
<div className="text-[11px] text-[#2a5c35] mt-0.5">{ft![0]}–{ft![1]} a.e.t.</div>
|
||
)}
|
||
<div className="text-[10px] text-[#2a5c35] tracking-[0.12em] uppercase mt-1.5">{match.round}</div>
|
||
<div className="text-xs text-[#1a3a22] mt-1">{match.date ? formatDate(match.date) : ''}</div>
|
||
{match.scoreEt && !match.scoreP && (
|
||
<div className="text-[10px] text-[#2a5c35] mt-1">a.e.t. {match.scoreEt[0]}–{match.scoreEt[1]}</div>
|
||
)}
|
||
</div>
|
||
<div className="text-center flex-1 min-w-[100px]">
|
||
<TeamFlag name={match.team2.name} iso2={match.team2.iso2} size="xl" className="mb-2.5" />
|
||
<div className="font-['Bebas_Neue'] text-xl tracking-[0.07em] text-[#dff5e8]">{match.team2.name}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</Link>
|
||
)
|
||
}
|