diff --git a/app/lib/bracket-templates.ts b/app/lib/bracket-templates.ts index 0399a14..e1fba39 100644 --- a/app/lib/bracket-templates.ts +++ b/app/lib/bracket-templates.ts @@ -582,6 +582,32 @@ export function getAllBracketTemplates(): BracketTemplate[] { return Object.values(BRACKET_TEMPLATES); } +/** + * Returns round names in chronological order (earliest first) for the given matches. + * When a template is provided its defined order is used; otherwise rounds are sorted + * by descending match count (more matches = earlier round). + */ +export function getOrderedRoundsFromMatches( + matches: Array<{ round: string }>, + template?: BracketTemplate +): string[] { + const roundsInMatches = new Set(matches.map((m) => m.round)); + + if (template) { + return template.rounds + .map((r) => r.name) + .filter((name) => roundsInMatches.has(name)); + } + + const roundMatchCounts = new Map(); + for (const m of matches) { + roundMatchCounts.set(m.round, (roundMatchCounts.get(m.round) || 0) + 1); + } + return Array.from(roundMatchCounts.keys()).sort( + (a, b) => (roundMatchCounts.get(b) || 0) - (roundMatchCounts.get(a) || 0) + ); +} + /** * Helper to determine scoring round type based on match count in scoring rounds * Used for determining placement sharing (5-8th, 3-4th, 1-2nd) diff --git a/app/routes/admin.sports-seasons.$id.events.$eventId.bracket.tsx b/app/routes/admin.sports-seasons.$id.events.$eventId.bracket.tsx index 59b61a0..6eac747 100644 --- a/app/routes/admin.sports-seasons.$id.events.$eventId.bracket.tsx +++ b/app/routes/admin.sports-seasons.$id.events.$eventId.bracket.tsx @@ -22,7 +22,7 @@ import { SelectValue, } from "~/components/ui/select"; import { ArrowLeft, Plus, Trophy, X, Check, ChevronDown, ChevronRight, Calendar, TrendingUp, Trash2 } from "lucide-react"; -import { getAllBracketTemplates, getBracketTemplate, buildNCAA68SlotMap, ALL_16_SEEDS, type BracketRegion } from "~/lib/bracket-templates"; +import { getAllBracketTemplates, getBracketTemplate, getOrderedRoundsFromMatches, buildNCAA68SlotMap, ALL_16_SEEDS, type BracketRegion } from "~/lib/bracket-templates"; import { Table, TableBody, @@ -277,18 +277,8 @@ export default function EventBracket({ // Memoized: Get available rounds in chronological order const availableRounds = useMemo(() => { - const roundsInMatches = Array.from(new Set(matches.map(m => m.round))); - - if (event.bracketTemplateId) { - const eventTemplate = getBracketTemplate(event.bracketTemplateId); - if (eventTemplate) { - return eventTemplate.rounds - .map((r) => r.name) - .filter((roundName: string) => roundsInMatches.includes(roundName)); - } - } - - return roundsInMatches; + const template = event.bracketTemplateId ? getBracketTemplate(event.bracketTemplateId) : undefined; + return getOrderedRoundsFromMatches(matches, template); }, [matches, event.bracketTemplateId]); // Check if all matches are complete diff --git a/app/routes/leagues/$leagueId.sports-seasons.$sportsSeasonId.server.ts b/app/routes/leagues/$leagueId.sports-seasons.$sportsSeasonId.server.ts index 0f0df0d..7012a0b 100644 --- a/app/routes/leagues/$leagueId.sports-seasons.$sportsSeasonId.server.ts +++ b/app/routes/leagues/$leagueId.sports-seasons.$sportsSeasonId.server.ts @@ -14,6 +14,7 @@ import { getUpcomingScoringEvents, getRecentCompletedEvents, } from "~/models/scoring-event"; +import { getBracketTemplate, getOrderedRoundsFromMatches } from "~/lib/bracket-templates"; import { database } from "~/database/context"; import * as schema from "~/database/schema"; import { eq, and, inArray } from "drizzle-orm"; @@ -160,13 +161,9 @@ export async function loader(args: Route.LoaderArgs) { }); playoffMatches = matches; - const roundMatchCounts = new Map(); - for (const m of matches) { - roundMatchCounts.set(m.round, (roundMatchCounts.get(m.round) || 0) + 1); - } - playoffRounds = Array.from(roundMatchCounts.keys()).sort( - (a, b) => (roundMatchCounts.get(b) || 0) - (roundMatchCounts.get(a) || 0) - ); + const templateId = events.find((e) => e.bracketTemplateId)?.bracketTemplateId; + const template = templateId ? getBracketTemplate(templateId) : undefined; + playoffRounds = getOrderedRoundsFromMatches(matches, template); } // Fetch group-stage losers and all participant results for bracket scoring