mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 13:22:14 +00:00
One-shot prettier pass so the new format:check gate starts from a clean baseline. Formatting only — no behaviour change. Generator-owned and vendored artifacts stay untouched via .prettierignore.
95 lines
3.4 KiB
TypeScript
95 lines
3.4 KiB
TypeScript
"use client";
|
|
|
|
import { useAuth } from "@/hooks/use-auth";
|
|
import {
|
|
hasMetricData,
|
|
type InsightMetric,
|
|
} from "@/lib/insights/metric-availability";
|
|
import { useAnalyticsQuery } from "@/lib/queries/use-analytics-query";
|
|
import type { SubPageAnalyticsData } from "@/types/analytics";
|
|
|
|
/**
|
|
* v1.4.28 R3d (BK-F-H1) — shared React-Query wrapper for the analytics
|
|
* payload behind every insights sub-page.
|
|
*
|
|
* The five hard-data sub-pages (`puls`, `blutdruck`, `gewicht`, `bmi`,
|
|
* `schlaf`) each used to declare:
|
|
*
|
|
* - a private `AnalyticsData` interface,
|
|
* - a `useQuery` block keyed on `["analytics"]` with a 60-second
|
|
* `staleTime`,
|
|
* - an `if (isAuthenticated && analytics && !hasMetricData(...)) { … }`
|
|
* short-circuit that rendered a sub-page-specific empty state.
|
|
*
|
|
* Those three are now collapsed onto this hook:
|
|
*
|
|
* - the query reuses the same `["analytics"]` cache key as the
|
|
* dashboard + the insights mother page, so navigating between
|
|
* surfaces is a free cache hit;
|
|
* - `isEmpty` runs `hasMetricData()` with the caller's metric so
|
|
* each sub-page checks the right gate without re-importing the
|
|
* helper;
|
|
* - the typed result keeps the existing `data` slot so any caller
|
|
* that still needs a richer field (today: none — the sub-pages
|
|
* only read `summaries`) can fall back to direct access.
|
|
*
|
|
* The mood and medication sub-pages still need richer payloads
|
|
* (`/api/insights/comprehensive`) so they don't consume this hook —
|
|
* those keep their bespoke fetch but adopt the same `<MetricEmptyState>`
|
|
* primitive for the empty-state render so the visual contract is one.
|
|
*/
|
|
export interface UseInsightsAnalyticsResult {
|
|
data: SubPageAnalyticsData | undefined;
|
|
isLoading: boolean;
|
|
/**
|
|
* True when the analytics payload arrived AND the metric has no
|
|
* observations. Sub-pages render the empty-state primitive when this
|
|
* flips true. False while the query is still in-flight (we don't
|
|
* want to flash the empty state before the data lands).
|
|
*/
|
|
isEmpty: boolean;
|
|
error: Error | null;
|
|
/**
|
|
* Re-issue the underlying `/api/analytics?slice=summaries` query. Wired
|
|
* to the error+retry control on the HealthKit sub-pages so a failed load
|
|
* recovers without a full reload.
|
|
*/
|
|
refetch: () => void;
|
|
}
|
|
|
|
export function useInsightsAnalytics(
|
|
metric: InsightMetric,
|
|
): UseInsightsAnalyticsResult {
|
|
const { isAuthenticated } = useAuth();
|
|
// v1.4.33 IW2 — sub-pages only read `summaries[METRIC].count` for the
|
|
// gating short-circuit, so they ride on the slim slice. The mother
|
|
// page keeps the default thick slice for `correlations` /
|
|
// `healthScore` / `bpInTargetPct*`; both consumers live in the same
|
|
// queryKey tree (root `["analytics"]`) but the slim slice has its own
|
|
// cache slot under `["analytics", "summaries"]`.
|
|
const query = useAnalyticsQuery({ slice: "summaries" });
|
|
const data = query.data as SubPageAnalyticsData | undefined;
|
|
|
|
const isEmpty =
|
|
Boolean(isAuthenticated) &&
|
|
data !== undefined &&
|
|
!hasMetricData(metric, {
|
|
summaries: data.summaries,
|
|
// Sub-pages that go through this hook are sensor-backed only
|
|
// (PULSE / WEIGHT / BMI / BLOOD_PRESSURE_SYS / SLEEP_DURATION).
|
|
// Mood + medication run their own gate.
|
|
hasMood: false,
|
|
hasMedication: false,
|
|
});
|
|
|
|
return {
|
|
data,
|
|
isLoading: query.isLoading,
|
|
isEmpty,
|
|
error: query.error as Error | null,
|
|
refetch: () => {
|
|
void query.refetch();
|
|
},
|
|
};
|
|
}
|