From e3a7a1a9b11b88206e767e3a256d7f49afe7e329 Mon Sep 17 00:00:00 2001 From: Chris Parsons Date: Sat, 23 May 2026 18:29:13 -0700 Subject: [PATCH] Fix autodraft settings panel not reflecting auto-disable after pick When next_queue autodraft fires and turns itself off, two bugs prevented the UI from behaving correctly: 1. After reconnect, useDraftAuthRecovery synced autodraftStatus (draft grid) but not userAutodraft (settings panel), leaving the settings badge stale until the next page load. 2. Toast notifications for autodraft auto-disable were unreliable: the condition checked prev.mode rather than why the server disabled it, causing the wrong toast for manual disables and queue-empty events. Fix the reconnect sync by calling setUserAutodraft in the revalidation effect alongside setAutodraftStatus. Fix the toast logic by adding a reason field ("pick_complete" | "queue_empty") to the server's autodraft-updated emit, so the client can show the right message without guessing from local state. Also removes the now-unused userAutodraftRef. Co-Authored-By: Claude Sonnet 4.6 --- app/hooks/useDraftAuthRecovery.ts | 19 +++++++++++-------- app/hooks/useDraftSocketEvents.ts | 8 ++++---- app/models/draft-utils.ts | 2 ++ .../leagues/$leagueId.draft.$seasonId.tsx | 2 -- server/socket.ts | 1 + 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/app/hooks/useDraftAuthRecovery.ts b/app/hooks/useDraftAuthRecovery.ts index 46dee59..d3df7a6 100644 --- a/app/hooks/useDraftAuthRecovery.ts +++ b/app/hooks/useDraftAuthRecovery.ts @@ -62,11 +62,6 @@ export function useDraftAuthRecovery({ mode: (userAutodraftSettings?.mode || "next_pick") as "next_pick" | "while_on", queueOnly: userAutodraftSettings?.queueOnly || false, }); - const userAutodraftRef = useRef(userAutodraft); - useEffect(() => { - userAutodraftRef.current = userAutodraft; - }, [userAutodraft]); - // Re-fetch loader data after each reconnect so stale picks/timers are refreshed. const revalidationRetryRef = useRef | null>(null); useEffect(() => { @@ -194,10 +189,19 @@ export function useDraftAuthRecovery({ }); return status; }); + + if (userAutodraftSettings) { + setUserAutodraft({ + isEnabled: userAutodraftSettings.isEnabled, + mode: userAutodraftSettings.mode, + queueOnly: userAutodraftSettings.queueOnly, + }); + } + setIsSyncing(false); } - }, [revalidatorState, draftPicks, season, userQueue, timers, autodraftSettings, currentUserId, - setPicks, setCurrentPick, setIsPaused, setIsDraftComplete, setQueue, setTeamTimers, setAutodraftStatus, setIsSyncing]); + }, [revalidatorState, draftPicks, season, userQueue, timers, autodraftSettings, currentUserId, userAutodraftSettings, + setPicks, setCurrentPick, setIsPaused, setIsDraftComplete, setQueue, setTeamTimers, setAutodraftStatus, setUserAutodraft, setIsSyncing]); const authFetch = useCallback(async (url: string, init?: RequestInit): Promise => { const response = await fetch(url, init); @@ -213,7 +217,6 @@ export function useDraftAuthRecovery({ authFetch, userAutodraft, setUserAutodraft, - userAutodraftRef, isRevalidatingRef, pendingPicksDuringRevalidationRef, pendingQueueMutationsRef, diff --git a/app/hooks/useDraftSocketEvents.ts b/app/hooks/useDraftSocketEvents.ts index af94f4a..da6aab2 100644 --- a/app/hooks/useDraftSocketEvents.ts +++ b/app/hooks/useDraftSocketEvents.ts @@ -22,7 +22,6 @@ interface UseDraftSocketEventsParams { isRevalidatingRef: RefObject; pendingPicksDuringRevalidationRef: MutableRefObject; pendingQueueMutationsRef: MutableRefObject; - userAutodraftRef: MutableRefObject<{ isEnabled: boolean; mode: "next_pick" | "while_on"; queueOnly: boolean }>; // Notification refs from the component sendNotificationRef: MutableRefObject<(title: string, body: string) => void>; notificationsModeRef: MutableRefObject; @@ -55,7 +54,6 @@ export function useDraftSocketEvents({ isRevalidatingRef, pendingPicksDuringRevalidationRef, pendingQueueMutationsRef, - userAutodraftRef, sendNotificationRef, notificationsModeRef, setPicks, @@ -139,6 +137,7 @@ export function useDraftSocketEvents({ mode: "next_pick" | "while_on"; queueOnly: boolean; source?: "commissioner" | "user"; + reason?: "queue_empty" | "pick_complete"; }) => { setAutodraftStatus((prev) => ({ ...prev, @@ -153,8 +152,9 @@ export function useDraftSocketEvents({ toast.info(`Commissioner changed your autodraft to "${getAutodraftLabel(data.isEnabled, data.mode, data.queueOnly)}"`); } } else { - const prev = userAutodraftRef.current; - if (!data.isEnabled && prev.isEnabled && prev.queueOnly && prev.mode === "while_on") { + if (!data.isEnabled && data.reason === "pick_complete") { + toast.info("Autodraft turned off — next pick complete"); + } else if (!data.isEnabled && data.reason === "queue_empty") { toast.info("Autodraft disabled — your queue is empty"); } } diff --git a/app/models/draft-utils.ts b/app/models/draft-utils.ts index 91cdb6b..d50a537 100644 --- a/app/models/draft-utils.ts +++ b/app/models/draft-utils.ts @@ -569,6 +569,7 @@ export async function executeAutoPick(params: { isEnabled: false, mode: autodraftSettings.mode, queueOnly: autodraftSettings.queueOnly, + reason: "queue_empty" as const, }); } catch (error) { logger.error("[AutoPick] Socket.IO autodraft-updated error (queue-empty shutoff):", error); @@ -774,6 +775,7 @@ export async function executeAutoPick(params: { isEnabled: false, mode: autodraftSettings.mode, queueOnly: autodraftSettings.queueOnly, + reason: "pick_complete" as const, }); } catch (error) { logger.error("[AutoPick] Socket.IO autodraft-updated error:", error); diff --git a/app/routes/leagues/$leagueId.draft.$seasonId.tsx b/app/routes/leagues/$leagueId.draft.$seasonId.tsx index 1ee9492..67afda8 100644 --- a/app/routes/leagues/$leagueId.draft.$seasonId.tsx +++ b/app/routes/leagues/$leagueId.draft.$seasonId.tsx @@ -343,7 +343,6 @@ export default function DraftRoom() { authFetch, userAutodraft, setUserAutodraft, - userAutodraftRef, isRevalidatingRef, pendingPicksDuringRevalidationRef, pendingQueueMutationsRef, @@ -504,7 +503,6 @@ export default function DraftRoom() { isRevalidatingRef, pendingPicksDuringRevalidationRef, pendingQueueMutationsRef, - userAutodraftRef, sendNotificationRef, notificationsModeRef, setPicks, diff --git a/server/socket.ts b/server/socket.ts index 4fbb51e..585210d 100644 --- a/server/socket.ts +++ b/server/socket.ts @@ -30,6 +30,7 @@ interface ServerToClientEvents { mode: "next_pick" | "while_on"; queueOnly: boolean; source?: "commissioner" | "user"; + reason?: "queue_empty" | "pick_complete"; }) => void; "team-connected": (data: { teamId: string }) => void; "team-disconnected": (data: { teamId: string }) => void;