diff --git a/app/components/league/DraftInfoCard.tsx b/app/components/league/DraftInfoCard.tsx index f22f1c9..e2b7d5b 100644 --- a/app/components/league/DraftInfoCard.tsx +++ b/app/components/league/DraftInfoCard.tsx @@ -121,7 +121,7 @@ function DraftInfoCardVariant({ ) : queueBuilderHref ? ( ) : null} diff --git a/app/routes/leagues/$leagueId.draft-queue.$seasonId.tsx b/app/routes/leagues/$leagueId.draft-queue.$seasonId.tsx index 38a97e6..7679e60 100644 --- a/app/routes/leagues/$leagueId.draft-queue.$seasonId.tsx +++ b/app/routes/leagues/$leagueId.draft-queue.$seasonId.tsx @@ -1,6 +1,6 @@ import { redirect, useFetcher, useLoaderData, useRevalidator, Link } from "react-router"; import { useCallback, useEffect, useMemo, useState } from "react"; -import { ArrowLeft, ListOrdered } from "lucide-react"; +import { ArrowLeft, ListOrdered, Users } from "lucide-react"; import { auth } from "~/lib/auth.server"; import { findSeasonWithTeamsAndLeague } from "~/models/season"; import { getDraftParticipants } from "~/models/season-participant"; @@ -8,10 +8,11 @@ import { getTeamQueue } from "~/models/draft-queue"; import { QueueSection } from "~/components/draft/QueueSection"; import { Button } from "~/components/ui/button"; import { Badge } from "~/components/ui/badge"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/components/ui/tabs"; import type { Route } from "./+types/$leagueId.draft-queue.$seasonId"; export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors { - return [{ title: `Pre-Draft Queue — ${data?.season?.league?.name ?? "League"} - Brackt` }]; + return [{ title: `Pre-Draft Rankings — ${data?.season?.league?.name ?? "League"} - Brackt` }]; } export async function loader(args: Route.LoaderArgs) { @@ -39,7 +40,7 @@ export async function loader(args: Route.LoaderArgs) { } if (!userId) { - throw new Response("You must be logged in to build a queue", { status: 401 }); + throw new Response("You must be logged in to set pre-draft rankings", { status: 401 }); } const userTeam = season.teams.find((t) => t.ownerId === userId); @@ -63,7 +64,7 @@ export async function loader(args: Route.LoaderArgs) { type QueueItem = { id: string; participantId: string }; -export default function PreDraftQueue() { +export default function PreDraftRankings() { const { season, leagueId, userTeam, availableParticipants, userQueue } = useLoaderData(); const { revalidate } = useRevalidator(); @@ -94,7 +95,6 @@ export default function PreDraftQueue() { const handleAdd = useCallback( (participantId: string) => { if (queuedParticipantIds.has(participantId)) return; - // Optimistic update with a temporary ID const tempId = `temp-${Date.now()}-${participantId}`; setLocalQueue((prev) => [...prev, { id: tempId, participantId }]); const formData = new FormData(); @@ -117,6 +117,15 @@ export default function PreDraftQueue() { [userTeam.id, removeFetcher] ); + // Remove by participantId — used from the All Players list + const handleRemoveByParticipantId = useCallback( + (participantId: string) => { + const item = localQueue.find((q) => q.participantId === participantId); + if (item) handleRemove(item.id); + }, + [localQueue, handleRemove] + ); + const handleReorder = useCallback( (participantIds: string[]) => { setLocalQueue((prev) => { @@ -134,6 +143,77 @@ export default function PreDraftQueue() { [userTeam.id, season.id, reorderFetcher] ); + // ── Shared panel content ──────────────────────────────────────────────────── + + const allPlayersPanel = ( +
+ {availableParticipants.map((p) => { + const inQueue = queuedParticipantIds.has(p.id); + return ( +
+
+

{p.name}

+

{p.sport.name}

+
+ {p.vorpValue != null && ( + + {Number(p.vorpValue).toFixed(1)} + + )} + {inQueue ? ( + + ) : ( + + )} +
+ ); + })} + {availableParticipants.length === 0 && ( +

+ No participants have been added to this season yet. +

+ )} +
+ ); + + const rankingsPanel = ( + <> +
+ +
+ {localQueue.length > 0 && ( +

+ Drag to reorder · Autopick follows this order +

+ )} + + ); + + // ── Render ────────────────────────────────────────────────────────────────── + return (
{/* Header */} @@ -147,79 +227,57 @@ export default function PreDraftQueue() {
-

Pre-Draft Queue

+

Pre-Draft Rankings

- Rank the participants you want. Your queue will carry into the live draft and determine - your autopick order. + Rank the players you want. Your rankings carry into the live draft as your autopick + priority order.

- {/* Two-panel layout */} -
- {/* Participant list */} + {/* Mobile: tabs */} +
+ + + + + All Players + + + + My Rankings + {localQueue.length > 0 && ( + + {localQueue.length} + + )} + + + +
+ Sorted by VORP +
+ {allPlayersPanel} +
+ {rankingsPanel} +
+
+ + {/* Desktop: side-by-side */} +
-

All Participants

+

All Players

Sorted by VORP
-
- {availableParticipants.map((p) => { - const inQueue = queuedParticipantIds.has(p.id); - return ( -
-
-

{p.name}

-

{p.sport.name}

-
- {p.vorpValue != null && ( - - {Number(p.vorpValue).toFixed(1)} - - )} - -
- ); - })} - {availableParticipants.length === 0 && ( -

- No participants have been added to this season yet. -

- )} -
+ {allPlayersPanel}
- - {/* Queue panel */}
-

Your Queue

+

My Rankings

{localQueue.length}
-
- -
- {localQueue.length > 0 && ( -

- Drag to reorder · Autopick follows this order -

- )} + {rankingsPanel}