mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 20:42:43 +00:00
The v1.9.0 time-range work imported ANALYTICS_RANGES as a value into the time-range pills and the insights layout-prefs hook from range-delta.ts. That module also pulls the rollup readers and the Postgres client, so the value import dragged pg (dns/fs/net/tls) into the browser bundle and broke the production build with eight "Module not found" errors. Move the client-safe pieces — the range list, its type, the per-range window length, and the period-over-period result shapes — into a new range-shared module that imports nothing server-side. The insights client components import from there; range-delta.ts re-exports the same names so the server route and the OpenAPI registry keep their import paths. The window-composition logic and the rollup/db imports stay server-side. No runtime behaviour change — a pure module-boundary split. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit 75124e76c1e987d8a022fb39d891049340199b38)
57 lines
1.6 KiB
TypeScript
57 lines
1.6 KiB
TypeScript
"use client";
|
|
|
|
import { useQuery } from "@tanstack/react-query";
|
|
|
|
import { useAuth } from "@/hooks/use-auth";
|
|
import { queryKeys } from "@/lib/query-keys";
|
|
import type { AnalyticsRange } from "@/lib/analytics/range-shared";
|
|
|
|
/**
|
|
* v1.9.0 — client reader for the single-metric period-over-period range
|
|
* read (`GET /api/analytics/range`). One cache slot per `(type, range)` via
|
|
* the centralised query-key factory, so switching the time-range pills is a
|
|
* cheap cache hit after first fetch and never collides with the shared
|
|
* `["analytics", "summaries"]` slot.
|
|
*/
|
|
export interface AnalyticsWindowAggregate {
|
|
count: number;
|
|
min: number | null;
|
|
max: number | null;
|
|
mean: number | null;
|
|
sum: number | null;
|
|
}
|
|
|
|
export interface AnalyticsRangeData {
|
|
range: AnalyticsRange;
|
|
windowDays: number;
|
|
granularity: string;
|
|
current: AnalyticsWindowAggregate;
|
|
previous: AnalyticsWindowAggregate;
|
|
delta: number | null;
|
|
deltaPct: number | null;
|
|
}
|
|
|
|
export function useAnalyticsRange(
|
|
type: string,
|
|
range: AnalyticsRange,
|
|
enabled = true,
|
|
) {
|
|
const { isAuthenticated } = useAuth();
|
|
|
|
return useQuery({
|
|
queryKey: queryKeys.analyticsRange(type, range),
|
|
queryFn: async (): Promise<AnalyticsRangeData> => {
|
|
const res = await fetch(
|
|
`/api/analytics/range?type=${encodeURIComponent(
|
|
type,
|
|
)}&range=${encodeURIComponent(range)}`,
|
|
);
|
|
if (!res.ok) throw new Error("Failed to load range");
|
|
const json = (await res.json()) as { data: AnalyticsRangeData };
|
|
return json.data;
|
|
},
|
|
enabled: isAuthenticated && enabled && type.length > 0,
|
|
staleTime: 60 * 1000,
|
|
});
|
|
}
|