mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-15 06:52:04 +00:00
feat(insights): add generic per-metric assessment loader
Add a parameterised query key (insightsMetricStatus) and a useInsightMetricStatus hook that reads the generic per-metric assessment route GET /api/insights/metric-status?metric=<id>. The seven bespoke status routes keep their own keys and hook union; this one covers the HealthKit metric sub-pages that share a single route keyed by the metric id. The hook mirrors the existing status loader: 8 s client ceiling, no inline retry, and the bounded preparing poll. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit a3407a2f6c1e9f54c92a6f182db894ae0593e69f)
This commit is contained in:
1 parent
e33911e2d4
commit
16b0c349f2
2 files changed
+66
No files matched your search
@@ -163,3 +163,59 @@ export function useInsightStatus(metric: InsightStatusMetric) {
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* v1.8.7.1 — generic per-metric assessment loader for the HealthKit
|
||||||
|
* metric sub-pages. The seven bespoke metrics above (`weight`, `pulse`,
|
||||||
|
* …) each own a hand-written `/api/insights/<metric>-status` route; the
|
||||||
|
* ~29 HealthKit pages instead share one generic route keyed by the
|
||||||
|
* metric id:
|
||||||
|
*
|
||||||
|
* GET /api/insights/metric-status?metric=<METRIC_ID>&locale=<locale>
|
||||||
|
*
|
||||||
|
* where METRIC_ID is the existing HealthKit measurement identifier
|
||||||
|
* (`HEART_RATE_VARIABILITY`, `RESTING_HEART_RATE`, `SLEEP_DURATION`, …).
|
||||||
|
* The response envelope, the 8 s client ceiling, the no-retry policy and
|
||||||
|
* the bounded `preparing` poll are identical to `useInsightStatus` — the
|
||||||
|
* card consumes the same `InsightStatusData` shape for every scope.
|
||||||
|
*
|
||||||
|
* `enabled` lets the page suppress the fetch entirely when the metric has
|
||||||
|
* no data (the page renders the insufficient-data empty state instead of
|
||||||
|
* the card), so a brand-new account never fires an assessment round-trip.
|
||||||
|
*/
|
||||||
|
export function useInsightMetricStatus(metric: string, enabled = true) {
|
||||||
|
const { isAuthenticated } = useAuth();
|
||||||
|
const { locale } = useTranslations();
|
||||||
|
|
||||||
|
return useQuery({
|
||||||
|
queryKey: queryKeys.insightsMetricStatus(metric, locale),
|
||||||
|
queryFn: async (): Promise<InsightStatusData> => {
|
||||||
|
const controller = new AbortController();
|
||||||
|
const timeoutHandle = setTimeout(
|
||||||
|
() => controller.abort(),
|
||||||
|
STATUS_TIMEOUT_MS,
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
const res = await fetch(
|
||||||
|
`/api/insights/metric-status?metric=${encodeURIComponent(
|
||||||
|
metric,
|
||||||
|
)}&locale=${locale}`,
|
||||||
|
{ signal: controller.signal },
|
||||||
|
);
|
||||||
|
if (!res.ok) throw new Error("Failed");
|
||||||
|
const json = (await res.json()) as { data: InsightStatusData };
|
||||||
|
return json.data;
|
||||||
|
} finally {
|
||||||
|
clearTimeout(timeoutHandle);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
enabled: isAuthenticated && enabled,
|
||||||
|
staleTime: 60 * 1000,
|
||||||
|
retry: 0,
|
||||||
|
refetchInterval: (query) =>
|
||||||
|
nextStatusPollInterval(
|
||||||
|
query.state.data?.preparing,
|
||||||
|
query.state.dataUpdateCount,
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -103,6 +103,16 @@ export const queryKeys = {
|
|||||||
["insights", "mood-status", locale] as const,
|
["insights", "mood-status", locale] as const,
|
||||||
insightsMedicationComplianceStatus: (locale: string) =>
|
insightsMedicationComplianceStatus: (locale: string) =>
|
||||||
["insights", "medication-compliance-status", locale] as const,
|
["insights", "medication-compliance-status", locale] as const,
|
||||||
|
/**
|
||||||
|
* v1.8.7.1 — per-metric insight assessment for the HealthKit metric
|
||||||
|
* sub-pages. One generic route (`/api/insights/metric-status?metric=…`)
|
||||||
|
* backs every HealthKit metric, so the key is parameterised by the
|
||||||
|
* metric id alongside the locale rather than minting a bespoke factory
|
||||||
|
* entry per metric. The seven bespoke `*-status` routes above keep
|
||||||
|
* their own keys; this one covers the ~29 generic HealthKit pages.
|
||||||
|
*/
|
||||||
|
insightsMetricStatus: (metric: string, locale: string) =>
|
||||||
|
["insights", "metric-status", metric, locale] as const,
|
||||||
|
|
||||||
medications: () => ["medications"] as const,
|
medications: () => ["medications"] as const,
|
||||||
medicationDetail: (id: string) => ["medications", id] as const,
|
medicationDetail: (id: string) => ["medications", id] as const,
|
||||||
|
|||||||
Reference in new issue
Block a user