SPB Git forge

spb/countryatlas

Public
20commits 1branches 0releases
268.3 MBsize
maindefault branch
12 days agolast push
TypeScript 57% Python 38.6% JavaScript 3.6% CSS 0.6%
2.3 KB · 66 lines tsx
Raw Blame History
1'use client';2import { createContext, useCallback, useContext, useMemo, useState, type ReactNode } from 'react';3import type { FormatSpec, ObservationStatus, Provenance } from '@/lib/types';45/** Indicator description the sheet needs (built from a MetricValue or an IndicatorCard). */6export interface ProvenanceIndicator extends FormatSpec {7  slug: string;8  name: string;9  methodology?: string | null;10  description?: string | null;11}1213/** The value being explained (a MetricValue or a SeriesValue reduced to what the sheet shows). */14export interface ProvenanceValue {15  value: number | null;16  formatted?: string | null;17  period: string | null;18  year?: number | null;19  unit?: string | null;20  is_estimate?: boolean;21  is_forecast?: boolean;22  status?: ObservationStatus | string | null;23  provenance: Provenance | null;24}2526export interface ProvenancePayload {27  indicator: ProvenanceIndicator;28  value: ProvenanceValue | null;29  country?: { id: string; slug: string | null; name: string; flag?: string | null } | null;30  /** Override download link; defaults to the country CSV, else the indicator CSV. */31  downloadHref?: string;32  /** Optional data-quality facts for the series (badges are derived when absent). */33  quality?: {34    badges?: Array<'fresh' | 'historical' | 'sparse' | 'limited-coverage' | 'stale' | 'flagged' | 'forecast'>;35    firstYear?: number | null;36    latestYear?: number | null;37    points?: number | null;38    missingYears?: number | null;39    continuityPct?: number | null;40    coveragePct?: number | null;41    referenceYear?: number | null;42  } | null;43}4445interface Ctx {46  payload: ProvenancePayload | null;47  open: (p: ProvenancePayload) => void;48  close: () => void;49}5051const ProvenanceCtx = createContext<Ctx | null>(null);5253export function ProvenanceProvider({ children }: { children: ReactNode }) {54  const [payload, setPayload] = useState<ProvenancePayload | null>(null);55  const open = useCallback((p: ProvenancePayload) => setPayload(p), []);56  const close = useCallback(() => setPayload(null), []);57  const value = useMemo(() => ({ payload, open, close }), [payload, open, close]);58  return <ProvenanceCtx.Provider value={value}>{children}</ProvenanceCtx.Provider>;59}6061export function useProvenance(): Ctx {62  const ctx = useContext(ProvenanceCtx);63  if (!ctx) return { payload: null, open: () => {}, close: () => {} };64  return ctx;65}66