@burdenoff/microfe-theglobalfuel 2026.704.1 → 2026.705.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 (133) hide show
  1. package/dist/node_modules/{.bun/clsx@2.1.1/node_modules/clsx → clsx}/dist/clsx.js +1 -1
  2. package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
  3. package/dist/node_modules/{.bun/tailwind-merge@3.5.0/node_modules/tailwind-merge → tailwind-merge}/dist/bundle-mjs.js +212 -170
  4. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
  5. package/dist/theglobalfuel/components/DataTable.js +37 -27
  6. package/dist/theglobalfuel/components/DataTable.js.map +1 -1
  7. package/dist/theglobalfuel/hooks/index.js +1 -0
  8. package/dist/theglobalfuel/hooks/useNotify.js +19 -0
  9. package/dist/theglobalfuel/hooks/useNotify.js.map +1 -0
  10. package/dist/theglobalfuel/hooks/useTheFiles.js +4 -1
  11. package/dist/theglobalfuel/hooks/useTheFiles.js.map +1 -1
  12. package/dist/theglobalfuel/hooks/useTheGlobalFuelApi.js +59 -31
  13. package/dist/theglobalfuel/hooks/useTheGlobalFuelApi.js.map +1 -1
  14. package/dist/theglobalfuel/pages/assets/AssetDetailPage.js +367 -321
  15. package/dist/theglobalfuel/pages/assets/AssetDetailPage.js.map +1 -1
  16. package/dist/theglobalfuel/pages/assets/AssetsPage.js +66 -54
  17. package/dist/theglobalfuel/pages/assets/AssetsPage.js.map +1 -1
  18. package/dist/theglobalfuel/pages/compliance/CompliancePage.js +346 -182
  19. package/dist/theglobalfuel/pages/compliance/CompliancePage.js.map +1 -1
  20. package/dist/theglobalfuel/pages/contracts/ContractDetailPage.js +418 -390
  21. package/dist/theglobalfuel/pages/contracts/ContractDetailPage.js.map +1 -1
  22. package/dist/theglobalfuel/pages/contracts/ContractsPage.js +238 -230
  23. package/dist/theglobalfuel/pages/contracts/ContractsPage.js.map +1 -1
  24. package/dist/theglobalfuel/pages/dashboard/DashboardPage.js +5 -3
  25. package/dist/theglobalfuel/pages/dashboard/DashboardPage.js.map +1 -1
  26. package/dist/theglobalfuel/pages/emissions/EmissionsPage.js +201 -177
  27. package/dist/theglobalfuel/pages/emissions/EmissionsPage.js.map +1 -1
  28. package/dist/theglobalfuel/pages/inventory/InventoryPage.js +271 -238
  29. package/dist/theglobalfuel/pages/inventory/InventoryPage.js.map +1 -1
  30. package/dist/theglobalfuel/pages/production/ProductionPage.js +185 -177
  31. package/dist/theglobalfuel/pages/production/ProductionPage.js.map +1 -1
  32. package/dist/theglobalfuel/pages/reserves/ReservesPage.js +160 -138
  33. package/dist/theglobalfuel/pages/reserves/ReservesPage.js.map +1 -1
  34. package/dist/theglobalfuel/pages/shipments/ShipmentsPage.js +250 -198
  35. package/dist/theglobalfuel/pages/shipments/ShipmentsPage.js.map +1 -1
  36. package/dist/theglobalfuel/utils/cn.js +2 -2
  37. package/dist/theglobalfuel/utils/formatters.js +6 -1
  38. package/dist/theglobalfuel/utils/formatters.js.map +1 -1
  39. package/dist/theglobalfuel/utils/transitions.js +70 -0
  40. package/dist/theglobalfuel/utils/transitions.js.map +1 -0
  41. package/package.json +1 -1
  42. package/dist/dev/main.d.ts +0 -2
  43. package/dist/dev/main.d.ts.map +0 -1
  44. package/dist/index.d.ts +0 -2
  45. package/dist/index.d.ts.map +0 -1
  46. package/dist/node_modules/.bun/clsx@2.1.1/node_modules/clsx/dist/clsx.js.map +0 -1
  47. package/dist/node_modules/.bun/tailwind-merge@3.5.0/node_modules/tailwind-merge/dist/bundle-mjs.js.map +0 -1
  48. package/dist/theglobalfuel/TheGlobalFuelRoot.d.ts +0 -5
  49. package/dist/theglobalfuel/TheGlobalFuelRoot.d.ts.map +0 -1
  50. package/dist/theglobalfuel/TheGlobalFuelRoutes.d.ts +0 -4
  51. package/dist/theglobalfuel/TheGlobalFuelRoutes.d.ts.map +0 -1
  52. package/dist/theglobalfuel/components/DataTable.d.ts +0 -28
  53. package/dist/theglobalfuel/components/DataTable.d.ts.map +0 -1
  54. package/dist/theglobalfuel/components/EmptyState.d.ts +0 -18
  55. package/dist/theglobalfuel/components/EmptyState.d.ts.map +0 -1
  56. package/dist/theglobalfuel/components/EvidenceUpload.d.ts +0 -14
  57. package/dist/theglobalfuel/components/EvidenceUpload.d.ts.map +0 -1
  58. package/dist/theglobalfuel/components/FileLink.d.ts +0 -15
  59. package/dist/theglobalfuel/components/FileLink.d.ts.map +0 -1
  60. package/dist/theglobalfuel/components/FilterTabs.d.ts +0 -18
  61. package/dist/theglobalfuel/components/FilterTabs.d.ts.map +0 -1
  62. package/dist/theglobalfuel/components/MetricsCard.d.ts +0 -23
  63. package/dist/theglobalfuel/components/MetricsCard.d.ts.map +0 -1
  64. package/dist/theglobalfuel/components/MiniBar.d.ts +0 -16
  65. package/dist/theglobalfuel/components/MiniBar.d.ts.map +0 -1
  66. package/dist/theglobalfuel/components/PageLayout.d.ts +0 -16
  67. package/dist/theglobalfuel/components/PageLayout.d.ts.map +0 -1
  68. package/dist/theglobalfuel/components/Pagination.d.ts +0 -22
  69. package/dist/theglobalfuel/components/Pagination.d.ts.map +0 -1
  70. package/dist/theglobalfuel/components/StateViews.d.ts +0 -24
  71. package/dist/theglobalfuel/components/StateViews.d.ts.map +0 -1
  72. package/dist/theglobalfuel/components/StatusBadge.d.ts +0 -9
  73. package/dist/theglobalfuel/components/StatusBadge.d.ts.map +0 -1
  74. package/dist/theglobalfuel/components/Tabs.d.ts +0 -17
  75. package/dist/theglobalfuel/components/Tabs.d.ts.map +0 -1
  76. package/dist/theglobalfuel/components/TheDiscussion.d.ts +0 -18
  77. package/dist/theglobalfuel/components/TheDiscussion.d.ts.map +0 -1
  78. package/dist/theglobalfuel/components/TheTags.d.ts +0 -17
  79. package/dist/theglobalfuel/components/TheTags.d.ts.map +0 -1
  80. package/dist/theglobalfuel/components/index.d.ts +0 -19
  81. package/dist/theglobalfuel/components/index.d.ts.map +0 -1
  82. package/dist/theglobalfuel/context/TheGlobalFuelContext.d.ts +0 -16
  83. package/dist/theglobalfuel/context/TheGlobalFuelContext.d.ts.map +0 -1
  84. package/dist/theglobalfuel/context/index.d.ts +0 -6
  85. package/dist/theglobalfuel/context/index.d.ts.map +0 -1
  86. package/dist/theglobalfuel/hooks/index.d.ts +0 -10
  87. package/dist/theglobalfuel/hooks/index.d.ts.map +0 -1
  88. package/dist/theglobalfuel/hooks/useCursorPager.d.ts +0 -33
  89. package/dist/theglobalfuel/hooks/useCursorPager.d.ts.map +0 -1
  90. package/dist/theglobalfuel/hooks/useTheComments.d.ts +0 -36
  91. package/dist/theglobalfuel/hooks/useTheComments.d.ts.map +0 -1
  92. package/dist/theglobalfuel/hooks/useTheFiles.d.ts +0 -47
  93. package/dist/theglobalfuel/hooks/useTheFiles.d.ts.map +0 -1
  94. package/dist/theglobalfuel/hooks/useTheGlobalFuelApi.d.ts +0 -75
  95. package/dist/theglobalfuel/hooks/useTheGlobalFuelApi.d.ts.map +0 -1
  96. package/dist/theglobalfuel/hooks/useTheTags.d.ts +0 -44
  97. package/dist/theglobalfuel/hooks/useTheTags.d.ts.map +0 -1
  98. package/dist/theglobalfuel/index.d.ts +0 -9
  99. package/dist/theglobalfuel/index.d.ts.map +0 -1
  100. package/dist/theglobalfuel/pages/assets/AssetDetailPage.d.ts +0 -13
  101. package/dist/theglobalfuel/pages/assets/AssetDetailPage.d.ts.map +0 -1
  102. package/dist/theglobalfuel/pages/assets/AssetsPage.d.ts +0 -10
  103. package/dist/theglobalfuel/pages/assets/AssetsPage.d.ts.map +0 -1
  104. package/dist/theglobalfuel/pages/compliance/CompliancePage.d.ts +0 -11
  105. package/dist/theglobalfuel/pages/compliance/CompliancePage.d.ts.map +0 -1
  106. package/dist/theglobalfuel/pages/contracts/ContractDetailPage.d.ts +0 -9
  107. package/dist/theglobalfuel/pages/contracts/ContractDetailPage.d.ts.map +0 -1
  108. package/dist/theglobalfuel/pages/contracts/ContractsPage.d.ts +0 -8
  109. package/dist/theglobalfuel/pages/contracts/ContractsPage.d.ts.map +0 -1
  110. package/dist/theglobalfuel/pages/dashboard/DashboardPage.d.ts +0 -13
  111. package/dist/theglobalfuel/pages/dashboard/DashboardPage.d.ts.map +0 -1
  112. package/dist/theglobalfuel/pages/emissions/EmissionsPage.d.ts +0 -12
  113. package/dist/theglobalfuel/pages/emissions/EmissionsPage.d.ts.map +0 -1
  114. package/dist/theglobalfuel/pages/inventory/InventoryPage.d.ts +0 -11
  115. package/dist/theglobalfuel/pages/inventory/InventoryPage.d.ts.map +0 -1
  116. package/dist/theglobalfuel/pages/production/ProductionPage.d.ts +0 -11
  117. package/dist/theglobalfuel/pages/production/ProductionPage.d.ts.map +0 -1
  118. package/dist/theglobalfuel/pages/reserves/ReservesPage.d.ts +0 -10
  119. package/dist/theglobalfuel/pages/reserves/ReservesPage.d.ts.map +0 -1
  120. package/dist/theglobalfuel/pages/shipments/ShipmentsPage.d.ts +0 -10
  121. package/dist/theglobalfuel/pages/shipments/ShipmentsPage.d.ts.map +0 -1
  122. package/dist/theglobalfuel/types/index.d.ts +0 -376
  123. package/dist/theglobalfuel/types/index.d.ts.map +0 -1
  124. package/dist/theglobalfuel/utils/cn.d.ts +0 -4
  125. package/dist/theglobalfuel/utils/cn.d.ts.map +0 -1
  126. package/dist/theglobalfuel/utils/formatters.d.ts +0 -36
  127. package/dist/theglobalfuel/utils/formatters.d.ts.map +0 -1
  128. package/dist/theglobalfuel/utils/i18n.d.ts +0 -6
  129. package/dist/theglobalfuel/utils/i18n.d.ts.map +0 -1
  130. package/dist/theglobalfuel/utils/index.d.ts +0 -9
  131. package/dist/theglobalfuel/utils/index.d.ts.map +0 -1
  132. package/dist/theglobalfuel/utils/navigation.d.ts +0 -14
  133. package/dist/theglobalfuel/utils/navigation.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ProductionPage.js","names":[],"sources":["../../../../src/theglobalfuel/pages/production/ProductionPage.tsx"],"sourcesContent":["/**\n * Production — every production record across all assets.\n * @module theglobalfuel/pages/production\n *\n * Reads `theListProductionRecords` (optionally filtered by asset); writes\n * `theRecordProduction`. Asset names are resolved from `theListAssets`. The KPI\n * strip summarises the volume + downtime captured on the current page. No mock\n * data — every number comes from the real `wspace-theglobalfuel-svc` contract.\n */\n\nimport { useMemo, useState, type ReactNode } from 'react';\nimport { Plus, BarChart3, Droplets, Clock, Gauge } 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 { DataTable, type Column } from '../../components/DataTable';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { EmptyState } from '../../components/EmptyState';\nimport { Pagination } from '../../components/Pagination';\nimport { useTheGlobalFuel } from '../../context';\nimport {\n useTheAssets,\n useTheProductionRecords,\n useTheRecordProduction,\n useCursorPager,\n} from '../../hooks';\nimport {\n formatDate,\n formatNumber,\n formatRelativeTime,\n formatVolume,\n formatEnumLabel,\n} from '../../utils/formatters';\nimport type { TheProductionRecord, TheUnit } from '../../types';\n\nconst UNITS: TheUnit[] = [\n 'BARRELS',\n 'CUBIC_METERS',\n 'TONNES',\n 'KILOGRAMS',\n 'MWH',\n 'GJ',\n 'MCF',\n];\n\nconst PAGE_SIZE = 25;\n\nconst today = (): string => new Date().toISOString().slice(0, 10);\n\ninterface RecordFormState {\n assetId: string;\n periodStart: string;\n periodEnd: string;\n volume: string;\n unit: TheUnit;\n grade: string;\n downtimeHours: string;\n notes: string;\n}\n\nconst emptyForm = (): RecordFormState => ({\n assetId: '',\n periodStart: today(),\n periodEnd: today(),\n volume: '',\n unit: 'BARRELS',\n grade: '',\n downtimeHours: '',\n notes: '',\n});\n\nexport function ProductionPage() {\n const { navigateTo } = useTheGlobalFuel();\n const [assetId, setAssetId] = useState<string>('ALL');\n const pager = useCursorPager();\n const [dialogOpen, setDialogOpen] = useState(false);\n const [form, setForm] = useState<RecordFormState>(emptyForm);\n const [formError, setFormError] = useState<string | null>(null);\n\n // Assets feed the filter Select, the create picker, and the id→name map.\n const assetsQuery = useTheAssets({ pagination: { limit: 100 } });\n const assetMap = useMemo<Record<string, string>>(() => {\n const map: Record<string, string> = {};\n for (const a of assetsQuery.data?.items ?? []) map[a.id] = a.name;\n return map;\n }, [assetsQuery.data]);\n\n const { data, isLoading, isError, refetch } = useTheProductionRecords({\n assetId: assetId === 'ALL' ? undefined : assetId,\n pagination: { limit: PAGE_SIZE, cursor: pager.cursor },\n });\n const recordProduction = useTheRecordProduction();\n\n const rows = useMemo(() => data?.items ?? [], [data]);\n\n // KPI summary — page-scoped totals (volume grouped by unit, downtime summed).\n const { volumeValue, volumeFooter, downtimeTotal } = useMemo(() => {\n const byUnit = new Map<TheUnit, number>();\n let downtime = 0;\n for (const r of rows) {\n byUnit.set(r.unit, (byUnit.get(r.unit) ?? 0) + r.volume);\n downtime += r.downtimeHours;\n }\n const units = [...byUnit.entries()];\n let value: string;\n let footer: ReactNode | undefined;\n if (units.length === 0) {\n value = '—';\n } else if (units.length === 1) {\n value = formatVolume(units[0][1], units[0][0]);\n } else {\n value = 'Mixed units';\n footer = (\n <p className=\"text-xs tabular-nums text-text-tertiary\">\n {units.map(([u, v]) => formatVolume(v, u)).join(' · ')}\n </p>\n );\n }\n return { volumeValue: value, volumeFooter: footer, downtimeTotal: downtime };\n }, [rows]);\n\n const columns: Column<TheProductionRecord>[] = [\n {\n key: 'asset',\n header: 'Asset',\n render: (r) => (\n <div className=\"min-w-0\">\n <p className=\"truncate font-semibold text-text-primary\">\n {assetMap[r.assetId] ?? `${r.assetId.slice(0, 8)}…`}\n </p>\n </div>\n ),\n },\n {\n key: 'period',\n header: 'Period',\n hideOnMobile: true,\n sortValue: (r) => new Date(r.periodStart).getTime(),\n render: (r) => (\n <span className=\"text-text-secondary\">\n {formatDate(r.periodStart)} – {formatDate(r.periodEnd)}\n </span>\n ),\n },\n {\n key: 'volume',\n header: 'Volume',\n align: 'right',\n sortValue: (r) => r.volume,\n render: (r) => (\n <span className=\"tabular-nums font-medium text-text-primary\">\n {formatVolume(r.volume, r.unit)}\n </span>\n ),\n },\n {\n key: 'grade',\n header: 'Grade',\n align: 'right',\n hideOnMobile: true,\n sortValue: (r) => r.grade ?? 0,\n render: (r) =>\n r.grade != null ? (\n <span className=\"tabular-nums text-text-secondary\">{formatNumber(r.grade)}</span>\n ) : (\n <span className=\"text-text-tertiary\">—</span>\n ),\n },\n {\n key: 'downtime',\n header: 'Downtime',\n align: 'right',\n hideOnMobile: true,\n sortValue: (r) => r.downtimeHours,\n render: (r) => (\n <span className=\"tabular-nums text-text-secondary\">{formatNumber(r.downtimeHours)}h</span>\n ),\n },\n {\n key: 'created',\n header: 'Logged',\n align: 'right',\n hideOnMobile: true,\n render: (r) => <span className=\"text-text-tertiary\">{formatRelativeTime(r.createdAt)}</span>,\n },\n ];\n\n const openDialog = () => {\n setForm(emptyForm());\n setFormError(null);\n setDialogOpen(true);\n };\n\n const handleRecord = async () => {\n if (!form.assetId) {\n setFormError('Select an asset.');\n return;\n }\n if (!form.periodStart || !form.periodEnd) {\n setFormError('Period start and end are required.');\n return;\n }\n if (new Date(form.periodEnd).getTime() < new Date(form.periodStart).getTime()) {\n setFormError('Period end must be on or after the period start.');\n return;\n }\n if (!form.volume) {\n setFormError('Volume is required.');\n return;\n }\n setFormError(null);\n try {\n await recordProduction.mutateAsync({\n assetId: form.assetId,\n periodStart: new Date(form.periodStart).toISOString(),\n periodEnd: new Date(form.periodEnd).toISOString(),\n volume: Number(form.volume),\n unit: form.unit,\n grade: form.grade ? Number(form.grade) : null,\n downtimeHours: form.downtimeHours ? Number(form.downtimeHours) : null,\n notes: form.notes.trim() || null,\n });\n setDialogOpen(false);\n setForm(emptyForm());\n } catch (err) {\n setFormError(err instanceof Error ? err.message : 'Failed to record production.');\n }\n };\n\n const assetOptions = assetsQuery.data?.items ?? [];\n\n return (\n <PageLayout\n title=\"Production\"\n description=\"Captured production volumes across every field, well, mine & plant — with downtime and grade.\"\n actions={\n <Button onClick={openDialog}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Record production\n </Button>\n }\n >\n {/* KPI strip — page-scoped totals */}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <MetricsCard\n icon={<Droplets className=\"h-5 w-5\" />}\n value={volumeValue}\n label=\"Volume on this page\"\n featured\n footer={volumeFooter}\n />\n <MetricsCard\n icon={<Clock className=\"h-5 w-5\" />}\n value={`${formatNumber(downtimeTotal)}h`}\n label=\"Downtime on this page\"\n accent={downtimeTotal > 0 ? 'warning' : undefined}\n />\n <MetricsCard\n icon={<BarChart3 className=\"h-5 w-5\" />}\n value={rows.length}\n label=\"Records on this page\"\n />\n </div>\n\n {/* Filter */}\n <div className=\"mt-6 mb-5 flex flex-wrap items-center gap-3\">\n <Select\n value={assetId}\n onValueChange={(v) => {\n setAssetId(v);\n pager.reset();\n }}\n >\n <SelectTrigger className=\"w-56\">\n <SelectValue placeholder=\"All assets\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">All assets</SelectItem>\n {assetOptions.map((a) => (\n <SelectItem key={a.id} value={a.id}>\n {a.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {isLoading ? (\n <LoadingView label=\"Loading production records…\" />\n ) : isError ? (\n <ErrorView message=\"Couldn't load production records.\" onRetry={() => refetch()} />\n ) : rows.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Gauge className=\"h-10 w-10\" />}\n title=\"No production recorded\"\n description={\n assetId === 'ALL'\n ? 'Record a production period to start tracking output, grade and downtime.'\n : 'No production has been recorded for this asset yet.'\n }\n action={\n <Button onClick={openDialog}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Record production\n </Button>\n }\n />\n ) : (\n <>\n <DataTable\n columns={columns}\n rows={rows}\n rowKey={(r) => r.id}\n onRowClick={(r) => navigateTo(`assets/${r.assetId}`)}\n defaultSort={{ key: 'period', 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={(target) => pager.onPageChange(target, data?.pageInfo?.cursor)}\n />\n </>\n )}\n\n {/* Record production dialog */}\n <ResponsiveDialog\n open={dialogOpen}\n onOpenChange={(open) => {\n setDialogOpen(open);\n if (!open) {\n setForm(emptyForm());\n setFormError(null);\n }\n }}\n >\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Record production</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Log the volume produced by an asset over a reporting period.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"grid gap-4 py-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"prAsset\">Asset *</Label>\n <Select\n value={form.assetId}\n onValueChange={(v) => setForm({ ...form, assetId: v })}\n >\n <SelectTrigger id=\"prAsset\">\n <SelectValue placeholder=\"Select an asset\" />\n </SelectTrigger>\n <SelectContent>\n {assetOptions.map((a) => (\n <SelectItem key={a.id} value={a.id}>\n {a.name}\n </SelectItem>\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=\"prStart\">Period start *</Label>\n <Input\n id=\"prStart\"\n type=\"date\"\n value={form.periodStart}\n onChange={(e) => setForm({ ...form, periodStart: e.target.value })}\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"prEnd\">Period end *</Label>\n <Input\n id=\"prEnd\"\n type=\"date\"\n value={form.periodEnd}\n onChange={(e) => setForm({ ...form, periodEnd: e.target.value })}\n />\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=\"prVolume\">Volume *</Label>\n <Input\n id=\"prVolume\"\n type=\"number\"\n min=\"0\"\n step=\"any\"\n value={form.volume}\n onChange={(e) => setForm({ ...form, volume: e.target.value })}\n placeholder=\"12500\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"prUnit\">Unit</Label>\n <Select\n value={form.unit}\n onValueChange={(v) => setForm({ ...form, unit: v as TheUnit })}\n >\n <SelectTrigger id=\"prUnit\">\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>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"prGrade\">Grade</Label>\n <Input\n id=\"prGrade\"\n type=\"number\"\n step=\"any\"\n value={form.grade}\n onChange={(e) => setForm({ ...form, grade: e.target.value })}\n placeholder=\"Quality / concentration\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"prDowntime\">Downtime (hours)</Label>\n <Input\n id=\"prDowntime\"\n type=\"number\"\n min=\"0\"\n step=\"any\"\n value={form.downtimeHours}\n onChange={(e) => setForm({ ...form, downtimeHours: e.target.value })}\n placeholder=\"0\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"prNotes\">Notes</Label>\n <Textarea\n id=\"prNotes\"\n rows={2}\n value={form.notes}\n onChange={(e) => setForm({ ...form, notes: e.target.value })}\n placeholder=\"Optional context about this period.\"\n />\n </div>\n\n {formError && <p className=\"text-sm text-status-error-text\">{formError}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => setDialogOpen(false)}>\n Cancel\n </Button>\n <Button onClick={handleRecord} disabled={recordProduction.isPending}>\n {recordProduction.isPending ? 'Recording…' : 'Record production'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ProductionPage.js","names":[],"sources":["../../../../src/theglobalfuel/pages/production/ProductionPage.tsx"],"sourcesContent":["/**\n * Production — every production record across all assets.\n * @module theglobalfuel/pages/production\n *\n * Reads `theListProductionRecords` (optionally filtered by asset); writes\n * `theRecordProduction`. Asset names are resolved from `theListAssets`. The KPI\n * strip summarises the volume + downtime captured on the current page. No mock\n * data — every number comes from the real `wspace-theglobalfuel-svc` contract.\n */\n\nimport { useMemo, useState, type ReactNode } from 'react';\nimport { Plus, BarChart3, Droplets, Clock, Gauge } 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 { DataTable, type Column } from '../../components/DataTable';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { EmptyState } from '../../components/EmptyState';\nimport { Pagination } from '../../components/Pagination';\nimport { useTheGlobalFuel } from '../../context';\nimport {\n useTheAssets,\n useTheProductionRecords,\n useTheRecordProduction,\n useCursorPager,\n useNotify,\n} from '../../hooks';\nimport {\n formatDate,\n formatNumber,\n formatRelativeTime,\n formatVolume,\n formatEnumLabel,\n} from '../../utils/formatters';\nimport { toBackendDate } from '../../utils';\nimport type { TheProductionRecord, TheUnit } from '../../types';\n\nconst UNITS: TheUnit[] = [\n 'BARRELS',\n 'CUBIC_METERS',\n 'TONNES',\n 'KILOGRAMS',\n 'MWH',\n 'GJ',\n 'MCF',\n];\n\nconst PAGE_SIZE = 25;\n\nconst today = (): string => new Date().toISOString().slice(0, 10);\n\ninterface RecordFormState {\n assetId: string;\n periodStart: string;\n periodEnd: string;\n volume: string;\n unit: TheUnit;\n grade: string;\n downtimeHours: string;\n notes: string;\n}\n\nconst emptyForm = (): RecordFormState => ({\n assetId: '',\n periodStart: today(),\n periodEnd: today(),\n volume: '',\n unit: 'BARRELS',\n grade: '',\n downtimeHours: '',\n notes: '',\n});\n\nexport function ProductionPage() {\n const { navigateTo } = useTheGlobalFuel();\n const notify = useNotify();\n const [assetId, setAssetId] = useState<string>('ALL');\n const pager = useCursorPager();\n const [dialogOpen, setDialogOpen] = useState(false);\n const [form, setForm] = useState<RecordFormState>(emptyForm);\n const [formError, setFormError] = useState<string | null>(null);\n\n // Assets feed the filter Select, the create picker, and the id→name map.\n const assetsQuery = useTheAssets({ pagination: { limit: 100 } });\n const assetMap = useMemo<Record<string, string>>(() => {\n const map: Record<string, string> = {};\n for (const a of assetsQuery.data?.items ?? []) map[a.id] = a.name;\n return map;\n }, [assetsQuery.data]);\n\n const { data, isLoading, isError, refetch } = useTheProductionRecords({\n assetId: assetId === 'ALL' ? undefined : assetId,\n pagination: { limit: PAGE_SIZE, cursor: pager.cursor },\n });\n const recordProduction = useTheRecordProduction();\n\n const rows = useMemo(() => data?.items ?? [], [data]);\n\n // KPI summary — page-scoped totals (volume grouped by unit, downtime summed).\n const { volumeValue, volumeFooter, downtimeTotal } = useMemo(() => {\n const byUnit = new Map<TheUnit, number>();\n let downtime = 0;\n for (const r of rows) {\n byUnit.set(r.unit, (byUnit.get(r.unit) ?? 0) + r.volume);\n downtime += r.downtimeHours;\n }\n const units = [...byUnit.entries()];\n let value: string;\n let footer: ReactNode | undefined;\n if (units.length === 0) {\n value = '—';\n } else if (units.length === 1) {\n value = formatVolume(units[0][1], units[0][0]);\n } else {\n value = 'Mixed units';\n footer = (\n <p className=\"text-xs tabular-nums text-text-tertiary\">\n {units.map(([u, v]) => formatVolume(v, u)).join(' · ')}\n </p>\n );\n }\n return { volumeValue: value, volumeFooter: footer, downtimeTotal: downtime };\n }, [rows]);\n\n const columns: Column<TheProductionRecord>[] = [\n {\n key: 'asset',\n header: 'Asset',\n render: (r) => (\n <div className=\"min-w-0\">\n <p className=\"truncate font-semibold text-text-primary\">\n {assetMap[r.assetId] ?? `${r.assetId.slice(0, 8)}…`}\n </p>\n </div>\n ),\n },\n {\n key: 'period',\n header: 'Period',\n hideOnMobile: true,\n sortValue: (r) => new Date(r.periodStart).getTime(),\n render: (r) => (\n <span className=\"text-text-secondary\">\n {formatDate(r.periodStart)} – {formatDate(r.periodEnd)}\n </span>\n ),\n },\n {\n key: 'volume',\n header: 'Volume',\n align: 'right',\n sortValue: (r) => r.volume,\n render: (r) => (\n <span className=\"tabular-nums font-medium text-text-primary\">\n {formatVolume(r.volume, r.unit)}\n </span>\n ),\n },\n {\n key: 'grade',\n header: 'Grade',\n align: 'right',\n hideOnMobile: true,\n sortValue: (r) => r.grade ?? 0,\n render: (r) =>\n r.grade != null ? (\n <span className=\"tabular-nums text-text-secondary\">{formatNumber(r.grade)}</span>\n ) : (\n <span className=\"text-text-tertiary\">—</span>\n ),\n },\n {\n key: 'downtime',\n header: 'Downtime',\n align: 'right',\n hideOnMobile: true,\n sortValue: (r) => r.downtimeHours,\n render: (r) => (\n <span className=\"tabular-nums text-text-secondary\">{formatNumber(r.downtimeHours)}h</span>\n ),\n },\n {\n key: 'created',\n header: 'Logged',\n align: 'right',\n hideOnMobile: true,\n render: (r) => <span className=\"text-text-tertiary\">{formatRelativeTime(r.createdAt)}</span>,\n },\n ];\n\n const openDialog = () => {\n setForm(emptyForm());\n setFormError(null);\n setDialogOpen(true);\n };\n\n const closeDialog = () => {\n setDialogOpen(false);\n setForm(emptyForm());\n setFormError(null);\n };\n\n const handleRecord = async () => {\n if (!form.assetId) {\n setFormError('Select an asset.');\n return;\n }\n // Anchor date-only inputs at noon UTC so the calendar day survives every TZ.\n const periodStart = toBackendDate(form.periodStart);\n const periodEnd = toBackendDate(form.periodEnd);\n if (!periodStart || !periodEnd) {\n setFormError('Period start and end are required.');\n return;\n }\n if (new Date(periodEnd).getTime() < new Date(periodStart).getTime()) {\n setFormError('Period end must be on or after the period start.');\n return;\n }\n const volume = Number(form.volume);\n if (!form.volume || Number.isNaN(volume) || volume <= 0) {\n const message = 'Volume must be greater than zero.';\n setFormError(message);\n notify.error(message);\n return;\n }\n setFormError(null);\n try {\n await recordProduction.mutateAsync({\n assetId: form.assetId,\n periodStart,\n periodEnd,\n volume,\n unit: form.unit,\n grade: form.grade ? Number(form.grade) : null,\n downtimeHours: form.downtimeHours ? Number(form.downtimeHours) : null,\n notes: form.notes.trim() || null,\n });\n notify.success('Production recorded');\n closeDialog();\n } catch (err) {\n setFormError(err instanceof Error ? err.message : 'Failed to record production.');\n notify.fromError(err);\n }\n };\n\n const assetOptions = assetsQuery.data?.items ?? [];\n\n return (\n <PageLayout\n title=\"Production\"\n description=\"Captured production volumes across every field, well, mine & plant — with downtime and grade.\"\n actions={\n <Button onClick={openDialog}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Record production\n </Button>\n }\n >\n {/* KPI strip — page-scoped totals */}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <MetricsCard\n icon={<Droplets className=\"h-5 w-5\" />}\n value={volumeValue}\n label=\"Volume on this page\"\n featured\n footer={volumeFooter}\n />\n <MetricsCard\n icon={<Clock className=\"h-5 w-5\" />}\n value={`${formatNumber(downtimeTotal)}h`}\n label=\"Downtime on this page\"\n accent={downtimeTotal > 0 ? 'warning' : undefined}\n />\n <MetricsCard\n icon={<BarChart3 className=\"h-5 w-5\" />}\n value={rows.length}\n label=\"Records on this page\"\n />\n </div>\n\n {/* Filter */}\n <div className=\"mt-6 mb-5 flex flex-wrap items-center gap-3\">\n <Select\n value={assetId}\n onValueChange={(v) => {\n setAssetId(v);\n pager.reset();\n }}\n >\n <SelectTrigger className=\"w-56\" aria-label=\"Filter by asset\">\n <SelectValue placeholder=\"All assets\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">All assets</SelectItem>\n {assetOptions.map((a) => (\n <SelectItem key={a.id} value={a.id}>\n {a.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {isLoading ? (\n <LoadingView label=\"Loading production records…\" />\n ) : isError ? (\n <ErrorView message=\"Couldn't load production records.\" onRetry={() => refetch()} />\n ) : rows.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Gauge className=\"h-10 w-10\" />}\n title=\"No production recorded\"\n description={\n assetId === 'ALL'\n ? 'Record a production period to start tracking output, grade and downtime.'\n : 'No production has been recorded for this asset yet.'\n }\n action={\n <Button onClick={openDialog}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Record production\n </Button>\n }\n />\n ) : (\n <>\n <DataTable\n columns={columns}\n rows={rows}\n rowKey={(r) => r.id}\n onRowClick={(r) => navigateTo(`assets/${r.assetId}`)}\n rowLabel={(r) => `Open ${assetMap[r.assetId] ?? 'asset'}`}\n defaultSort={{ key: 'period', 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={(target) => pager.onPageChange(target, data?.pageInfo?.cursor)}\n />\n </>\n )}\n\n {/* Record production dialog */}\n <ResponsiveDialog\n open={dialogOpen}\n onOpenChange={(open) => (open ? setDialogOpen(true) : closeDialog())}\n >\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Record production</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Log the volume produced by an asset over a reporting period.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <form\n onSubmit={(e) => {\n e.preventDefault();\n void handleRecord();\n }}\n >\n <div className=\"grid gap-4 py-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"prAsset\">Asset *</Label>\n <Select\n value={form.assetId}\n onValueChange={(v) => setForm({ ...form, assetId: v })}\n >\n <SelectTrigger id=\"prAsset\">\n <SelectValue placeholder=\"Select an asset\" />\n </SelectTrigger>\n <SelectContent>\n {assetOptions.map((a) => (\n <SelectItem key={a.id} value={a.id}>\n {a.name}\n </SelectItem>\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=\"prStart\">Period start *</Label>\n <Input\n id=\"prStart\"\n type=\"date\"\n value={form.periodStart}\n onChange={(e) => setForm({ ...form, periodStart: e.target.value })}\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"prEnd\">Period end *</Label>\n <Input\n id=\"prEnd\"\n type=\"date\"\n value={form.periodEnd}\n onChange={(e) => setForm({ ...form, periodEnd: e.target.value })}\n />\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=\"prVolume\">Volume *</Label>\n <Input\n id=\"prVolume\"\n type=\"number\"\n min=\"0\"\n step=\"any\"\n value={form.volume}\n onChange={(e) => setForm({ ...form, volume: e.target.value })}\n placeholder=\"12500\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"prUnit\">Unit</Label>\n <Select\n value={form.unit}\n onValueChange={(v) => setForm({ ...form, unit: v as TheUnit })}\n >\n <SelectTrigger id=\"prUnit\">\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>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"prGrade\">Grade</Label>\n <Input\n id=\"prGrade\"\n type=\"number\"\n step=\"any\"\n value={form.grade}\n onChange={(e) => setForm({ ...form, grade: e.target.value })}\n placeholder=\"Quality / concentration\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"prDowntime\">Downtime (hours)</Label>\n <Input\n id=\"prDowntime\"\n type=\"number\"\n min=\"0\"\n step=\"any\"\n value={form.downtimeHours}\n onChange={(e) => setForm({ ...form, downtimeHours: e.target.value })}\n placeholder=\"0\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"prNotes\">Notes</Label>\n <Textarea\n id=\"prNotes\"\n rows={2}\n value={form.notes}\n onChange={(e) => setForm({ ...form, notes: e.target.value })}\n placeholder=\"Optional context about this period.\"\n />\n </div>\n\n {formError && <p className=\"text-sm text-status-error-text\">{formError}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={closeDialog}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={recordProduction.isPending}>\n {recordProduction.isPending ? 'Recording…' : 'Record production'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -1,19 +1,22 @@
1
1
  import { PageLayout as e } from "../../components/PageLayout.js";
2
2
  import { MetricsCard as t } from "../../components/MetricsCard.js";
3
- import { formatDate as n, formatEnumLabel as r, formatPercent as i, formatUnit as a, formatVolume as o } from "../../utils/formatters.js";
4
- import { StatusBadge as ee } from "../../components/StatusBadge.js";
5
- import { DataTable as te } from "../../components/DataTable.js";
6
- import { ErrorView as ne, LoadingView as re } from "../../components/StateViews.js";
7
- import { EmptyState as s } from "../../components/EmptyState.js";
8
- import { useTheAssets as c, useTheCreateReserveEstimate as l, useTheReserveEstimates as u } from "../../hooks/useTheGlobalFuelApi.js";
3
+ import { formatDate as n, formatEnumLabel as r, formatPercent as i, formatUnit as a, formatVolume as o, toBackendDate as ee } from "../../utils/formatters.js";
4
+ import { StatusBadge as te } from "../../components/StatusBadge.js";
5
+ import { DataTable as ne } from "../../components/DataTable.js";
6
+ import { ErrorView as re, LoadingView as s } from "../../components/StateViews.js";
7
+ import { EmptyState as ie } from "../../components/EmptyState.js";
8
+ import { useTheAssets as ae, useTheCreateReserveEstimate as oe, useTheReserveEstimates as c } from "../../hooks/useTheGlobalFuelApi.js";
9
+ import { useCursorPager as se } from "../../hooks/useCursorPager.js";
10
+ import { useNotify as l } from "../../hooks/useNotify.js";
9
11
  import "../../hooks/index.js";
10
- import { FilterTabs as ie } from "../../components/FilterTabs.js";
11
- import { useMemo as d, useState as f } from "react";
12
- import { Database as p, Layers as m, Percent as h, Plus as g } from "lucide-react";
13
- import { jsx as _, jsxs as v } from "react/jsx-runtime";
14
- import { Button as y, Input as b, Label as x, ResponsiveDialog as ae, ResponsiveDialogContent as oe, ResponsiveDialogDescription as S, ResponsiveDialogFooter as C, ResponsiveDialogHeader as w, ResponsiveDialogTitle as T, Select as E, SelectContent as D, SelectItem as O, SelectTrigger as k, SelectValue as A, Textarea as se } from "@burdenoff/fe-libs/ui";
12
+ import { FilterTabs as u } from "../../components/FilterTabs.js";
13
+ import { Pagination as d } from "../../components/Pagination.js";
14
+ import { useMemo as f, useState as p } from "react";
15
+ import { Database as ce, Layers as m, Percent as le, Plus as h } from "lucide-react";
16
+ import { Fragment as g, jsx as _, jsxs as v } from "react/jsx-runtime";
17
+ import { Button as y, Input as b, Label as x, ResponsiveDialog as ue, ResponsiveDialogContent as de, ResponsiveDialogDescription as fe, ResponsiveDialogFooter as pe, ResponsiveDialogHeader as me, ResponsiveDialogTitle as he, Select as S, SelectContent as C, SelectItem as w, SelectTrigger as T, SelectValue as E, Textarea as ge } from "@burdenoff/fe-libs/ui";
15
18
  //#region src/theglobalfuel/pages/reserves/ReservesPage.tsx
16
- var j = [
19
+ var _e = [
17
20
  {
18
21
  value: "ALL",
19
22
  label: "All"
@@ -38,13 +41,13 @@ var j = [
38
41
  value: "PROSPECTIVE",
39
42
  label: "Prospective"
40
43
  }
41
- ], M = [
44
+ ], ve = [
42
45
  "PROVED",
43
46
  "PROBABLE",
44
47
  "POSSIBLE",
45
48
  "CONTINGENT",
46
49
  "PROSPECTIVE"
47
- ], N = [
50
+ ], ye = [
48
51
  "BARRELS",
49
52
  "CUBIC_METERS",
50
53
  "TONNES",
@@ -52,7 +55,7 @@ var j = [
52
55
  "MWH",
53
56
  "GJ",
54
57
  "MCF"
55
- ], P = () => (/* @__PURE__ */ new Date()).toISOString().slice(0, 10), F = {
58
+ ], D = 25, O = () => (/* @__PURE__ */ new Date()).toISOString().slice(0, 10), k = {
56
59
  assetId: "",
57
60
  category: "PROVED",
58
61
  asOfDate: "",
@@ -62,30 +65,33 @@ var j = [
62
65
  methodology: "",
63
66
  notes: ""
64
67
  };
65
- function I() {
66
- let [I, L] = f("ALL"), [R, z] = f("ALL"), [B, V] = f(!1), [H, U] = f(F), [W, G] = f(null), K = c({ pagination: {
68
+ function A() {
69
+ let A = l(), [j, M] = p("ALL"), [N, P] = p("ALL"), F = se(), [be, I] = p(!1), [L, R] = p(k), [z, B] = p(null), V = ae({ pagination: {
67
70
  limit: 100,
68
71
  offset: 0
69
- } }), q = d(() => {
72
+ } }), H = f(() => {
70
73
  let e = {};
71
- for (let t of K.data?.items ?? []) e[t.id] = t.name;
74
+ for (let t of V.data?.items ?? []) e[t.id] = t.name;
72
75
  return e;
73
- }, [K.data]), { data: J, isLoading: ce, isError: le, refetch: ue } = u(R === "ALL" ? void 0 : R, I === "ALL" ? void 0 : I), Y = l(), X = d(() => J ?? [], [J]), Z = d(() => {
76
+ }, [V.data]), U = N === "ALL" ? void 0 : N, W = j === "ALL" ? void 0 : j, { data: G, isLoading: xe, isError: Se, refetch: Ce } = c(U, W, {
77
+ limit: D,
78
+ cursor: F.cursor
79
+ }), K = c(U, W, { limit: 200 }), q = oe(), J = f(() => G?.items ?? [], [G]), Y = f(() => K.data?.items ?? [], [K.data]), X = f(() => {
74
80
  let e = {};
75
- for (let t of X) e[t.unit] = (e[t.unit] ?? 0) + 1;
76
- let t = Object.entries(e).sort((e, t) => t[1] - e[1])[0]?.[0], n = t ? X.filter((e) => e.unit === t).reduce((e, t) => e + t.recoverable, 0) : 0, r = X.filter((e) => e.recoveryFactor != null);
81
+ for (let t of Y) e[t.unit] = (e[t.unit] ?? 0) + 1;
82
+ let t = Object.entries(e).sort((e, t) => t[1] - e[1])[0]?.[0], n = t ? Y.filter((e) => e.unit === t).reduce((e, t) => e + t.recoverable, 0) : 0, r = Y.filter((e) => e.recoveryFactor != null);
77
83
  return {
78
84
  dominantUnit: t,
79
85
  totalRecoverable: n,
80
86
  avgFactor: r.length ? r.reduce((e, t) => e + (t.recoveryFactor ?? 0), 0) / r.length * 100 : null
81
87
  };
82
- }, [X]), de = [
88
+ }, [Y]), we = [
83
89
  {
84
90
  key: "asset",
85
91
  header: "Asset",
86
92
  render: (e) => /* @__PURE__ */ _("span", {
87
93
  className: "font-semibold text-text-primary",
88
- children: q[e.assetId] ?? /* @__PURE__ */ _("span", {
94
+ children: H[e.assetId] ?? /* @__PURE__ */ _("span", {
89
95
  className: "text-text-tertiary",
90
96
  children: "Unknown asset"
91
97
  })
@@ -94,7 +100,7 @@ function I() {
94
100
  {
95
101
  key: "category",
96
102
  header: "Category",
97
- render: (e) => /* @__PURE__ */ _(ee, { status: e.category })
103
+ render: (e) => /* @__PURE__ */ _(te, { status: e.category })
98
104
  },
99
105
  {
100
106
  key: "asOfDate",
@@ -142,125 +148,141 @@ function I() {
142
148
  children: "—"
143
149
  })
144
150
  }
145
- ], Q = () => {
146
- U({
147
- ...F,
148
- asOfDate: P()
149
- }), G(null), V(!0);
150
- }, fe = async () => {
151
- if (!H.assetId) {
152
- G("Select the asset this estimate belongs to.");
151
+ ], Z = () => {
152
+ R({
153
+ ...k,
154
+ asOfDate: O()
155
+ }), B(null), I(!0);
156
+ }, Q = () => {
157
+ I(!1), R(k), B(null);
158
+ }, Te = async () => {
159
+ if (!L.assetId) {
160
+ B("Select the asset this estimate belongs to.");
153
161
  return;
154
162
  }
155
- if (!H.asOfDate) {
156
- G("An \"as of\" date is required.");
163
+ let e = ee(L.asOfDate);
164
+ if (!e) {
165
+ B("An \"as of\" date is required.");
157
166
  return;
158
167
  }
159
- if (!H.recoverable) {
160
- G("A recoverable volume is required.");
168
+ let t = Number(L.recoverable);
169
+ if (!L.recoverable || Number.isNaN(t) || t <= 0) {
170
+ let e = "Recoverable volume must be greater than zero.";
171
+ B(e), A.error(e);
161
172
  return;
162
173
  }
163
- let e = H.recoveryFactor ? Number(H.recoveryFactor) : null;
164
- if (e != null && (e < 0 || e > 1)) {
165
- G("Recovery factor must be between 0 and 1.");
174
+ let n = L.recoveryFactor ? Number(L.recoveryFactor) : null;
175
+ if (n != null && (n < 0 || n > 1)) {
176
+ B("Recovery factor must be between 0 and 1.");
166
177
  return;
167
178
  }
168
- G(null);
179
+ B(null);
169
180
  try {
170
- await Y.mutateAsync({
171
- assetId: H.assetId,
172
- category: H.category,
173
- asOfDate: new Date(H.asOfDate).toISOString(),
174
- recoverable: Number(H.recoverable),
175
- recoveryFactor: e,
176
- unit: H.unit,
177
- methodology: H.methodology.trim() || null,
178
- notes: H.notes.trim() || null
179
- }), V(!1), U(F);
181
+ await q.mutateAsync({
182
+ assetId: L.assetId,
183
+ category: L.category,
184
+ asOfDate: e,
185
+ recoverable: t,
186
+ recoveryFactor: n,
187
+ unit: L.unit,
188
+ methodology: L.methodology.trim() || null,
189
+ notes: L.notes.trim() || null
190
+ }), A.success("Reserve estimate created"), Q();
180
191
  } catch (e) {
181
- G(e instanceof Error ? e.message : "Failed to create reserve estimate.");
192
+ B(e instanceof Error ? e.message : "Failed to create reserve estimate."), A.fromError(e);
182
193
  }
183
- }, $ = !K.isLoading && (K.data?.items.length ?? 0) === 0;
194
+ }, $ = !V.isLoading && (V.data?.items.length ?? 0) === 0;
184
195
  return /* @__PURE__ */ v(e, {
185
196
  title: "Reserve Estimates",
186
197
  description: "Booked recoverable volumes per asset — proved, probable, possible, contingent & prospective.",
187
198
  actions: /* @__PURE__ */ v(y, {
188
- onClick: Q,
199
+ onClick: Z,
189
200
  disabled: $,
190
- children: [/* @__PURE__ */ _(g, { className: "mr-1.5 h-4 w-4" }), " Add estimate"]
201
+ children: [/* @__PURE__ */ _(h, { className: "mr-1.5 h-4 w-4" }), " Add estimate"]
191
202
  }),
192
203
  children: [
193
204
  /* @__PURE__ */ v("div", {
194
205
  className: "grid grid-cols-1 gap-4 sm:grid-cols-3",
195
206
  children: [
196
207
  /* @__PURE__ */ _(t, {
197
- icon: /* @__PURE__ */ _(p, { className: "h-5 w-5" }),
198
- value: X.length,
208
+ icon: /* @__PURE__ */ _(ce, { className: "h-5 w-5" }),
209
+ value: Y.length,
199
210
  label: "Reserve estimates",
200
211
  featured: !0
201
212
  }),
202
213
  /* @__PURE__ */ _(t, {
203
214
  icon: /* @__PURE__ */ _(m, { className: "h-5 w-5" }),
204
- value: Z.dominantUnit ? o(Z.totalRecoverable, Z.dominantUnit) : "—",
205
- label: Z.dominantUnit ? `Total recoverable (${a(Z.dominantUnit)})` : "Total recoverable"
215
+ value: X.dominantUnit ? o(X.totalRecoverable, X.dominantUnit) : "—",
216
+ label: X.dominantUnit ? `Total recoverable (${a(X.dominantUnit)})` : "Total recoverable"
206
217
  }),
207
218
  /* @__PURE__ */ _(t, {
208
- icon: /* @__PURE__ */ _(h, { className: "h-5 w-5" }),
209
- value: Z.avgFactor == null ? "—" : i(Z.avgFactor),
219
+ icon: /* @__PURE__ */ _(le, { className: "h-5 w-5" }),
220
+ value: X.avgFactor == null ? "—" : i(X.avgFactor),
210
221
  label: "Avg recovery factor"
211
222
  })
212
223
  ]
213
224
  }),
214
225
  /* @__PURE__ */ v("div", {
215
226
  className: "mt-6 mb-5 flex flex-wrap items-center gap-3",
216
- children: [/* @__PURE__ */ _(ie, {
217
- options: j,
218
- value: I,
219
- onChange: L
220
- }), /* @__PURE__ */ v(E, {
221
- value: R,
222
- onValueChange: z,
223
- children: [/* @__PURE__ */ _(k, {
227
+ children: [/* @__PURE__ */ _(u, {
228
+ options: _e,
229
+ value: j,
230
+ onChange: (e) => {
231
+ M(e), F.reset();
232
+ }
233
+ }), /* @__PURE__ */ v(S, {
234
+ value: N,
235
+ onValueChange: (e) => {
236
+ P(e), F.reset();
237
+ },
238
+ children: [/* @__PURE__ */ _(T, {
224
239
  className: "w-56",
225
- children: /* @__PURE__ */ _(A, { placeholder: "All assets" })
226
- }), /* @__PURE__ */ v(D, { children: [/* @__PURE__ */ _(O, {
240
+ "aria-label": "Filter by asset",
241
+ children: /* @__PURE__ */ _(E, { placeholder: "All assets" })
242
+ }), /* @__PURE__ */ v(C, { children: [/* @__PURE__ */ _(w, {
227
243
  value: "ALL",
228
244
  children: "All assets"
229
- }), Object.entries(q).map(([e, t]) => /* @__PURE__ */ _(O, {
245
+ }), Object.entries(H).map(([e, t]) => /* @__PURE__ */ _(w, {
230
246
  value: e,
231
247
  children: t
232
248
  }, e))] })]
233
249
  })]
234
250
  }),
235
- ce ? /* @__PURE__ */ _(re, { label: "Loading reserve estimates…" }) : le ? /* @__PURE__ */ _(ne, {
251
+ xe ? /* @__PURE__ */ _(s, { label: "Loading reserve estimates…" }) : Se ? /* @__PURE__ */ _(re, {
236
252
  message: "Couldn't load reserve estimates.",
237
- onRetry: () => ue()
238
- }) : X.length === 0 ? /* @__PURE__ */ _(s, {
253
+ onRetry: () => Ce()
254
+ }) : J.length === 0 ? /* @__PURE__ */ _(ie, {
239
255
  illustration: "empty-data",
240
256
  icon: /* @__PURE__ */ _(m, { className: "h-10 w-10" }),
241
257
  title: "No reserve estimates",
242
- description: $ ? "Register a resource asset first, then book its recoverable reserves here." : I === "ALL" && R === "ALL" ? "Book your first recoverable-reserves estimate against an asset." : "No estimates match these filters.",
258
+ description: $ ? "Register a resource asset first, then book its recoverable reserves here." : j === "ALL" && N === "ALL" ? "Book your first recoverable-reserves estimate against an asset." : "No estimates match these filters.",
243
259
  action: $ ? void 0 : /* @__PURE__ */ v(y, {
244
- onClick: Q,
245
- children: [/* @__PURE__ */ _(g, { className: "mr-1.5 h-4 w-4" }), " Add estimate"]
260
+ onClick: Z,
261
+ children: [/* @__PURE__ */ _(h, { className: "mr-1.5 h-4 w-4" }), " Add estimate"]
246
262
  })
247
- }) : /* @__PURE__ */ _(te, {
248
- columns: de,
249
- rows: X,
263
+ }) : /* @__PURE__ */ v(g, { children: [/* @__PURE__ */ _(ne, {
264
+ columns: we,
265
+ rows: J,
250
266
  rowKey: (e) => e.id,
251
267
  defaultSort: {
252
268
  key: "asOfDate",
253
269
  dir: "desc"
254
270
  }
255
- }),
256
- /* @__PURE__ */ _(ae, {
257
- open: B,
258
- onOpenChange: (e) => {
259
- V(e), e || (U(F), G(null));
260
- },
261
- children: /* @__PURE__ */ v(oe, { children: [
262
- /* @__PURE__ */ v(w, { children: [/* @__PURE__ */ _(T, { children: "Add reserve estimate" }), /* @__PURE__ */ _(S, { children: "Book a recoverable-reserves figure for an asset as of a valuation date." })] }),
263
- /* @__PURE__ */ v("div", {
271
+ }), /* @__PURE__ */ _(d, {
272
+ page: F.page,
273
+ pageSize: D,
274
+ itemCount: J.length,
275
+ hasMore: G?.pageInfo?.hasMore ?? !1,
276
+ onPageChange: (e) => F.onPageChange(e, G?.pageInfo?.cursor)
277
+ })] }),
278
+ /* @__PURE__ */ _(ue, {
279
+ open: be,
280
+ onOpenChange: (e) => e ? I(!0) : Q(),
281
+ children: /* @__PURE__ */ v(de, { children: [/* @__PURE__ */ v(me, { children: [/* @__PURE__ */ _(he, { children: "Add reserve estimate" }), /* @__PURE__ */ _(fe, { children: "Book a recoverable-reserves figure for an asset as of a valuation date." })] }), /* @__PURE__ */ v("form", {
282
+ onSubmit: (e) => {
283
+ e.preventDefault(), Te();
284
+ },
285
+ children: [/* @__PURE__ */ v("div", {
264
286
  className: "grid gap-4 py-2",
265
287
  children: [
266
288
  /* @__PURE__ */ v("div", {
@@ -268,16 +290,16 @@ function I() {
268
290
  children: [/* @__PURE__ */ _(x, {
269
291
  htmlFor: "reAsset",
270
292
  children: "Asset *"
271
- }), /* @__PURE__ */ v(E, {
272
- value: H.assetId,
273
- onValueChange: (e) => U({
274
- ...H,
293
+ }), /* @__PURE__ */ v(S, {
294
+ value: L.assetId,
295
+ onValueChange: (e) => R({
296
+ ...L,
275
297
  assetId: e
276
298
  }),
277
- children: [/* @__PURE__ */ _(k, {
299
+ children: [/* @__PURE__ */ _(T, {
278
300
  id: "reAsset",
279
- children: /* @__PURE__ */ _(A, { placeholder: "Select an asset" })
280
- }), /* @__PURE__ */ _(D, { children: Object.entries(q).map(([e, t]) => /* @__PURE__ */ _(O, {
301
+ children: /* @__PURE__ */ _(E, { placeholder: "Select an asset" })
302
+ }), /* @__PURE__ */ _(C, { children: Object.entries(H).map(([e, t]) => /* @__PURE__ */ _(w, {
281
303
  value: e,
282
304
  children: t
283
305
  }, e)) })]
@@ -290,16 +312,16 @@ function I() {
290
312
  children: [/* @__PURE__ */ _(x, {
291
313
  htmlFor: "reCategory",
292
314
  children: "Category"
293
- }), /* @__PURE__ */ v(E, {
294
- value: H.category,
295
- onValueChange: (e) => U({
296
- ...H,
315
+ }), /* @__PURE__ */ v(S, {
316
+ value: L.category,
317
+ onValueChange: (e) => R({
318
+ ...L,
297
319
  category: e
298
320
  }),
299
- children: [/* @__PURE__ */ _(k, {
321
+ children: [/* @__PURE__ */ _(T, {
300
322
  id: "reCategory",
301
- children: /* @__PURE__ */ _(A, {})
302
- }), /* @__PURE__ */ _(D, { children: M.map((e) => /* @__PURE__ */ _(O, {
323
+ children: /* @__PURE__ */ _(E, {})
324
+ }), /* @__PURE__ */ _(C, { children: ve.map((e) => /* @__PURE__ */ _(w, {
303
325
  value: e,
304
326
  children: r(e)
305
327
  }, e)) })]
@@ -312,9 +334,9 @@ function I() {
312
334
  }), /* @__PURE__ */ _(b, {
313
335
  id: "reAsOf",
314
336
  type: "date",
315
- value: H.asOfDate,
316
- onChange: (e) => U({
317
- ...H,
337
+ value: L.asOfDate,
338
+ onChange: (e) => R({
339
+ ...L,
318
340
  asOfDate: e.target.value
319
341
  })
320
342
  })]
@@ -333,9 +355,9 @@ function I() {
333
355
  type: "number",
334
356
  min: "0",
335
357
  step: "any",
336
- value: H.recoverable,
337
- onChange: (e) => U({
338
- ...H,
358
+ value: L.recoverable,
359
+ onChange: (e) => R({
360
+ ...L,
339
361
  recoverable: e.target.value
340
362
  }),
341
363
  placeholder: "1200000"
@@ -346,16 +368,16 @@ function I() {
346
368
  children: [/* @__PURE__ */ _(x, {
347
369
  htmlFor: "reUnit",
348
370
  children: "Unit"
349
- }), /* @__PURE__ */ v(E, {
350
- value: H.unit,
351
- onValueChange: (e) => U({
352
- ...H,
371
+ }), /* @__PURE__ */ v(S, {
372
+ value: L.unit,
373
+ onValueChange: (e) => R({
374
+ ...L,
353
375
  unit: e
354
376
  }),
355
- children: [/* @__PURE__ */ _(k, {
377
+ children: [/* @__PURE__ */ _(T, {
356
378
  id: "reUnit",
357
- children: /* @__PURE__ */ _(A, {})
358
- }), /* @__PURE__ */ _(D, { children: N.map((e) => /* @__PURE__ */ _(O, {
379
+ children: /* @__PURE__ */ _(E, {})
380
+ }), /* @__PURE__ */ _(C, { children: ye.map((e) => /* @__PURE__ */ _(w, {
359
381
  value: e,
360
382
  children: a(e)
361
383
  }, e)) })]
@@ -372,9 +394,9 @@ function I() {
372
394
  min: "0",
373
395
  max: "1",
374
396
  step: "any",
375
- value: H.recoveryFactor,
376
- onChange: (e) => U({
377
- ...H,
397
+ value: L.recoveryFactor,
398
+ onChange: (e) => R({
399
+ ...L,
378
400
  recoveryFactor: e.target.value
379
401
  }),
380
402
  placeholder: "0.35"
@@ -389,9 +411,9 @@ function I() {
389
411
  children: "Methodology"
390
412
  }), /* @__PURE__ */ _(b, {
391
413
  id: "reMethodology",
392
- value: H.methodology,
393
- onChange: (e) => U({
394
- ...H,
414
+ value: L.methodology,
415
+ onChange: (e) => R({
416
+ ...L,
395
417
  methodology: e.target.value
396
418
  }),
397
419
  placeholder: "Volumetric / decline curve / PRMS deterministic"
@@ -402,38 +424,38 @@ function I() {
402
424
  children: [/* @__PURE__ */ _(x, {
403
425
  htmlFor: "reNotes",
404
426
  children: "Notes"
405
- }), /* @__PURE__ */ _(se, {
427
+ }), /* @__PURE__ */ _(ge, {
406
428
  id: "reNotes",
407
429
  rows: 2,
408
- value: H.notes,
409
- onChange: (e) => U({
410
- ...H,
430
+ value: L.notes,
431
+ onChange: (e) => R({
432
+ ...L,
411
433
  notes: e.target.value
412
434
  }),
413
435
  placeholder: "Optional context about this estimate."
414
436
  })]
415
437
  }),
416
- W && /* @__PURE__ */ _("p", {
438
+ z && /* @__PURE__ */ _("p", {
417
439
  className: "text-sm text-status-error-text",
418
- children: W
440
+ children: z
419
441
  })
420
442
  ]
421
- }),
422
- /* @__PURE__ */ v(C, { children: [/* @__PURE__ */ _(y, {
443
+ }), /* @__PURE__ */ v(pe, { children: [/* @__PURE__ */ _(y, {
444
+ type: "button",
423
445
  variant: "outline",
424
- onClick: () => V(!1),
446
+ onClick: Q,
425
447
  children: "Cancel"
426
448
  }), /* @__PURE__ */ _(y, {
427
- onClick: fe,
428
- disabled: Y.isPending,
429
- children: Y.isPending ? "Saving…" : "Add estimate"
430
- })] })
431
- ] })
449
+ type: "submit",
450
+ disabled: q.isPending,
451
+ children: q.isPending ? "Saving…" : "Add estimate"
452
+ })] })]
453
+ })] })
432
454
  })
433
455
  ]
434
456
  });
435
457
  }
436
458
  //#endregion
437
- export { I as ReservesPage };
459
+ export { A as ReservesPage };
438
460
 
439
461
  //# sourceMappingURL=ReservesPage.js.map