import { useLoaderData } from "react-router"; import { eq, and, asc, notInArray } from "drizzle-orm"; import { database } from "~/database/context"; import * as schema from "~/database/schema"; import { useDraftSocket } from "~/hooks/useDraftSocket"; import { useEffect, useState } from "react"; import { Card } from "~/components/ui/card"; import { Badge } from "~/components/ui/badge"; export async function loader({ params }: { params: { seasonId: string } }) { const { seasonId } = params; if (!seasonId) { throw new Response("Season ID is required", { status: 400 }); } const db = database(); // Get season details const season = await db.query.seasons.findFirst({ where: eq(schema.seasons.id, seasonId), with: { league: true, teams: true, }, }); if (!season) { throw new Response("Season not found", { status: 404 }); } // Get draft slots (draft order) - using select instead of query builder const draftSlots = await db .select({ id: schema.draftSlots.id, draftOrder: schema.draftSlots.draftOrder, team: schema.teams, }) .from(schema.draftSlots) .innerJoin(schema.teams, eq(schema.draftSlots.teamId, schema.teams.id)) .where(eq(schema.draftSlots.seasonId, seasonId)) .orderBy(asc(schema.draftSlots.draftOrder)); // Get all draft picks - using select instead of query builder const draftPicks = await db .select({ id: schema.draftPicks.id, pickNumber: schema.draftPicks.pickNumber, round: schema.draftPicks.round, pickInRound: schema.draftPicks.pickInRound, timeUsed: schema.draftPicks.timeUsed, team: schema.teams, participant: schema.participants, sport: schema.sports, }) .from(schema.draftPicks) .innerJoin(schema.teams, eq(schema.draftPicks.teamId, schema.teams.id)) .innerJoin(schema.participants, eq(schema.draftPicks.participantId, schema.participants.id)) .innerJoin(schema.sportsSeasons, eq(schema.participants.sportsSeasonId, schema.sportsSeasons.id)) .innerJoin(schema.sports, eq(schema.sportsSeasons.sportId, schema.sports.id)) .where(eq(schema.draftPicks.seasonId, seasonId)) .orderBy(asc(schema.draftPicks.pickNumber)); // Get available participants (not yet picked) const pickedParticipantIds = draftPicks.map((p) => p.participant.id); const 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( and( eq(schema.participants.sportsSeasonId, season.templateId!), pickedParticipantIds.length > 0 ? notInArray(schema.participants.id, pickedParticipantIds) : undefined ) ) .orderBy(asc(schema.participants.name)); return { season, draftSlots, draftPicks, availableParticipants, }; } export default function DraftRoom() { const { season, draftSlots, draftPicks, availableParticipants } = useLoaderData(); const { isConnected, on, off } = useDraftSocket(season.id); const [picks, setPicks] = useState(draftPicks); const [currentPick, setCurrentPick] = useState(season.currentPickNumber || 1); // Listen for new picks from other users useEffect(() => { const handlePickMade = (data: any) => { console.log("Pick made:", data); setPicks((prev: any) => [...prev, data.pick]); setCurrentPick(data.nextPickNumber); }; on("pick-made", handlePickMade); return () => { off("pick-made", handlePickMade); }; }, [on, off]); // Calculate current team on the clock const currentDraftSlot = draftSlots[(currentPick - 1) % draftSlots.length]; const currentRound = Math.ceil(currentPick / draftSlots.length); return (
{/* Header */}

{season.league.name} - {season.year} Draft

{isConnected ? "Live" : "Disconnected"}
Round: {currentRound} Pick: {currentPick} Status: {season.status}
{/* Left Column: Draft Board */}

Draft Board

{/* Current Pick */} {currentDraftSlot && (

Now Picking:

{currentDraftSlot.team.name}

Pick #{currentPick}
)} {/* Recent Picks */}

Recent Picks

{picks.length === 0 ? (

No picks yet...

) : (
{picks .slice() .reverse() .slice(0, 10) .map((pick: any) => (
#{pick.pickNumber}

{pick.participant.name}

{pick.sport.name}

{pick.team.name}

Round {pick.round}

))}
)}
{/* Right Column: Available Participants */}

Available Participants ({availableParticipants.length})

{availableParticipants.map((participant: any) => (

{participant.name}

{participant.sport.name}

))}
); }