Code review fixes for TeamsDraftedGrid and draft route

- Fix misleading early-return message: "No picks have been made yet" only
  fires when there are no sports configured, so update to say "No sports
  have been configured for this season."
- Remove unused draftOrder and team.seasonId from TeamsDraftedGrid props
- Replace availableParticipants prop with sports prop to eliminate
  duplicate sports derivation; route already computes seasonSportsData
- Add alphabetical sort to seasonSportsData so ordering is consistent
- Fix availableParticipants: any[] in loader — restructure to ternary so
  TypeScript infers the Drizzle select type directly
- Remove any annotation from seasonSportsData forEach callback (now typed)
- Fix teamSportPicks.indexOf(pick) O(n) re-scan — use map callback index i

https://claude.ai/code/session_01DZ6jqgZTDEmJucanBtRCtM
This commit is contained in:
Claude 2026-02-21 05:24:04 +00:00
parent ab03ebf9de
commit 2bd7dca863
No known key found for this signature in database
2 changed files with 36 additions and 59 deletions

View file

@ -4,11 +4,9 @@ import { useMemo } from "react";
interface TeamsDraftedGridProps {
draftSlots: Array<{
id: string;
draftOrder: number;
team: {
id: string;
name: string;
seasonId: string;
};
}>;
picks: Array<{
@ -26,13 +24,9 @@ interface TeamsDraftedGridProps {
name: string;
};
}>;
availableParticipants: Array<{
sports: Array<{
id: string;
name: string;
sport: {
id: string;
name: string;
};
}>;
season: {
numFlexPicks: number;
@ -42,25 +36,9 @@ interface TeamsDraftedGridProps {
export function TeamsDraftedGrid({
draftSlots,
picks,
availableParticipants,
sports,
season,
}: TeamsDraftedGridProps) {
// Get unique sports from all available participants (not just picked ones)
const sports = useMemo(() => {
const sportMap = new Map<string, { id: string; name: string }>();
availableParticipants.forEach((participant) => {
if (!sportMap.has(participant.sport.id)) {
sportMap.set(participant.sport.id, {
id: participant.sport.id,
name: participant.sport.name,
});
}
});
return Array.from(sportMap.values()).sort((a, b) =>
a.name.localeCompare(b.name)
);
}, [availableParticipants]);
// Calculate picks by team and sport
const picksByTeamAndSport = useMemo(() => {
const map = new Map<string, Map<string, typeof picks>>();
@ -96,7 +74,7 @@ export function TeamsDraftedGrid({
if (sports.length === 0) {
return (
<div className="flex items-center justify-center h-full p-8 text-muted-foreground">
<p>No picks have been made yet</p>
<p>No sports have been configured for this season.</p>
</div>
);
}
@ -157,7 +135,7 @@ export function TeamsDraftedGrid({
>
{teamSportPicks.length > 0 ? (
<div className="flex flex-col gap-1">
{teamSportPicks.map((pick) => (
{teamSportPicks.map((pick, i) => (
<div
key={pick.id}
className="text-sm flex items-center gap-1"
@ -168,7 +146,7 @@ export function TeamsDraftedGrid({
variant="secondary"
className="text-xs px-1 py-0"
>
{teamSportPicks.indexOf(pick) + 1}
{i + 1}
</Badge>
)}
</div>

View file

@ -119,35 +119,32 @@ export async function loader(args: any) {
// Get ALL participants (both drafted and undrafted) - sorted by EV desc, then name
// Filtering will be done on the client side based on the "Show Drafted" toggle
let availableParticipants: any[] = [];
if (sportsSeasonIds.length > 0) {
availableParticipants = await db
.select({
id: schema.participants.id,
name: schema.participants.name,
sport: schema.sports,
})
.from(schema.participants)
.innerJoin(
schema.sportsSeasons,
eq(schema.participants.sportsSeasonId, schema.sportsSeasons.id)
)
.innerJoin(
schema.sports,
eq(schema.sportsSeasons.sportId, schema.sports.id)
)
.where(
sportsSeasonIds.length === 1
? eq(schema.participants.sportsSeasonId, sportsSeasonIds[0])
: inArray(schema.participants.sportsSeasonId, sportsSeasonIds)
)
.orderBy(
desc(schema.participants.expectedValue),
asc(schema.participants.name)
);
}
const availableParticipants = sportsSeasonIds.length > 0
? await db
.select({
id: schema.participants.id,
name: schema.participants.name,
sport: schema.sports,
})
.from(schema.participants)
.innerJoin(
schema.sportsSeasons,
eq(schema.participants.sportsSeasonId, schema.sportsSeasons.id)
)
.innerJoin(
schema.sports,
eq(schema.sportsSeasons.sportId, schema.sports.id)
)
.where(
sportsSeasonIds.length === 1
? eq(schema.participants.sportsSeasonId, sportsSeasonIds[0])
: inArray(schema.participants.sportsSeasonId, sportsSeasonIds)
)
.orderBy(
desc(schema.participants.expectedValue),
asc(schema.participants.name)
)
: [];
// Load user's team queue if they have a team
const userQueue = userTeam ? await getTeamQueue(userTeam.id) : [];
@ -305,12 +302,14 @@ export default function DraftRoom() {
const seasonSportsData = useMemo(() => {
const sportsMap = new Map<string, { id: string; name: string }>();
availableParticipants.forEach((p: any) => {
availableParticipants.forEach((p) => {
if (!sportsMap.has(p.sport.id)) {
sportsMap.set(p.sport.id, { id: p.sport.id, name: p.sport.name });
}
});
return Array.from(sportsMap.values());
return Array.from(sportsMap.values()).sort((a, b) =>
a.name.localeCompare(b.name)
);
}, [availableParticipants]);
// Calculate draft eligibility for current user's team
@ -979,7 +978,7 @@ export default function DraftRoom() {
<TeamsDraftedGrid
draftSlots={draftSlots}
picks={picks}
availableParticipants={availableParticipants}
sports={seasonSportsData}
season={{ numFlexPicks }}
/>
</div>