103 lines
5.1 KiB
React
103 lines
5.1 KiB
React
// frontend/src/components/Tournament/Podium.jsx
|
|
|
|
import { Trophy } from 'lucide-react';
|
|
import { printName } from '../../utils/helpers';
|
|
|
|
export default function Podium({ matches }) {
|
|
const isDoubleElim = matches.some(m => m.bracket === 'Loser');
|
|
|
|
const wb = matches.filter(m => m.bracket === 'Winner').sort((a, b) => a.round - b.round);
|
|
const lb = matches.filter(m => m.bracket === 'Loser').sort((a, b) => a.round - b.round);
|
|
const finals = matches.filter(m => m.bracket === 'Finals').sort((a, b) => a.round - b.round);
|
|
|
|
let gfMatch = null;
|
|
let resetMatch = null;
|
|
let tpMatch = null;
|
|
|
|
if (isDoubleElim) {
|
|
tpMatch = lb[lb.length - 1];
|
|
gfMatch = finals[0];
|
|
resetMatch = finals[1];
|
|
} else {
|
|
gfMatch = wb[wb.length - 1];
|
|
tpMatch = finals[0];
|
|
}
|
|
|
|
const podium = [
|
|
{ rank: 1, label: "1st", team: "TBD", isReal: false, color: "bg-yellow-400 text-yellow-900 dark:text-yellow-950 shadow-yellow-400/50" },
|
|
{ rank: 2, label: "2nd", team: "TBD", isReal: false, color: "bg-zinc-300 dark:bg-zinc-400 text-zinc-800 dark:text-zinc-900 shadow-zinc-400/50" },
|
|
{ rank: 3, label: "3rd", team: "TBD", isReal: false, color: "bg-amber-600 text-amber-50 dark:text-amber-50 shadow-amber-600/50", hidden: false }
|
|
];
|
|
|
|
// --- CALCULATE 3RD PLACE ---
|
|
if (tpMatch) {
|
|
if (tpMatch.isFinished && tpMatch.winnerName) {
|
|
// If match is done, grab the actual team name
|
|
podium[2].team = isDoubleElim
|
|
? (tpMatch.winnerName === tpMatch.p1 ? tpMatch.p2 : tpMatch.p1) // DE: Loser of LB Final
|
|
: tpMatch.winnerName; // SE: Winner of 3rd Place Match
|
|
podium[2].isReal = true;
|
|
} else {
|
|
// Set the exact string expected by the print formatter
|
|
podium[2].team = isDoubleElim ? `Loser of #${tpMatch.number}` : `Winner of #${tpMatch.number}`;
|
|
}
|
|
} else {
|
|
podium[2].hidden = true;
|
|
}
|
|
|
|
// --- CALCULATE 1ST & 2ND PLACE ---
|
|
if (resetMatch && resetMatch.isFinished && resetMatch.winnerName) {
|
|
podium[0].team = resetMatch.winnerName;
|
|
podium[0].isReal = true;
|
|
podium[1].team = resetMatch.winnerName === resetMatch.p1 ? resetMatch.p2 : resetMatch.p1;
|
|
podium[1].isReal = true;
|
|
} else if (gfMatch) {
|
|
if (gfMatch.isFinished && gfMatch.winnerName) {
|
|
// Has the loser bracket champ won, forcing a reset?
|
|
const isResetForced = resetMatch && resetMatch.hasTeams;
|
|
|
|
if (!isResetForced) {
|
|
// GF Winner is 1st, GF Loser is 2nd
|
|
podium[0].team = gfMatch.winnerName;
|
|
podium[0].isReal = true;
|
|
podium[1].team = gfMatch.winnerName === gfMatch.p1 ? gfMatch.p2 : gfMatch.p1;
|
|
podium[1].isReal = true;
|
|
} else {
|
|
// Reset forced, wait for the final match
|
|
podium[0].team = `Winner of #${resetMatch.number}`;
|
|
podium[1].team = `Loser of #${resetMatch.number}`;
|
|
}
|
|
} else {
|
|
// GF not finished yet
|
|
podium[0].team = `Winner of #${gfMatch.number}`;
|
|
podium[1].team = `Loser of #${gfMatch.number}`;
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="bg-white dark:bg-zinc-900 print:!bg-white border border-zinc-200 dark:border-zinc-800 print:!border-zinc-400 rounded-xl shadow-sm w-64 overflow-hidden z-10 print:!shadow-none">
|
|
<div className="bg-zinc-50 dark:bg-zinc-900/50 print:!bg-transparent p-3 border-b border-zinc-200 dark:border-zinc-800 print:!border-zinc-400">
|
|
<h3 className="text-[10px] font-black uppercase tracking-[0.2em] text-zinc-500 print:!text-zinc-600 text-center flex items-center justify-center gap-2">
|
|
<Trophy size={14} className="text-orange-500 print:!text-black" /> Final Standings
|
|
</h3>
|
|
</div>
|
|
<div className="p-4 space-y-4">
|
|
{podium.filter(p => !p.hidden).map(p => (
|
|
<div key={p.rank} className="flex items-center gap-3">
|
|
<div className={`w-7 h-7 rounded-full flex items-center justify-center font-black text-xs shrink-0 shadow-sm print:!shadow-none print:!bg-white print:!border print:!border-zinc-400 print:!text-black ${p.color}`}>
|
|
{p.rank}
|
|
</div>
|
|
{/* Web Label */}
|
|
<div className={`text-sm truncate print:hidden ${p.isReal ? 'font-bold text-zinc-900 dark:text-white print:!text-black' : 'font-medium italic text-zinc-400 print:!text-zinc-600'}`} title={p.team}>
|
|
{p.team}
|
|
</div>
|
|
{/* Print Label */}
|
|
<div className={`hidden print:block text-sm print:whitespace-normal print:overflow-visible ${p.isReal ? 'font-bold print:!text-black' : 'font-medium italic print:!text-zinc-600'}`}>
|
|
{printName(p.team)}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
} |