From a7248c48e69792f4be4d67febc695302313bddc0 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 20 May 2026 00:35:26 +0000 Subject: [PATCH] Fix draft order showing only new team when league size increased before order was set When a commissioner increased the team count on a league that had teams but no draft order set yet, the server created draft slots only for the newly-added teams. This left the DB with N+K teams but only K slots, causing the drag-and-drop list to display only the K new teams. Two fixes: 1. Server: only append new draft slots when an order was already set (existingSlots.length > 0). If no order exists yet, skip slot creation so the page correctly treats the order as unset for all teams. 2. Frontend: buildDraftOrderTeams() appends any unslotted teams after the slotted ones, so a partially-corrupt DB state still shows all teams. https://claude.ai/code/session_01M3H55gnMxRztJK9KMXqqZo --- .../leagues/$leagueId.settings.server.ts | 19 ++++++++++++------- app/routes/leagues/$leagueId.settings.tsx | 17 ++++++++++++----- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/app/routes/leagues/$leagueId.settings.server.ts b/app/routes/leagues/$leagueId.settings.server.ts index 5120899..b50a966 100644 --- a/app/routes/leagues/$leagueId.settings.server.ts +++ b/app/routes/leagues/$leagueId.settings.server.ts @@ -751,13 +751,18 @@ export async function action(args: Route.ActionArgs) { .insert(schema.teams) .values(teamsToAdd) .returning(); - await tx.insert(schema.draftSlots).values( - newTeams.map((team, i) => ({ - seasonId: season.id, - teamId: team.id, - draftOrder: maxOrder + i + 1, - })) - ); + // Only append draft slots if a draft order was already set for existing teams. + // When existingSlots is empty, draft order was never configured — don't create + // partial slots for only the new teams (that would break the order UI). + if (existingSlots.length > 0) { + await tx.insert(schema.draftSlots).values( + newTeams.map((team, i) => ({ + seasonId: season.id, + teamId: team.id, + draftOrder: maxOrder + i + 1, + })) + ); + } }); await syncPrivateBracktParticipants(season.id); } else if (newTeamCount < currentTeamCount) { diff --git a/app/routes/leagues/$leagueId.settings.tsx b/app/routes/leagues/$leagueId.settings.tsx index 3356cfe..285b30e 100644 --- a/app/routes/leagues/$leagueId.settings.tsx +++ b/app/routes/leagues/$leagueId.settings.tsx @@ -112,6 +112,16 @@ const UPDATE_SECTIONS: SettingsSectionId[] = [ "notifications", ]; +function buildDraftOrderTeams( + slots: { teamId: string }[], + allTeams: { id: string }[] +): string[] { + if (slots.length === 0) return allTeams.map((t) => t.id); + const slottedIds = new Set(slots.map((s) => s.teamId)); + const unslotted = allTeams.filter((t) => !slottedIds.has(t.id)).map((t) => t.id); + return [...slots.map((s) => s.teamId), ...unslotted]; +} + export default function LeagueSettings({ loaderData, actionData }: Route.ComponentProps) { const { league, season, teams, teamCount, teamsWithOwners, allSportsSeasons, @@ -165,17 +175,14 @@ export default function LeagueSettings({ loaderData, actionData }: Route.Compone // Draft order state (separate form, separate dirty flag) const [draftOrderTeams, setDraftOrderTeams] = useState( - draftSlots.length > 0 ? draftSlots.map((slot) => slot.teamId) : teams.map((team) => team.id) + () => buildDraftOrderTeams(draftSlots, teams) ); const [copied, setCopied] = useState(false); // Sync draft order from loader after randomization or other server updates useEffect(() => { - const savedOrder = draftSlots.length > 0 - ? draftSlots.map((slot) => slot.teamId) - : teams.map((team) => team.id); - setDraftOrderTeams(savedOrder); + setDraftOrderTeams(buildDraftOrderTeams(draftSlots, teams)); setHasDraftOrderChanges(false); }, [draftSlots, teams]);