From 4847d2fc40f836c1c5266f46801abd8b658b87e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Fri, 5 Jun 2026 14:06:25 +0200 Subject: [PATCH] fix(insights): surface an error + retry on the overview, not the empty state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The overview empty-state gated on the comprehensive query reporting zero measurements, but a transient 500 / network drop settles the query with no data too — so a user with history saw the false 'no data yet — add a measurement' prompt with no way to recover. Add an isError branch above the empty-state that renders a load-error message plus a Retry that refetches the query, mirroring the vitals-dashboard pattern. Reuses the existing insights.loadError + common.retry keys. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/app/insights/page.tsx | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/app/insights/page.tsx b/src/app/insights/page.tsx index 7258f99b1..be7a0aaeb 100644 --- a/src/app/insights/page.tsx +++ b/src/app/insights/page.tsx @@ -3,7 +3,7 @@ import { useQuery } from "@tanstack/react-query"; import dynamic from "next/dynamic"; import Link from "next/link"; -import { TrendingUp } from "lucide-react"; +import { RefreshCw, TrendingUp } from "lucide-react"; import { useAuth } from "@/hooks/use-auth"; import { queryKeys } from "@/lib/query-keys"; @@ -214,7 +214,7 @@ export default function InsightsPage() { // empty-state branch only fires once the query has resolved AND // reported zero measurements; while it's in-flight the page paints // the regular shell and the tiles fill in as their data lands. - const { data, isLoading, isFetched } = useQuery({ + const { data, isLoading, isFetched, isError, refetch } = useQuery({ queryKey: queryKeys.insightsComprehensive(), queryFn: async () => { const res = await fetch("/api/insights/comprehensive"); @@ -244,6 +244,35 @@ export default function InsightsPage() { // single query instance, so the wellness lift adds no second request. const dashboardDerived = useDashboardDerived(isAuthenticated); + // Error branch — a transient 500 / network drop (after the query's + // retries are exhausted) settles the comprehensive query with no data. + // Without this gate the page would fall through to the "no data yet — + // add a measurement" empty-state, which reads false for a user with + // history. Surface an error + a Retry that refetches the one query, + // mirroring the error pattern. + if (isError) { + return ( +
+ {t("insights.loadError")} + +
+ ); + } + // Empty-state shortcut — only paint once the comprehensive query has // resolved AND reported zero measurements. While it's in-flight we // fall through to the streamed shell so the user gets the hero +