From cfd5585f9d604d57089380101f5da84efffc6879 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 7 Nov 2025 22:45:23 +0000 Subject: [PATCH] fix: Remove double .data access in dashboard hooks causing undefined data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CRITICAL BUG FIX: This was the ACTUAL root cause of infinite loading state! The Bug: -------- apiClient.get() already returns response.data (line 494 in apiClient.ts): ```typescript async get(url: string): Promise { const response = await this.client.get(url); return response.data; // Returns data directly } ``` But hooks were doing: ```typescript queryFn: async () => { const response = await apiClient.get('/endpoint'); return response.data; // Bug! Accessing .data on data = undefined } ``` Flow of the Bug: ---------------- 1. API call succeeds with 200 OK 2. apiClient.get() returns: {status: "green", headline: "..."} 3. Hook tries to access .data on that object 4. Returns undefined to React Query 5. Component checks: if (!healthStatus) → true (because undefined) 6. Shows skeleton loader forever The Fix: -------- Changed all 5 hooks to: ```typescript queryFn: async () => { return await apiClient.get('/endpoint'); // ✅ Returns data directly } ``` Now: 1. API call succeeds with 200 OK 2. apiClient.get() returns: {status: "green", headline: "..."} 3. Hook returns data to React Query 4. React Query sets data 5. Component receives data → exits loading state 6. Dashboard renders! 🎉 Fixed hooks: - useBakeryHealthStatus - useOrchestrationSummary - useActionQueue - useProductionTimeline - useInsights Previous fixes that were needed but insufficient: - Added enabled: !!tenantId (prevented queries when tenantId empty) - Added useTenantInitializer (populated tenantId) - But data was still undefined due to this .data bug! --- frontend/src/api/hooks/newDashboard.ts | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/frontend/src/api/hooks/newDashboard.ts b/frontend/src/api/hooks/newDashboard.ts index 30ed5d82..66fdff67 100644 --- a/frontend/src/api/hooks/newDashboard.ts +++ b/frontend/src/api/hooks/newDashboard.ts @@ -152,10 +152,9 @@ export function useBakeryHealthStatus(tenantId: string) { return useQuery({ queryKey: ['bakery-health-status', tenantId], queryFn: async () => { - const response = await apiClient.get( + return await apiClient.get( `/tenants/${tenantId}/dashboard/health-status` ); - return response.data; }, enabled: !!tenantId, // Only fetch when tenantId is available refetchInterval: 30000, // Refresh every 30 seconds @@ -174,11 +173,10 @@ export function useOrchestrationSummary(tenantId: string, runId?: string) { queryKey: ['orchestration-summary', tenantId, runId], queryFn: async () => { const params = runId ? { run_id: runId } : {}; - const response = await apiClient.get( + return await apiClient.get( `/tenants/${tenantId}/dashboard/orchestration-summary`, { params } ); - return response.data; }, enabled: !!tenantId, // Only fetch when tenantId is available staleTime: 60000, // Summary doesn't change often @@ -196,10 +194,9 @@ export function useActionQueue(tenantId: string) { return useQuery({ queryKey: ['action-queue', tenantId], queryFn: async () => { - const response = await apiClient.get( + return await apiClient.get( `/tenants/${tenantId}/dashboard/action-queue` ); - return response.data; }, enabled: !!tenantId, // Only fetch when tenantId is available refetchInterval: 60000, // Refresh every minute @@ -217,10 +214,9 @@ export function useProductionTimeline(tenantId: string) { return useQuery({ queryKey: ['production-timeline', tenantId], queryFn: async () => { - const response = await apiClient.get( + return await apiClient.get( `/tenants/${tenantId}/dashboard/production-timeline` ); - return response.data; }, enabled: !!tenantId, // Only fetch when tenantId is available refetchInterval: 60000, // Refresh every minute @@ -238,10 +234,9 @@ export function useInsights(tenantId: string) { return useQuery({ queryKey: ['dashboard-insights', tenantId], queryFn: async () => { - const response = await apiClient.get( + return await apiClient.get( `/tenants/${tenantId}/dashboard/insights` ); - return response.data; }, enabled: !!tenantId, // Only fetch when tenantId is available refetchInterval: 120000, // Refresh every 2 minutes