Fix draft timer creation for teams without existing timers (#26)
* Create timer when adding time to a team with no existing timer When a commissioner tries to add time to a team that has no draft timer, instead of returning a 404 error, create a new timer record with the specified amount of time. Removing time still returns a 404 if no timer exists (nothing to remove from). https://claude.ai/code/session_016VpJKZZFNQQqzfmLu8pHoc * Fix silent timer failures and missing seasonId filter in timer model - draft.make-pick.ts: create a timer with the increment amount instead of logging a warning and silently skipping when no timer exists for the picking team - draft.force-manual-pick.ts: same fix for the commissioner force-pick path; also unconditionally emit the timer-update socket event so clients always see the updated time - models/draft-timer.ts: add seasonId parameter to getTeamTimer and updateTeamTimer so they cannot match the wrong season's timer when a team participates in multiple seasons https://claude.ai/code/session_016VpJKZZFNQQqzfmLu8pHoc --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
parent
a3ec556ecc
commit
34da0594d1
4 changed files with 60 additions and 41 deletions
|
|
@ -1,6 +1,6 @@
|
|||
import { database } from "~/database/context";
|
||||
import * as schema from "~/database/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { eq, and } from "drizzle-orm";
|
||||
|
||||
export async function initializeDraftTimers(seasonId: string, teams: { id: string }[], initialTime: number) {
|
||||
const timerData = teams.map((team) => ({
|
||||
|
|
@ -8,17 +8,17 @@ export async function initializeDraftTimers(seasonId: string, teams: { id: strin
|
|||
teamId: team.id,
|
||||
timeRemaining: initialTime,
|
||||
}));
|
||||
|
||||
|
||||
const db = database();
|
||||
await db.insert(schema.draftTimers).values(timerData);
|
||||
}
|
||||
|
||||
export async function getTeamTimer(teamId: string) {
|
||||
export async function getTeamTimer(seasonId: string, teamId: string) {
|
||||
const db = database();
|
||||
const [timer] = await db
|
||||
.select()
|
||||
.from(schema.draftTimers)
|
||||
.where(eq(schema.draftTimers.teamId, teamId));
|
||||
.where(and(eq(schema.draftTimers.seasonId, seasonId), eq(schema.draftTimers.teamId, teamId)));
|
||||
return timer;
|
||||
}
|
||||
|
||||
|
|
@ -30,12 +30,12 @@ export async function getSeasonTimers(seasonId: string) {
|
|||
.where(eq(schema.draftTimers.seasonId, seasonId));
|
||||
}
|
||||
|
||||
export async function updateTeamTimer(teamId: string, timeRemaining: number) {
|
||||
export async function updateTeamTimer(seasonId: string, teamId: string, timeRemaining: number) {
|
||||
const db = database();
|
||||
const [timer] = await db
|
||||
.update(schema.draftTimers)
|
||||
.set({ timeRemaining, updatedAt: new Date() })
|
||||
.where(eq(schema.draftTimers.teamId, teamId))
|
||||
.where(and(eq(schema.draftTimers.seasonId, seasonId), eq(schema.draftTimers.teamId, teamId)))
|
||||
.returning();
|
||||
return timer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,17 +61,26 @@ export async function action(args: any) {
|
|||
)
|
||||
);
|
||||
|
||||
let newTime: number;
|
||||
|
||||
if (!currentTimer) {
|
||||
return Response.json({ error: "Timer not found for this team" }, { status: 404 });
|
||||
if (adjustment <= 0) {
|
||||
return Response.json({ error: "Timer not found for this team" }, { status: 404 });
|
||||
}
|
||||
newTime = adjustment;
|
||||
await db.insert(schema.draftTimers).values({
|
||||
seasonId,
|
||||
teamId,
|
||||
timeRemaining: newTime,
|
||||
});
|
||||
} else {
|
||||
newTime = Math.max(0, currentTimer.timeRemaining + adjustment);
|
||||
await db
|
||||
.update(schema.draftTimers)
|
||||
.set({ timeRemaining: newTime, updatedAt: new Date() })
|
||||
.where(eq(schema.draftTimers.id, currentTimer.id));
|
||||
}
|
||||
|
||||
const newTime = Math.max(0, currentTimer.timeRemaining + adjustment);
|
||||
|
||||
await db
|
||||
.update(schema.draftTimers)
|
||||
.set({ timeRemaining: newTime, updatedAt: new Date() })
|
||||
.where(eq(schema.draftTimers.id, currentTimer.id));
|
||||
|
||||
try {
|
||||
getSocketIO()
|
||||
.to(`draft-${seasonId}`)
|
||||
|
|
|
|||
|
|
@ -148,9 +148,9 @@ export async function action(args: any) {
|
|||
),
|
||||
});
|
||||
|
||||
const incrementTime = season.draftIncrementTime || 30;
|
||||
const newTimeRemaining = (currentTimer?.timeRemaining ?? 0) + incrementTime;
|
||||
if (currentTimer) {
|
||||
const incrementTime = season.draftIncrementTime || 30;
|
||||
const newTimeRemaining = currentTimer.timeRemaining + incrementTime;
|
||||
await db
|
||||
.update(schema.draftTimers)
|
||||
.set({
|
||||
|
|
@ -158,18 +158,24 @@ export async function action(args: any) {
|
|||
updatedAt: new Date(),
|
||||
})
|
||||
.where(eq(schema.draftTimers.id, currentTimer.id));
|
||||
} else {
|
||||
await db.insert(schema.draftTimers).values({
|
||||
seasonId,
|
||||
teamId,
|
||||
timeRemaining: newTimeRemaining,
|
||||
});
|
||||
}
|
||||
|
||||
// Emit timer update to all clients
|
||||
try {
|
||||
getSocketIO().to(`draft-${seasonId}`).emit("timer-update", {
|
||||
seasonId,
|
||||
teamId,
|
||||
timeRemaining: newTimeRemaining,
|
||||
currentPickNumber: pickNumber,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Socket.IO timer-update error:", error);
|
||||
}
|
||||
// Emit timer update to all clients
|
||||
try {
|
||||
getSocketIO().to(`draft-${seasonId}`).emit("timer-update", {
|
||||
seasonId,
|
||||
teamId,
|
||||
timeRemaining: newTimeRemaining,
|
||||
currentPickNumber: pickNumber,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Socket.IO timer-update error:", error);
|
||||
}
|
||||
|
||||
// Initialize timer for the next team BEFORE updating pick number (prevents race condition)
|
||||
|
|
|
|||
|
|
@ -186,25 +186,29 @@ export async function action(args: any) {
|
|||
),
|
||||
});
|
||||
|
||||
if (!currentTimer) {
|
||||
console.warn(`[Pick] No timer found for team ${currentDraftSlot.teamId} in season ${seasonId}`);
|
||||
} else {
|
||||
const newTimeRemaining = currentTimer.timeRemaining + incrementTime;
|
||||
const newTimeRemaining = (currentTimer?.timeRemaining ?? 0) + incrementTime;
|
||||
if (currentTimer) {
|
||||
await db
|
||||
.update(schema.draftTimers)
|
||||
.set({ timeRemaining: newTimeRemaining, updatedAt: new Date() })
|
||||
.where(eq(schema.draftTimers.id, currentTimer.id));
|
||||
} else {
|
||||
await db.insert(schema.draftTimers).values({
|
||||
seasonId,
|
||||
teamId: currentDraftSlot.teamId,
|
||||
timeRemaining: newTimeRemaining,
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
getSocketIO().to(`draft-${seasonId}`).emit("timer-update", {
|
||||
seasonId,
|
||||
teamId: currentDraftSlot.teamId,
|
||||
timeRemaining: newTimeRemaining,
|
||||
currentPickNumber,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Socket.IO timer-update error:", error);
|
||||
}
|
||||
try {
|
||||
getSocketIO().to(`draft-${seasonId}`).emit("timer-update", {
|
||||
seasonId,
|
||||
teamId: currentDraftSlot.teamId,
|
||||
timeRemaining: newTimeRemaining,
|
||||
currentPickNumber,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Socket.IO timer-update error:", error);
|
||||
}
|
||||
|
||||
// Next team's timer is unchanged — their bank carries forward as-is
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue