"use client"; import { useCallback, useEffect, useRef, useState } from "react"; import { fetchChartView } from "@/lib/chart-view-client"; import type { ChartViewResponse } from "@/lib/chart-view-contract"; import type { ChartViewLayer } from "@/lib/chart-view-engine"; import { CHART_VIEW_COPY } from "@/lib/chart-view-labels"; import { peekChartPage, refreshChartPage, writeChartPage, type ChartPageSnapshot, } from "@/lib/secondary-page-data"; function unavailableBody(): ChartViewResponse { return { status: "chart_unavailable", billed: false, message: CHART_VIEW_COPY.unavailable }; } function warnClientFailure(label: string, error: unknown, extra?: Record): void { console.warn(label, { errorName: error instanceof Error ? error.name : "Error", message: error instanceof Error ? error.message : "unknown", ...extra, }); } function viewFromSnapshot(snapshot: ChartPageSnapshot | null): ChartViewResponse | null { return snapshot?.kind === "view" ? snapshot.view : null; } export function useChartPage() { const [view, setView] = useState(() => viewFromSnapshot(peekChartPage())); const [pendingLayers, setPendingLayers] = useState>(new Set()); const loadedLayers = useRef(new Set()); const inflightLayers = useRef(new Set()); useEffect(() => { const cached = peekChartPage(); if (cached?.kind === "unauthenticated") { window.location.assign("/login"); return; } let cancelled = false; void refreshChartPage() .then((snapshot) => { if (cancelled) return; if (snapshot.kind === "unauthenticated") { window.location.assign("/login"); return; } setView(snapshot.view); }) .catch((error: unknown) => { if (cancelled) return; warnClientFailure("chart_page_fetch_failed", error); if (peekChartPage()?.kind === "view") return; const fallback = unavailableBody(); writeChartPage({ kind: "view", view: fallback }); setView(fallback); }); return () => { cancelled = true; }; }, []); const requestLayer = useCallback((layer: ChartViewLayer) => { if (loadedLayers.current.has(layer) || inflightLayers.current.has(layer)) return; inflightLayers.current.add(layer); setPendingLayers((current) => { if (current.has(layer)) return current; const next = new Set(current); next.add(layer); return next; }); void fetchChartView({ layers: [layer] }) .then((result) => { if (result.body?.status === "ok") { const stored = writeChartPage({ kind: "view", view: result.body }); if (stored.kind !== "view" || stored.view.status !== "ok") { setView(stored.kind === "view" ? stored.view : result.body); return; } loadedLayers.current.add(layer); setView(stored.view); } }) .catch((error: unknown) => { warnClientFailure("chart_page_layer_failed", error, { layer }); }) .finally(() => { inflightLayers.current.delete(layer); setPendingLayers((current) => { if (!current.has(layer)) return current; const next = new Set(current); next.delete(layer); return next; }); }); }, []); return { view, pendingLayers, requestLayer }; }