@burdenoff/microfe-theglobalfuel 2026.705.2 → 2026.705.4

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 (80) hide show
  1. package/dist/theglobalfuel/TheGlobalFuelRoot.js +54 -46
  2. package/dist/theglobalfuel/TheGlobalFuelRoot.js.map +1 -1
  3. package/dist/theglobalfuel/TheGlobalFuelRoutes.js +10 -6
  4. package/dist/theglobalfuel/TheGlobalFuelRoutes.js.map +1 -1
  5. package/dist/theglobalfuel/components/DataTable.js +126 -58
  6. package/dist/theglobalfuel/components/DataTable.js.map +1 -1
  7. package/dist/theglobalfuel/components/EmptyState.js +4 -4
  8. package/dist/theglobalfuel/components/EmptyState.js.map +1 -1
  9. package/dist/theglobalfuel/components/MetricsCard.js +2 -2
  10. package/dist/theglobalfuel/components/MetricsCard.js.map +1 -1
  11. package/dist/theglobalfuel/components/WorldMap.js +115 -0
  12. package/dist/theglobalfuel/components/WorldMap.js.map +1 -0
  13. package/dist/theglobalfuel/components/index.js +9 -0
  14. package/dist/theglobalfuel/components/viz/AllocationBar.js +68 -0
  15. package/dist/theglobalfuel/components/viz/AllocationBar.js.map +1 -0
  16. package/dist/theglobalfuel/components/viz/AreaChart.js +102 -0
  17. package/dist/theglobalfuel/components/viz/AreaChart.js.map +1 -0
  18. package/dist/theglobalfuel/components/viz/AvatarStack.js +2 -0
  19. package/dist/theglobalfuel/components/viz/BarChart.js +4 -0
  20. package/dist/theglobalfuel/components/viz/CertificateCard.js +4 -0
  21. package/dist/theglobalfuel/components/viz/DonutChart.js +109 -0
  22. package/dist/theglobalfuel/components/viz/DonutChart.js.map +1 -0
  23. package/dist/theglobalfuel/components/viz/HBarFunnel.js +3 -0
  24. package/dist/theglobalfuel/components/viz/Heatmap.js +3 -0
  25. package/dist/theglobalfuel/components/viz/KanbanBoard.js +2 -0
  26. package/dist/theglobalfuel/components/viz/LineChart.js +4 -0
  27. package/dist/theglobalfuel/components/viz/OrgTree.js +2 -0
  28. package/dist/theglobalfuel/components/viz/PathSteps.js +68 -0
  29. package/dist/theglobalfuel/components/viz/PathSteps.js.map +1 -0
  30. package/dist/theglobalfuel/components/viz/ProgressRing.js +6 -0
  31. package/dist/theglobalfuel/components/viz/ProgressRing.js.map +1 -0
  32. package/dist/theglobalfuel/components/viz/RatingStars.js +3 -0
  33. package/dist/theglobalfuel/components/viz/SegmentedTabs.js +3 -0
  34. package/dist/theglobalfuel/components/viz/SkillBar.js +3 -0
  35. package/dist/theglobalfuel/components/viz/Sparkline.js +74 -0
  36. package/dist/theglobalfuel/components/viz/Sparkline.js.map +1 -0
  37. package/dist/theglobalfuel/components/viz/StatCard.js +3 -0
  38. package/dist/theglobalfuel/components/viz/StepProgress.js +64 -0
  39. package/dist/theglobalfuel/components/viz/StepProgress.js.map +1 -0
  40. package/dist/theglobalfuel/components/viz/Timeline.js +66 -0
  41. package/dist/theglobalfuel/components/viz/Timeline.js.map +1 -0
  42. package/dist/theglobalfuel/components/viz/index.js +23 -0
  43. package/dist/theglobalfuel/components/viz/lib/Avatar.js +1 -0
  44. package/dist/theglobalfuel/components/viz/lib/CartesianFrame.js +119 -0
  45. package/dist/theglobalfuel/components/viz/lib/CartesianFrame.js.map +1 -0
  46. package/dist/theglobalfuel/components/viz/lib/ResponsiveSvg.js +35 -0
  47. package/dist/theglobalfuel/components/viz/lib/ResponsiveSvg.js.map +1 -0
  48. package/dist/theglobalfuel/components/viz/lib/format.js +17 -0
  49. package/dist/theglobalfuel/components/viz/lib/format.js.map +1 -0
  50. package/dist/theglobalfuel/components/viz/lib/geometry.js +61 -0
  51. package/dist/theglobalfuel/components/viz/lib/geometry.js.map +1 -0
  52. package/dist/theglobalfuel/components/viz/lib/hooks.js +39 -0
  53. package/dist/theglobalfuel/components/viz/lib/hooks.js.map +1 -0
  54. package/dist/theglobalfuel/components/viz/lib/palette.js +27 -0
  55. package/dist/theglobalfuel/components/viz/lib/palette.js.map +1 -0
  56. package/dist/theglobalfuel/hooks/useCursorPager.js +6 -15
  57. package/dist/theglobalfuel/hooks/useCursorPager.js.map +1 -1
  58. package/dist/theglobalfuel/pages/assets/AssetDetailPage.js +431 -316
  59. package/dist/theglobalfuel/pages/assets/AssetDetailPage.js.map +1 -1
  60. package/dist/theglobalfuel/pages/assets/AssetsPage.js +99 -99
  61. package/dist/theglobalfuel/pages/assets/AssetsPage.js.map +1 -1
  62. package/dist/theglobalfuel/pages/compliance/CompliancePage.js +250 -250
  63. package/dist/theglobalfuel/pages/compliance/CompliancePage.js.map +1 -1
  64. package/dist/theglobalfuel/pages/contracts/ContractsPage.js +2 -2
  65. package/dist/theglobalfuel/pages/contracts/ContractsPage.js.map +1 -1
  66. package/dist/theglobalfuel/pages/dashboard/DashboardPage.js +525 -227
  67. package/dist/theglobalfuel/pages/dashboard/DashboardPage.js.map +1 -1
  68. package/dist/theglobalfuel/pages/emissions/EmissionsPage.js +255 -206
  69. package/dist/theglobalfuel/pages/emissions/EmissionsPage.js.map +1 -1
  70. package/dist/theglobalfuel/pages/inventory/InventoryPage.js +60 -60
  71. package/dist/theglobalfuel/pages/inventory/InventoryPage.js.map +1 -1
  72. package/dist/theglobalfuel/pages/production/ProductionPage.js +2 -2
  73. package/dist/theglobalfuel/pages/production/ProductionPage.js.map +1 -1
  74. package/dist/theglobalfuel/pages/provenance/ProvenancePage.js +465 -0
  75. package/dist/theglobalfuel/pages/provenance/ProvenancePage.js.map +1 -0
  76. package/dist/theglobalfuel/pages/reserves/ReservesPage.js +152 -152
  77. package/dist/theglobalfuel/pages/reserves/ReservesPage.js.map +1 -1
  78. package/dist/theglobalfuel/pages/shipments/ShipmentsPage.js +356 -227
  79. package/dist/theglobalfuel/pages/shipments/ShipmentsPage.js.map +1 -1
  80. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ShipmentsPage.js","names":[],"sources":["../../../../src/theglobalfuel/pages/shipments/ShipmentsPage.tsx"],"sourcesContent":["/**\n * Shipments — schedule and track cargo movements against offtake contracts.\n * @module theglobalfuel/pages/shipments\n *\n * Reads `theListShipments` (a cursor connection — `{ items, pageInfo }`, filtered\n * by contract + status) and `theListContracts` (to resolve contract references +\n * populate the picker); writes `theScheduleShipment`, `theDeliverShipment` and\n * lifecycle transitions via `theTransitionShipment`.\n */\n\nimport { useMemo, useState } from 'react';\nimport { Plus, Ship, CalendarClock, Truck, PackageCheck, ArrowRight } from 'lucide-react';\nimport {\n Button,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { MetricsCard } from '../../components/MetricsCard';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { DataTable, type Column } from '../../components/DataTable';\nimport { FilterTabs, type FilterOption } from '../../components/FilterTabs';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { EmptyState } from '../../components/EmptyState';\nimport { FileLink } from '../../components/FileLink';\nimport { EvidenceUpload } from '../../components/EvidenceUpload';\nimport { Pagination } from '../../components/Pagination';\nimport {\n useNotify,\n useTheShipments,\n useTheContracts,\n useTheScheduleShipment,\n useTheDeliverShipment,\n useTheTransitionShipment,\n useCursorPager,\n type UploadedTheFile,\n} from '../../hooks';\nimport { formatEnumLabel, formatDate, formatVolume } from '../../utils/formatters';\nimport {\n toBackendDate,\n SHIPMENT_TRANSITIONS,\n SHIPMENT_DELIVERABLE_FROM,\n nextStatuses,\n} from '../../utils';\nimport type {\n TheShipment,\n TheShipmentStatus,\n TheTransportMode,\n TheUnit,\n TheOfftakeContract,\n} from '../../types';\n\nconst STATUS_FILTERS: Array<{ value: TheShipmentStatus | 'ALL'; label: string }> = [\n { value: 'ALL', label: 'All' },\n { value: 'SCHEDULED', label: 'Scheduled' },\n { value: 'LOADING', label: 'Loading' },\n { value: 'IN_TRANSIT', label: 'In transit' },\n { value: 'DELIVERED', label: 'Delivered' },\n { value: 'CANCELLED', label: 'Cancelled' },\n];\n\nconst TRANSPORT_MODES: TheTransportMode[] = [\n 'PIPELINE',\n 'TANKER',\n 'VESSEL_BULK',\n 'RAIL',\n 'TRUCK',\n 'GRID',\n];\n\nconst UNITS: TheUnit[] = ['BARRELS', 'CUBIC_METERS', 'TONNES', 'KILOGRAMS', 'MWH', 'GJ', 'MCF'];\n\nconst PAGE_SIZE = 25;\n\ninterface ScheduleFormState {\n contractId: string;\n reference: string;\n mode: TheTransportMode;\n carrier: string;\n origin: string;\n destination: string;\n volume: string;\n unit: TheUnit;\n scheduledAt: string;\n notes: string;\n}\n\nconst EMPTY_FORM: ScheduleFormState = {\n contractId: '',\n reference: '',\n mode: 'TANKER',\n carrier: '',\n origin: '',\n destination: '',\n volume: '',\n unit: 'BARRELS',\n scheduledAt: '',\n notes: '',\n};\n\nexport function ShipmentsPage() {\n const [status, setStatus] = useState<TheShipmentStatus | 'ALL'>('ALL');\n const [contractId, setContractId] = useState<string | 'ALL'>('ALL');\n const pager = useCursorPager();\n const [dialogOpen, setDialogOpen] = useState(false);\n const [form, setForm] = useState<ScheduleFormState>(EMPTY_FORM);\n const [doc, setDoc] = useState<UploadedTheFile | null>(null);\n const [formError, setFormError] = useState<string | null>(null);\n // Track the shipment whose transition is in flight so only that row's Select\n // disables (transitionShipment.isPending is shared across all rows).\n const [transitioningId, setTransitioningId] = useState<string | null>(null);\n\n const notify = useNotify();\n\n const scopedContractId = contractId === 'ALL' ? undefined : contractId;\n\n // Table query — respects both the contract scope and the status filter, and is\n // cursor-paginated to PAGE_SIZE.\n const { data, isLoading, isError, refetch } = useTheShipments(\n scopedContractId,\n status === 'ALL' ? undefined : status,\n { limit: PAGE_SIZE, cursor: pager.cursor }\n );\n // Metrics query — same contract scope but ignores the status filter so the\n // header counts stay stable as the table is narrowed. A broad limit keeps the\n // KPI status mix representative (the table itself is paginated to PAGE_SIZE).\n const metricsQuery = useTheShipments(scopedContractId, undefined, { limit: 200 });\n\n // Contracts drive the picker + let us resolve a shipment's contract reference.\n const contractsQuery = useTheContracts({ pagination: { limit: 100 } });\n const contractItems = useMemo(\n () => contractsQuery.data?.items ?? [],\n [contractsQuery.data]\n );\n const contractMap = useMemo(() => {\n const map = new Map<string, TheOfftakeContract>();\n for (const c of contractItems) map.set(c.id, c);\n return map;\n }, [contractItems]);\n\n const scheduleShipment = useTheScheduleShipment();\n const deliverShipment = useTheDeliverShipment();\n const transitionShipment = useTheTransitionShipment();\n\n const rows = useMemo(() => data?.items ?? [], [data]);\n const metricsRows = useMemo(() => metricsQuery.data?.items ?? [], [metricsQuery.data]);\n\n // ── Header metrics (derived from the contract-scoped, status-agnostic list) ──\n const scheduledCount = metricsRows.filter((s) => s.status === 'SCHEDULED').length;\n const inTransitCount = metricsRows.filter((s) => s.status === 'IN_TRANSIT').length;\n const deliveredCount = metricsRows.filter((s) => s.status === 'DELIVERED').length;\n\n const statusCounts = useMemo(() => {\n const counts: Record<string, number> = {};\n for (const s of metricsRows) counts[s.status] = (counts[s.status] ?? 0) + 1;\n return counts;\n }, [metricsRows]);\n\n const filterOptions: FilterOption<TheShipmentStatus | 'ALL'>[] = STATUS_FILTERS.map((opt) => ({\n value: opt.value,\n label: opt.label,\n count: opt.value === 'ALL' ? metricsRows.length : (statusCounts[opt.value] ?? 0),\n }));\n\n const resetForm = () => {\n setForm(EMPTY_FORM);\n setDoc(null);\n setFormError(null);\n };\n\n const handleSchedule = async () => {\n if (!form.contractId) {\n setFormError('Select the contract this shipment fulfils.');\n return;\n }\n if (!form.reference.trim()) {\n setFormError('A shipment reference is required.');\n return;\n }\n const volume = Number(form.volume);\n if (!form.volume || Number.isNaN(volume) || volume <= 0) {\n setFormError('Enter a volume greater than zero.');\n notify.error('Enter a volume greater than zero.');\n return;\n }\n setFormError(null);\n try {\n await scheduleShipment.mutateAsync({\n contractId: form.contractId,\n reference: form.reference.trim(),\n mode: form.mode,\n carrier: form.carrier.trim() || null,\n origin: form.origin.trim() || null,\n destination: form.destination.trim() || null,\n volume,\n unit: form.unit,\n scheduledAt: toBackendDate(form.scheduledAt) ?? null,\n documentFileId: doc?.fileId ?? null,\n notes: form.notes.trim() || null,\n });\n notify.success('Shipment scheduled');\n setDialogOpen(false);\n resetForm();\n } catch (err) {\n setFormError(err instanceof Error ? err.message : 'Failed to schedule shipment.');\n notify.fromError(err);\n }\n };\n\n const columns: Column<TheShipment>[] = [\n {\n key: 'reference',\n header: 'Shipment',\n render: (s) => (\n <div className=\"min-w-0\">\n <p className=\"truncate font-semibold text-text-primary\">{s.reference}</p>\n <p className=\"truncate text-xs text-text-tertiary md:hidden\">{formatEnumLabel(s.mode)}</p>\n </div>\n ),\n },\n {\n key: 'contract',\n header: 'Contract',\n hideOnMobile: true,\n render: (s) => {\n const contract = contractMap.get(s.contractId);\n return contract ? (\n <div className=\"min-w-0\">\n <p className=\"truncate font-medium text-text-primary\">{contract.reference}</p>\n <p className=\"truncate text-xs text-text-tertiary\">{contract.counterparty}</p>\n </div>\n ) : (\n <span className=\"font-mono text-xs text-text-tertiary\">{s.contractId.slice(0, 8)}</span>\n );\n },\n },\n {\n key: 'mode',\n header: 'Mode',\n hideOnMobile: true,\n render: (s) => <span className=\"text-text-secondary\">{formatEnumLabel(s.mode)}</span>,\n },\n {\n key: 'status',\n header: 'Status',\n render: (s) => <StatusBadge status={s.status} />,\n },\n {\n key: 'route',\n header: 'Route',\n hideOnMobile: true,\n render: (s) => {\n const origin = s.origin?.trim();\n const destination = s.destination?.trim();\n if (!origin && !destination) return <span className=\"text-text-tertiary\">—</span>;\n return (\n <span className=\"inline-flex items-center gap-1.5 text-text-secondary\">\n <span className=\"truncate\">{origin ?? '—'}</span>\n <ArrowRight className=\"h-3.5 w-3.5 shrink-0 text-text-tertiary\" />\n <span className=\"truncate\">{destination ?? '—'}</span>\n </span>\n );\n },\n },\n {\n key: 'volume',\n header: 'Volume',\n align: 'right',\n sortValue: (s) => s.volume,\n render: (s) => (\n <span className=\"tabular-nums text-text-primary\">{formatVolume(s.volume, s.unit)}</span>\n ),\n },\n {\n key: 'scheduledAt',\n header: 'Scheduled',\n align: 'right',\n hideOnMobile: true,\n sortValue: (s) => s.scheduledAt ?? '',\n render: (s) => <span className=\"text-text-tertiary\">{formatDate(s.scheduledAt)}</span>,\n },\n {\n key: 'document',\n header: 'Document',\n hideOnMobile: true,\n render: (s) =>\n s.document?.id ? (\n <FileLink fileId={s.document.id} />\n ) : (\n <span className=\"text-text-tertiary\">—</span>\n ),\n },\n {\n key: 'action',\n header: '',\n align: 'right',\n render: (s) => {\n // Lifecycle transitions reachable via theTransitionShipment (SCHEDULED →\n // LOADING → IN_TRANSIT → CANCELLED). DELIVERED is NOT offered here — it is\n // reached through \"Mark delivered\", which additionally rolls volume into\n // the contract. Terminal states (DELIVERED / CANCELLED) expose neither.\n const nexts = nextStatuses(SHIPMENT_TRANSITIONS, s.status);\n const canDeliver = SHIPMENT_DELIVERABLE_FROM.includes(s.status);\n const rowBusy = transitioningId === s.id;\n if (nexts.length === 0 && !canDeliver) {\n return <span className=\"text-text-tertiary\">—</span>;\n }\n return (\n <div className=\"flex items-center justify-end gap-2\">\n {nexts.length > 0 && (\n <Select\n value={s.status}\n disabled={rowBusy}\n onValueChange={(v) => {\n if (v === s.status) return;\n setTransitioningId(s.id);\n transitionShipment.mutate(\n { id: s.id, status: v as TheShipmentStatus },\n {\n onSuccess: () => notify.success('Shipment updated'),\n onError: (e) => notify.fromError(e),\n onSettled: () => setTransitioningId(null),\n }\n );\n }}\n >\n <SelectTrigger\n className=\"h-8 w-36\"\n aria-label={`Change status for shipment ${s.reference}`}\n >\n <SelectValue placeholder={formatEnumLabel(s.status)} />\n </SelectTrigger>\n <SelectContent>\n {nexts.map((st) => (\n <SelectItem key={st} value={st}>\n {formatEnumLabel(st)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n {canDeliver && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n disabled={deliverShipment.isPending || rowBusy}\n onClick={() =>\n deliverShipment.mutate(s.id, {\n onSuccess: () => notify.success('Shipment delivered'),\n onError: (e) => notify.fromError(e),\n })\n }\n >\n <PackageCheck className=\"mr-1.5 h-4 w-4\" /> Mark delivered\n </Button>\n )}\n </div>\n );\n },\n },\n ];\n\n const isFiltered = status !== 'ALL' || contractId !== 'ALL';\n\n return (\n <PageLayout\n title=\"Shipments\"\n description=\"Cargo movements delivering offtake contracts — pipelines, tankers, vessels, rail & grid.\"\n actions={\n <Button onClick={() => setDialogOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Schedule shipment\n </Button>\n }\n >\n {/* Header metrics — status mix within the current contract scope. */}\n <div className=\"mb-6 grid grid-cols-2 gap-4 lg:grid-cols-4\">\n <MetricsCard\n featured\n icon={<Ship className=\"h-5 w-5\" />}\n value={metricsRows.length}\n label=\"Total shipments\"\n />\n <MetricsCard\n icon={<CalendarClock className=\"h-5 w-5\" />}\n value={scheduledCount}\n label=\"Scheduled\"\n />\n <MetricsCard\n accent=\"warning\"\n icon={<Truck className=\"h-5 w-5\" />}\n value={inTransitCount}\n label=\"In transit\"\n />\n <MetricsCard\n accent=\"success\"\n icon={<PackageCheck className=\"h-5 w-5\" />}\n value={deliveredCount}\n label=\"Delivered\"\n />\n </div>\n\n <div className=\"mb-5 flex flex-wrap items-center gap-3\">\n <FilterTabs\n options={filterOptions}\n value={status}\n onChange={(v) => {\n setStatus(v);\n pager.reset();\n }}\n />\n <Select\n value={contractId}\n onValueChange={(v) => {\n setContractId(v as string | 'ALL');\n pager.reset();\n }}\n >\n <SelectTrigger className=\"w-56\" aria-label=\"Filter by contract\">\n <SelectValue placeholder=\"All contracts\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">All contracts</SelectItem>\n {contractItems.map((c) => (\n <SelectItem key={c.id} value={c.id}>\n {c.reference} · {c.counterparty}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {isLoading ? (\n <LoadingView label=\"Loading shipments…\" />\n ) : isError ? (\n <ErrorView message=\"Couldn't load shipments.\" onRetry={() => refetch()} />\n ) : rows.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Ship className=\"h-10 w-10\" />}\n title={isFiltered ? 'No matching shipments' : 'No shipments yet'}\n description={\n isFiltered\n ? 'No shipments match these filters. Try a different status or contract.'\n : 'Schedule your first shipment to start tracking cargo against your offtake contracts.'\n }\n action={\n <Button onClick={() => setDialogOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Schedule shipment\n </Button>\n }\n />\n ) : (\n <>\n <DataTable\n columns={columns}\n rows={rows}\n rowKey={(s) => s.id}\n defaultSort={{ key: 'scheduledAt', dir: 'desc' }}\n />\n <Pagination\n page={pager.page}\n pageSize={PAGE_SIZE}\n itemCount={rows.length}\n hasMore={data?.pageInfo?.hasMore ?? false}\n onPageChange={(p) => pager.onPageChange(p, data?.pageInfo?.cursor)}\n />\n </>\n )}\n\n {/* Schedule shipment dialog */}\n <ResponsiveDialog\n open={dialogOpen}\n onOpenChange={(open) => {\n setDialogOpen(open);\n if (!open) resetForm();\n }}\n >\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Schedule shipment</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Book a cargo movement against an offtake contract and track it to delivery.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <form\n onSubmit={(e) => {\n e.preventDefault();\n void handleSchedule();\n }}\n >\n <div className=\"grid gap-4 py-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"shipContract\">Contract *</Label>\n <Select\n value={form.contractId}\n onValueChange={(v) => {\n // Default the unit to the contract's unit for a sensible start.\n const contract = contractMap.get(v);\n setForm((prev) => ({\n ...prev,\n contractId: v,\n unit: contract?.unit ?? prev.unit,\n }));\n }}\n >\n <SelectTrigger id=\"shipContract\">\n <SelectValue placeholder=\"Select a contract\" />\n </SelectTrigger>\n <SelectContent>\n {contractItems.length === 0 ? (\n <SelectItem value=\"none\" disabled>\n No contracts available\n </SelectItem>\n ) : (\n contractItems.map((c) => (\n <SelectItem key={c.id} value={c.id}>\n {c.reference} · {c.counterparty}\n </SelectItem>\n ))\n )}\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"shipRef\">Reference *</Label>\n <Input\n id=\"shipRef\"\n value={form.reference}\n onChange={(e) => setForm({ ...form, reference: e.target.value })}\n placeholder=\"SHP-2026-0142\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"shipMode\">Mode</Label>\n <Select\n value={form.mode}\n onValueChange={(v) => setForm({ ...form, mode: v as TheTransportMode })}\n >\n <SelectTrigger id=\"shipMode\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {TRANSPORT_MODES.map((m) => (\n <SelectItem key={m} value={m}>\n {formatEnumLabel(m)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"shipOrigin\">Origin</Label>\n <Input\n id=\"shipOrigin\"\n value={form.origin}\n onChange={(e) => setForm({ ...form, origin: e.target.value })}\n placeholder=\"Ras Tanura Terminal\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"shipDest\">Destination</Label>\n <Input\n id=\"shipDest\"\n value={form.destination}\n onChange={(e) => setForm({ ...form, destination: e.target.value })}\n placeholder=\"Rotterdam\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-3\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"shipVolume\">Volume *</Label>\n <Input\n id=\"shipVolume\"\n type=\"number\"\n min=\"0\"\n step=\"any\"\n value={form.volume}\n onChange={(e) => setForm({ ...form, volume: e.target.value })}\n placeholder=\"500000\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"shipUnit\">Unit</Label>\n <Select\n value={form.unit}\n onValueChange={(v) => setForm({ ...form, unit: v as TheUnit })}\n >\n <SelectTrigger id=\"shipUnit\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {UNITS.map((u) => (\n <SelectItem key={u} value={u}>\n {formatEnumLabel(u)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"shipScheduled\">Scheduled date</Label>\n <Input\n id=\"shipScheduled\"\n type=\"date\"\n value={form.scheduledAt}\n onChange={(e) => setForm({ ...form, scheduledAt: e.target.value })}\n />\n </div>\n </div>\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"shipCarrier\">Carrier</Label>\n <Input\n id=\"shipCarrier\"\n value={form.carrier}\n onChange={(e) => setForm({ ...form, carrier: e.target.value })}\n placeholder=\"Frontline Ltd.\"\n />\n </div>\n\n <EvidenceUpload\n id=\"shipDocument\"\n label=\"Bill of lading (optional)\"\n value={doc}\n onChange={setDoc}\n hint=\"Attach the bill of lading or shipping document (PDF or image).\"\n />\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"shipNotes\">Notes</Label>\n <Textarea\n id=\"shipNotes\"\n value={form.notes}\n onChange={(e) => setForm({ ...form, notes: e.target.value })}\n placeholder=\"Optional context — laycan window, inspector, terms.\"\n rows={2}\n />\n </div>\n\n {formError && <p className=\"text-sm text-status-error-text\">{formError}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => {\n setDialogOpen(false);\n resetForm();\n }}\n >\n Cancel\n </Button>\n <Button type=\"submit\" disabled={scheduleShipment.isPending}>\n {scheduleShipment.isPending ? 'Scheduling…' : 'Schedule shipment'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ShipmentsPage.js","names":[],"sources":["../../../../src/theglobalfuel/pages/shipments/ShipmentsPage.tsx"],"sourcesContent":["/**\n * Shipments — schedule and track cargo movements against offtake contracts.\n * @module theglobalfuel/pages/shipments\n *\n * Reads `theListShipments` (a cursor connection — `{ items, pageInfo }`, filtered\n * by contract + status) and `theListContracts` (to resolve contract references +\n * populate the picker); writes `theScheduleShipment`, `theDeliverShipment` and\n * lifecycle transitions via `theTransitionShipment`.\n */\n\nimport { useMemo, useState } from 'react';\nimport { Plus, Ship, CalendarClock, Truck, PackageCheck, ArrowRight, MapPin } from 'lucide-react';\nimport {\n Button,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { MetricsCard } from '../../components/MetricsCard';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { DataTable, type Column } from '../../components/DataTable';\nimport { FilterTabs, type FilterOption } from '../../components/FilterTabs';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { EmptyState } from '../../components/EmptyState';\nimport { FileLink } from '../../components/FileLink';\nimport { EvidenceUpload } from '../../components/EvidenceUpload';\nimport { Pagination } from '../../components/Pagination';\nimport { AllocationBar, PathSteps, type PathStep, type Segment } from '../../components';\nimport {\n useNotify,\n useTheShipments,\n useTheContracts,\n useTheScheduleShipment,\n useTheDeliverShipment,\n useTheTransitionShipment,\n useCursorPager,\n type UploadedTheFile,\n} from '../../hooks';\nimport { formatEnumLabel, formatDate, formatVolume } from '../../utils/formatters';\nimport {\n toBackendDate,\n SHIPMENT_TRANSITIONS,\n SHIPMENT_DELIVERABLE_FROM,\n nextStatuses,\n} from '../../utils';\nimport type {\n TheShipment,\n TheShipmentStatus,\n TheTransportMode,\n TheUnit,\n TheOfftakeContract,\n} from '../../types';\n\nconst STATUS_FILTERS: Array<{ value: TheShipmentStatus | 'ALL'; label: string }> = [\n { value: 'ALL', label: 'All' },\n { value: 'SCHEDULED', label: 'Scheduled' },\n { value: 'LOADING', label: 'Loading' },\n { value: 'IN_TRANSIT', label: 'In transit' },\n { value: 'DELIVERED', label: 'Delivered' },\n { value: 'CANCELLED', label: 'Cancelled' },\n];\n\nconst TRANSPORT_MODES: TheTransportMode[] = [\n 'PIPELINE',\n 'TANKER',\n 'VESSEL_BULK',\n 'RAIL',\n 'TRUCK',\n 'GRID',\n];\n\nconst UNITS: TheUnit[] = ['BARRELS', 'CUBIC_METERS', 'TONNES', 'KILOGRAMS', 'MWH', 'GJ', 'MCF'];\n\nconst PAGE_SIZE = 25;\n\n/** Lifecycle order for the status-distribution bar + legend. */\nconst STATUS_ORDER: TheShipmentStatus[] = [\n 'SCHEDULED',\n 'LOADING',\n 'IN_TRANSIT',\n 'DELIVERED',\n 'CANCELLED',\n];\n\nconst STATUS_LABEL: Record<TheShipmentStatus, string> = {\n SCHEDULED: 'Scheduled',\n LOADING: 'Loading',\n IN_TRANSIT: 'In transit',\n DELIVERED: 'Delivered',\n CANCELLED: 'Cancelled',\n};\n\n/**\n * Tokenized AllocationBar color per shipment status — aligned to the StatusBadge\n * palette (neutral → info → warning → success → danger). All are semantic CSS\n * variables so the bar themes automatically.\n */\nconst STATUS_SEGMENT_COLOR: Record<TheShipmentStatus, string> = {\n SCHEDULED: 'var(--color-text-muted)',\n LOADING: 'var(--color-accent-blue)',\n IN_TRANSIT: 'var(--color-status-warning-text)',\n DELIVERED: 'var(--color-status-success-text)',\n CANCELLED: 'var(--color-status-error-text)',\n};\n\n/**\n * Build an origin → mode → destination route flow for a shipment, with node\n * states derived from its lifecycle status. Origin/destination are free-text\n * strings — never plotted on a map. Only call with shipments that carry both.\n */\nconst routeSteps = (s: TheShipment): PathStep[] => {\n const cancelled = s.status === 'CANCELLED';\n const delivered = s.status === 'DELIVERED';\n const inTransit = s.status === 'IN_TRANSIT';\n const departed = delivered || inTransit;\n const midMeta = cancelled\n ? 'Cancelled'\n : delivered\n ? 'Delivered'\n : inTransit\n ? 'In transit'\n : formatEnumLabel(s.status);\n return [\n {\n label: (s.origin ?? '').trim(),\n meta: 'Origin',\n state: cancelled ? 'todo' : departed ? 'done' : 'active',\n },\n {\n label: formatEnumLabel(s.mode),\n meta: midMeta,\n state: cancelled ? 'locked' : delivered ? 'done' : inTransit ? 'active' : 'todo',\n },\n {\n label: (s.destination ?? '').trim(),\n meta: 'Destination',\n state: cancelled ? 'locked' : delivered ? 'done' : 'todo',\n },\n ];\n};\n\ninterface ScheduleFormState {\n contractId: string;\n reference: string;\n mode: TheTransportMode;\n carrier: string;\n origin: string;\n destination: string;\n volume: string;\n unit: TheUnit;\n scheduledAt: string;\n notes: string;\n}\n\nconst EMPTY_FORM: ScheduleFormState = {\n contractId: '',\n reference: '',\n mode: 'TANKER',\n carrier: '',\n origin: '',\n destination: '',\n volume: '',\n unit: 'BARRELS',\n scheduledAt: '',\n notes: '',\n};\n\nexport function ShipmentsPage() {\n const [status, setStatus] = useState<TheShipmentStatus | 'ALL'>('ALL');\n const [contractId, setContractId] = useState<string | 'ALL'>('ALL');\n const pager = useCursorPager();\n const [dialogOpen, setDialogOpen] = useState(false);\n const [form, setForm] = useState<ScheduleFormState>(EMPTY_FORM);\n const [doc, setDoc] = useState<UploadedTheFile | null>(null);\n const [formError, setFormError] = useState<string | null>(null);\n // Track the shipment whose transition is in flight so only that row's Select\n // disables (transitionShipment.isPending is shared across all rows).\n const [transitioningId, setTransitioningId] = useState<string | null>(null);\n // The shipment whose route flow is traced in the logistics panel (falls back\n // to the first routeable shipment when unset or no longer present).\n const [tracedId, setTracedId] = useState<string | null>(null);\n\n const notify = useNotify();\n\n const scopedContractId = contractId === 'ALL' ? undefined : contractId;\n\n // Table query — respects both the contract scope and the status filter, and is\n // cursor-paginated to PAGE_SIZE.\n const { data, isLoading, isError, refetch } = useTheShipments(\n scopedContractId,\n status === 'ALL' ? undefined : status,\n { limit: PAGE_SIZE, offset: pager.page * PAGE_SIZE }\n );\n // Metrics query — same contract scope but ignores the status filter so the\n // header counts stay stable as the table is narrowed. A broad limit keeps the\n // KPI status mix representative (the table itself is paginated to PAGE_SIZE).\n const metricsQuery = useTheShipments(scopedContractId, undefined, { limit: 200 });\n\n // Contracts drive the picker + let us resolve a shipment's contract reference.\n const contractsQuery = useTheContracts({ pagination: { limit: 100 } });\n const contractItems = useMemo(\n () => contractsQuery.data?.items ?? [],\n [contractsQuery.data]\n );\n const contractMap = useMemo(() => {\n const map = new Map<string, TheOfftakeContract>();\n for (const c of contractItems) map.set(c.id, c);\n return map;\n }, [contractItems]);\n\n const scheduleShipment = useTheScheduleShipment();\n const deliverShipment = useTheDeliverShipment();\n const transitionShipment = useTheTransitionShipment();\n\n const rows = useMemo(() => data?.items ?? [], [data]);\n const metricsRows = useMemo(() => metricsQuery.data?.items ?? [], [metricsQuery.data]);\n\n // ── Header metrics (derived from the contract-scoped, status-agnostic list) ──\n const scheduledCount = metricsRows.filter((s) => s.status === 'SCHEDULED').length;\n const inTransitCount = metricsRows.filter((s) => s.status === 'IN_TRANSIT').length;\n const deliveredCount = metricsRows.filter((s) => s.status === 'DELIVERED').length;\n\n const statusCounts = useMemo(() => {\n const counts: Record<string, number> = {};\n for (const s of metricsRows) counts[s.status] = (counts[s.status] ?? 0) + 1;\n return counts;\n }, [metricsRows]);\n\n const filterOptions: FilterOption<TheShipmentStatus | 'ALL'>[] = STATUS_FILTERS.map((opt) => ({\n value: opt.value,\n label: opt.label,\n count: opt.value === 'ALL' ? metricsRows.length : (statusCounts[opt.value] ?? 0),\n }));\n\n // ── Logistics viz (derived from the broad, contract-scoped metrics list) ──\n // Status distribution → AllocationBar segments (lifecycle-ordered, tokenized).\n const statusSegments = useMemo<Segment[]>(\n () =>\n STATUS_ORDER.filter((st) => (statusCounts[st] ?? 0) > 0).map((st) => ({\n label: STATUS_LABEL[st],\n value: statusCounts[st] ?? 0,\n color: STATUS_SEGMENT_COLOR[st],\n })),\n [statusCounts]\n );\n\n // Shipments that carry both an origin and a destination can be route-traced.\n const routeableShipments = useMemo(\n () => metricsRows.filter((s) => (s.origin ?? '').trim() && (s.destination ?? '').trim()),\n [metricsRows]\n );\n\n // Distinct origin → destination lanes across the routeable set.\n const distinctLanes = useMemo(() => {\n const lanes = new Set<string>();\n for (const s of routeableShipments) {\n lanes.add(`${(s.origin ?? '').trim()} → ${(s.destination ?? '').trim()}`);\n }\n return lanes.size;\n }, [routeableShipments]);\n\n const tracedShipment = useMemo(\n () => routeableShipments.find((s) => s.id === tracedId) ?? routeableShipments[0] ?? null,\n [routeableShipments, tracedId]\n );\n\n const resetForm = () => {\n setForm(EMPTY_FORM);\n setDoc(null);\n setFormError(null);\n };\n\n const handleSchedule = async () => {\n if (!form.contractId) {\n setFormError('Select the contract this shipment fulfils.');\n return;\n }\n if (!form.reference.trim()) {\n setFormError('A shipment reference is required.');\n return;\n }\n const volume = Number(form.volume);\n if (!form.volume || Number.isNaN(volume) || volume <= 0) {\n setFormError('Enter a volume greater than zero.');\n notify.error('Enter a volume greater than zero.');\n return;\n }\n setFormError(null);\n try {\n await scheduleShipment.mutateAsync({\n contractId: form.contractId,\n reference: form.reference.trim(),\n mode: form.mode,\n carrier: form.carrier.trim() || null,\n origin: form.origin.trim() || null,\n destination: form.destination.trim() || null,\n volume,\n unit: form.unit,\n scheduledAt: toBackendDate(form.scheduledAt) ?? null,\n documentFileId: doc?.fileId ?? null,\n notes: form.notes.trim() || null,\n });\n notify.success('Shipment scheduled');\n setDialogOpen(false);\n resetForm();\n } catch (err) {\n setFormError(err instanceof Error ? err.message : 'Failed to schedule shipment.');\n notify.fromError(err);\n }\n };\n\n const columns: Column<TheShipment>[] = [\n {\n key: 'reference',\n header: 'Shipment',\n render: (s) => (\n <div className=\"min-w-0\">\n <p className=\"truncate font-semibold text-text-primary\">{s.reference}</p>\n <p className=\"truncate text-xs text-text-tertiary md:hidden\">{formatEnumLabel(s.mode)}</p>\n </div>\n ),\n },\n {\n key: 'contract',\n header: 'Contract',\n hideOnMobile: true,\n render: (s) => {\n const contract = contractMap.get(s.contractId);\n return contract ? (\n <div className=\"min-w-0\">\n <p className=\"truncate font-medium text-text-primary\">{contract.reference}</p>\n <p className=\"truncate text-xs text-text-tertiary\">{contract.counterparty}</p>\n </div>\n ) : (\n <span className=\"font-mono text-xs text-text-tertiary\">{s.contractId.slice(0, 8)}</span>\n );\n },\n },\n {\n key: 'mode',\n header: 'Mode',\n hideOnMobile: true,\n render: (s) => <span className=\"text-text-secondary\">{formatEnumLabel(s.mode)}</span>,\n },\n {\n key: 'status',\n header: 'Status',\n render: (s) => <StatusBadge status={s.status} />,\n },\n {\n key: 'route',\n header: 'Route',\n hideOnMobile: true,\n render: (s) => {\n const origin = s.origin?.trim();\n const destination = s.destination?.trim();\n if (!origin && !destination) return <span className=\"text-text-tertiary\">—</span>;\n return (\n <span className=\"inline-flex items-center gap-1.5 text-text-secondary\">\n <span className=\"truncate\">{origin ?? '—'}</span>\n <ArrowRight className=\"h-3.5 w-3.5 shrink-0 text-text-tertiary\" />\n <span className=\"truncate\">{destination ?? '—'}</span>\n </span>\n );\n },\n },\n {\n key: 'volume',\n header: 'Volume',\n align: 'right',\n sortValue: (s) => s.volume,\n render: (s) => (\n <span className=\"tabular-nums text-text-primary\">{formatVolume(s.volume, s.unit)}</span>\n ),\n },\n {\n key: 'scheduledAt',\n header: 'Scheduled',\n align: 'right',\n hideOnMobile: true,\n sortValue: (s) => s.scheduledAt ?? '',\n render: (s) => <span className=\"text-text-tertiary\">{formatDate(s.scheduledAt)}</span>,\n },\n {\n key: 'document',\n header: 'Document',\n hideOnMobile: true,\n render: (s) =>\n s.document?.id ? (\n <FileLink fileId={s.document.id} />\n ) : (\n <span className=\"text-text-tertiary\">—</span>\n ),\n },\n {\n key: 'action',\n header: '',\n align: 'right',\n render: (s) => {\n // Lifecycle transitions reachable via theTransitionShipment (SCHEDULED →\n // LOADING → IN_TRANSIT → CANCELLED). DELIVERED is NOT offered here — it is\n // reached through \"Mark delivered\", which additionally rolls volume into\n // the contract. Terminal states (DELIVERED / CANCELLED) expose neither.\n const nexts = nextStatuses(SHIPMENT_TRANSITIONS, s.status);\n const canDeliver = SHIPMENT_DELIVERABLE_FROM.includes(s.status);\n const rowBusy = transitioningId === s.id;\n if (nexts.length === 0 && !canDeliver) {\n return <span className=\"text-text-tertiary\">—</span>;\n }\n return (\n <div className=\"flex items-center justify-end gap-2\">\n {nexts.length > 0 && (\n <Select\n value={s.status}\n disabled={rowBusy}\n onValueChange={(v) => {\n if (v === s.status) return;\n setTransitioningId(s.id);\n transitionShipment.mutate(\n { id: s.id, status: v as TheShipmentStatus },\n {\n onSuccess: () => notify.success('Shipment updated'),\n onError: (e) => notify.fromError(e),\n onSettled: () => setTransitioningId(null),\n }\n );\n }}\n >\n <SelectTrigger\n className=\"h-8 w-36\"\n aria-label={`Change status for shipment ${s.reference}`}\n >\n <SelectValue placeholder={formatEnumLabel(s.status)} />\n </SelectTrigger>\n <SelectContent>\n {nexts.map((st) => (\n <SelectItem key={st} value={st}>\n {formatEnumLabel(st)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n {canDeliver && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n disabled={deliverShipment.isPending || rowBusy}\n onClick={() =>\n deliverShipment.mutate(s.id, {\n onSuccess: () => notify.success('Shipment delivered'),\n onError: (e) => notify.fromError(e),\n })\n }\n >\n <PackageCheck className=\"mr-1.5 h-4 w-4\" /> Mark delivered\n </Button>\n )}\n </div>\n );\n },\n },\n ];\n\n const isFiltered = status !== 'ALL' || contractId !== 'ALL';\n\n return (\n <PageLayout\n title=\"Shipments\"\n description=\"Cargo movements delivering offtake contracts — pipelines, tankers, vessels, rail & grid.\"\n actions={\n <Button onClick={() => setDialogOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Schedule shipment\n </Button>\n }\n >\n {/* Header metrics — status mix within the current contract scope. */}\n <div className=\"mb-4 grid grid-cols-2 gap-4 lg:grid-cols-4\">\n <MetricsCard\n featured\n icon={<Ship className=\"h-5 w-5\" />}\n value={metricsRows.length}\n label=\"Total shipments\"\n />\n <MetricsCard\n icon={<CalendarClock className=\"h-5 w-5\" />}\n value={scheduledCount}\n label=\"Scheduled\"\n />\n <MetricsCard\n accent=\"warning\"\n icon={<Truck className=\"h-5 w-5\" />}\n value={inTransitCount}\n label=\"In transit\"\n />\n <MetricsCard\n accent=\"success\"\n icon={<PackageCheck className=\"h-5 w-5\" />}\n value={deliveredCount}\n label=\"Delivered\"\n />\n </div>\n\n {/* Logistics — status distribution + per-shipment route flow (broad, contract-scoped). */}\n <div className=\"mb-6 grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <div className=\"flex flex-col gap-4 rounded-[var(--radius-card)] border border-border-subtle bg-bg-surface p-5 shadow-elevation-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <h3 className=\"text-sm font-semibold text-text-secondary\">Status distribution</h3>\n <Ship className=\"h-4 w-4 shrink-0 text-text-muted\" aria-hidden=\"true\" />\n </div>\n {statusSegments.length > 0 ? (\n <AllocationBar\n segments={statusSegments}\n height={14}\n label=\"By status\"\n rightLabel={`${metricsRows.length} shipment${metricsRows.length === 1 ? '' : 's'}`}\n />\n ) : (\n <p className=\"py-6 text-sm text-text-tertiary\">\n No shipments yet — schedule one to see the status mix.\n </p>\n )}\n </div>\n\n <div className=\"flex flex-col gap-3 rounded-[var(--radius-card)] border border-border-subtle bg-bg-surface p-5 shadow-elevation-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <h3 className=\"text-sm font-semibold text-text-secondary\">Route flow</h3>\n <span className=\"inline-flex items-center gap-1.5 text-xs text-text-tertiary\">\n <MapPin className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n {distinctLanes} lane{distinctLanes === 1 ? '' : 's'}\n </span>\n </div>\n {tracedShipment ? (\n <>\n <Select value={tracedShipment.id} onValueChange={setTracedId}>\n <SelectTrigger aria-label=\"Trace a shipment route\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {routeableShipments.map((s) => (\n <SelectItem key={s.id} value={s.id}>\n {s.reference} · {(s.origin ?? '').trim()} → {(s.destination ?? '').trim()}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <PathSteps steps={routeSteps(tracedShipment)} />\n <div className=\"flex flex-wrap items-center gap-x-3 gap-y-1.5 text-xs text-text-tertiary\">\n <StatusBadge status={tracedShipment.status} />\n <span>{formatEnumLabel(tracedShipment.mode)}</span>\n <span className=\"tabular-nums text-text-secondary\">\n {formatVolume(tracedShipment.volume, tracedShipment.unit)}\n </span>\n {tracedShipment.scheduledAt ? (\n <span className=\"tabular-nums\">Sched {formatDate(tracedShipment.scheduledAt)}</span>\n ) : null}\n </div>\n </>\n ) : (\n <p className=\"py-6 text-sm text-text-tertiary\">\n Add an origin and destination to a shipment to trace its route.\n </p>\n )}\n </div>\n </div>\n\n <div className=\"mb-5 flex flex-wrap items-center gap-3\">\n <FilterTabs\n options={filterOptions}\n value={status}\n onChange={(v) => {\n setStatus(v);\n pager.reset();\n }}\n />\n <Select\n value={contractId}\n onValueChange={(v) => {\n setContractId(v as string | 'ALL');\n pager.reset();\n }}\n >\n <SelectTrigger className=\"w-56\" aria-label=\"Filter by contract\">\n <SelectValue placeholder=\"All contracts\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">All contracts</SelectItem>\n {contractItems.map((c) => (\n <SelectItem key={c.id} value={c.id}>\n {c.reference} · {c.counterparty}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {isLoading ? (\n <LoadingView label=\"Loading shipments…\" />\n ) : isError ? (\n <ErrorView message=\"Couldn't load shipments.\" onRetry={() => refetch()} />\n ) : rows.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Ship className=\"h-10 w-10\" />}\n title={isFiltered ? 'No matching shipments' : 'No shipments yet'}\n description={\n isFiltered\n ? 'No shipments match these filters. Try a different status or contract.'\n : 'Schedule your first shipment to start tracking cargo against your offtake contracts.'\n }\n action={\n <Button onClick={() => setDialogOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Schedule shipment\n </Button>\n }\n />\n ) : (\n <>\n <DataTable\n columns={columns}\n rows={rows}\n rowKey={(s) => s.id}\n defaultSort={{ key: 'scheduledAt', dir: 'desc' }}\n />\n <Pagination\n page={pager.page}\n pageSize={PAGE_SIZE}\n itemCount={rows.length}\n hasMore={data?.pageInfo?.hasMore ?? false}\n onPageChange={pager.onPageChange}\n />\n </>\n )}\n\n {/* Schedule shipment dialog */}\n <ResponsiveDialog\n open={dialogOpen}\n onOpenChange={(open) => {\n setDialogOpen(open);\n if (!open) resetForm();\n }}\n >\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Schedule shipment</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Book a cargo movement against an offtake contract and track it to delivery.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <form\n onSubmit={(e) => {\n e.preventDefault();\n void handleSchedule();\n }}\n >\n <div className=\"grid gap-4 py-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"shipContract\">Contract *</Label>\n <Select\n value={form.contractId}\n onValueChange={(v) => {\n // Default the unit to the contract's unit for a sensible start.\n const contract = contractMap.get(v);\n setForm((prev) => ({\n ...prev,\n contractId: v,\n unit: contract?.unit ?? prev.unit,\n }));\n }}\n >\n <SelectTrigger id=\"shipContract\">\n <SelectValue placeholder=\"Select a contract\" />\n </SelectTrigger>\n <SelectContent>\n {contractItems.length === 0 ? (\n <SelectItem value=\"none\" disabled>\n No contracts available\n </SelectItem>\n ) : (\n contractItems.map((c) => (\n <SelectItem key={c.id} value={c.id}>\n {c.reference} · {c.counterparty}\n </SelectItem>\n ))\n )}\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"shipRef\">Reference *</Label>\n <Input\n id=\"shipRef\"\n value={form.reference}\n onChange={(e) => setForm({ ...form, reference: e.target.value })}\n placeholder=\"SHP-2026-0142\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"shipMode\">Mode</Label>\n <Select\n value={form.mode}\n onValueChange={(v) => setForm({ ...form, mode: v as TheTransportMode })}\n >\n <SelectTrigger id=\"shipMode\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {TRANSPORT_MODES.map((m) => (\n <SelectItem key={m} value={m}>\n {formatEnumLabel(m)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"shipOrigin\">Origin</Label>\n <Input\n id=\"shipOrigin\"\n value={form.origin}\n onChange={(e) => setForm({ ...form, origin: e.target.value })}\n placeholder=\"Ras Tanura Terminal\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"shipDest\">Destination</Label>\n <Input\n id=\"shipDest\"\n value={form.destination}\n onChange={(e) => setForm({ ...form, destination: e.target.value })}\n placeholder=\"Rotterdam\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-3\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"shipVolume\">Volume *</Label>\n <Input\n id=\"shipVolume\"\n type=\"number\"\n min=\"0\"\n step=\"any\"\n value={form.volume}\n onChange={(e) => setForm({ ...form, volume: e.target.value })}\n placeholder=\"500000\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"shipUnit\">Unit</Label>\n <Select\n value={form.unit}\n onValueChange={(v) => setForm({ ...form, unit: v as TheUnit })}\n >\n <SelectTrigger id=\"shipUnit\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {UNITS.map((u) => (\n <SelectItem key={u} value={u}>\n {formatEnumLabel(u)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"shipScheduled\">Scheduled date</Label>\n <Input\n id=\"shipScheduled\"\n type=\"date\"\n value={form.scheduledAt}\n onChange={(e) => setForm({ ...form, scheduledAt: e.target.value })}\n />\n </div>\n </div>\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"shipCarrier\">Carrier</Label>\n <Input\n id=\"shipCarrier\"\n value={form.carrier}\n onChange={(e) => setForm({ ...form, carrier: e.target.value })}\n placeholder=\"Frontline Ltd.\"\n />\n </div>\n\n <EvidenceUpload\n id=\"shipDocument\"\n label=\"Bill of lading (optional)\"\n value={doc}\n onChange={setDoc}\n hint=\"Attach the bill of lading or shipping document (PDF or image).\"\n />\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"shipNotes\">Notes</Label>\n <Textarea\n id=\"shipNotes\"\n value={form.notes}\n onChange={(e) => setForm({ ...form, notes: e.target.value })}\n placeholder=\"Optional context — laycan window, inspector, terms.\"\n rows={2}\n />\n </div>\n\n {formError && <p className=\"text-sm text-status-error-text\">{formError}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => {\n setDialogOpen(false);\n resetForm();\n }}\n >\n Cancel\n </Button>\n <Button type=\"submit\" disabled={scheduleShipment.isPending}>\n {scheduleShipment.isPending ? 'Scheduling…' : 'Schedule shipment'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAiEA,IAAM,KAA6E;CACjF;EAAE,OAAO;EAAO,OAAO;EAAO;CAC9B;EAAE,OAAO;EAAa,OAAO;EAAa;CAC1C;EAAE,OAAO;EAAW,OAAO;EAAW;CACtC;EAAE,OAAO;EAAc,OAAO;EAAc;CAC5C;EAAE,OAAO;EAAa,OAAO;EAAa;CAC1C;EAAE,OAAO;EAAa,OAAO;EAAa;CAC3C,EAEK,KAAsC;CAC1C;CACA;CACA;CACA;CACA;CACA;CACD,EAEK,KAAmB;CAAC;CAAW;CAAgB;CAAU;CAAa;CAAO;CAAM;CAAM,EAEzF,IAAY,IAGZ,KAAoC;CACxC;CACA;CACA;CACA;CACA;CACD,EAEK,KAAkD;CACtD,WAAW;CACX,SAAS;CACT,YAAY;CACZ,WAAW;CACX,WAAW;CACZ,EAOK,KAA0D;CAC9D,WAAW;CACX,SAAS;CACT,YAAY;CACZ,WAAW;CACX,WAAW;CACZ,EAOK,MAAc,MAA+B;CACjD,IAAM,IAAY,EAAE,WAAW,aACzB,IAAY,EAAE,WAAW,aACzB,IAAY,EAAE,WAAW,cACzB,IAAW,KAAa,GACxB,IAAU,IACZ,cACA,IACE,cACA,IACE,eACA,EAAgB,EAAE,OAAO;AACjC,QAAO;EACL;GACE,QAAQ,EAAE,UAAU,IAAI,MAAM;GAC9B,MAAM;GACN,OAAO,IAAY,SAAS,IAAW,SAAS;GACjD;EACD;GACE,OAAO,EAAgB,EAAE,KAAK;GAC9B,MAAM;GACN,OAAO,IAAY,WAAW,IAAY,SAAS,IAAY,WAAW;GAC3E;EACD;GACE,QAAQ,EAAE,eAAe,IAAI,MAAM;GACnC,MAAM;GACN,OAAO,IAAY,WAAW,IAAY,SAAS;GACpD;EACF;GAgBG,IAAgC;CACpC,YAAY;CACZ,WAAW;CACX,MAAM;CACN,SAAS;CACT,QAAQ;CACR,aAAa;CACb,QAAQ;CACR,MAAM;CACN,aAAa;CACb,OAAO;CACR;AAED,SAAgB,IAAgB;CAC9B,IAAM,CAAC,GAAQ,MAAa,EAAoC,MAAM,EAChE,CAAC,GAAY,MAAiB,EAAyB,MAAM,EAC7D,IAAQ,IAAgB,EACxB,CAAC,IAAY,KAAiB,EAAS,GAAM,EAC7C,CAAC,GAAM,KAAW,EAA4B,EAAW,EACzD,CAAC,GAAK,KAAU,EAAiC,KAAK,EACtD,CAAC,GAAW,KAAgB,EAAwB,KAAK,EAGzD,CAAC,IAAiB,KAAsB,EAAwB,KAAK,EAGrE,CAAC,GAAU,MAAe,EAAwB,KAAK,EAEvD,IAAS,IAAW,EAEpB,IAAmB,MAAe,QAAQ,KAAA,IAAY,GAItD,EAAE,SAAM,eAAW,aAAS,gBAAY,EAC5C,GACA,MAAW,QAAQ,KAAA,IAAY,GAC/B;EAAE,OAAO;EAAW,QAAQ,EAAM,OAAO;EAAW,CACrD,EAIK,IAAe,EAAgB,GAAkB,KAAA,GAAW,EAAE,OAAO,KAAK,CAAC,EAG3E,IAAiB,GAAgB,EAAE,YAAY,EAAE,OAAO,KAAK,EAAE,CAAC,EAChE,IAAgB,QACd,EAAe,MAAM,SAAS,EAAE,EACtC,CAAC,EAAe,KAAK,CACtB,EACK,IAAc,QAAc;EAChC,IAAM,oBAAM,IAAI,KAAiC;AACjD,OAAK,IAAM,KAAK,EAAe,GAAI,IAAI,EAAE,IAAI,EAAE;AAC/C,SAAO;IACN,CAAC,EAAc,CAAC,EAEb,IAAmB,IAAwB,EAC3C,IAAkB,IAAuB,EACzC,KAAqB,IAA0B,EAE/C,IAAO,QAAc,GAAM,SAAS,EAAE,EAAE,CAAC,EAAK,CAAC,EAC/C,IAAc,QAAc,EAAa,MAAM,SAAS,EAAE,EAAE,CAAC,EAAa,KAAK,CAAC,EAGhF,KAAiB,EAAY,QAAQ,MAAM,EAAE,WAAW,YAAY,CAAC,QACrE,KAAiB,EAAY,QAAQ,MAAM,EAAE,WAAW,aAAa,CAAC,QACtE,KAAiB,EAAY,QAAQ,MAAM,EAAE,WAAW,YAAY,CAAC,QAErE,IAAe,QAAc;EACjC,IAAM,IAAiC,EAAE;AACzC,OAAK,IAAM,KAAK,EAAa,GAAO,EAAE,WAAW,EAAO,EAAE,WAAW,KAAK;AAC1E,SAAO;IACN,CAAC,EAAY,CAAC,EAEX,KAA2D,GAAe,KAAK,OAAS;EAC5F,OAAO,EAAI;EACX,OAAO,EAAI;EACX,OAAO,EAAI,UAAU,QAAQ,EAAY,SAAU,EAAa,EAAI,UAAU;EAC/E,EAAE,EAIG,IAAiB,QAEnB,GAAa,QAAQ,OAAQ,EAAa,MAAO,KAAK,EAAE,CAAC,KAAK,OAAQ;EACpE,OAAO,GAAa;EACpB,OAAO,EAAa,MAAO;EAC3B,OAAO,GAAqB;EAC7B,EAAE,EACL,CAAC,EAAa,CACf,EAGK,IAAqB,QACnB,EAAY,QAAQ,OAAO,EAAE,UAAU,IAAI,MAAM,KAAK,EAAE,eAAe,IAAI,MAAM,CAAC,EACxF,CAAC,EAAY,CACd,EAGK,KAAgB,QAAc;EAClC,IAAM,oBAAQ,IAAI,KAAa;AAC/B,OAAK,IAAM,KAAK,EACd,GAAM,IAAI,IAAI,EAAE,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,eAAe,IAAI,MAAM,GAAG;AAE3E,SAAO,EAAM;IACZ,CAAC,EAAmB,CAAC,EAElB,IAAiB,QACf,EAAmB,MAAM,MAAM,EAAE,OAAO,EAAS,IAAI,EAAmB,MAAM,MACpF,CAAC,GAAoB,EAAS,CAC/B,EAEK,UAAkB;AAGtB,EAFA,EAAQ,EAAW,EACnB,EAAO,KAAK,EACZ,EAAa,KAAK;IAGd,KAAiB,YAAY;AACjC,MAAI,CAAC,EAAK,YAAY;AACpB,KAAa,6CAA6C;AAC1D;;AAEF,MAAI,CAAC,EAAK,UAAU,MAAM,EAAE;AAC1B,KAAa,oCAAoC;AACjD;;EAEF,IAAM,IAAS,OAAO,EAAK,OAAO;AAClC,MAAI,CAAC,EAAK,UAAU,OAAO,MAAM,EAAO,IAAI,KAAU,GAAG;AAEvD,GADA,EAAa,oCAAoC,EACjD,EAAO,MAAM,oCAAoC;AACjD;;AAEF,IAAa,KAAK;AAClB,MAAI;AAgBF,GAfA,MAAM,EAAiB,YAAY;IACjC,YAAY,EAAK;IACjB,WAAW,EAAK,UAAU,MAAM;IAChC,MAAM,EAAK;IACX,SAAS,EAAK,QAAQ,MAAM,IAAI;IAChC,QAAQ,EAAK,OAAO,MAAM,IAAI;IAC9B,aAAa,EAAK,YAAY,MAAM,IAAI;IACxC;IACA,MAAM,EAAK;IACX,aAAa,EAAc,EAAK,YAAY,IAAI;IAChD,gBAAgB,GAAK,UAAU;IAC/B,OAAO,EAAK,MAAM,MAAM,IAAI;IAC7B,CAAC,EACF,EAAO,QAAQ,qBAAqB,EACpC,EAAc,GAAM,EACpB,GAAW;WACJ,GAAK;AAEZ,GADA,EAAa,aAAe,QAAQ,EAAI,UAAU,+BAA+B,EACjF,EAAO,UAAU,EAAI;;IAInB,KAAiC;EACrC;GACE,KAAK;GACL,QAAQ;GACR,SAAS,MACP,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,KAAD;KAAG,WAAU;eAA4C,EAAE;KAAc,CAAA,EACzE,kBAAC,KAAD;KAAG,WAAU;eAAiD,EAAgB,EAAE,KAAK;KAAK,CAAA,CACtF;;GAET;EACD;GACE,KAAK;GACL,QAAQ;GACR,cAAc;GACd,SAAS,MAAM;IACb,IAAM,IAAW,EAAY,IAAI,EAAE,WAAW;AAC9C,WAAO,IACL,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,KAAD;MAAG,WAAU;gBAA0C,EAAS;MAAc,CAAA,EAC9E,kBAAC,KAAD;MAAG,WAAU;gBAAuC,EAAS;MAAiB,CAAA,CAC1E;SAEN,kBAAC,QAAD;KAAM,WAAU;eAAwC,EAAE,WAAW,MAAM,GAAG,EAAE;KAAQ,CAAA;;GAG7F;EACD;GACE,KAAK;GACL,QAAQ;GACR,cAAc;GACd,SAAS,MAAM,kBAAC,QAAD;IAAM,WAAU;cAAuB,EAAgB,EAAE,KAAK;IAAQ,CAAA;GACtF;EACD;GACE,KAAK;GACL,QAAQ;GACR,SAAS,MAAM,kBAAC,GAAD,EAAa,QAAQ,EAAE,QAAU,CAAA;GACjD;EACD;GACE,KAAK;GACL,QAAQ;GACR,cAAc;GACd,SAAS,MAAM;IACb,IAAM,IAAS,EAAE,QAAQ,MAAM,EACzB,IAAc,EAAE,aAAa,MAAM;AAEzC,WADI,CAAC,KAAU,CAAC,IAAoB,kBAAC,QAAD;KAAM,WAAU;eAAqB;KAAQ,CAAA,GAE/E,kBAAC,QAAD;KAAM,WAAU;eAAhB;MACE,kBAAC,QAAD;OAAM,WAAU;iBAAY,KAAU;OAAW,CAAA;MACjD,kBAAC,IAAD,EAAY,WAAU,2CAA4C,CAAA;MAClE,kBAAC,QAAD;OAAM,WAAU;iBAAY,KAAe;OAAW,CAAA;MACjD;;;GAGZ;EACD;GACE,KAAK;GACL,QAAQ;GACR,OAAO;GACP,YAAY,MAAM,EAAE;GACpB,SAAS,MACP,kBAAC,QAAD;IAAM,WAAU;cAAkC,EAAa,EAAE,QAAQ,EAAE,KAAK;IAAQ,CAAA;GAE3F;EACD;GACE,KAAK;GACL,QAAQ;GACR,OAAO;GACP,cAAc;GACd,YAAY,MAAM,EAAE,eAAe;GACnC,SAAS,MAAM,kBAAC,QAAD;IAAM,WAAU;cAAsB,EAAW,EAAE,YAAY;IAAQ,CAAA;GACvF;EACD;GACE,KAAK;GACL,QAAQ;GACR,cAAc;GACd,SAAS,MACP,EAAE,UAAU,KACV,kBAAC,IAAD,EAAU,QAAQ,EAAE,SAAS,IAAM,CAAA,GAEnC,kBAAC,QAAD;IAAM,WAAU;cAAqB;IAAQ,CAAA;GAElD;EACD;GACE,KAAK;GACL,QAAQ;GACR,OAAO;GACP,SAAS,MAAM;IAKb,IAAM,IAAQ,GAAa,IAAsB,EAAE,OAAO,EACpD,IAAa,GAA0B,SAAS,EAAE,OAAO,EACzD,IAAU,OAAoB,EAAE;AAItC,WAHI,EAAM,WAAW,KAAK,CAAC,IAClB,kBAAC,QAAD;KAAM,WAAU;eAAqB;KAAQ,CAAA,GAGpD,kBAAC,OAAD;KAAK,WAAU;eAAf,CACG,EAAM,SAAS,KACd,kBAAC,GAAD;MACE,OAAO,EAAE;MACT,UAAU;MACV,gBAAgB,MAAM;AAChB,aAAM,EAAE,WACZ,EAAmB,EAAE,GAAG,EACxB,GAAmB,OACjB;QAAE,IAAI,EAAE;QAAI,QAAQ;QAAwB,EAC5C;QACE,iBAAiB,EAAO,QAAQ,mBAAmB;QACnD,UAAU,MAAM,EAAO,UAAU,EAAE;QACnC,iBAAiB,EAAmB,KAAK;QAC1C,CACF;;gBAbL,CAgBE,kBAAC,GAAD;OACE,WAAU;OACV,cAAY,8BAA8B,EAAE;iBAE5C,kBAAC,GAAD,EAAa,aAAa,EAAgB,EAAE,OAAO,EAAI,CAAA;OACzC,CAAA,EAChB,kBAAC,GAAD,EAAA,UACG,EAAM,KAAK,MACV,kBAAC,GAAD;OAAqB,OAAO;iBACzB,EAAgB,EAAG;OACT,EAFI,EAEJ,CACb,EACY,CAAA,CACT;SAEV,KACC,kBAAC,GAAD;MACE,MAAK;MACL,SAAQ;MACR,UAAU,EAAgB,aAAa;MACvC,eACE,EAAgB,OAAO,EAAE,IAAI;OAC3B,iBAAiB,EAAO,QAAQ,qBAAqB;OACrD,UAAU,MAAM,EAAO,UAAU,EAAE;OACpC,CAAC;gBARN,CAWE,kBAAC,GAAD,EAAc,WAAU,kBAAmB,CAAA,EAAA,kBACpC;QAEP;;;GAGX;EACF,EAEK,IAAa,MAAW,SAAS,MAAe;AAEtD,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;EACZ,SACE,kBAAC,GAAD;GAAQ,eAAe,EAAc,GAAK;aAA1C,CACE,kBAAC,GAAD,EAAM,WAAU,kBAAmB,CAAA,EAAA,qBAC5B;;YANb;GAUE,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD;MACE,UAAA;MACA,MAAM,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA;MAClC,OAAO,EAAY;MACnB,OAAM;MACN,CAAA;KACF,kBAAC,GAAD;MACE,MAAM,kBAAC,IAAD,EAAe,WAAU,WAAY,CAAA;MAC3C,OAAO;MACP,OAAM;MACN,CAAA;KACF,kBAAC,GAAD;MACE,QAAO;MACP,MAAM,kBAAC,IAAD,EAAO,WAAU,WAAY,CAAA;MACnC,OAAO;MACP,OAAM;MACN,CAAA;KACF,kBAAC,GAAD;MACE,QAAO;MACP,MAAM,kBAAC,GAAD,EAAc,WAAU,WAAY,CAAA;MAC1C,OAAO;MACP,OAAM;MACN,CAAA;KACE;;GAGN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,MAAD;OAAI,WAAU;iBAA4C;OAAwB,CAAA,EAClF,kBAAC,GAAD;OAAM,WAAU;OAAmC,eAAY;OAAS,CAAA,CACpE;SACL,EAAe,SAAS,IACvB,kBAAC,IAAD;MACE,UAAU;MACV,QAAQ;MACR,OAAM;MACN,YAAY,GAAG,EAAY,OAAO,WAAW,EAAY,WAAW,IAAI,KAAK;MAC7E,CAAA,GAEF,kBAAC,KAAD;MAAG,WAAU;gBAAkC;MAE3C,CAAA,CAEF;QAEN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,MAAD;OAAI,WAAU;iBAA4C;OAAe,CAAA,EACzE,kBAAC,QAAD;OAAM,WAAU;iBAAhB;QACE,kBAAC,IAAD;SAAQ,WAAU;SAAc,eAAY;SAAS,CAAA;QACpD;QAAc;QAAM,OAAkB,IAAI,KAAK;QAC3C;SACH;SACL,IACC,kBAAA,IAAA,EAAA,UAAA;MACE,kBAAC,GAAD;OAAQ,OAAO,EAAe;OAAI,eAAe;iBAAjD,CACE,kBAAC,GAAD;QAAe,cAAW;kBACxB,kBAAC,GAAD,EAAe,CAAA;QACD,CAAA,EAChB,kBAAC,GAAD,EAAA,UACG,EAAmB,KAAK,MACvB,kBAAC,GAAD;QAAuB,OAAO,EAAE;kBAAhC;SACG,EAAE;SAAU;UAAK,EAAE,UAAU,IAAI,MAAM;SAAC;UAAK,EAAE,eAAe,IAAI,MAAM;SAC9D;UAFI,EAAE,GAEN,CACb,EACY,CAAA,CACT;;MACT,kBAAC,IAAD,EAAW,OAAO,GAAW,EAAe,EAAI,CAAA;MAChD,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,GAAD,EAAa,QAAQ,EAAe,QAAU,CAAA;QAC9C,kBAAC,QAAD,EAAA,UAAO,EAAgB,EAAe,KAAK,EAAQ,CAAA;QACnD,kBAAC,QAAD;SAAM,WAAU;mBACb,EAAa,EAAe,QAAQ,EAAe,KAAK;SACpD,CAAA;QACN,EAAe,cACd,kBAAC,QAAD;SAAM,WAAU;mBAAhB,CAA+B,UAAO,EAAW,EAAe,YAAY,CAAQ;aAClF;QACA;;MACL,EAAA,CAAA,GAEH,kBAAC,KAAD;MAAG,WAAU;gBAAkC;MAE3C,CAAA,CAEF;OACF;;GAEN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,IAAD;KACE,SAAS;KACT,OAAO;KACP,WAAW,MAAM;AAEf,MADA,GAAU,EAAE,EACZ,EAAM,OAAO;;KAEf,CAAA,EACF,kBAAC,GAAD;KACE,OAAO;KACP,gBAAgB,MAAM;AAEpB,MADA,GAAc,EAAoB,EAClC,EAAM,OAAO;;eAJjB,CAOE,kBAAC,GAAD;MAAe,WAAU;MAAO,cAAW;gBACzC,kBAAC,GAAD,EAAa,aAAY,iBAAkB,CAAA;MAC7B,CAAA,EAChB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;MAAY,OAAM;gBAAM;MAA0B,CAAA,EACjD,EAAc,KAAK,MAClB,kBAAC,GAAD;MAAuB,OAAO,EAAE;gBAAhC;OACG,EAAE;OAAU;OAAI,EAAE;OACR;QAFI,EAAE,GAEN,CACb,CACY,EAAA,CAAA,CACT;OACL;;GAEL,KACC,kBAAC,IAAD,EAAa,OAAM,sBAAuB,CAAA,GACxC,KACF,kBAAC,IAAD;IAAW,SAAQ;IAA2B,eAAe,IAAS;IAAI,CAAA,GACxE,EAAK,WAAW,IAClB,kBAAC,IAAD;IACE,cAAa;IACb,MAAM,kBAAC,GAAD,EAAM,WAAU,aAAc,CAAA;IACpC,OAAO,IAAa,0BAA0B;IAC9C,aACE,IACI,0EACA;IAEN,QACE,kBAAC,GAAD;KAAQ,eAAe,EAAc,GAAK;eAA1C,CACE,kBAAC,GAAD,EAAM,WAAU,kBAAmB,CAAA,EAAA,qBAC5B;;IAEX,CAAA,GAEF,kBAAA,IAAA,EAAA,UAAA,CACE,kBAAC,IAAD;IACW;IACH;IACN,SAAS,MAAM,EAAE;IACjB,aAAa;KAAE,KAAK;KAAe,KAAK;KAAQ;IAChD,CAAA,EACF,kBAAC,IAAD;IACE,MAAM,EAAM;IACZ,UAAU;IACV,WAAW,EAAK;IAChB,SAAS,GAAM,UAAU,WAAW;IACpC,cAAc,EAAM;IACpB,CAAA,CACD,EAAA,CAAA;GAIL,kBAAC,IAAD;IACE,MAAM;IACN,eAAe,MAAS;AAEtB,KADA,EAAc,EAAK,EACd,KAAM,GAAW;;cAGxB,kBAAC,IAAD,EAAA,UAAA,CACE,kBAAC,IAAD,EAAA,UAAA,CACE,kBAAC,IAAD,EAAA,UAAuB,qBAAyC,CAAA,EAChE,kBAAC,IAAD,EAAA,UAA6B,+EAEC,CAAA,CACP,EAAA,CAAA,EAEzB,kBAAC,QAAD;KACE,WAAW,MAAM;AAEV,MADL,EAAE,gBAAgB,EACb,IAAgB;;eAHzB,CAME,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACA,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD;SAAO,SAAQ;mBAAe;SAAkB,CAAA,EAChD,kBAAC,GAAD;SACE,OAAO,EAAK;SACZ,gBAAgB,MAAM;UAEpB,IAAM,IAAW,EAAY,IAAI,EAAE;AACnC,aAAS,OAAU;WACjB,GAAG;WACH,YAAY;WACZ,MAAM,GAAU,QAAQ,EAAK;WAC9B,EAAE;;mBATP,CAYE,kBAAC,GAAD;UAAe,IAAG;oBAChB,kBAAC,GAAD,EAAa,aAAY,qBAAsB,CAAA;UACjC,CAAA,EAChB,kBAAC,GAAD,EAAA,UACG,EAAc,WAAW,IACxB,kBAAC,GAAD;UAAY,OAAM;UAAO,UAAA;oBAAS;UAErB,CAAA,GAEb,EAAc,KAAK,MACjB,kBAAC,GAAD;UAAuB,OAAO,EAAE;oBAAhC;WACG,EAAE;WAAU;WAAI,EAAE;WACR;YAFI,EAAE,GAEN,CACb,EAEU,CAAA,CACT;WACL;;OAEN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UAAO,SAAQ;oBAAU;UAAmB,CAAA,EAC5C,kBAAC,GAAD;UACE,IAAG;UACH,OAAO,EAAK;UACZ,WAAW,MAAM,EAAQ;WAAE,GAAG;WAAM,WAAW,EAAE,OAAO;WAAO,CAAC;UAChE,aAAY;UACZ,CAAA,CACE;YACN,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UAAO,SAAQ;oBAAW;UAAY,CAAA,EACtC,kBAAC,GAAD;UACE,OAAO,EAAK;UACZ,gBAAgB,MAAM,EAAQ;WAAE,GAAG;WAAM,MAAM;WAAuB,CAAC;oBAFzE,CAIE,kBAAC,GAAD;WAAe,IAAG;qBAChB,kBAAC,GAAD,EAAe,CAAA;WACD,CAAA,EAChB,kBAAC,GAAD,EAAA,UACG,GAAgB,KAAK,MACpB,kBAAC,GAAD;WAAoB,OAAO;qBACxB,EAAgB,EAAE;WACR,EAFI,EAEJ,CACb,EACY,CAAA,CACT;YACL;WACF;;OAEN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UAAO,SAAQ;oBAAa;UAAc,CAAA,EAC1C,kBAAC,GAAD;UACE,IAAG;UACH,OAAO,EAAK;UACZ,WAAW,MAAM,EAAQ;WAAE,GAAG;WAAM,QAAQ,EAAE,OAAO;WAAO,CAAC;UAC7D,aAAY;UACZ,CAAA,CACE;YACN,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UAAO,SAAQ;oBAAW;UAAmB,CAAA,EAC7C,kBAAC,GAAD;UACE,IAAG;UACH,OAAO,EAAK;UACZ,WAAW,MAAM,EAAQ;WAAE,GAAG;WAAM,aAAa,EAAE,OAAO;WAAO,CAAC;UAClE,aAAY;UACZ,CAAA,CACE;WACF;;OAEN,kBAAC,OAAD;QAAK,WAAU;kBAAf;SACE,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,GAAD;WAAO,SAAQ;qBAAa;WAAgB,CAAA,EAC5C,kBAAC,GAAD;WACE,IAAG;WACH,MAAK;WACL,KAAI;WACJ,MAAK;WACL,OAAO,EAAK;WACZ,WAAW,MAAM,EAAQ;YAAE,GAAG;YAAM,QAAQ,EAAE,OAAO;YAAO,CAAC;WAC7D,aAAY;WACZ,CAAA,CACE;;SACN,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,GAAD;WAAO,SAAQ;qBAAW;WAAY,CAAA,EACtC,kBAAC,GAAD;WACE,OAAO,EAAK;WACZ,gBAAgB,MAAM,EAAQ;YAAE,GAAG;YAAM,MAAM;YAAc,CAAC;qBAFhE,CAIE,kBAAC,GAAD;YAAe,IAAG;sBAChB,kBAAC,GAAD,EAAe,CAAA;YACD,CAAA,EAChB,kBAAC,GAAD,EAAA,UACG,GAAM,KAAK,MACV,kBAAC,GAAD;YAAoB,OAAO;sBACxB,EAAgB,EAAE;YACR,EAFI,EAEJ,CACb,EACY,CAAA,CACT;aACL;;SACN,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,GAAD;WAAO,SAAQ;qBAAgB;WAAsB,CAAA,EACrD,kBAAC,GAAD;WACE,IAAG;WACH,MAAK;WACL,OAAO,EAAK;WACZ,WAAW,MAAM,EAAQ;YAAE,GAAG;YAAM,aAAa,EAAE,OAAO;YAAO,CAAC;WAClE,CAAA,CACE;;SACF;;OAEN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD;SAAO,SAAQ;mBAAc;SAAe,CAAA,EAC5C,kBAAC,GAAD;SACE,IAAG;SACH,OAAO,EAAK;SACZ,WAAW,MAAM,EAAQ;UAAE,GAAG;UAAM,SAAS,EAAE,OAAO;UAAO,CAAC;SAC9D,aAAY;SACZ,CAAA,CACE;;OAEN,kBAAC,IAAD;QACE,IAAG;QACH,OAAM;QACN,OAAO;QACP,UAAU;QACV,MAAK;QACL,CAAA;OAEF,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD;SAAO,SAAQ;mBAAY;SAAa,CAAA,EACxC,kBAAC,IAAD;SACE,IAAG;SACH,OAAO,EAAK;SACZ,WAAW,MAAM,EAAQ;UAAE,GAAG;UAAM,OAAO,EAAE,OAAO;UAAO,CAAC;SAC5D,aAAY;SACZ,MAAM;SACN,CAAA,CACE;;OAEL,KAAa,kBAAC,KAAD;QAAG,WAAU;kBAAkC;QAAc,CAAA;OACvE;SAEN,kBAAC,IAAD,EAAA,UAAA,CACE,kBAAC,GAAD;MACE,MAAK;MACL,SAAQ;MACR,eAAe;AAEb,OADA,EAAc,GAAM,EACpB,GAAW;;gBAEd;MAEQ,CAAA,EACT,kBAAC,GAAD;MAAQ,MAAK;MAAS,UAAU,EAAiB;gBAC9C,EAAiB,YAAY,gBAAgB;MACvC,CAAA,CACc,EAAA,CAAA,CAClB;OACiB,EAAA,CAAA;IACT,CAAA;GACR"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-theglobalfuel",
3
- "version": "2026.705.2",
3
+ "version": "2026.705.4",
4
4
  "description": "Burdenoff TheGlobalFuel Microfrontend — Energy, Mineral & Commodity Resource operating system",
5
5
  "type": "module",
6
6
  "files": [