| 1 | import { format } from "date-fns";
|
| 2 | import { useQuery } from "@tanstack/react-query";
|
| 3 | import { apiClient, Insight, InsightType, InsightPeriod } from "@/lib/api";
|
| 4 |
|
| 5 | // The device's local calendar day, used only to roll the cache over at midnight
|
| 6 | // so the pair refetches; the server still resolves the actual day boundary
|
| 7 | function localDay(): string {
|
| 8 | return format(new Date(), "yyyy-MM-dd");
|
| 9 | }
|
| 10 |
|
| 11 | export const insightKeys = {
|
| 12 | all: () => ["insights"] as const,
|
| 13 | lists: () => [...insightKeys.all(), "list"] as const,
|
| 14 | list: (filters?: InsightFilters) =>
|
| 15 | [...insightKeys.lists(), filters] as const,
|
| 16 | byType: (type: InsightType) =>
|
| 17 | [...insightKeys.all(), "type", type, localDay()] as const,
|
| 18 | };
|
| 19 |
|
| 20 | interface InsightFilters {
|
| 21 | type?: InsightType;
|
| 22 | period?: InsightPeriod;
|
| 23 | limit?: number;
|
| 24 | }
|
| 25 |
|
| 26 | const INSIGHT_STALE_TIMES: Record<InsightPeriod, number> = {
|
| 27 | DAILY: 1000 * 60 * 30, // 30 min, regenerates during the day
|
| 28 | WEEKLY: 1000 * 60 * 60 * 4, // 4h only changes on cron or mutations
|
| 29 | MONTHLY: 1000 * 60 * 60 * 24, // 24h
|
| 30 | };
|
| 31 |
|
| 32 | const INSIGHT_PERIOD: Record<InsightType, InsightPeriod> = {
|
| 33 | DAILY_ENERGY: "DAILY",
|
| 34 | MOOD_TREND: "WEEKLY",
|
| 35 | ENERGY_SLEEP_CORRELATION: "WEEKLY",
|
| 36 | TRIGGER_PATTERN: "WEEKLY",
|
| 37 | DAILY_SLEEP: "DAILY",
|
| 38 | };
|
| 39 |
|
| 40 | export const useInsight = <T extends InsightType>(type: T) => {
|
| 41 | const period = INSIGHT_PERIOD[type];
|
| 42 | const staleTime = INSIGHT_STALE_TIMES[period];
|
| 43 |
|
| 44 | return useQuery({
|
| 45 | queryKey: insightKeys.byType(type),
|
| 46 | queryFn: () =>
|
| 47 | apiClient
|
| 48 | .getInsights<T>({ type, limit: 1 })
|
| 49 | .then((res) => res.insights[0] ?? null),
|
| 50 | staleTime,
|
| 51 | });
|
| 52 | };
|
| 53 |
|
| 54 | export const useInsights = (filters?: InsightFilters) => {
|
| 55 | return useQuery({
|
| 56 | queryKey: insightKeys.list(filters),
|
| 57 | queryFn: () => apiClient.getInsights(filters).then((res) => res.insights),
|
| 58 | staleTime: 1000 * 60 * 15,
|
| 59 | });
|
| 60 | };
|