Files
nxdns/admin/src/features/overview/overviewWindow.ts
T
mokhtar 6a0630c288
Gates / frontend (push) Successful in 2m6s
Gates / test (push) Successful in 2m57s
Gates / test-aarch64 (push) Successful in 8m31s
Gates / package (push) Successful in 4m19s
Gates / container (push) Failing after 2s
CI / gates (push) Failing after 26m21s
overview: one endpoint, live projections and a response cache (m36)
2026-08-27 17:48:20 +02:00

35 lines
1.7 KiB
TypeScript

/**
* One period, one request, one window.
*
* The five per-panel endpoints this replaces could each answer for a different
* span, so the page had to reconcile five window identities, retry the laggards
* and fail the ones that stayed behind. `GET /api/overview` answers every panel
* out of a single read transaction: the totals, both timelines and both
* breakdowns describe the same span and the same database state by construction,
* and none of that reconciliation has anything left to reconcile.
*
* What remains is the one rule a single request does not settle by itself.
* `keepPreviousData` holds the body of the period the reader just left — a
* complete, self-consistent answer, and still the wrong one to draw under the
* new label — so a body is a member of this window only while its own `period`
* is the selected one. Until then the page is loading.
*/
import { useCallback } from "react";
import { keepPreviousData, useQuery } from "@tanstack/react-query";
import { overviewQuery } from "@/lib/queries";
import type { Overview, Period } from "@/lib/types";
export type Panel<T> =
{ status: "loading" } | { status: "error"; error: unknown; retry: () => void } | { status: "ready"; data: T };
export function useOverviewWindow(period: Period): Panel<Overview> {
const query = useQuery({ ...overviewQuery(period), placeholderData: keepPreviousData });
const { refetch } = query;
const retry = useCallback(() => void refetch(), [refetch]);
if (query.isError) return { status: "error", error: query.error, retry };
if (query.data !== undefined && query.data.period === period) return { status: "ready", data: query.data };
return { status: "loading" };
}