Show manager username instead of team name on draft board
Both the read-only draft board and the active draft room now display the manager's username (falling back to displayName if no username is set, and to team name if the team is unassigned) in the column headers of the draft grid. https://claude.ai/code/session_01C97GauJaAB83NVWxdpNVh1
This commit is contained in:
parent
b35791e76a
commit
4aa3309e61
4 changed files with 60 additions and 3 deletions
|
|
@ -25,6 +25,7 @@ interface DraftGridProps {
|
|||
onForceManualPick?: (pickNumber: number, teamId: string) => void;
|
||||
autodraftStatus?: Record<string, boolean>;
|
||||
connectedTeams?: Set<string>;
|
||||
ownerMap?: Record<string, string>;
|
||||
}
|
||||
|
||||
export function DraftGrid({
|
||||
|
|
@ -39,6 +40,7 @@ export function DraftGrid({
|
|||
onForceManualPick,
|
||||
autodraftStatus = {},
|
||||
connectedTeams = new Set(),
|
||||
ownerMap = {},
|
||||
}: DraftGridProps) {
|
||||
const totalTeams = draftSlots.length;
|
||||
|
||||
|
|
@ -58,7 +60,7 @@ export function DraftGrid({
|
|||
<div
|
||||
className={`font-semibold text-sm truncate px-2 ${!isConnected ? "italic text-muted-foreground" : ""}`}
|
||||
>
|
||||
{slot.team.name}
|
||||
{ownerMap[slot.team.id] || slot.team.name}
|
||||
</div>
|
||||
{teamTimers && formatTime && (
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ interface DraftGridSectionProps {
|
|||
onForceManualPickOpen: (pickNumber: number, teamId: string) => void;
|
||||
onReplacePick?: (pickNumber: number, teamId: string) => void;
|
||||
onRollbackToPick?: (pickNumber: number) => void;
|
||||
ownerMap?: Record<string, string>;
|
||||
}
|
||||
|
||||
export function DraftGridSection({
|
||||
|
|
@ -57,6 +58,7 @@ export function DraftGridSection({
|
|||
onForceManualPickOpen,
|
||||
onReplacePick,
|
||||
onRollbackToPick,
|
||||
ownerMap = {},
|
||||
}: DraftGridSectionProps) {
|
||||
const currentTeamId = useMemo(
|
||||
() => draftGrid.flat().find((c) => c.pickNumber === currentPick)?.teamId ?? null,
|
||||
|
|
@ -86,7 +88,7 @@ export function DraftGridSection({
|
|||
: ""
|
||||
}`}
|
||||
>
|
||||
{slot.team.name}
|
||||
{ownerMap[slot.team.id] || slot.team.name}
|
||||
</div>
|
||||
<div
|
||||
className={`text-xs font-mono ${getTimerColorClass(teamTime)}`}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import * as schema from "~/database/schema";
|
|||
import { DraftGrid } from "~/components/DraftGrid";
|
||||
import { useDraftSocket } from "~/hooks/useDraftSocket";
|
||||
import { useState, useEffect } from "react";
|
||||
import { findUserByClerkId } from "~/models/user";
|
||||
|
||||
export async function loader(args: any) {
|
||||
const { params } = args;
|
||||
|
|
@ -102,15 +103,39 @@ export async function loader(args: any) {
|
|||
.where(eq(schema.draftPicks.seasonId, seasonId))
|
||||
.orderBy(asc(schema.draftPicks.pickNumber));
|
||||
|
||||
// Build ownerMap: teamId -> username/displayName
|
||||
const ownerIds = draftSlots
|
||||
.map((s) => s.team.ownerId)
|
||||
.filter((id): id is string => id !== null);
|
||||
const uniqueOwnerIds = [...new Set(ownerIds)];
|
||||
const ownerEntries = await Promise.all(
|
||||
uniqueOwnerIds.map(async (ownerId) => {
|
||||
const user = await findUserByClerkId(ownerId);
|
||||
return user ? { ownerId, name: user.username || user.displayName } : null;
|
||||
})
|
||||
);
|
||||
const ownerByClerkId = new Map(
|
||||
ownerEntries
|
||||
.filter((e): e is NonNullable<typeof e> => e !== null)
|
||||
.map((e) => [e.ownerId, e.name])
|
||||
);
|
||||
const ownerMap: Record<string, string> = {};
|
||||
for (const slot of draftSlots) {
|
||||
if (slot.team.ownerId && ownerByClerkId.has(slot.team.ownerId)) {
|
||||
ownerMap[slot.team.id] = ownerByClerkId.get(slot.team.ownerId)!;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
season,
|
||||
draftSlots,
|
||||
draftPicks,
|
||||
ownerMap,
|
||||
};
|
||||
}
|
||||
|
||||
export default function DraftBoard() {
|
||||
const { season, draftSlots, draftPicks: initialPicks } = useLoaderData<typeof loader>();
|
||||
const { season, draftSlots, draftPicks: initialPicks, ownerMap } = useLoaderData<typeof loader>();
|
||||
const { isConnected, on, off } = useDraftSocket(season.id);
|
||||
const [picks, setPicks] = useState(initialPicks);
|
||||
const [currentPick, setCurrentPick] = useState(season.currentPickNumber || 1);
|
||||
|
|
@ -186,6 +211,7 @@ export default function DraftBoard() {
|
|||
draftSlots={draftSlots}
|
||||
draftGrid={draftGrid}
|
||||
currentPick={currentPick}
|
||||
ownerMap={ownerMap}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/components/ui/tabs";
|
|||
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "~/components/ui/dialog";
|
||||
import { getAuth } from "@clerk/react-router/server";
|
||||
import { getTeamQueue } from "~/models/draft-queue";
|
||||
import { findUserByClerkId } from "~/models/user";
|
||||
import { DraftSidebar } from "~/components/DraftSidebar";
|
||||
import { TeamsDraftedGrid } from "~/components/draft/TeamsDraftedGrid";
|
||||
import { QueueSection } from "~/components/draft/QueueSection";
|
||||
|
|
@ -166,6 +167,29 @@ export async function loader(args: any) {
|
|||
? (autodraftSettings.find((s) => s.teamId === userTeam.id) ?? null)
|
||||
: null;
|
||||
|
||||
// Build ownerMap: teamId -> username/displayName
|
||||
const ownerIds = draftSlots
|
||||
.map((s) => s.team.ownerId)
|
||||
.filter((id): id is string => id !== null);
|
||||
const uniqueOwnerIds = [...new Set(ownerIds)];
|
||||
const ownerEntries = await Promise.all(
|
||||
uniqueOwnerIds.map(async (ownerId) => {
|
||||
const user = await findUserByClerkId(ownerId);
|
||||
return user ? { ownerId, name: user.username || user.displayName } : null;
|
||||
})
|
||||
);
|
||||
const ownerByClerkId = new Map(
|
||||
ownerEntries
|
||||
.filter((e): e is NonNullable<typeof e> => e !== null)
|
||||
.map((e) => [e.ownerId, e.name])
|
||||
);
|
||||
const ownerMap: Record<string, string> = {};
|
||||
for (const slot of draftSlots) {
|
||||
if (slot.team.ownerId && ownerByClerkId.has(slot.team.ownerId)) {
|
||||
ownerMap[slot.team.id] = ownerByClerkId.get(slot.team.ownerId)!;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
season,
|
||||
draftSlots,
|
||||
|
|
@ -179,6 +203,7 @@ export async function loader(args: any) {
|
|||
isCommissioner: !!isCommissioner,
|
||||
currentUserId: userId,
|
||||
numFlexPicks: Math.max(0, season.draftRounds - seasonSports.length),
|
||||
ownerMap,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -196,6 +221,7 @@ export default function DraftRoom() {
|
|||
isCommissioner,
|
||||
currentUserId,
|
||||
numFlexPicks,
|
||||
ownerMap,
|
||||
} = useLoaderData<typeof loader>();
|
||||
const { revalidate } = useRevalidator();
|
||||
const { isConnected, connectionError, isReconnecting, on, off } = useDraftSocket(season.id, userTeam?.id);
|
||||
|
|
@ -1224,6 +1250,7 @@ export default function DraftRoom() {
|
|||
autodraftStatus={autodraftStatus}
|
||||
connectedTeams={connectedTeams}
|
||||
isCommissioner={isCommissioner}
|
||||
ownerMap={ownerMap}
|
||||
onAdjustTimeBankOpen={isCommissioner ? handleAdjustTimeBankOpen : undefined}
|
||||
onForceAutopick={handleForceAutopick}
|
||||
onForceManualPickOpen={(pickNumber, teamId) => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue