@burdenoff/microfe-theglobalfuel 2026.716.1 → 2026.720.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/theglobalfuel/TheGlobalFuelRoutes.d.ts.map +1 -1
  2. package/dist/theglobalfuel/TheGlobalFuelRoutes.js +34 -22
  3. package/dist/theglobalfuel/TheGlobalFuelRoutes.js.map +1 -1
  4. package/dist/theglobalfuel/components/DataTable.js +1 -1
  5. package/dist/theglobalfuel/components/DataTable.js.map +1 -1
  6. package/dist/theglobalfuel/components/MiniBar.d.ts.map +1 -1
  7. package/dist/theglobalfuel/components/MiniBar.js +1 -1
  8. package/dist/theglobalfuel/components/MiniBar.js.map +1 -1
  9. package/dist/theglobalfuel/components/Tabs.js +1 -1
  10. package/dist/theglobalfuel/components/Tabs.js.map +1 -1
  11. package/dist/theglobalfuel/components/index.js +2 -0
  12. package/dist/theglobalfuel/components/viz/BarChart.js +83 -4
  13. package/dist/theglobalfuel/components/viz/BarChart.js.map +1 -0
  14. package/dist/theglobalfuel/components/viz/StatCard.js +60 -3
  15. package/dist/theglobalfuel/components/viz/StatCard.js.map +1 -0
  16. package/dist/theglobalfuel/hooks/useTheGlobalFuelApi.d.ts +10 -1
  17. package/dist/theglobalfuel/hooks/useTheGlobalFuelApi.d.ts.map +1 -1
  18. package/dist/theglobalfuel/hooks/useTheGlobalFuelApi.js +1 -1
  19. package/dist/theglobalfuel/hooks/useTheGlobalFuelApi.js.map +1 -1
  20. package/dist/theglobalfuel/pages/alerts/AlertsPage.d.ts +16 -0
  21. package/dist/theglobalfuel/pages/alerts/AlertsPage.d.ts.map +1 -0
  22. package/dist/theglobalfuel/pages/alerts/AlertsPage.js +295 -0
  23. package/dist/theglobalfuel/pages/alerts/AlertsPage.js.map +1 -0
  24. package/dist/theglobalfuel/pages/analytics/AnalyticsPage.d.ts +13 -0
  25. package/dist/theglobalfuel/pages/analytics/AnalyticsPage.d.ts.map +1 -0
  26. package/dist/theglobalfuel/pages/analytics/AnalyticsPage.js +358 -0
  27. package/dist/theglobalfuel/pages/analytics/AnalyticsPage.js.map +1 -0
  28. package/dist/theglobalfuel/pages/assets/AssetDetailPage.d.ts.map +1 -1
  29. package/dist/theglobalfuel/pages/assets/AssetDetailPage.js +386 -342
  30. package/dist/theglobalfuel/pages/assets/AssetDetailPage.js.map +1 -1
  31. package/dist/theglobalfuel/pages/assets/AssetsPage.d.ts.map +1 -1
  32. package/dist/theglobalfuel/pages/assets/AssetsPage.js +277 -199
  33. package/dist/theglobalfuel/pages/assets/AssetsPage.js.map +1 -1
  34. package/dist/theglobalfuel/pages/contracts/ContractsPage.js +1 -1
  35. package/dist/theglobalfuel/pages/contracts/ContractsPage.js.map +1 -1
  36. package/dist/theglobalfuel/pages/dashboard/DashboardPage.js +6 -6
  37. package/dist/theglobalfuel/pages/dashboard/DashboardPage.js.map +1 -1
  38. package/dist/theglobalfuel/pages/emissions/EmissionsPage.js +1 -1
  39. package/dist/theglobalfuel/pages/emissions/EmissionsPage.js.map +1 -1
  40. package/dist/theglobalfuel/pages/inventory/InventoryPage.js +1 -1
  41. package/dist/theglobalfuel/pages/inventory/InventoryPage.js.map +1 -1
  42. package/dist/theglobalfuel/pages/provenance/ProvenancePage.d.ts.map +1 -1
  43. package/dist/theglobalfuel/pages/provenance/ProvenancePage.js +372 -216
  44. package/dist/theglobalfuel/pages/provenance/ProvenancePage.js.map +1 -1
  45. package/dist/theglobalfuel/pages/reports/ReportsPage.d.ts +16 -0
  46. package/dist/theglobalfuel/pages/reports/ReportsPage.d.ts.map +1 -0
  47. package/dist/theglobalfuel/pages/reports/ReportsPage.js +578 -0
  48. package/dist/theglobalfuel/pages/reports/ReportsPage.js.map +1 -0
  49. package/dist/theglobalfuel/pages/shipments/ShipmentsPage.d.ts.map +1 -1
  50. package/dist/theglobalfuel/pages/shipments/ShipmentsPage.js +43 -12
  51. package/dist/theglobalfuel/pages/shipments/ShipmentsPage.js.map +1 -1
  52. package/dist/theglobalfuel/types/index.d.ts +37 -8
  53. package/dist/theglobalfuel/types/index.d.ts.map +1 -1
  54. package/dist/theglobalfuel/utils/csv.d.ts +16 -0
  55. package/dist/theglobalfuel/utils/csv.d.ts.map +1 -0
  56. package/dist/theglobalfuel/utils/csv.js +14 -0
  57. package/dist/theglobalfuel/utils/csv.js.map +1 -0
  58. package/dist/theglobalfuel/utils/index.d.ts +2 -0
  59. package/dist/theglobalfuel/utils/index.d.ts.map +1 -1
  60. package/dist/theglobalfuel/utils/pageContext.d.ts.map +1 -1
  61. package/dist/theglobalfuel/utils/pageContext.js +32 -0
  62. package/dist/theglobalfuel/utils/pageContext.js.map +1 -1
  63. package/dist/theglobalfuel/utils/provenance.d.ts +135 -0
  64. package/dist/theglobalfuel/utils/provenance.d.ts.map +1 -0
  65. package/dist/theglobalfuel/utils/provenance.js +57 -0
  66. package/dist/theglobalfuel/utils/provenance.js.map +1 -0
  67. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ProvenancePage.js","names":[],"sources":["../../../../src/theglobalfuel/pages/provenance/ProvenancePage.tsx"],"sourcesContent":["/**\n * Provenance — chain-of-custody traceability (pit → port → certificate).\n * @module theglobalfuel/pages/provenance\n *\n * The flagship end-to-end traceability view. The user picks a resource asset and\n * we assemble its custody chain entirely from REAL linked records:\n * Asset (registry) → Production → Inventory lot → Shipment (+ document) →\n * Delivered → Chain-of-custody certificate (+ evidence)\n *\n * Sources — all `the*` endpoints, no mock data:\n * - useTheAsset(id) → the asset + nested productionRecords/reserves\n * - useTheInventoryLots() → filtered client-side to lot.assetId === id\n * - useTheEmissionRecords() → attributed emissions for the summary\n * - useTheComplianceCerts(id) → CHAIN_OF_CUSTODY / evidence certs\n * - useTheContracts({commodity}) + useTheContract() → offtake + nested shipments\n *\n * The chain renders as a StepProgress flow + a row of rich node cards (each\n * carrying the real record and a FileLink for its document/evidence), a Timeline\n * of the real dated events, an origin map and a provenance summary. Every stage\n * degrades gracefully when its downstream record does not exist yet (pre-launch).\n */\n\nimport { useMemo, useState, type ReactNode } from 'react';\nimport {\n Link2,\n MapPin,\n Gauge,\n Boxes,\n Ship,\n CheckCircle2,\n ShieldCheck,\n Shield,\n Fuel,\n Factory,\n Route,\n Layers,\n} from 'lucide-react';\nimport {\n GlassCard,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@burdenoff/fe-libs/ui';\nimport {\n PageLayout,\n StatusBadge,\n LoadingView,\n ErrorView,\n EmptyState,\n FileLink,\n WorldMap,\n StepProgress,\n Timeline,\n type TimelineItem,\n type StepProgressStep,\n type PathStepState,\n} from '../../components';\nimport { useTheGlobalFuel } from '../../context';\nimport {\n useTheAssets,\n useTheAsset,\n useTheInventoryLots,\n useTheEmissionRecords,\n useTheComplianceCerts,\n useTheContracts,\n useTheContract,\n useThePageView,\n useTheTranslation,\n} from '../../hooks';\nimport { cn } from '../../utils/cn';\nimport {\n formatDate,\n formatVolume,\n formatEnumLabel,\n formatCoords,\n formatNumber,\n formatTonnesCo2e,\n} from '../../utils';\nimport type { TheProductionRecord, TheInventoryLot, TheShipment } from '../../types';\n\nconst PAGE: { limit: number } = { limit: 200 };\n\n/** Latest-first by an optional date field, falling back to createdAt. */\nfunction byDateDesc<T extends { createdAt: string }>(pick: (row: T) => string | null | undefined) {\n return (a: T, b: T): number => {\n const av = new Date(pick(a) ?? a.createdAt).getTime();\n const bv = new Date(pick(b) ?? b.createdAt).getTime();\n return bv - av;\n };\n}\n\n// ── Chain node card ──────────────────────────────────────────────────────────\n\ninterface ChainNodeVM {\n step: number;\n icon: ReactNode;\n label: string;\n /** Real primary value; shown muted as \"Pending\" when the artifact is absent. */\n primary: ReactNode;\n secondary?: ReactNode;\n badge?: ReactNode;\n fileId?: string | null;\n state: PathStepState;\n present: boolean;\n}\n\nconst NUMBER_STYLE: Record<PathStepState, string> = {\n done: 'bg-status-success-bg-subtle text-status-success-text',\n active: 'bg-[var(--color-accent-soft)] text-accent',\n todo: 'bg-bg-sunken text-text-muted',\n locked: 'bg-bg-sunken text-text-muted',\n};\n\nconst ICON_STYLE: Record<PathStepState, string> = {\n done: 'bg-status-success-bg-subtle text-status-success-text',\n active: 'bg-[var(--color-accent-soft)] text-accent',\n todo: 'bg-bg-sunken text-text-tertiary',\n locked: 'bg-bg-sunken text-text-tertiary',\n};\n\nconst DOT_STYLE: Record<PathStepState, string> = {\n done: 'bg-status-success-text',\n active: 'bg-[var(--color-accent-primary)] motion-safe:animate-vc-glow-pulse',\n todo: 'bg-border-strong',\n locked: 'bg-border-strong',\n};\n\nfunction ChainNodeCard({ node }: { node: ChainNodeVM }) {\n return (\n <GlassCard\n treatment=\"glass\"\n className={cn(\n 'relative flex h-full flex-col gap-3 p-5 transition-shadow',\n node.state === 'done' && 'shadow-[inset_0_2px_0_0_var(--color-status-success-text)]',\n node.state === 'active' && 'shadow-[inset_0_2px_0_0_var(--color-accent-primary)]'\n )}\n >\n <div className=\"flex items-center justify-between\">\n <span\n className={cn(\n 'flex size-7 items-center justify-center rounded-full text-xs font-semibold tabular-nums',\n NUMBER_STYLE[node.state]\n )}\n >\n {node.step}\n </span>\n <span aria-hidden=\"true\" className={cn('size-2 rounded-full', DOT_STYLE[node.state])} />\n </div>\n\n <span\n className={cn(\n 'flex size-11 items-center justify-center rounded-xl [&_svg]:size-6',\n ICON_STYLE[node.state]\n )}\n >\n {node.icon}\n </span>\n\n <div className=\"min-w-0\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-tertiary\">\n {node.label}\n </p>\n <p\n className={cn(\n 'mt-1 truncate text-base font-semibold',\n node.present ? 'text-text-primary' : 'text-text-muted'\n )}\n title={typeof node.primary === 'string' ? node.primary : undefined}\n >\n {node.present ? node.primary : 'Pending'}\n </p>\n {node.present && node.secondary && (\n <p className=\"mt-0.5 line-clamp-2 text-xs text-text-secondary\">{node.secondary}</p>\n )}\n </div>\n\n {(node.badge || (node.present && node.fileId)) && (\n <div className=\"mt-auto flex flex-wrap items-center gap-2 pt-1\">\n {node.badge}\n {node.present && node.fileId && <FileLink fileId={node.fileId} />}\n </div>\n )}\n </GlassCard>\n );\n}\n\n// ── Summary cell ─────────────────────────────────────────────────────────────\n\nfunction SummaryCell({\n icon,\n label,\n value,\n caption,\n}: {\n icon: ReactNode;\n label: string;\n value: ReactNode;\n caption?: ReactNode;\n}) {\n return (\n <div className=\"flex items-start gap-3\">\n <span className=\"mt-0.5 flex size-9 shrink-0 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-accent [&_svg]:size-4\">\n {icon}\n </span>\n <div className=\"min-w-0\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-tertiary\">{label}</p>\n <p className=\"mt-0.5 truncate text-sm font-semibold text-text-primary\">{value}</p>\n {caption && <p className=\"truncate text-xs text-text-tertiary\">{caption}</p>}\n </div>\n </div>\n );\n}\n\n// ── Page ─────────────────────────────────────────────────────────────────────\n\nexport function ProvenancePage() {\n useThePageView('provenance');\n const t = useTheTranslation();\n const { navigateTo } = useTheGlobalFuel();\n\n const assets = useTheAssets({ pagination: PAGE });\n const assetRows = useMemo(() => assets.data?.items ?? [], [assets.data]);\n\n const [selectedAssetId, setSelectedAssetId] = useState<string>('');\n // Auto-focus a *producing* asset first (no effect needed) — those carry the\n // downstream production / shipment / certificate activity, so the chain reads\n // as a real, populated trace on first paint instead of a string of \"Pending\"\n // nodes. Falls back to the first asset. An explicit user selection always wins.\n const defaultAssetId = useMemo(() => {\n const producing = assetRows.find((a) => a.status === 'PRODUCING');\n return producing?.id ?? assetRows[0]?.id ?? '';\n }, [assetRows]);\n const effectiveAssetId = selectedAssetId || defaultAssetId;\n\n const asset = useTheAsset(effectiveAssetId || undefined);\n const inventory = useTheInventoryLots({ pagination: PAGE });\n const emissions = useTheEmissionRecords({\n assetId: effectiveAssetId || undefined,\n pagination: PAGE,\n });\n const compliance = useTheComplianceCerts(\n effectiveAssetId || undefined,\n undefined,\n undefined,\n PAGE\n );\n const contracts = useTheContracts({ commodity: asset.data?.commodity, pagination: PAGE });\n\n // Pick the contract most likely to carry a delivered shipment for this\n // commodity: prefer one that has already delivered volume (SELL first), else\n // the most recent. Its nested shipments give us the movement + delivery nodes.\n const pickedContractId = useMemo(() => {\n const rows = [...(contracts.data?.items ?? [])].sort(byDateDesc((c) => c.createdAt));\n const pick =\n rows.find((c) => c.deliveredVolume > 0 && c.side === 'SELL') ??\n rows.find((c) => c.deliveredVolume > 0) ??\n rows.find((c) => c.side === 'SELL') ??\n rows[0];\n return pick?.id;\n }, [contracts.data]);\n\n const contractDetail = useTheContract(pickedContractId);\n\n // ── Derive the chain from real linked records ──────────────────────────────\n const productionRecords = useMemo(\n () => [...(asset.data?.productionRecords ?? [])].sort(byDateDesc((r) => r.periodEnd)),\n [asset.data]\n );\n const latestProduction: TheProductionRecord | undefined = productionRecords[0];\n\n const assetLots = useMemo<TheInventoryLot[]>(\n () =>\n (inventory.data?.items ?? [])\n .filter((l) => l.assetId === effectiveAssetId)\n .sort(byDateDesc((l) => l.producedAt)),\n [inventory.data, effectiveAssetId]\n );\n const latestLot: TheInventoryLot | undefined = assetLots[0];\n\n const shipments = useMemo<TheShipment[]>(\n () => contractDetail.data?.shipments ?? [],\n [contractDetail.data]\n );\n const deliveredShipment = useMemo<TheShipment | undefined>(\n () =>\n [...shipments]\n .filter((s) => s.status === 'DELIVERED')\n .sort(byDateDesc((s) => s.deliveredAt))[0],\n [shipments]\n );\n const primaryShipment = useMemo<TheShipment | undefined>(\n () =>\n deliveredShipment ?? [...shipments].sort(byDateDesc((s) => s.departedAt ?? s.scheduledAt))[0],\n [deliveredShipment, shipments]\n );\n const pickedContract = useMemo(\n () => contracts.data?.items.find((c) => c.id === pickedContractId),\n [contracts.data, pickedContractId]\n );\n\n const certRows = useMemo(() => compliance.data?.items ?? [], [compliance.data]);\n const custodyCert = useMemo(\n () =>\n certRows.find((c) => c.category === 'CHAIN_OF_CUSTODY') ??\n certRows.find((c) => c.status === 'APPROVED') ??\n certRows[0],\n [certRows]\n );\n const certApproved = custodyCert?.status === 'APPROVED';\n\n const emissionRows = useMemo(() => emissions.data?.items ?? [], [emissions.data]);\n const totalTonnes = emissionRows.reduce((sum, e) => sum + (e.co2eTonnes ?? 0), 0);\n const verifiedEmissions = emissionRows.filter((e) => e.verified).length;\n\n const a = asset.data;\n\n // Stage completeness, in chain order.\n const completeFlags = [\n Boolean(a),\n productionRecords.length > 0,\n assetLots.length > 0,\n Boolean(primaryShipment),\n Boolean(deliveredShipment),\n certApproved,\n ];\n const completeCount = completeFlags.filter(Boolean).length;\n const firstIncomplete = completeFlags.findIndex((f) => !f);\n const current = firstIncomplete === -1 ? completeFlags.length : firstIncomplete;\n const verified = certApproved && Boolean(deliveredShipment);\n\n const stateFor = (i: number): PathStepState =>\n completeFlags[i] ? 'done' : i === current ? 'active' : 'todo';\n\n const progressSteps: StepProgressStep[] = [\n { label: 'Asset', description: 'Origin' },\n { label: 'Production', description: 'Extracted' },\n { label: 'Inventory', description: 'Lotted' },\n { label: 'Shipment', description: 'In transit' },\n { label: 'Delivered', description: 'Received' },\n { label: 'Certificate', description: 'Verified' },\n ];\n\n const shipmentRoute =\n primaryShipment && (primaryShipment.origin || primaryShipment.destination)\n ? [primaryShipment.origin, primaryShipment.destination].filter(Boolean).join(' → ')\n : undefined;\n\n const nodes: ChainNodeVM[] = a\n ? [\n {\n step: 1,\n icon: <MapPin />,\n label: 'Asset',\n primary: a.name,\n secondary: a.location ?? formatCoords(a.latitude, a.longitude),\n badge: <StatusBadge status={a.status} />,\n state: stateFor(0),\n present: true,\n },\n {\n step: 2,\n icon: <Gauge />,\n label: 'Production',\n primary: latestProduction\n ? formatVolume(latestProduction.volume, latestProduction.unit)\n : 'Not yet recorded',\n secondary: latestProduction\n ? `${formatDate(latestProduction.periodStart)} – ${formatDate(latestProduction.periodEnd)}`\n : undefined,\n state: stateFor(1),\n present: Boolean(latestProduction),\n },\n {\n step: 3,\n icon: <Boxes />,\n label: 'Inventory lot',\n primary: latestLot ? latestLot.lotCode : 'No lot yet',\n secondary: latestLot ? formatVolume(latestLot.quantity, latestLot.unit) : undefined,\n badge: latestLot ? <StatusBadge status={latestLot.status} /> : undefined,\n state: stateFor(2),\n present: Boolean(latestLot),\n },\n {\n step: 4,\n icon: <Ship />,\n label: 'Shipment',\n primary: primaryShipment ? primaryShipment.reference : 'Not shipped',\n secondary: primaryShipment\n ? [formatEnumLabel(primaryShipment.mode), shipmentRoute].filter(Boolean).join(' · ')\n : undefined,\n badge: primaryShipment ? <StatusBadge status={primaryShipment.status} /> : undefined,\n fileId: primaryShipment?.document?.id,\n state: stateFor(3),\n present: Boolean(primaryShipment),\n },\n {\n step: 5,\n icon: <CheckCircle2 />,\n label: 'Delivered',\n primary: deliveredShipment\n ? formatVolume(deliveredShipment.volume, deliveredShipment.unit)\n : 'Awaiting delivery',\n secondary: deliveredShipment\n ? [\n deliveredShipment.deliveredAt ? formatDate(deliveredShipment.deliveredAt) : null,\n pickedContract ? `Contract ${pickedContract.reference}` : null,\n ]\n .filter(Boolean)\n .join(' · ') || undefined\n : undefined,\n state: stateFor(4),\n present: Boolean(deliveredShipment),\n },\n {\n step: 6,\n icon: <ShieldCheck />,\n label: 'Certificate',\n primary: custodyCert ? (custodyCert.certNumber ?? custodyCert.title) : 'No certificate',\n secondary: custodyCert ? formatEnumLabel(custodyCert.category) : undefined,\n badge: custodyCert ? <StatusBadge status={custodyCert.status} /> : undefined,\n fileId: custodyCert?.evidence?.id,\n state: stateFor(5),\n present: Boolean(custodyCert),\n },\n ]\n : [];\n\n // ── Timeline (real dated events, ascending) ────────────────────────────────\n const timelineItems = useMemo<TimelineItem[]>(() => {\n if (!a) return [];\n const raw: { date: string; item: Omit<TimelineItem, 'time'> }[] = [];\n const push = (date: string | null | undefined, item: Omit<TimelineItem, 'time'>) => {\n if (!date) return;\n const t = new Date(date).getTime();\n if (Number.isNaN(t)) return;\n raw.push({ date, item });\n };\n\n push(a.commissionedAt ?? a.createdAt, {\n title: 'Asset registered',\n meta: a.name,\n tone: 'accent',\n icon: <MapPin className=\"h-3 w-3\" />,\n });\n if (latestProduction) {\n push(latestProduction.periodEnd ?? latestProduction.createdAt, {\n title: 'Production recorded',\n meta: formatVolume(latestProduction.volume, latestProduction.unit),\n tone: 'info',\n icon: <Gauge className=\"h-3 w-3\" />,\n });\n }\n if (latestLot) {\n push(latestLot.producedAt ?? latestLot.createdAt, {\n title: 'Inventory lot created',\n meta: `${latestLot.lotCode} · ${formatVolume(latestLot.quantity, latestLot.unit)}`,\n tone: 'info',\n icon: <Boxes className=\"h-3 w-3\" />,\n });\n }\n if (primaryShipment) {\n push(primaryShipment.departedAt ?? primaryShipment.scheduledAt ?? primaryShipment.createdAt, {\n title: primaryShipment.departedAt ? 'Shipment departed' : 'Shipment scheduled',\n meta: [primaryShipment.reference, shipmentRoute].filter(Boolean).join(' · '),\n tone: 'accent',\n icon: <Ship className=\"h-3 w-3\" />,\n });\n }\n if (deliveredShipment?.deliveredAt) {\n push(deliveredShipment.deliveredAt, {\n title: 'Delivered',\n meta: formatVolume(deliveredShipment.volume, deliveredShipment.unit),\n tone: 'success',\n icon: <CheckCircle2 className=\"h-3 w-3\" />,\n });\n }\n if (custodyCert) {\n push(custodyCert.issuedAt ?? custodyCert.createdAt, {\n title: certApproved ? 'Certificate approved' : 'Certificate registered',\n meta: custodyCert.certNumber ?? custodyCert.title,\n tone: certApproved ? 'success' : 'warning',\n icon: <ShieldCheck className=\"h-3 w-3\" />,\n });\n }\n\n return raw\n .sort((x, y) => new Date(x.date).getTime() - new Date(y.date).getTime())\n .map(({ date, item }) => ({ ...item, time: formatDate(date) }));\n }, [\n a,\n latestProduction,\n latestLot,\n primaryShipment,\n deliveredShipment,\n custodyCert,\n certApproved,\n shipmentRoute,\n ]);\n\n const originPoint =\n a && typeof a.latitude === 'number' && typeof a.longitude === 'number'\n ? { lat: a.latitude, lng: a.longitude, label: a.name, primary: true }\n : null;\n\n const description = t(\n 'theglobalfuel.pages.provenance.description',\n 'Pit to port to certificate — end-to-end traceability from origin to verified certificate.'\n );\n\n // ── Render ─────────────────────────────────────────────────────────────────\n const pageTitle = t('theglobalfuel.pages.provenance.title', 'Provenance');\n\n if (assets.isLoading && assetRows.length === 0) {\n return (\n <PageLayout\n title={pageTitle}\n description={description}\n dataTour=\"theglobalfuel-provenance-page\"\n >\n <LoadingView label=\"Loading assets…\" />\n </PageLayout>\n );\n }\n if (assets.isError) {\n return (\n <PageLayout\n title={pageTitle}\n description={description}\n dataTour=\"theglobalfuel-provenance-page\"\n >\n <ErrorView message=\"Couldn't load assets to trace.\" onRetry={() => assets.refetch()} />\n </PageLayout>\n );\n }\n if (assetRows.length === 0) {\n return (\n <PageLayout\n title={pageTitle}\n description={description}\n dataTour=\"theglobalfuel-provenance-page\"\n >\n <EmptyState\n illustration=\"empty-data\"\n icon={<Link2 className=\"h-10 w-10\" />}\n title=\"No assets to trace\"\n description=\"Register a resource asset to build its end-to-end chain of custody.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('assets')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n Go to assets\n </button>\n }\n />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title={pageTitle}\n description={description}\n dataTour=\"theglobalfuel-provenance-page\"\n >\n {/* Control bar: asset picker + trust state */}\n <GlassCard\n treatment=\"glass\"\n className=\"flex flex-col gap-4 p-5 sm:flex-row sm:items-center sm:justify-between\"\n >\n <div className=\"flex min-w-0 flex-1 flex-col gap-1.5\">\n <label\n htmlFor=\"provenance-asset\"\n className=\"text-xs font-medium uppercase tracking-wide text-text-tertiary\"\n >\n Trace asset\n </label>\n <Select value={effectiveAssetId} onValueChange={setSelectedAssetId}>\n <SelectTrigger\n id=\"provenance-asset\"\n className=\"h-10 w-full sm:w-96\"\n aria-label=\"Select an asset to trace\"\n >\n <SelectValue placeholder=\"Select an asset to trace\" />\n </SelectTrigger>\n <SelectContent>\n {assetRows.map((row) => (\n <SelectItem key={row.id} value={row.id}>\n {row.name} · {formatEnumLabel(row.commodity)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div\n className={cn(\n 'flex items-center gap-2 self-start rounded-full px-3.5 py-1.5 text-sm font-medium',\n verified\n ? 'bg-status-success-bg-subtle text-status-success-text'\n : 'bg-bg-sunken text-text-secondary'\n )}\n >\n {verified ? <ShieldCheck className=\"h-4 w-4\" /> : <Shield className=\"h-4 w-4\" />}\n {verified ? 'Chain of custody verified' : `Traceability in progress · ${completeCount}/6`}\n </div>\n </GlassCard>\n\n {asset.isLoading ? (\n <div className=\"mt-6\">\n <LoadingView label=\"Assembling chain of custody…\" />\n </div>\n ) : asset.isError || !a ? (\n <div className=\"mt-6\">\n <ErrorView\n message=\"Couldn't load this asset's provenance.\"\n onRetry={() => asset.refetch()}\n />\n </div>\n ) : (\n <>\n {/* Flow ribbon */}\n <GlassCard treatment=\"glass\" className=\"mt-6 p-5\">\n <StepProgress steps={progressSteps} current={current} />\n </GlassCard>\n\n {/* Chain nodes */}\n <div className=\"mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-6\">\n {nodes.map((node) => (\n <ChainNodeCard key={node.step} node={node} />\n ))}\n </div>\n\n {/* Timeline + origin */}\n <div className=\"mt-6 grid grid-cols-1 gap-6 lg:grid-cols-3\">\n <GlassCard treatment=\"glass\" className=\"p-5 lg:col-span-2\">\n <div className=\"mb-4 flex items-center gap-2.5\">\n <span className=\"flex size-8 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-accent\">\n <Route className=\"h-4 w-4\" />\n </span>\n <div>\n <h2 className=\"text-base font-semibold text-text-primary\">\n Traceability timeline\n </h2>\n <p className=\"text-xs text-text-tertiary\">\n Recorded custody events, oldest to newest.\n </p>\n </div>\n </div>\n {timelineItems.length > 0 ? (\n <Timeline items={timelineItems} />\n ) : (\n <div className=\"rounded-xl border border-dashed border-border-seam py-8 text-center text-sm text-text-secondary\">\n No dated custody events yet.\n </div>\n )}\n </GlassCard>\n\n <GlassCard treatment=\"glass\" className=\"flex flex-col gap-4 p-5\">\n <div className=\"flex items-center gap-2.5\">\n <span className=\"flex size-8 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-accent\">\n <MapPin className=\"h-4 w-4\" />\n </span>\n <div className=\"min-w-0\">\n <h2 className=\"text-base font-semibold text-text-primary\">Origin</h2>\n <p className=\"truncate text-xs text-text-tertiary\">\n {a.location ?? formatEnumLabel(a.kind)}\n </p>\n </div>\n </div>\n {originPoint ? (\n <WorldMap points={[originPoint]} />\n ) : (\n <div className=\"rounded-xl border border-dashed border-border-seam py-8 text-center text-sm text-text-secondary\">\n No coordinates recorded for this asset.\n </div>\n )}\n </GlassCard>\n </div>\n\n {/* Provenance summary */}\n <GlassCard treatment=\"glass\" className=\"mt-6 p-5\">\n <h2 className=\"mb-4 text-base font-semibold text-text-primary\">Provenance summary</h2>\n <div className=\"grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-6\">\n <SummaryCell\n icon={<Fuel />}\n label=\"Commodity\"\n value={formatEnumLabel(a.commodity)}\n caption={formatEnumLabel(a.kind)}\n />\n <SummaryCell\n icon={<MapPin />}\n label=\"Origin\"\n value={a.location ?? a.name}\n caption={formatCoords(a.latitude, a.longitude)}\n />\n <SummaryCell\n icon={<Gauge />}\n label=\"Production\"\n value={`${formatNumber(productionRecords.length)} records`}\n caption={\n latestProduction\n ? `Latest ${formatVolume(latestProduction.volume, latestProduction.unit)}`\n : 'None yet'\n }\n />\n <SummaryCell\n icon={<Boxes />}\n label=\"Inventory\"\n value={`${formatNumber(assetLots.length)} lots`}\n caption={latestLot ? latestLot.lotCode : 'None yet'}\n />\n <SummaryCell\n icon={<Factory />}\n label=\"Emissions\"\n value={emissions.isError ? '—' : formatTonnesCo2e(totalTonnes)}\n caption={`${verifiedEmissions} verified`}\n />\n <SummaryCell\n icon={<ShieldCheck />}\n label=\"Certificates\"\n value={`${formatNumber(certRows.length)} tracked`}\n caption={\n certApproved ? 'Custody approved' : custodyCert ? 'Under review' : 'None yet'\n }\n />\n </div>\n </GlassCard>\n\n {/* Reserves footnote — surface proved reserves when present */}\n {(a.reserveEstimates?.length ?? 0) > 0 && (\n <p className=\"mt-4 flex items-center gap-1.5 text-xs text-text-tertiary\">\n <Layers className=\"h-3.5 w-3.5\" />\n {formatNumber(a.reserveEstimates?.length ?? 0)} reserve estimate\n {(a.reserveEstimates?.length ?? 0) === 1 ? '' : 's'} on record for this asset.\n </p>\n )}\n </>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ProvenancePage.js","names":[],"sources":["../../../../src/theglobalfuel/pages/provenance/ProvenancePage.tsx"],"sourcesContent":["/**\n * Provenance — chain-of-custody traceability (pit → port → certificate).\n * @module theglobalfuel/pages/provenance\n *\n * The flagship end-to-end traceability view. The user picks a resource asset and\n * we assemble its custody chain entirely from REAL linked records:\n * Asset (registry) → Production → Inventory lot → Shipment (+ document) →\n * Delivered → Chain-of-custody certificate (+ evidence)\n *\n * Sources — all `the*` endpoints, no mock data:\n * - useTheAsset(id) → the asset + nested productionRecords/reserves\n * - useTheInventoryLots() → filtered client-side to lot.assetId === id\n * - useTheEmissionRecords() → attributed emissions for the summary\n * - useTheComplianceCerts(id) → CHAIN_OF_CUSTODY / evidence certs\n * - useTheContracts({commodity}) + useTheContract() → offtake + nested shipments\n *\n * The chain renders as a StepProgress flow + a row of rich node cards (each\n * carrying the real record and a FileLink for its document/evidence), a Timeline\n * of the real dated events, an origin map and a provenance summary. Every stage\n * degrades gracefully when its downstream record does not exist yet (pre-launch).\n */\n\nimport { useMemo, useState, type ReactNode } from 'react';\nimport {\n Link2,\n MapPin,\n Gauge,\n Boxes,\n Ship,\n CheckCircle2,\n ShieldCheck,\n Shield,\n Fuel,\n Factory,\n Route,\n Layers,\n Download,\n Share2,\n Fingerprint,\n Network,\n} from 'lucide-react';\nimport {\n Button,\n GlassCard,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@burdenoff/fe-libs/ui';\nimport {\n PageLayout,\n StatusBadge,\n LoadingView,\n ErrorView,\n EmptyState,\n FileLink,\n WorldMap,\n StepProgress,\n Timeline,\n type TimelineItem,\n type StepProgressStep,\n type PathStepState,\n} from '../../components';\nimport { useTheGlobalFuel } from '../../context';\nimport {\n useTheAssets,\n useTheAsset,\n useTheInventoryLots,\n useTheEmissionRecords,\n useTheComplianceCerts,\n useTheContracts,\n useTheContract,\n useThePageView,\n useTheTranslation,\n useNotify,\n} from '../../hooks';\nimport { cn } from '../../utils/cn';\nimport {\n formatDate,\n formatVolume,\n formatEnumLabel,\n formatCoords,\n formatNumber,\n formatTonnesCo2e,\n buildProvenanceDocument,\n shortDigest,\n downloadTextFile,\n slugify,\n type ProvenanceChainInput,\n} from '../../utils';\nimport type { TheProductionRecord, TheInventoryLot, TheShipment } from '../../types';\n\nconst PAGE: { limit: number } = { limit: 200 };\n\n/** Total stages in the chain of custody (asset → … → certificate). */\nconst CHAIN_STAGES = 6;\n\n/**\n * Read the shared-link asset selection (`?assetId=…`) once, at mount. Returns\n * '' outside a DOM environment so the page falls back to its own default pick.\n */\nfunction readSharedAssetId(): string {\n if (typeof window === 'undefined') return '';\n return new URLSearchParams(window.location.search).get('assetId') ?? '';\n}\n\n/** Absolute, shareable deep link to one asset's chain of custody. */\nfunction buildShareUrl(assetId: string): string {\n if (typeof window === 'undefined') return '';\n const url = new URL(window.location.href);\n url.searchParams.set('assetId', assetId);\n url.hash = '';\n return url.toString();\n}\n\n/** Latest-first by an optional date field, falling back to createdAt. */\nfunction byDateDesc<T extends { createdAt: string }>(pick: (row: T) => string | null | undefined) {\n return (a: T, b: T): number => {\n const av = new Date(pick(a) ?? a.createdAt).getTime();\n const bv = new Date(pick(b) ?? b.createdAt).getTime();\n return bv - av;\n };\n}\n\n// ── Chain node card ──────────────────────────────────────────────────────────\n\ninterface ChainNodeVM {\n step: number;\n icon: ReactNode;\n label: string;\n /** Real primary value; shown muted as \"Pending\" when the artifact is absent. */\n primary: ReactNode;\n secondary?: ReactNode;\n badge?: ReactNode;\n fileId?: string | null;\n state: PathStepState;\n present: boolean;\n}\n\nconst NUMBER_STYLE: Record<PathStepState, string> = {\n done: 'bg-status-success-bg-subtle text-status-success-text',\n active: 'bg-[var(--color-accent-soft)] text-action-primary-bg',\n todo: 'bg-bg-sunken text-text-muted',\n locked: 'bg-bg-sunken text-text-muted',\n};\n\nconst ICON_STYLE: Record<PathStepState, string> = {\n done: 'bg-status-success-bg-subtle text-status-success-text',\n active: 'bg-[var(--color-accent-soft)] text-action-primary-bg',\n todo: 'bg-bg-sunken text-text-tertiary',\n locked: 'bg-bg-sunken text-text-tertiary',\n};\n\nconst DOT_STYLE: Record<PathStepState, string> = {\n done: 'bg-status-success-text',\n active: 'bg-[var(--color-accent-primary)] motion-safe:animate-vc-glow-pulse',\n todo: 'bg-border-strong',\n locked: 'bg-border-strong',\n};\n\nfunction ChainNodeCard({ node }: { node: ChainNodeVM }) {\n return (\n <GlassCard\n treatment=\"glass\"\n className={cn(\n 'relative flex h-full flex-col gap-3 p-5 transition-shadow',\n node.state === 'done' && 'shadow-[inset_0_2px_0_0_var(--color-status-success-text)]',\n node.state === 'active' && 'shadow-[inset_0_2px_0_0_var(--color-accent-primary)]'\n )}\n >\n <div className=\"flex items-center justify-between\">\n <span\n className={cn(\n 'flex size-7 items-center justify-center rounded-full text-xs font-semibold tabular-nums',\n NUMBER_STYLE[node.state]\n )}\n >\n {node.step}\n </span>\n <span aria-hidden=\"true\" className={cn('size-2 rounded-full', DOT_STYLE[node.state])} />\n </div>\n\n <span\n className={cn(\n 'flex size-11 items-center justify-center rounded-xl [&_svg]:size-6',\n ICON_STYLE[node.state]\n )}\n >\n {node.icon}\n </span>\n\n <div className=\"min-w-0\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-tertiary\">\n {node.label}\n </p>\n <p\n className={cn(\n 'mt-1 truncate text-base font-semibold',\n node.present ? 'text-text-primary' : 'text-text-muted'\n )}\n title={typeof node.primary === 'string' ? node.primary : undefined}\n >\n {node.present ? node.primary : 'Pending'}\n </p>\n {node.present && node.secondary && (\n <p className=\"mt-0.5 line-clamp-2 text-xs text-text-secondary\">{node.secondary}</p>\n )}\n </div>\n\n {(node.badge || (node.present && node.fileId)) && (\n <div className=\"mt-auto flex flex-wrap items-center gap-2 pt-1\">\n {node.badge}\n {node.present && node.fileId && <FileLink fileId={node.fileId} />}\n </div>\n )}\n </GlassCard>\n );\n}\n\n// ── Summary cell ─────────────────────────────────────────────────────────────\n\nfunction SummaryCell({\n icon,\n label,\n value,\n caption,\n}: {\n icon: ReactNode;\n label: string;\n value: ReactNode;\n caption?: ReactNode;\n}) {\n return (\n <div className=\"flex items-start gap-3\">\n <span className=\"mt-0.5 flex size-9 shrink-0 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-action-primary-bg [&_svg]:size-4\">\n {icon}\n </span>\n <div className=\"min-w-0\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-tertiary\">{label}</p>\n <p className=\"mt-0.5 truncate text-sm font-semibold text-text-primary\">{value}</p>\n {caption && <p className=\"truncate text-xs text-text-tertiary\">{caption}</p>}\n </div>\n </div>\n );\n}\n\n// ── Page ─────────────────────────────────────────────────────────────────────\n\nexport function ProvenancePage() {\n useThePageView('provenance');\n const t = useTheTranslation();\n const { navigateTo } = useTheGlobalFuel();\n\n const assets = useTheAssets({ pagination: PAGE });\n const assetRows = useMemo(() => assets.data?.items ?? [], [assets.data]);\n\n const notify = useNotify();\n // A shared `?assetId=` link wins over the page's own default pick; an explicit\n // in-page selection then wins over both.\n const [selectedAssetId, setSelectedAssetId] = useState<string>(readSharedAssetId);\n // Auto-focus a *producing* asset first (no effect needed) — those carry the\n // downstream production / shipment / certificate activity, so the chain reads\n // as a real, populated trace on first paint instead of a string of \"Pending\"\n // nodes. Falls back to the first asset. An explicit user selection always wins.\n const defaultAssetId = useMemo(() => {\n const producing = assetRows.find((a) => a.status === 'PRODUCING');\n return producing?.id ?? assetRows[0]?.id ?? '';\n }, [assetRows]);\n const effectiveAssetId = selectedAssetId || defaultAssetId;\n\n const asset = useTheAsset(effectiveAssetId || undefined);\n const inventory = useTheInventoryLots({ pagination: PAGE });\n const emissions = useTheEmissionRecords({\n assetId: effectiveAssetId || undefined,\n pagination: PAGE,\n });\n const compliance = useTheComplianceCerts(\n effectiveAssetId || undefined,\n undefined,\n undefined,\n PAGE\n );\n const contracts = useTheContracts({ commodity: asset.data?.commodity, pagination: PAGE });\n\n // Pick the contract most likely to carry a delivered shipment for this\n // commodity: prefer one that has already delivered volume (SELL first), else\n // the most recent. Its nested shipments give us the movement + delivery nodes.\n const pickedContractId = useMemo(() => {\n const rows = [...(contracts.data?.items ?? [])].sort(byDateDesc((c) => c.createdAt));\n const pick =\n rows.find((c) => c.deliveredVolume > 0 && c.side === 'SELL') ??\n rows.find((c) => c.deliveredVolume > 0) ??\n rows.find((c) => c.side === 'SELL') ??\n rows[0];\n return pick?.id;\n }, [contracts.data]);\n\n const contractDetail = useTheContract(pickedContractId);\n\n // ── Derive the chain from real linked records ──────────────────────────────\n const productionRecords = useMemo(\n () => [...(asset.data?.productionRecords ?? [])].sort(byDateDesc((r) => r.periodEnd)),\n [asset.data]\n );\n const latestProduction: TheProductionRecord | undefined = productionRecords[0];\n\n const assetLots = useMemo<TheInventoryLot[]>(\n () =>\n (inventory.data?.items ?? [])\n .filter((l) => l.assetId === effectiveAssetId)\n .sort(byDateDesc((l) => l.producedAt)),\n [inventory.data, effectiveAssetId]\n );\n const latestLot: TheInventoryLot | undefined = assetLots[0];\n\n const shipments = useMemo<TheShipment[]>(\n () => contractDetail.data?.shipments ?? [],\n [contractDetail.data]\n );\n const deliveredShipment = useMemo<TheShipment | undefined>(\n () =>\n [...shipments]\n .filter((s) => s.status === 'DELIVERED')\n .sort(byDateDesc((s) => s.deliveredAt))[0],\n [shipments]\n );\n const primaryShipment = useMemo<TheShipment | undefined>(\n () =>\n deliveredShipment ?? [...shipments].sort(byDateDesc((s) => s.departedAt ?? s.scheduledAt))[0],\n [deliveredShipment, shipments]\n );\n const pickedContract = useMemo(\n () => contracts.data?.items.find((c) => c.id === pickedContractId),\n [contracts.data, pickedContractId]\n );\n\n const certRows = useMemo(() => compliance.data?.items ?? [], [compliance.data]);\n const custodyCert = useMemo(\n () =>\n certRows.find((c) => c.category === 'CHAIN_OF_CUSTODY') ??\n certRows.find((c) => c.status === 'APPROVED') ??\n certRows[0],\n [certRows]\n );\n const certApproved = custodyCert?.status === 'APPROVED';\n\n const emissionRows = useMemo(() => emissions.data?.items ?? [], [emissions.data]);\n const totalTonnes = emissionRows.reduce((sum, e) => sum + (e.co2eTonnes ?? 0), 0);\n const verifiedEmissions = emissionRows.filter((e) => e.verified).length;\n\n const a = asset.data;\n\n // Stage completeness, in chain order.\n const completeFlags = [\n Boolean(a),\n productionRecords.length > 0,\n assetLots.length > 0,\n Boolean(primaryShipment),\n Boolean(deliveredShipment),\n certApproved,\n ];\n const completeCount = completeFlags.filter(Boolean).length;\n const firstIncomplete = completeFlags.findIndex((f) => !f);\n const current = firstIncomplete === -1 ? completeFlags.length : firstIncomplete;\n const verified = certApproved && Boolean(deliveredShipment);\n\n const stateFor = (i: number): PathStepState =>\n completeFlags[i] ? 'done' : i === current ? 'active' : 'todo';\n\n const progressSteps: StepProgressStep[] = [\n { label: 'Asset', description: 'Origin' },\n { label: 'Production', description: 'Extracted' },\n { label: 'Inventory', description: 'Lotted' },\n { label: 'Shipment', description: 'In transit' },\n { label: 'Delivered', description: 'Received' },\n { label: 'Certificate', description: 'Verified' },\n ];\n\n const shipmentRoute =\n primaryShipment && (primaryShipment.origin || primaryShipment.destination)\n ? [primaryShipment.origin, primaryShipment.destination].filter(Boolean).join(' → ')\n : undefined;\n\n const nodes: ChainNodeVM[] = a\n ? [\n {\n step: 1,\n icon: <MapPin />,\n label: 'Asset',\n primary: a.name,\n secondary: a.location ?? formatCoords(a.latitude, a.longitude),\n badge: <StatusBadge status={a.status} />,\n state: stateFor(0),\n present: true,\n },\n {\n step: 2,\n icon: <Gauge />,\n label: 'Production',\n primary: latestProduction\n ? formatVolume(latestProduction.volume, latestProduction.unit)\n : 'Not yet recorded',\n secondary: latestProduction\n ? `${formatDate(latestProduction.periodStart)} – ${formatDate(latestProduction.periodEnd)}`\n : undefined,\n state: stateFor(1),\n present: Boolean(latestProduction),\n },\n {\n step: 3,\n icon: <Boxes />,\n label: 'Inventory lot',\n primary: latestLot ? latestLot.lotCode : 'No lot yet',\n secondary: latestLot ? formatVolume(latestLot.quantity, latestLot.unit) : undefined,\n badge: latestLot ? <StatusBadge status={latestLot.status} /> : undefined,\n state: stateFor(2),\n present: Boolean(latestLot),\n },\n {\n step: 4,\n icon: <Ship />,\n label: 'Shipment',\n primary: primaryShipment ? primaryShipment.reference : 'Not shipped',\n secondary: primaryShipment\n ? [formatEnumLabel(primaryShipment.mode), shipmentRoute].filter(Boolean).join(' · ')\n : undefined,\n badge: primaryShipment ? <StatusBadge status={primaryShipment.status} /> : undefined,\n fileId: primaryShipment?.document?.id,\n state: stateFor(3),\n present: Boolean(primaryShipment),\n },\n {\n step: 5,\n icon: <CheckCircle2 />,\n label: 'Delivered',\n primary: deliveredShipment\n ? formatVolume(deliveredShipment.volume, deliveredShipment.unit)\n : 'Awaiting delivery',\n secondary: deliveredShipment\n ? [\n deliveredShipment.deliveredAt ? formatDate(deliveredShipment.deliveredAt) : null,\n pickedContract ? `Contract ${pickedContract.reference}` : null,\n ]\n .filter(Boolean)\n .join(' · ') || undefined\n : undefined,\n state: stateFor(4),\n present: Boolean(deliveredShipment),\n },\n {\n step: 6,\n icon: <ShieldCheck />,\n label: 'Certificate',\n primary: custodyCert ? (custodyCert.certNumber ?? custodyCert.title) : 'No certificate',\n secondary: custodyCert ? formatEnumLabel(custodyCert.category) : undefined,\n badge: custodyCert ? <StatusBadge status={custodyCert.status} /> : undefined,\n fileId: custodyCert?.evidence?.id,\n state: stateFor(5),\n present: Boolean(custodyCert),\n },\n ]\n : [];\n\n // ── Timeline (real dated events, ascending) ────────────────────────────────\n const timelineItems = useMemo<TimelineItem[]>(() => {\n if (!a) return [];\n const raw: { date: string; item: Omit<TimelineItem, 'time'> }[] = [];\n const push = (date: string | null | undefined, item: Omit<TimelineItem, 'time'>) => {\n if (!date) return;\n const t = new Date(date).getTime();\n if (Number.isNaN(t)) return;\n raw.push({ date, item });\n };\n\n push(a.commissionedAt ?? a.createdAt, {\n title: 'Asset registered',\n meta: a.name,\n tone: 'accent',\n icon: <MapPin className=\"h-3 w-3\" />,\n });\n if (latestProduction) {\n push(latestProduction.periodEnd ?? latestProduction.createdAt, {\n title: 'Production recorded',\n meta: formatVolume(latestProduction.volume, latestProduction.unit),\n tone: 'info',\n icon: <Gauge className=\"h-3 w-3\" />,\n });\n }\n if (latestLot) {\n push(latestLot.producedAt ?? latestLot.createdAt, {\n title: 'Inventory lot created',\n meta: `${latestLot.lotCode} · ${formatVolume(latestLot.quantity, latestLot.unit)}`,\n tone: 'info',\n icon: <Boxes className=\"h-3 w-3\" />,\n });\n }\n if (primaryShipment) {\n push(primaryShipment.departedAt ?? primaryShipment.scheduledAt ?? primaryShipment.createdAt, {\n title: primaryShipment.departedAt ? 'Shipment departed' : 'Shipment scheduled',\n meta: [primaryShipment.reference, shipmentRoute].filter(Boolean).join(' · '),\n tone: 'accent',\n icon: <Ship className=\"h-3 w-3\" />,\n });\n }\n if (deliveredShipment?.deliveredAt) {\n push(deliveredShipment.deliveredAt, {\n title: 'Delivered',\n meta: formatVolume(deliveredShipment.volume, deliveredShipment.unit),\n tone: 'success',\n icon: <CheckCircle2 className=\"h-3 w-3\" />,\n });\n }\n if (custodyCert) {\n push(custodyCert.issuedAt ?? custodyCert.createdAt, {\n title: certApproved ? 'Certificate approved' : 'Certificate registered',\n meta: custodyCert.certNumber ?? custodyCert.title,\n tone: certApproved ? 'success' : 'warning',\n icon: <ShieldCheck className=\"h-3 w-3\" />,\n });\n }\n\n return raw\n .sort((x, y) => new Date(x.date).getTime() - new Date(y.date).getTime())\n .map(({ date, item }) => ({ ...item, time: formatDate(date) }));\n }, [\n a,\n latestProduction,\n latestLot,\n primaryShipment,\n deliveredShipment,\n custodyCert,\n certApproved,\n shipmentRoute,\n ]);\n\n // ── Canonical export document + integrity digest ───────────────────────────\n // Assembled from exactly the records rendered above, so what a user exports\n // is byte-for-byte the chain they are looking at.\n const chainInput = useMemo<ProvenanceChainInput | null>(() => {\n if (!a) return null;\n return {\n asset: {\n id: a.id,\n name: a.name,\n code: a.code ?? null,\n commodity: a.commodity,\n kind: a.kind,\n status: a.status,\n location: a.location ?? null,\n latitude: a.latitude ?? null,\n longitude: a.longitude ?? null,\n commissionedAt: a.commissionedAt ?? null,\n createdAt: a.createdAt,\n },\n production: latestProduction\n ? {\n id: latestProduction.id,\n periodStart: latestProduction.periodStart,\n periodEnd: latestProduction.periodEnd,\n volume: latestProduction.volume,\n unit: latestProduction.unit,\n source: latestProduction.source ?? null,\n createdAt: latestProduction.createdAt,\n }\n : null,\n lot: latestLot\n ? {\n id: latestLot.id,\n lotCode: latestLot.lotCode,\n quantity: latestLot.quantity,\n unit: latestLot.unit,\n status: latestLot.status,\n location: latestLot.location ?? null,\n producedAt: latestLot.producedAt ?? null,\n createdAt: latestLot.createdAt,\n }\n : null,\n shipment: primaryShipment\n ? {\n id: primaryShipment.id,\n reference: primaryShipment.reference,\n status: primaryShipment.status,\n mode: primaryShipment.mode,\n volume: primaryShipment.volume,\n unit: primaryShipment.unit,\n carrier: primaryShipment.carrier ?? null,\n trackingId: primaryShipment.trackingId ?? null,\n origin: primaryShipment.origin ?? null,\n destination: primaryShipment.destination ?? null,\n scheduledAt: primaryShipment.scheduledAt ?? null,\n departedAt: primaryShipment.departedAt ?? null,\n deliveredAt: primaryShipment.deliveredAt ?? null,\n createdAt: primaryShipment.createdAt,\n }\n : null,\n contract: pickedContract\n ? {\n id: pickedContract.id,\n reference: pickedContract.reference,\n counterparty: pickedContract.counterparty,\n side: pickedContract.side,\n status: pickedContract.status,\n }\n : null,\n certificate: custodyCert\n ? {\n id: custodyCert.id,\n title: custodyCert.title,\n category: custodyCert.category,\n status: custodyCert.status,\n certNumber: custodyCert.certNumber ?? null,\n authority: custodyCert.authority ?? null,\n issuedAt: custodyCert.issuedAt ?? null,\n expiresAt: custodyCert.expiresAt ?? null,\n createdAt: custodyCert.createdAt,\n }\n : null,\n emissions: {\n totalCo2eTonnes: totalTonnes,\n recordCount: emissionRows.length,\n verifiedCount: verifiedEmissions,\n },\n };\n }, [\n a,\n latestProduction,\n latestLot,\n primaryShipment,\n pickedContract,\n custodyCert,\n totalTonnes,\n emissionRows.length,\n verifiedEmissions,\n ]);\n\n const provenanceDocument = useMemo(\n () =>\n chainInput && a\n ? buildProvenanceDocument(a.workspaceId, chainInput, completeCount, CHAIN_STAGES, verified)\n : null,\n [chainInput, a, completeCount, verified]\n );\n\n const handleExport = () => {\n if (!provenanceDocument || !a) return;\n const name = `${slugify(a.name)}-chain-of-custody.json`;\n const ok = downloadTextFile(\n name,\n 'application/json',\n JSON.stringify(provenanceDocument, null, 2)\n );\n if (ok) notify.success('Chain of custody exported');\n else notify.error(\"This browser can't download the export.\");\n };\n\n const handleShare = () => {\n if (!effectiveAssetId) return;\n const url = buildShareUrl(effectiveAssetId);\n const clipboard = typeof navigator !== 'undefined' ? navigator.clipboard : undefined;\n if (!clipboard) {\n notify.error(\"This browser doesn't allow copying to the clipboard.\");\n return;\n }\n void clipboard.writeText(url).then(\n () => notify.success('Provenance link copied'),\n () => notify.error(\"Couldn't copy the provenance link.\")\n );\n };\n\n const originPoint =\n a && typeof a.latitude === 'number' && typeof a.longitude === 'number'\n ? { lat: a.latitude, lng: a.longitude, label: a.name, primary: true }\n : null;\n\n const description = t(\n 'theglobalfuel.pages.provenance.description',\n 'Pit to port to certificate — end-to-end traceability from origin to verified certificate.'\n );\n\n // ── Render ─────────────────────────────────────────────────────────────────\n const pageTitle = t('theglobalfuel.pages.provenance.title', 'Provenance');\n\n if (assets.isLoading && assetRows.length === 0) {\n return (\n <PageLayout\n title={pageTitle}\n description={description}\n dataTour=\"theglobalfuel-provenance-page\"\n >\n <LoadingView label=\"Loading assets…\" />\n </PageLayout>\n );\n }\n if (assets.isError) {\n return (\n <PageLayout\n title={pageTitle}\n description={description}\n dataTour=\"theglobalfuel-provenance-page\"\n >\n <ErrorView message=\"Couldn't load assets to trace.\" onRetry={() => assets.refetch()} />\n </PageLayout>\n );\n }\n if (assetRows.length === 0) {\n return (\n <PageLayout\n title={pageTitle}\n description={description}\n dataTour=\"theglobalfuel-provenance-page\"\n >\n <EmptyState\n illustration=\"empty-data\"\n icon={<Link2 className=\"h-10 w-10\" />}\n title=\"No assets to trace\"\n description=\"Register a resource asset to build its end-to-end chain of custody.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('assets')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n Go to assets\n </button>\n }\n />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title={pageTitle}\n description={description}\n dataTour=\"theglobalfuel-provenance-page\"\n actions={\n <>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={handleShare}\n disabled={!effectiveAssetId}\n data-tour=\"theglobalfuel-provenance-share\"\n >\n <Share2 className=\"mr-2 h-4 w-4\" />\n Share\n </Button>\n <Button\n size=\"sm\"\n onClick={handleExport}\n disabled={!provenanceDocument}\n data-tour=\"theglobalfuel-provenance-export\"\n >\n <Download className=\"mr-2 h-4 w-4\" />\n Export\n </Button>\n </>\n }\n >\n {/* Control bar: asset picker + trust state */}\n <GlassCard\n treatment=\"glass\"\n className=\"flex flex-col gap-4 p-5 sm:flex-row sm:items-center sm:justify-between\"\n >\n <div className=\"flex min-w-0 flex-1 flex-col gap-1.5\">\n <label\n htmlFor=\"provenance-asset\"\n className=\"text-xs font-medium uppercase tracking-wide text-text-tertiary\"\n >\n Trace asset\n </label>\n <Select value={effectiveAssetId} onValueChange={setSelectedAssetId}>\n <SelectTrigger\n id=\"provenance-asset\"\n className=\"h-10 w-full sm:w-96\"\n aria-label=\"Select an asset to trace\"\n >\n <SelectValue placeholder=\"Select an asset to trace\" />\n </SelectTrigger>\n <SelectContent>\n {assetRows.map((row) => (\n <SelectItem key={row.id} value={row.id}>\n {row.name} · {formatEnumLabel(row.commodity)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div\n className={cn(\n 'flex items-center gap-2 self-start rounded-full px-3.5 py-1.5 text-sm font-medium',\n verified\n ? 'bg-status-success-bg-subtle text-status-success-text'\n : 'bg-bg-sunken text-text-secondary'\n )}\n >\n {verified ? <ShieldCheck className=\"h-4 w-4\" /> : <Shield className=\"h-4 w-4\" />}\n {verified ? 'Chain of custody verified' : `Traceability in progress · ${completeCount}/6`}\n </div>\n </GlassCard>\n\n {asset.isLoading ? (\n <div className=\"mt-6\">\n <LoadingView label=\"Assembling chain of custody…\" />\n </div>\n ) : asset.isError || !a ? (\n <div className=\"mt-6\">\n <ErrorView\n message=\"Couldn't load this asset's provenance.\"\n onRetry={() => asset.refetch()}\n />\n </div>\n ) : (\n <>\n {/* Trust banner — states the verification claim in plain language and\n never overstates it: unverified chains say exactly what is missing. */}\n <div\n className={cn(\n 'mt-6 flex flex-col gap-2 rounded-xl border p-4 sm:flex-row sm:items-center sm:gap-3',\n verified\n ? 'border-status-success-border bg-status-success-bg-subtle'\n : 'border-border-seam bg-bg-sunken'\n )}\n role=\"status\"\n >\n <span\n className={cn(\n 'flex size-9 shrink-0 items-center justify-center rounded-lg',\n verified\n ? 'bg-status-success-bg-subtle text-status-success-text'\n : 'bg-bg-surface text-text-secondary'\n )}\n >\n {verified ? <ShieldCheck className=\"h-5 w-5\" /> : <Shield className=\"h-5 w-5\" />}\n </span>\n <div className=\"min-w-0\">\n <p\n className={cn(\n 'text-sm font-semibold',\n verified ? 'text-status-success-text' : 'text-text-primary'\n )}\n >\n {verified\n ? 'Verified chain of custody'\n : `Chain of custody incomplete · ${completeCount} of ${CHAIN_STAGES} stages`}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {verified\n ? 'Every stage from origin to delivery is backed by a linked record, and the chain-of-custody certificate is approved.'\n : 'Stages without a linked record are shown as pending below. A chain is only marked verified once it is delivered and its custody certificate is approved.'}\n </p>\n </div>\n </div>\n\n {/* Flow ribbon */}\n <GlassCard treatment=\"glass\" className=\"mt-6 p-5\">\n <StepProgress steps={progressSteps} current={current} />\n </GlassCard>\n\n {/* Chain nodes */}\n <div className=\"mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-6\">\n {nodes.map((node) => (\n <ChainNodeCard key={node.step} node={node} />\n ))}\n </div>\n\n {/* Timeline + origin */}\n <div className=\"mt-6 grid grid-cols-1 gap-6 lg:grid-cols-3\">\n <GlassCard treatment=\"glass\" className=\"p-5 lg:col-span-2\">\n <div className=\"mb-4 flex items-center gap-2.5\">\n <span className=\"flex size-8 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-action-primary-bg\">\n <Route className=\"h-4 w-4\" />\n </span>\n <div>\n <h2 className=\"text-base font-semibold text-text-primary\">\n Traceability timeline\n </h2>\n <p className=\"text-xs text-text-tertiary\">\n Recorded custody events, oldest to newest.\n </p>\n </div>\n </div>\n {timelineItems.length > 0 ? (\n <Timeline items={timelineItems} />\n ) : (\n <div className=\"rounded-xl border border-dashed border-border-seam py-8 text-center text-sm text-text-secondary\">\n No dated custody events yet.\n </div>\n )}\n </GlassCard>\n\n <GlassCard treatment=\"glass\" className=\"flex flex-col gap-4 p-5\">\n <div className=\"flex items-center gap-2.5\">\n <span className=\"flex size-8 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-action-primary-bg\">\n <MapPin className=\"h-4 w-4\" />\n </span>\n <div className=\"min-w-0\">\n <h2 className=\"text-base font-semibold text-text-primary\">Origin</h2>\n <p className=\"truncate text-xs text-text-tertiary\">\n {a.location ?? formatEnumLabel(a.kind)}\n </p>\n </div>\n </div>\n {originPoint ? (\n <WorldMap points={[originPoint]} />\n ) : (\n <div className=\"rounded-xl border border-dashed border-border-seam py-8 text-center text-sm text-text-secondary\">\n No coordinates recorded for this asset.\n </div>\n )}\n </GlassCard>\n </div>\n\n {/* Provenance summary */}\n <GlassCard treatment=\"glass\" className=\"mt-6 p-5\">\n <h2 className=\"mb-4 text-base font-semibold text-text-primary\">Provenance summary</h2>\n <div className=\"grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-6\">\n <SummaryCell\n icon={<Fuel />}\n label=\"Commodity\"\n value={formatEnumLabel(a.commodity)}\n caption={formatEnumLabel(a.kind)}\n />\n <SummaryCell\n icon={<MapPin />}\n label=\"Origin\"\n value={a.location ?? a.name}\n caption={formatCoords(a.latitude, a.longitude)}\n />\n <SummaryCell\n icon={<Gauge />}\n label=\"Production\"\n value={`${formatNumber(productionRecords.length)} records`}\n caption={\n latestProduction\n ? `Latest ${formatVolume(latestProduction.volume, latestProduction.unit)}`\n : 'None yet'\n }\n />\n <SummaryCell\n icon={<Boxes />}\n label=\"Inventory\"\n value={`${formatNumber(assetLots.length)} lots`}\n caption={latestLot ? latestLot.lotCode : 'None yet'}\n />\n <SummaryCell\n icon={<Factory />}\n label=\"Emissions\"\n value={emissions.isError ? '—' : formatTonnesCo2e(totalTonnes)}\n caption={`${verifiedEmissions} verified`}\n />\n <SummaryCell\n icon={<ShieldCheck />}\n label=\"Certificates\"\n value={`${formatNumber(certRows.length)} tracked`}\n caption={\n certApproved ? 'Custody approved' : custodyCert ? 'Under review' : 'None yet'\n }\n />\n <SummaryCell\n icon={<Ship />}\n label=\"Tracking ID\"\n value={primaryShipment?.trackingId ?? 'Not issued'}\n caption={\n primaryShipment\n ? [primaryShipment.reference, primaryShipment.carrier]\n .filter(Boolean)\n .join(' · ')\n : 'No shipment yet'\n }\n />\n <SummaryCell\n icon={<Fingerprint />}\n label=\"Data integrity\"\n value={\n provenanceDocument\n ? shortDigest(provenanceDocument.integrityDigest)\n : 'Unavailable'\n }\n caption=\"Checksum over the linked records — re-export to compare\"\n />\n <SummaryCell\n icon={<Network />}\n label=\"Record network\"\n value=\"Federated workspace records\"\n caption=\"Registry · Commerce · Sustainability subgraphs\"\n />\n </div>\n </GlassCard>\n\n {/* Reserves footnote — surface proved reserves when present */}\n {(a.reserveEstimates?.length ?? 0) > 0 && (\n <p className=\"mt-4 flex items-center gap-1.5 text-xs text-text-tertiary\">\n <Layers className=\"h-3.5 w-3.5\" />\n {formatNumber(a.reserveEstimates?.length ?? 0)} reserve estimate\n {(a.reserveEstimates?.length ?? 0) === 1 ? '' : 's'} on record for this asset.\n </p>\n )}\n </>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Reports — generate and download operational / ESG / commercial extracts.
3
+ * @module theglobalfuel/pages/reports
4
+ *
5
+ * A catalogue of report definitions over the live `the*` records. Each report
6
+ * declares its own columns and row source; the page renders a live preview
7
+ * (first rows + real row count) and downloads the full extract as CSV.
8
+ *
9
+ * This is deliberately a client-side extract rather than a server-side report
10
+ * job: every row is data the caller is already authorized to read through the
11
+ * gateway, the volumes are page-sized, and it means a report can never drift
12
+ * from what the product UI shows. Anything needing scheduling, retention or
13
+ * cross-workspace scope belongs in a backend reporting service, not here.
14
+ */
15
+ export declare function ReportsPage(): import("react").JSX.Element;
16
+ //# sourceMappingURL=ReportsPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReportsPage.d.ts","sourceRoot":"","sources":["../../../../src/theglobalfuel/pages/reports/ReportsPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAiGH,wBAAgB,WAAW,gCA4Z1B"}