fix: address code review issues from draft board scrolling and team creation changes (#35)
- DraftGrid: wrap header and rows in a single min-w-max container so column widths share a sizing context and can't desync - Settings: wrap team + draft slot creation in a DB transaction so a slot insert failure can't leave orphaned teams with no slots - Settings: replace Math.max(...spread) with reduce to avoid the JS argument limit (defensive, given the 6-16 team cap) - Settings: remove now-unused createManyTeams import Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f33e39264d
commit
3343e7a405
3 changed files with 31 additions and 9 deletions
|
|
@ -47,7 +47,8 @@ export function DraftGrid({
|
||||||
return (
|
return (
|
||||||
<Card className="p-4">
|
<Card className="p-4">
|
||||||
{title && <h2 className="text-xl font-semibold mb-4">{title}</h2>}
|
{title && <h2 className="text-xl font-semibold mb-4">{title}</h2>}
|
||||||
<div className="w-full">
|
<div className="w-full overflow-x-auto">
|
||||||
|
<div className="min-w-max">
|
||||||
{/* Team Headers */}
|
{/* Team Headers */}
|
||||||
<div className="flex gap-2 mb-2">
|
<div className="flex gap-2 mb-2">
|
||||||
{draftSlots.map((slot) => {
|
{draftSlots.map((slot) => {
|
||||||
|
|
@ -175,6 +176,7 @@ export function DraftGrid({
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -81,10 +81,10 @@ export function DraftGridSection({
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full overflow-auto p-4">
|
<div className="h-full flex flex-col p-4">
|
||||||
<h2 className="text-xl font-semibold mb-4">Draft Grid</h2>
|
<h2 className="text-xl font-semibold mb-4 flex-shrink-0">Draft Grid</h2>
|
||||||
<div className="overflow-x-auto">
|
<div className="flex-1 overflow-auto">
|
||||||
<div className="inline-block min-w-full">
|
<div className="inline-block min-w-full min-h-full">
|
||||||
{/* Team Headers */}
|
{/* Team Headers */}
|
||||||
<div className="flex gap-2 mb-2 sticky top-0 z-10 bg-background/95 backdrop-blur-sm py-1">
|
<div className="flex gap-2 mb-2 sticky top-0 z-10 bg-background/95 backdrop-blur-sm py-1">
|
||||||
{/* Spacer for round column — sticky so it covers the corner when scrolling both axes */}
|
{/* Spacer for round column — sticky so it covers the corner when scrolling both axes */}
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,13 @@ import {
|
||||||
removeCommissionerByLeagueAndUser,
|
removeCommissionerByLeagueAndUser,
|
||||||
} from "~/models/commissioner";
|
} from "~/models/commissioner";
|
||||||
import { findCurrentSeasonWithSports, updateSeason } from "~/models/season";
|
import { findCurrentSeasonWithSports, updateSeason } from "~/models/season";
|
||||||
import { findTeamsBySeasonId, createManyTeams, deleteTeam, removeTeamOwner, assignTeamOwner } from "~/models/team";
|
import { findTeamsBySeasonId, deleteTeam, removeTeamOwner, assignTeamOwner } from "~/models/team";
|
||||||
import { findAllUsers, findUserByClerkId, isUserAdminByClerkId } from "~/models/user";
|
import { findAllUsers, findUserByClerkId, isUserAdminByClerkId } from "~/models/user";
|
||||||
import { unlinkSportFromSeason, linkMultipleSportsToSeason } from "~/models/season-sport";
|
import { unlinkSportFromSeason, linkMultipleSportsToSeason } from "~/models/season-sport";
|
||||||
import { findAllSportsSeasons } from "~/models/sports-season";
|
import { findAllSportsSeasons } from "~/models/sports-season";
|
||||||
import { findDraftSlotsBySeasonId, setDraftOrder, randomizeDraftOrder } from "~/models/draft-slot";
|
import { findDraftSlotsBySeasonId, setDraftOrder, randomizeDraftOrder } from "~/models/draft-slot";
|
||||||
|
import { database } from "~/database/context";
|
||||||
|
import * as schema from "~/database/schema";
|
||||||
import { deleteAllDraftPicks } from "~/models/draft-pick";
|
import { deleteAllDraftPicks } from "~/models/draft-pick";
|
||||||
import { clearAllQueuesForSeason } from "~/models/draft-queue";
|
import { clearAllQueuesForSeason } from "~/models/draft-queue";
|
||||||
import { deleteSeasonTimers } from "~/models/draft-timer";
|
import { deleteSeasonTimers } from "~/models/draft-timer";
|
||||||
|
|
@ -482,16 +484,34 @@ export async function action(args: Route.ActionArgs) {
|
||||||
|
|
||||||
// Add or remove teams as needed
|
// Add or remove teams as needed
|
||||||
if (newTeamCount > currentTeamCount) {
|
if (newTeamCount > currentTeamCount) {
|
||||||
// Add new teams
|
|
||||||
const teamsToAdd = Array.from(
|
const teamsToAdd = Array.from(
|
||||||
{ length: newTeamCount - currentTeamCount },
|
{ length: newTeamCount - currentTeamCount },
|
||||||
(_, i) => ({
|
(_, i) => ({
|
||||||
seasonId: season.id,
|
seasonId: season.id,
|
||||||
name: `Team ${currentTeamCount + i + 1}`,
|
name: `Team ${currentTeamCount + i + 1}`,
|
||||||
ownerId: null,
|
ownerId: null as null,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
await createManyTeams(teamsToAdd);
|
|
||||||
|
// Fetch existing slots before the transaction to determine append position
|
||||||
|
const existingSlots = await findDraftSlotsBySeasonId(season.id);
|
||||||
|
const maxOrder = existingSlots.reduce((max, s) => Math.max(max, s.draftOrder), 0);
|
||||||
|
|
||||||
|
// Create teams and their draft slots atomically
|
||||||
|
const db = database();
|
||||||
|
await db.transaction(async (tx) => {
|
||||||
|
const newTeams = await tx
|
||||||
|
.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,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
});
|
||||||
} else if (newTeamCount < currentTeamCount) {
|
} else if (newTeamCount < currentTeamCount) {
|
||||||
// Remove teams without owners (from the end)
|
// Remove teams without owners (from the end)
|
||||||
const teamsToRemove = teams
|
const teamsToRemove = teams
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue