import { data, type ActionFunctionArgs } from "react-router"; import { getAuth } from "@clerk/react-router/server"; import { findSeasonById, updateSeason, updateSeasonStatus, findTeamsBySeasonId, isCommissioner, createDraftPick, isParticipantDrafted, updateTeamTimer, getSeasonTimers, calculatePickInfo, getTeamForPick, findDraftSlotsBySeasonId, removeFromQueue, getTeamQueue, } from "~/models"; import { getSocketIO } from "../../../server/socket.js"; export async function action(args: ActionFunctionArgs) { const { userId } = await getAuth(args); if (!userId) { return data({ error: "Unauthorized" }, { status: 401 }); } const { request } = args; const formData = await request.formData(); const seasonId = formData.get("seasonId"); const teamId = formData.get("teamId"); const participantId = formData.get("participantId"); if (!seasonId || typeof seasonId !== "string") { return data({ error: "Season ID is required" }, { status: 400 }); } if (!teamId || typeof teamId !== "string") { return data({ error: "Team ID is required" }, { status: 400 }); } if (!participantId || typeof participantId !== "string") { return data({ error: "Participant ID is required" }, { status: 400 }); } try { // Get season const season = await findSeasonById(seasonId); if (!season) { return data({ error: "Season not found" }, { status: 404 }); } // Check if draft has started if (!season.draftStartedAt) { return data({ error: "Draft has not started" }, { status: 400 }); } // Check if draft is paused if (season.draftPaused) { return data({ error: "Draft is currently paused" }, { status: 400 }); } // Check if draft is complete const teams = await findTeamsBySeasonId(seasonId); const totalPicks = season.draftRounds * teams.length; const currentPickNumber = season.currentPickNumber || 1; if (currentPickNumber > totalPicks) { return data({ error: "Draft is already complete" }, { status: 400 }); } // Get draft slots to determine current team const draftSlots = await findDraftSlotsBySeasonId(seasonId); const draftOrder = draftSlots.map((slot: any) => ({ teamId: slot.teamId, draftOrder: slot.draftOrder, })); const currentTeamId = getTeamForPick(currentPickNumber, draftOrder); if (!currentTeamId) { return data({ error: "Could not determine current team" }, { status: 400 }); } // Verify it's the correct team's turn if (teamId !== currentTeamId) { return data({ error: "It is not this team's turn" }, { status: 400 }); } // Verify user has permission (team owner or commissioner) const team = teams.find((t: any) => t.id === teamId); const isTeamOwner = team?.ownerId === userId; const isUserCommissioner = await isCommissioner(season.leagueId, userId); if (!isTeamOwner && !isUserCommissioner) { return data({ error: "You do not have permission to make this pick" }, { status: 403 }); } // Check if participant is already drafted const isDrafted = await isParticipantDrafted(seasonId, participantId); if (isDrafted) { return data({ error: "This participant has already been drafted" }, { status: 400 }); } // Calculate pick info const { round, pickInRound } = calculatePickInfo(currentPickNumber, teams.length); // Determine picked by type const pickedByType = isUserCommissioner && !isTeamOwner ? "commissioner" : "owner"; // Create the draft pick const pick = await createDraftPick({ seasonId, teamId, participantId, pickNumber: currentPickNumber, round, pickInRound, pickedByUserId: userId, pickedByType, timeUsed: 0, }); // Remove from queue if it was queued const queue = await getTeamQueue(teamId); const queueItem = queue.find((item: any) => item.participantId === participantId); if (queueItem) { await removeFromQueue(queueItem.id); } // Update season to next pick const nextPickNumber = currentPickNumber + 1; await updateSeason(seasonId, { currentPickNumber: nextPickNumber }); // Add increment time to current team's timer if (season.draftIncrementTime) { const timers = await getSeasonTimers(seasonId); const currentTimer = timers.find((t: any) => t.teamId === teamId); if (currentTimer) { const newTime = currentTimer.timeRemaining + season.draftIncrementTime; await updateTeamTimer(teamId, newTime); } } // Check if draft is complete const io = getSocketIO(); if (nextPickNumber > totalPicks) { await updateSeasonStatus(seasonId, "active"); io.to(`draft-${seasonId}`).emit("draft-completed", { seasonId, }); } // Broadcast pick to all clients in the room io.to(`draft-${seasonId}`).emit("pick-made", { pick, nextPickNumber, isDraftComplete: nextPickNumber > totalPicks, }); // Emit queue update to team owner const updatedQueue = await getTeamQueue(teamId); io.to(`draft-${seasonId}`).emit("queue-updated", { teamId, queue: updatedQueue, }); return data({ success: true, pick }); } catch (error) { console.error("Error making pick:", error); return data({ error: error instanceof Error ? error.message : "Failed to make pick", }, { status: 500 }); } }