diff --git a/app/components/draft/DraftQueue.tsx b/app/components/draft/DraftQueue.tsx new file mode 100644 index 0000000..a83eeac --- /dev/null +++ b/app/components/draft/DraftQueue.tsx @@ -0,0 +1,125 @@ +import { useState } from "react"; +import { Button } from "~/components/ui/button"; +import { Badge } from "~/components/ui/badge"; +import { GripVertical, X } from "lucide-react"; + +interface Participant { + id: string; + name: string; + sport: string; + expectedValue: number; +} + +interface QueueItem { + id: string; + participantId: string; + queuePosition: number; +} + +interface DraftQueueProps { + queueItems: QueueItem[]; + participants: Participant[]; + onReorder?: (participantIds: string[]) => void; + onRemove?: (queueItemId: string) => void; +} + +export function DraftQueue({ + queueItems, + participants, + onReorder, + onRemove, +}: DraftQueueProps) { + const [draggedIndex, setDraggedIndex] = useState(null); + + // Create a map for quick participant lookup + const participantMap = new Map(participants.map((p) => [p.id, p])); + + // Sort queue items by position + const sortedQueue = [...queueItems].sort((a, b) => a.queuePosition - b.queuePosition); + + const handleDragStart = (index: number) => { + setDraggedIndex(index); + }; + + const handleDragOver = (e: React.DragEvent, index: number) => { + e.preventDefault(); + if (draggedIndex === null || draggedIndex === index) return; + + // Reorder the items + const newQueue = [...sortedQueue]; + const draggedItem = newQueue[draggedIndex]; + newQueue.splice(draggedIndex, 1); + newQueue.splice(index, 0, draggedItem); + + // Update positions and notify parent + const participantIds = newQueue.map((item) => item.participantId); + onReorder?.(participantIds); + setDraggedIndex(index); + }; + + const handleDragEnd = () => { + setDraggedIndex(null); + }; + + if (sortedQueue.length === 0) { + return ( +
+

Your queue is empty

+

Add players from the Available Players list

+
+ ); + } + + return ( +
+ {sortedQueue.map((item, index) => { + const participant = participantMap.get(item.participantId); + if (!participant) return null; + + return ( +
handleDragStart(index)} + onDragOver={(e) => handleDragOver(e, index)} + onDragEnd={handleDragEnd} + className={`flex items-center gap-2 p-3 rounded-lg border bg-card transition-all ${ + draggedIndex === index ? "opacity-50" : "hover:bg-accent cursor-move" + }`} + > + {/* Drag Handle */} +
+ + {index + 1} +
+ + {/* Player Info */} +
+
{participant.name}
+
+ + {participant.sport} + + + EV: {participant.expectedValue.toFixed(1)} + +
+
+ + {/* Remove Button */} + {onRemove && ( + + )} +
+ ); + })} +
+ ); +} diff --git a/app/routes/leagues/$leagueId.draft.tsx b/app/routes/leagues/$leagueId.draft.tsx index 1feb187..954ac6b 100644 --- a/app/routes/leagues/$leagueId.draft.tsx +++ b/app/routes/leagues/$leagueId.draft.tsx @@ -10,9 +10,11 @@ import { getDraftPicks, getSeasonTimers, findSeasonWithSportsSeasons, + getTeamQueue, } from "~/models"; import { DraftGrid } from "~/components/draft/DraftGrid"; import { PlayerList } from "~/components/draft/PlayerList"; +import { DraftQueue } from "~/components/draft/DraftQueue"; export async function loader(args: LoaderFunctionArgs) { const { userId } = await getAuth(args); @@ -68,6 +70,9 @@ export async function loader(args: LoaderFunctionArgs) { // Get draft data const draftPicks = await getDraftPicks(season.id); const timers = await getSeasonTimers(season.id); + + // Get user's queue if they have a team + const queueItems = userTeam ? await getTeamQueue(userTeam.id) : []; // Calculate current pick info const totalPicks = season.draftRounds * teams.length; @@ -83,6 +88,7 @@ export async function loader(args: LoaderFunctionArgs) { userTeam, draftPicks, participants, + queueItems, timers, currentPickNumber, totalPicks, @@ -98,6 +104,7 @@ export default function DraftRoom({ loaderData }: { loaderData: Awaited {/* Your Queue */} -
+

Your Queue

-
- Queue will be implemented in Phase 7 +
+