@burdenoff/microfe-theglobalfuel 2026.705.5 → 2026.709.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.
- package/README.md +3 -0
- package/dist/dev/main.d.ts +2 -0
- package/dist/dev/main.d.ts.map +1 -0
- package/dist/generated/global-operations.d.ts +2 -0
- package/dist/generated/global-operations.d.ts.map +1 -0
- package/dist/generated/global-types.d.ts +18199 -0
- package/dist/generated/global-types.d.ts.map +1 -0
- package/dist/generated/wspace-operations.d.ts +2 -0
- package/dist/generated/wspace-operations.d.ts.map +1 -0
- package/dist/generated/wspace-types.d.ts +43046 -0
- package/dist/generated/wspace-types.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -1
- package/dist/theglobalfuel/TheGlobalFuelRoot.d.ts +5 -0
- package/dist/theglobalfuel/TheGlobalFuelRoot.d.ts.map +1 -0
- package/dist/theglobalfuel/TheGlobalFuelRoot.js +106 -104
- package/dist/theglobalfuel/TheGlobalFuelRoot.js.map +1 -1
- package/dist/theglobalfuel/TheGlobalFuelRoutes.d.ts +4 -0
- package/dist/theglobalfuel/TheGlobalFuelRoutes.d.ts.map +1 -0
- package/dist/theglobalfuel/TheGlobalFuelRoutes.js +60 -38
- package/dist/theglobalfuel/TheGlobalFuelRoutes.js.map +1 -1
- package/dist/theglobalfuel/components/DataTable.d.ts +30 -0
- package/dist/theglobalfuel/components/DataTable.d.ts.map +1 -0
- package/dist/theglobalfuel/components/DataTable.js.map +1 -1
- package/dist/theglobalfuel/components/EmptyState.d.ts +18 -0
- package/dist/theglobalfuel/components/EmptyState.d.ts.map +1 -0
- package/dist/theglobalfuel/components/EvidenceUpload.d.ts +14 -0
- package/dist/theglobalfuel/components/EvidenceUpload.d.ts.map +1 -0
- package/dist/theglobalfuel/components/FileLink.d.ts +15 -0
- package/dist/theglobalfuel/components/FileLink.d.ts.map +1 -0
- package/dist/theglobalfuel/components/FilterTabs.d.ts +18 -0
- package/dist/theglobalfuel/components/FilterTabs.d.ts.map +1 -0
- package/dist/theglobalfuel/components/MetricsCard.d.ts +23 -0
- package/dist/theglobalfuel/components/MetricsCard.d.ts.map +1 -0
- package/dist/theglobalfuel/components/MiniBar.d.ts +16 -0
- package/dist/theglobalfuel/components/MiniBar.d.ts.map +1 -0
- package/dist/theglobalfuel/components/PageLayout.d.ts +18 -0
- package/dist/theglobalfuel/components/PageLayout.d.ts.map +1 -0
- package/dist/theglobalfuel/components/PageLayout.js +2 -1
- package/dist/theglobalfuel/components/PageLayout.js.map +1 -1
- package/dist/theglobalfuel/components/Pagination.d.ts +22 -0
- package/dist/theglobalfuel/components/Pagination.d.ts.map +1 -0
- package/dist/theglobalfuel/components/StateViews.d.ts +24 -0
- package/dist/theglobalfuel/components/StateViews.d.ts.map +1 -0
- package/dist/theglobalfuel/components/StatusBadge.d.ts +9 -0
- package/dist/theglobalfuel/components/StatusBadge.d.ts.map +1 -0
- package/dist/theglobalfuel/components/Tabs.d.ts +17 -0
- package/dist/theglobalfuel/components/Tabs.d.ts.map +1 -0
- package/dist/theglobalfuel/components/TheDiscussion.d.ts +18 -0
- package/dist/theglobalfuel/components/TheDiscussion.d.ts.map +1 -0
- package/dist/theglobalfuel/components/TheTags.d.ts +17 -0
- package/dist/theglobalfuel/components/TheTags.d.ts.map +1 -0
- package/dist/theglobalfuel/components/WorldMap.d.ts +18 -0
- package/dist/theglobalfuel/components/WorldMap.d.ts.map +1 -0
- package/dist/theglobalfuel/components/WorldMap.js.map +1 -1
- package/dist/theglobalfuel/components/index.d.ts +21 -0
- package/dist/theglobalfuel/components/index.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/AllocationBar.d.ts +21 -0
- package/dist/theglobalfuel/components/viz/AllocationBar.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/AreaChart.d.ts +18 -0
- package/dist/theglobalfuel/components/viz/AreaChart.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/AvatarStack.d.ts +13 -0
- package/dist/theglobalfuel/components/viz/AvatarStack.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/BarChart.d.ts +17 -0
- package/dist/theglobalfuel/components/viz/BarChart.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/CertificateCard.d.ts +14 -0
- package/dist/theglobalfuel/components/viz/CertificateCard.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/DonutChart.d.ts +20 -0
- package/dist/theglobalfuel/components/viz/DonutChart.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/HBarFunnel.d.ts +17 -0
- package/dist/theglobalfuel/components/viz/HBarFunnel.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/Heatmap.d.ts +26 -0
- package/dist/theglobalfuel/components/viz/Heatmap.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/KanbanBoard.d.ts +17 -0
- package/dist/theglobalfuel/components/viz/KanbanBoard.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/LineChart.d.ts +20 -0
- package/dist/theglobalfuel/components/viz/LineChart.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/OrgTree.d.ts +14 -0
- package/dist/theglobalfuel/components/viz/OrgTree.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/PathSteps.d.ts +17 -0
- package/dist/theglobalfuel/components/viz/PathSteps.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/ProgressRing.d.ts +20 -0
- package/dist/theglobalfuel/components/viz/ProgressRing.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/RatingStars.d.ts +14 -0
- package/dist/theglobalfuel/components/viz/RatingStars.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/SegmentedTabs.d.ts +26 -0
- package/dist/theglobalfuel/components/viz/SegmentedTabs.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/SkillBar.d.ts +17 -0
- package/dist/theglobalfuel/components/viz/SkillBar.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/Sparkline.d.ts +16 -0
- package/dist/theglobalfuel/components/viz/Sparkline.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/StatCard.d.ts +22 -0
- package/dist/theglobalfuel/components/viz/StatCard.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/StepProgress.d.ts +17 -0
- package/dist/theglobalfuel/components/viz/StepProgress.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/Timeline.d.ts +21 -0
- package/dist/theglobalfuel/components/viz/Timeline.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/index.d.ts +35 -0
- package/dist/theglobalfuel/components/viz/index.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/lib/Avatar.d.ts +15 -0
- package/dist/theglobalfuel/components/viz/lib/Avatar.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/lib/CartesianFrame.d.ts +44 -0
- package/dist/theglobalfuel/components/viz/lib/CartesianFrame.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/lib/ResponsiveSvg.d.ts +27 -0
- package/dist/theglobalfuel/components/viz/lib/ResponsiveSvg.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/lib/format.d.ts +10 -0
- package/dist/theglobalfuel/components/viz/lib/format.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/lib/geometry.d.ts +41 -0
- package/dist/theglobalfuel/components/viz/lib/geometry.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/lib/hooks.d.ts +18 -0
- package/dist/theglobalfuel/components/viz/lib/hooks.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/lib/palette.d.ts +31 -0
- package/dist/theglobalfuel/components/viz/lib/palette.d.ts.map +1 -0
- package/dist/theglobalfuel/components/viz/lib/types.d.ts +27 -0
- package/dist/theglobalfuel/components/viz/lib/types.d.ts.map +1 -0
- package/dist/theglobalfuel/context/TheGlobalFuelContext.d.ts +16 -0
- package/dist/theglobalfuel/context/TheGlobalFuelContext.d.ts.map +1 -0
- package/dist/theglobalfuel/context/index.d.ts +6 -0
- package/dist/theglobalfuel/context/index.d.ts.map +1 -0
- package/dist/theglobalfuel/hooks/index.d.ts +15 -0
- package/dist/theglobalfuel/hooks/index.d.ts.map +1 -0
- package/dist/theglobalfuel/hooks/index.js +4 -0
- package/dist/theglobalfuel/hooks/useCursorPager.d.ts +26 -0
- package/dist/theglobalfuel/hooks/useCursorPager.d.ts.map +1 -0
- package/dist/theglobalfuel/hooks/useNotify.d.ts +23 -0
- package/dist/theglobalfuel/hooks/useNotify.d.ts.map +1 -0
- package/dist/theglobalfuel/hooks/useTheAnalytics.d.ts +38 -0
- package/dist/theglobalfuel/hooks/useTheAnalytics.d.ts.map +1 -0
- package/dist/theglobalfuel/hooks/useTheAnalytics.js +46 -0
- package/dist/theglobalfuel/hooks/useTheAnalytics.js.map +1 -0
- package/dist/theglobalfuel/hooks/useTheComments.d.ts +36 -0
- package/dist/theglobalfuel/hooks/useTheComments.d.ts.map +1 -0
- package/dist/theglobalfuel/hooks/useTheFiles.d.ts +47 -0
- package/dist/theglobalfuel/hooks/useTheFiles.d.ts.map +1 -0
- package/dist/theglobalfuel/hooks/useTheGlobalFuelApi.d.ts +79 -0
- package/dist/theglobalfuel/hooks/useTheGlobalFuelApi.d.ts.map +1 -0
- package/dist/theglobalfuel/hooks/useTheGlobalFuelApi.js +2 -9
- package/dist/theglobalfuel/hooks/useTheGlobalFuelApi.js.map +1 -1
- package/dist/theglobalfuel/hooks/useTheNativeControls.d.ts +20 -0
- package/dist/theglobalfuel/hooks/useTheNativeControls.d.ts.map +1 -0
- package/dist/theglobalfuel/hooks/useTheNativeControls.js +22 -0
- package/dist/theglobalfuel/hooks/useTheNativeControls.js.map +1 -0
- package/dist/theglobalfuel/hooks/useThePageView.d.ts +10 -0
- package/dist/theglobalfuel/hooks/useThePageView.d.ts.map +1 -0
- package/dist/theglobalfuel/hooks/useThePageView.js +13 -0
- package/dist/theglobalfuel/hooks/useThePageView.js.map +1 -0
- package/dist/theglobalfuel/hooks/useTheTags.d.ts +44 -0
- package/dist/theglobalfuel/hooks/useTheTags.d.ts.map +1 -0
- package/dist/theglobalfuel/hooks/useTheTranslation.d.ts +4 -0
- package/dist/theglobalfuel/hooks/useTheTranslation.d.ts.map +1 -0
- package/dist/theglobalfuel/hooks/useTheTranslation.js +12 -0
- package/dist/theglobalfuel/hooks/useTheTranslation.js.map +1 -0
- package/dist/theglobalfuel/index.d.ts +11 -0
- package/dist/theglobalfuel/index.d.ts.map +1 -0
- package/dist/theglobalfuel/index.js +2 -0
- package/dist/theglobalfuel/pages/assets/AssetDetailPage.d.ts +13 -0
- package/dist/theglobalfuel/pages/assets/AssetDetailPage.d.ts.map +1 -0
- package/dist/theglobalfuel/pages/assets/AssetDetailPage.js +395 -353
- package/dist/theglobalfuel/pages/assets/AssetDetailPage.js.map +1 -1
- package/dist/theglobalfuel/pages/assets/AssetsPage.d.ts +10 -0
- package/dist/theglobalfuel/pages/assets/AssetsPage.d.ts.map +1 -0
- package/dist/theglobalfuel/pages/assets/AssetsPage.js +152 -146
- package/dist/theglobalfuel/pages/assets/AssetsPage.js.map +1 -1
- package/dist/theglobalfuel/pages/compliance/CompliancePage.d.ts +11 -0
- package/dist/theglobalfuel/pages/compliance/CompliancePage.d.ts.map +1 -0
- package/dist/theglobalfuel/pages/compliance/CompliancePage.js +233 -229
- package/dist/theglobalfuel/pages/compliance/CompliancePage.js.map +1 -1
- package/dist/theglobalfuel/pages/contracts/ContractDetailPage.d.ts +9 -0
- package/dist/theglobalfuel/pages/contracts/ContractDetailPage.d.ts.map +1 -0
- package/dist/theglobalfuel/pages/contracts/ContractDetailPage.js +410 -389
- package/dist/theglobalfuel/pages/contracts/ContractDetailPage.js.map +1 -1
- package/dist/theglobalfuel/pages/contracts/ContractsPage.d.ts +8 -0
- package/dist/theglobalfuel/pages/contracts/ContractsPage.d.ts.map +1 -0
- package/dist/theglobalfuel/pages/contracts/ContractsPage.js +237 -231
- package/dist/theglobalfuel/pages/contracts/ContractsPage.js.map +1 -1
- package/dist/theglobalfuel/pages/dashboard/DashboardPage.d.ts +17 -0
- package/dist/theglobalfuel/pages/dashboard/DashboardPage.d.ts.map +1 -0
- package/dist/theglobalfuel/pages/dashboard/DashboardPage.js +255 -250
- package/dist/theglobalfuel/pages/dashboard/DashboardPage.js.map +1 -1
- package/dist/theglobalfuel/pages/emissions/EmissionsPage.d.ts +13 -0
- package/dist/theglobalfuel/pages/emissions/EmissionsPage.d.ts.map +1 -0
- package/dist/theglobalfuel/pages/emissions/EmissionsPage.js +154 -150
- package/dist/theglobalfuel/pages/emissions/EmissionsPage.js.map +1 -1
- package/dist/theglobalfuel/pages/inventory/InventoryPage.d.ts +11 -0
- package/dist/theglobalfuel/pages/inventory/InventoryPage.d.ts.map +1 -0
- package/dist/theglobalfuel/pages/inventory/InventoryPage.js +151 -147
- package/dist/theglobalfuel/pages/inventory/InventoryPage.js.map +1 -1
- package/dist/theglobalfuel/pages/production/ProductionPage.d.ts +11 -0
- package/dist/theglobalfuel/pages/production/ProductionPage.d.ts.map +1 -0
- package/dist/theglobalfuel/pages/production/ProductionPage.js +175 -171
- package/dist/theglobalfuel/pages/production/ProductionPage.js.map +1 -1
- package/dist/theglobalfuel/pages/provenance/ProvenancePage.d.ts +23 -0
- package/dist/theglobalfuel/pages/provenance/ProvenancePage.d.ts.map +1 -0
- package/dist/theglobalfuel/pages/provenance/ProvenancePage.js +153 -146
- package/dist/theglobalfuel/pages/provenance/ProvenancePage.js.map +1 -1
- package/dist/theglobalfuel/pages/reserves/ReservesPage.d.ts +10 -0
- package/dist/theglobalfuel/pages/reserves/ReservesPage.d.ts.map +1 -0
- package/dist/theglobalfuel/pages/reserves/ReservesPage.js +168 -164
- package/dist/theglobalfuel/pages/reserves/ReservesPage.js.map +1 -1
- package/dist/theglobalfuel/pages/shipments/ShipmentsPage.d.ts +11 -0
- package/dist/theglobalfuel/pages/shipments/ShipmentsPage.d.ts.map +1 -0
- package/dist/theglobalfuel/pages/shipments/ShipmentsPage.js +179 -175
- package/dist/theglobalfuel/pages/shipments/ShipmentsPage.js.map +1 -1
- package/dist/theglobalfuel/services/assistantApi.d.ts +25 -0
- package/dist/theglobalfuel/services/assistantApi.d.ts.map +1 -0
- package/dist/theglobalfuel/services/assistantApi.js +225 -0
- package/dist/theglobalfuel/services/assistantApi.js.map +1 -0
- package/dist/theglobalfuel/services/createSandboxAssistantTransport.d.ts +38 -0
- package/dist/theglobalfuel/services/createSandboxAssistantTransport.d.ts.map +1 -0
- package/dist/theglobalfuel/services/createSandboxAssistantTransport.js +120 -0
- package/dist/theglobalfuel/services/createSandboxAssistantTransport.js.map +1 -0
- package/dist/theglobalfuel/services/index.d.ts +7 -0
- package/dist/theglobalfuel/services/index.d.ts.map +1 -0
- package/dist/theglobalfuel/types/assistant.d.ts +65 -0
- package/dist/theglobalfuel/types/assistant.d.ts.map +1 -0
- package/dist/theglobalfuel/types/index.d.ts +376 -0
- package/dist/theglobalfuel/types/index.d.ts.map +1 -0
- package/dist/theglobalfuel/utils/cn.d.ts +4 -0
- package/dist/theglobalfuel/utils/cn.d.ts.map +1 -0
- package/dist/theglobalfuel/utils/formatters.d.ts +44 -0
- package/dist/theglobalfuel/utils/formatters.d.ts.map +1 -0
- package/dist/theglobalfuel/utils/i18n.d.ts +5 -0
- package/dist/theglobalfuel/utils/i18n.d.ts.map +1 -0
- package/dist/theglobalfuel/utils/i18n.js +15 -0
- package/dist/theglobalfuel/utils/i18n.js.map +1 -0
- package/dist/theglobalfuel/utils/index.d.ts +10 -0
- package/dist/theglobalfuel/utils/index.d.ts.map +1 -0
- package/dist/theglobalfuel/utils/navigation.d.ts +14 -0
- package/dist/theglobalfuel/utils/navigation.d.ts.map +1 -0
- package/dist/theglobalfuel/utils/pageContext.d.ts +26 -0
- package/dist/theglobalfuel/utils/pageContext.d.ts.map +1 -0
- package/dist/theglobalfuel/utils/pageContext.js +65 -0
- package/dist/theglobalfuel/utils/pageContext.js.map +1 -0
- package/dist/theglobalfuel/utils/transitions.d.ts +17 -0
- package/dist/theglobalfuel/utils/transitions.d.ts.map +1 -0
- package/package.json +5 -1
- package/dist/node_modules/clsx/dist/clsx.js +0 -18
- package/dist/node_modules/clsx/dist/clsx.js.map +0 -1
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +0 -1716
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.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 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, offset: pager.page * PAGE_SIZE },\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={pager.onPageChange}\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
|
+
{"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 useThePageView,\n useTheTranslation,\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[] = ['BARRELS', 'CUBIC_METERS', 'TONNES', 'KILOGRAMS', 'MWH', 'GJ', 'MCF'];\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 useThePageView('production');\n const t = useTheTranslation();\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, offset: pager.page * PAGE_SIZE },\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={t('theglobalfuel.pages.production.title', 'Production')}\n description={t(\n 'theglobalfuel.pages.production.description',\n 'Captured production volumes across every field, well, mine & plant — with downtime and grade.'\n )}\n dataTour=\"theglobalfuel-production-page\"\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={pager.onPageChange}\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":";;;;;;;;;;;;;;;;;;;;AAuDA,IAAM,IAAmB;CAAC;CAAW;CAAgB;CAAU;CAAa;CAAO;CAAM;CAAM,EAEzF,IAAY,IAEZ,2BAAsB,IAAI,MAAM,EAAC,aAAa,CAAC,MAAM,GAAG,GAAG,EAa3D,WAAoC;CACxC,SAAS;CACT,aAAa,GAAO;CACpB,WAAW,GAAO;CAClB,QAAQ;CACR,MAAM;CACN,OAAO;CACP,eAAe;CACf,OAAO;CACR;AAED,SAAgB,IAAiB;AAC/B,GAAe,aAAa;CAC5B,IAAM,IAAI,IAAmB,EACvB,EAAE,kBAAe,GAAkB,EACnC,IAAS,IAAW,EACpB,CAAC,GAAS,KAAc,EAAiB,MAAM,EAC/C,IAAQ,IAAgB,EACxB,CAAC,IAAY,KAAiB,EAAS,GAAM,EAC7C,CAAC,GAAM,KAAW,EAA0B,EAAU,EACtD,CAAC,GAAW,KAAgB,EAAwB,KAAK,EAGzD,IAAc,EAAa,EAAE,YAAY,EAAE,OAAO,KAAK,EAAE,CAAC,EAC1D,IAAW,QAAsC;EACrD,IAAM,IAA8B,EAAE;AACtC,OAAK,IAAM,KAAK,EAAY,MAAM,SAAS,EAAE,CAAE,GAAI,EAAE,MAAM,EAAE;AAC7D,SAAO;IACN,CAAC,EAAY,KAAK,CAAC,EAEhB,EAAE,SAAM,eAAW,aAAS,gBAAY,EAAwB;EACpE,SAAS,MAAY,QAAQ,KAAA,IAAY;EACzC,YAAY;GAAE,OAAO;GAAW,QAAQ,EAAM,OAAO;GAAW;EACjE,CAAC,EACI,IAAmB,IAAwB,EAE3C,IAAO,QAAc,GAAM,SAAS,EAAE,EAAE,CAAC,EAAK,CAAC,EAG/C,EAAE,iBAAa,kBAAc,qBAAkB,QAAc;EACjE,IAAM,oBAAS,IAAI,KAAsB,EACrC,IAAW;AACf,OAAK,IAAM,KAAK,EAEd,CADA,EAAO,IAAI,EAAE,OAAO,EAAO,IAAI,EAAE,KAAK,IAAI,KAAK,EAAE,OAAO,EACxD,KAAY,EAAE;EAEhB,IAAM,IAAQ,CAAC,GAAG,EAAO,SAAS,CAAC,EAC/B,GACA;AAaJ,SAZI,EAAM,WAAW,IACnB,IAAQ,MACC,EAAM,WAAW,IAC1B,IAAQ,EAAa,EAAM,GAAG,IAAI,EAAM,GAAG,GAAG,IAE9C,IAAQ,eACR,IACE,kBAAC,KAAD;GAAG,WAAU;aACV,EAAM,KAAK,CAAC,GAAG,OAAO,EAAa,GAAG,EAAE,CAAC,CAAC,KAAK,MAAM;GACpD,CAAA,GAGD;GAAE,aAAa;GAAO,cAAc;GAAQ,eAAe;GAAU;IAC3E,CAAC,EAAK,CAAC,EAEJ,KAAyC;EAC7C;GACE,KAAK;GACL,QAAQ;GACR,SAAS,MACP,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,KAAD;KAAG,WAAU;eACV,EAAS,EAAE,YAAY,GAAG,EAAE,QAAQ,MAAM,GAAG,EAAE,CAAC;KAC/C,CAAA;IACA,CAAA;GAET;EACD;GACE,KAAK;GACL,QAAQ;GACR,cAAc;GACd,YAAY,MAAM,IAAI,KAAK,EAAE,YAAY,CAAC,SAAS;GACnD,SAAS,MACP,kBAAC,QAAD;IAAM,WAAU;cAAhB;KACG,EAAW,EAAE,YAAY;KAAC;KAAI,EAAW,EAAE,UAAU;KACjD;;GAEV;EACD;GACE,KAAK;GACL,QAAQ;GACR,OAAO;GACP,YAAY,MAAM,EAAE;GACpB,SAAS,MACP,kBAAC,QAAD;IAAM,WAAU;cACb,EAAa,EAAE,QAAQ,EAAE,KAAK;IAC1B,CAAA;GAEV;EACD;GACE,KAAK;GACL,QAAQ;GACR,OAAO;GACP,cAAc;GACd,YAAY,MAAM,EAAE,SAAS;GAC7B,SAAS,MACP,EAAE,SAAS,OAGT,kBAAC,QAAD;IAAM,WAAU;cAAqB;IAAQ,CAAA,GAF7C,kBAAC,QAAD;IAAM,WAAU;cAAoC,EAAa,EAAE,MAAM;IAAQ,CAAA;GAItF;EACD;GACE,KAAK;GACL,QAAQ;GACR,OAAO;GACP,cAAc;GACd,YAAY,MAAM,EAAE;GACpB,SAAS,MACP,kBAAC,QAAD;IAAM,WAAU;cAAhB,CAAoD,EAAa,EAAE,cAAc,EAAC,IAAQ;;GAE7F;EACD;GACE,KAAK;GACL,QAAQ;GACR,OAAO;GACP,cAAc;GACd,SAAS,MAAM,kBAAC,QAAD;IAAM,WAAU;cAAsB,EAAmB,EAAE,UAAU;IAAQ,CAAA;GAC7F;EACF,EAEK,UAAmB;AAGvB,EAFA,EAAQ,GAAW,CAAC,EACpB,EAAa,KAAK,EAClB,EAAc,GAAK;IAGf,UAAoB;AAGxB,EAFA,EAAc,GAAM,EACpB,EAAQ,GAAW,CAAC,EACpB,EAAa,KAAK;IAGd,KAAe,YAAY;AAC/B,MAAI,CAAC,EAAK,SAAS;AACjB,KAAa,mBAAmB;AAChC;;EAGF,IAAM,IAAc,EAAc,EAAK,YAAY,EAC7C,IAAY,EAAc,EAAK,UAAU;AAC/C,MAAI,CAAC,KAAe,CAAC,GAAW;AAC9B,KAAa,qCAAqC;AAClD;;AAEF,MAAI,IAAI,KAAK,EAAU,CAAC,SAAS,GAAG,IAAI,KAAK,EAAY,CAAC,SAAS,EAAE;AACnE,KAAa,mDAAmD;AAChE;;EAEF,IAAM,IAAS,OAAO,EAAK,OAAO;AAClC,MAAI,CAAC,EAAK,UAAU,OAAO,MAAM,EAAO,IAAI,KAAU,GAAG;GACvD,IAAM,IAAU;AAEhB,GADA,EAAa,EAAQ,EACrB,EAAO,MAAM,EAAQ;AACrB;;AAEF,IAAa,KAAK;AAClB,MAAI;AAYF,GAXA,MAAM,EAAiB,YAAY;IACjC,SAAS,EAAK;IACd;IACA;IACA;IACA,MAAM,EAAK;IACX,OAAO,EAAK,QAAQ,OAAO,EAAK,MAAM,GAAG;IACzC,eAAe,EAAK,gBAAgB,OAAO,EAAK,cAAc,GAAG;IACjE,OAAO,EAAK,MAAM,MAAM,IAAI;IAC7B,CAAC,EACF,EAAO,QAAQ,sBAAsB,EACrC,GAAa;WACN,GAAK;AAEZ,GADA,EAAa,aAAe,QAAQ,EAAI,UAAU,+BAA+B,EACjF,EAAO,UAAU,EAAI;;IAInB,IAAe,EAAY,MAAM,SAAS,EAAE;AAElD,QACE,kBAAC,GAAD;EACE,OAAO,EAAE,wCAAwC,aAAa;EAC9D,aAAa,EACX,8CACA,gGACD;EACD,UAAS;EACT,SACE,kBAAC,GAAD;GAAQ,SAAS;aAAjB,CACE,kBAAC,GAAD,EAAM,WAAU,kBAAmB,CAAA,EAAA,qBAC5B;;YAVb;GAcE,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD;MACE,MAAM,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA;MACtC,OAAO;MACP,OAAM;MACN,UAAA;MACA,QAAQ;MACR,CAAA;KACF,kBAAC,GAAD;MACE,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;MACnC,OAAO,GAAG,EAAa,EAAc,CAAC;MACtC,OAAM;MACN,QAAQ,IAAgB,IAAI,YAAY,KAAA;MACxC,CAAA;KACF,kBAAC,GAAD;MACE,MAAM,kBAAC,IAAD,EAAW,WAAU,WAAY,CAAA;MACvC,OAAO,EAAK;MACZ,OAAM;MACN,CAAA;KACE;;GAGN,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD;KACE,OAAO;KACP,gBAAgB,MAAM;AAEpB,MADA,EAAW,EAAE,EACb,EAAM,OAAO;;eAJjB,CAOE,kBAAC,GAAD;MAAe,WAAU;MAAO,cAAW;gBACzC,kBAAC,GAAD,EAAa,aAAY,cAAe,CAAA;MAC1B,CAAA,EAChB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;MAAY,OAAM;gBAAM;MAAuB,CAAA,EAC9C,EAAa,KAAK,MACjB,kBAAC,GAAD;MAAuB,OAAO,EAAE;gBAC7B,EAAE;MACQ,EAFI,EAAE,GAEN,CACb,CACY,EAAA,CAAA,CACT;;IACL,CAAA;GAEL,KACC,kBAAC,IAAD,EAAa,OAAM,+BAAgC,CAAA,GACjD,KACF,kBAAC,IAAD;IAAW,SAAQ;IAAoC,eAAe,IAAS;IAAI,CAAA,GACjF,EAAK,WAAW,IAClB,kBAAC,GAAD;IACE,cAAa;IACb,MAAM,kBAAC,GAAD,EAAO,WAAU,aAAc,CAAA;IACrC,OAAM;IACN,aACE,MAAY,QACR,6EACA;IAEN,QACE,kBAAC,GAAD;KAAQ,SAAS;eAAjB,CACE,kBAAC,GAAD,EAAM,WAAU,kBAAmB,CAAA,EAAA,qBAC5B;;IAEX,CAAA,GAEF,kBAAA,IAAA,EAAA,UAAA,CACE,kBAAC,GAAD;IACW;IACH;IACN,SAAS,MAAM,EAAE;IACjB,aAAa,MAAM,EAAW,UAAU,EAAE,UAAU;IACpD,WAAW,MAAM,QAAQ,EAAS,EAAE,YAAY;IAChD,aAAa;KAAE,KAAK;KAAU,KAAK;KAAQ;IAC3C,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,MAAU,IAAO,EAAc,GAAK,GAAG,GAAa;cAEnE,kBAAC,IAAD,EAAA,UAAA,CACE,kBAAC,IAAD,EAAA,UAAA,CACE,kBAAC,IAAD,EAAA,UAAuB,qBAAyC,CAAA,EAChE,kBAAC,IAAD,EAAA,UAA6B,gEAEC,CAAA,CACP,EAAA,CAAA,EAEzB,kBAAC,QAAD;KACE,WAAW,MAAM;AAEV,MADL,EAAE,gBAAgB,EACb,IAAc;;eAHvB,CAME,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD;SAAO,SAAQ;mBAAU;SAAe,CAAA,EACxC,kBAAC,GAAD;SACE,OAAO,EAAK;SACZ,gBAAgB,MAAM,EAAQ;UAAE,GAAG;UAAM,SAAS;UAAG,CAAC;mBAFxD,CAIE,kBAAC,GAAD;UAAe,IAAG;oBAChB,kBAAC,GAAD,EAAa,aAAY,mBAAoB,CAAA;UAC/B,CAAA,EAChB,kBAAC,GAAD,EAAA,UACG,EAAa,KAAK,MACjB,kBAAC,GAAD;UAAuB,OAAO,EAAE;oBAC7B,EAAE;UACQ,EAFI,EAAE,GAEN,CACb,EACY,CAAA,CACT;WACL;;OAEN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UAAO,SAAQ;oBAAU;UAAsB,CAAA,EAC/C,kBAAC,GAAD;UACE,IAAG;UACH,MAAK;UACL,OAAO,EAAK;UACZ,WAAW,MAAM,EAAQ;WAAE,GAAG;WAAM,aAAa,EAAE,OAAO;WAAO,CAAC;UAClE,CAAA,CACE;YACN,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UAAO,SAAQ;oBAAQ;UAAoB,CAAA,EAC3C,kBAAC,GAAD;UACE,IAAG;UACH,MAAK;UACL,OAAO,EAAK;UACZ,WAAW,MAAM,EAAQ;WAAE,GAAG;WAAM,WAAW,EAAE,OAAO;WAAO,CAAC;UAChE,CAAA,CACE;WACF;;OAEN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UAAO,SAAQ;oBAAW;UAAgB,CAAA,EAC1C,kBAAC,GAAD;UACE,IAAG;UACH,MAAK;UACL,KAAI;UACJ,MAAK;UACL,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;oBAAS;UAAY,CAAA,EACpC,kBAAC,GAAD;UACE,OAAO,EAAK;UACZ,gBAAgB,MAAM,EAAQ;WAAE,GAAG;WAAM,MAAM;WAAc,CAAC;oBAFhE,CAIE,kBAAC,GAAD;WAAe,IAAG;qBAChB,kBAAC,GAAD,EAAe,CAAA;WACD,CAAA,EAChB,kBAAC,GAAD,EAAA,UACG,EAAM,KAAK,MACV,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;oBAAU;UAAa,CAAA,EACtC,kBAAC,GAAD;UACE,IAAG;UACH,MAAK;UACL,MAAK;UACL,OAAO,EAAK;UACZ,WAAW,MAAM,EAAQ;WAAE,GAAG;WAAM,OAAO,EAAE,OAAO;WAAO,CAAC;UAC5D,aAAY;UACZ,CAAA,CACE;YACN,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UAAO,SAAQ;oBAAa;UAAwB,CAAA,EACpD,kBAAC,GAAD;UACE,IAAG;UACH,MAAK;UACL,KAAI;UACJ,MAAK;UACL,OAAO,EAAK;UACZ,WAAW,MAAM,EAAQ;WAAE,GAAG;WAAM,eAAe,EAAE,OAAO;WAAO,CAAC;UACpE,aAAY;UACZ,CAAA,CACE;WACF;;OAEN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD;SAAO,SAAQ;mBAAU;SAAa,CAAA,EACtC,kBAAC,GAAD;SACE,IAAG;SACH,MAAM;SACN,OAAO,EAAK;SACZ,WAAW,MAAM,EAAQ;UAAE,GAAG;UAAM,OAAO,EAAE,OAAO;UAAO,CAAC;SAC5D,aAAY;SACZ,CAAA,CACE;;OAEL,KAAa,kBAAC,KAAD;QAAG,WAAU;kBAAkC;QAAc,CAAA;OACvE;SAEN,kBAAC,IAAD,EAAA,UAAA,CACE,kBAAC,GAAD;MAAQ,MAAK;MAAS,SAAQ;MAAU,SAAS;gBAAa;MAErD,CAAA,EACT,kBAAC,GAAD;MAAQ,MAAK;MAAS,UAAU,EAAiB;gBAC9C,EAAiB,YAAY,eAAe;MACtC,CAAA,CACc,EAAA,CAAA,CACpB;OACiB,EAAA,CAAA;IACT,CAAA;GACR"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provenance — chain-of-custody traceability (pit → port → certificate).
|
|
3
|
+
* @module theglobalfuel/pages/provenance
|
|
4
|
+
*
|
|
5
|
+
* The flagship end-to-end traceability view. The user picks a resource asset and
|
|
6
|
+
* we assemble its custody chain entirely from REAL linked records:
|
|
7
|
+
* Asset (registry) → Production → Inventory lot → Shipment (+ document) →
|
|
8
|
+
* Delivered → Chain-of-custody certificate (+ evidence)
|
|
9
|
+
*
|
|
10
|
+
* Sources — all `the*` endpoints, no mock data:
|
|
11
|
+
* - useTheAsset(id) → the asset + nested productionRecords/reserves
|
|
12
|
+
* - useTheInventoryLots() → filtered client-side to lot.assetId === id
|
|
13
|
+
* - useTheEmissionRecords() → attributed emissions for the summary
|
|
14
|
+
* - useTheComplianceCerts(id) → CHAIN_OF_CUSTODY / evidence certs
|
|
15
|
+
* - useTheContracts({commodity}) + useTheContract() → offtake + nested shipments
|
|
16
|
+
*
|
|
17
|
+
* The chain renders as a StepProgress flow + a row of rich node cards (each
|
|
18
|
+
* carrying the real record and a FileLink for its document/evidence), a Timeline
|
|
19
|
+
* of the real dated events, an origin map and a provenance summary. Every stage
|
|
20
|
+
* degrades gracefully when its downstream record does not exist yet (pre-launch).
|
|
21
|
+
*/
|
|
22
|
+
export declare function ProvenancePage(): import("react").JSX.Element;
|
|
23
|
+
//# sourceMappingURL=ProvenancePage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProvenancePage.d.ts","sourceRoot":"","sources":["../../../../src/theglobalfuel/pages/provenance/ProvenancePage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAqMH,wBAAgB,cAAc,gCA8gB7B"}
|