import { cn } from "~/lib/utils"; import type { BracketPhase, ConferenceGroup } from "~/lib/bracket-templates"; import { TreeColumns, BracketMatchSlot, type BracketMatch, type BracketOwnership } from "./BracketTreeView"; import { BracketTreePaginated } from "./BracketTreePaginated"; interface TabbedBracketLayoutProps { rounds: string[]; matchesByRound: Map; ownershipMap: Map; userParticipantIds: Set; phases: BracketPhase[]; scoringRoundIdx: number; } const CARD_H = 112; const CARD_GAP = 14; function groupMatches( matchesByRound: Map, group: ConferenceGroup ): Map { const out = new Map(); for (const [round, allowed] of Object.entries(group.roundMatchNumbers)) { const filtered = (matchesByRound.get(round) ?? []).filter((m) => allowed.includes(m.matchNumber) ); if (filtered.length > 0) out.set(round, filtered); } return out; } function phaseHeight(matchesByRound: Map, rounds: string[]): number { const max = Math.max(...rounds.map((r) => matchesByRound.get(r)?.length ?? 0), 1); return max * (CARD_H + CARD_GAP); } // ─── Play-In Layout ─────────────────────────────────────────────────────────── interface PlayInColumnProps { label: string; description: string; match: BracketMatch | undefined; ownershipMap: Map; userParticipantIds: Set; } function PlayInColumn({ label, description, match, ownershipMap, userParticipantIds, }: PlayInColumnProps) { return (

{label}

{match ? ( ) : (
)}

{description}

); } interface PlayInLayoutProps { matchesByRound: Map; ownershipMap: Map; userParticipantIds: Set; } function PlayInLayout({ matchesByRound, ownershipMap, userParticipantIds }: PlayInLayoutProps) { const pir1 = matchesByRound.get("Play-In Round 1") ?? []; const pir2 = matchesByRound.get("Play-In Round 2") ?? []; const conferences = [ { name: "Eastern Conference", match78: pir1.find((m) => m.matchNumber === 1), match910: pir1.find((m) => m.matchNumber === 2), matchFor8: pir2.find((m) => m.matchNumber === 1), }, { name: "Western Conference", match78: pir1.find((m) => m.matchNumber === 3), match910: pir1.find((m) => m.matchNumber === 4), matchFor8: pir2.find((m) => m.matchNumber === 2), }, ]; return (
{conferences.map((conf) => (

{conf.name}

))}
); } // ─── Main component ─────────────────────────────────────────────────────────── export function TabbedBracketLayout({ rounds, matchesByRound, ownershipMap, userParticipantIds, phases, scoringRoundIdx, }: TabbedBracketLayoutProps) { return (
{phases.map((phase) => { const groupRounds = phase.groups ? rounds.filter((r) => phase.groups?.some((g) => g.roundMatchNumbers[r] !== undefined)) : []; const sharedRounds = (phase.sharedRounds ?? []).filter((r) => rounds.includes(r)); const simpleRounds = phase.groups ? [] : (phase.rounds ?? []).filter((r) => rounds.includes(r)); const phaseRounds = phase.groups ? [...groupRounds, ...sharedRounds] : simpleRounds; const phaseMatchesByRound = new Map(phaseRounds.map((r) => [r, matchesByRound.get(r) ?? []])); const sharedMatchesByRound = new Map(sharedRounds.map((r) => [r, matchesByRound.get(r) ?? []])); const phaseFirstScoringIdx = phaseRounds.findIndex((r) => rounds.indexOf(r) >= scoringRoundIdx); return (

1 ? "text-muted-foreground" : "hidden" )}> {phase.name}

{/* Desktop */}
{phase.layout === "play-in" ? ( ) : phase.groups ? (
{phase.groups.map((group) => { const gMatches = groupMatches(matchesByRound, group); const gRounds = groupRounds.filter((r) => group.roundMatchNumbers[r] !== undefined); return (

{group.name}

); })} {sharedRounds.length > 0 && ( )}
) : ( )}
{/* Mobile */}
{phase.layout === "play-in" ? ( ) : ( = 0 ? phaseFirstScoringIdx : undefined} /> )}
); })}
); }