diff --git a/packages/web/app/components/board-provider/board-provider-context.tsx b/packages/web/app/components/board-provider/board-provider-context.tsx index e9d49ce9..54bbcc00 100644 --- a/packages/web/app/components/board-provider/board-provider-context.tsx +++ b/packages/web/app/components/board-provider/board-provider-context.tsx @@ -78,7 +78,7 @@ interface BoardContextType { error: string | null; isInitialized: boolean; logbook: LogbookEntry[]; - getLogbook: (climbUuids: ClimbUuid[]) => Promise; + getLogbook: (climbUuids: ClimbUuid[]) => Promise; saveTick: (options: SaveTickOptions) => Promise; saveClimb: (options: Omit) => Promise; } @@ -167,16 +167,17 @@ export function BoardProvider({ boardName, children }: { boardName: BoardName; c }, [boardName, sessionStatus]); // Internal fetch function (not memoized, called by getLogbook and effect) - const fetchLogbook = async (climbUuids: ClimbUuid[]) => { + // Returns true if the fetch was successful, false if it was skipped or failed + const fetchLogbook = async (climbUuids: ClimbUuid[]): Promise => { if (sessionStatus !== 'authenticated') { setLogbook([]); - return; + return false; } // CRITICAL: Wait for wsAuthToken to be available if (!wsAuthToken) { console.log('[fetchLogbook] Waiting for auth token...'); - return; // Will be called again when wsAuthToken becomes available + return false; // Caller should retry when wsAuthToken becomes available } try { @@ -215,17 +216,20 @@ export function BoardProvider({ boardName, children }: { boardName: BoardName; c })); setLogbook(entries); + return true; } catch (err) { console.error('Failed to fetch logbook:', err); setLogbook([]); + return false; } }; // Fetch logbook from local ticks API (works without Aurora credentials) - const getLogbook = useCallback(async (climbUuids: ClimbUuid[]) => { + // Returns true if the fetch was successful, false if it was skipped or failed + const getLogbook = useCallback(async (climbUuids: ClimbUuid[]): Promise => { // Store the UUIDs in ref to avoid re-render loops currentClimbUuidsRef.current = climbUuids; - await fetchLogbook(climbUuids); + return await fetchLogbook(climbUuids); }, [boardName, sessionStatus, wsAuthToken]); // Refetch logbook only when session status changes from non-authenticated to authenticated diff --git a/packages/web/app/components/queue-control/__tests__/hooks/use-queue-data-fetching.test.tsx b/packages/web/app/components/queue-control/__tests__/hooks/use-queue-data-fetching.test.tsx index 6eb97462..12fea013 100644 --- a/packages/web/app/components/queue-control/__tests__/hooks/use-queue-data-fetching.test.tsx +++ b/packages/web/app/components/queue-control/__tests__/hooks/use-queue-data-fetching.test.tsx @@ -15,7 +15,7 @@ vi.mock('@/app/lib/url-utils', () => ({ vi.mock('../../../board-provider/board-provider-context', () => ({ useBoardProvider: vi.fn(() => ({ - getLogbook: vi.fn() + getLogbook: vi.fn().mockResolvedValue(true) })) })); @@ -129,7 +129,7 @@ const createWrapper = () => { describe('useQueueDataFetching', () => { const mockSetHasDoneFirstFetch = vi.fn(); - const mockGetLogbook = vi.fn(); + const mockGetLogbook = vi.fn().mockResolvedValue(true); beforeEach(() => { vi.clearAllMocks(); diff --git a/packages/web/app/components/queue-control/hooks/use-queue-data-fetching.tsx b/packages/web/app/components/queue-control/hooks/use-queue-data-fetching.tsx index 85c0cf9f..04c721a8 100644 --- a/packages/web/app/components/queue-control/hooks/use-queue-data-fetching.tsx +++ b/packages/web/app/components/queue-control/hooks/use-queue-data-fetching.tsx @@ -266,8 +266,13 @@ export const useQueueDataFetching = ({ const climbUuids = JSON.parse(climbUuidsString); if (climbUuids.length > 0) { - getLogbook(climbUuids); - fetchedUuidsRef.current = climbUuidsString; + // Only mark as fetched if the fetch actually succeeded + // This ensures we retry when wsAuthToken becomes available + getLogbook(climbUuids).then((success) => { + if (success) { + fetchedUuidsRef.current = climbUuidsString; + } + }); } }, [climbUuidsString, getLogbook]);