@burdenoff/microfe-ecoimpacthub 2026.819.2 → 2026.819.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"EcoImpactHubAdminRoot.js","names":[],"sources":["../../src/ecoimpacthub/EcoImpactHubAdminRoot.tsx"],"sourcesContent":["/**\n * EcoImpactHub Admin Root\n * @module ecoimpacthub\n *\n * Product-specific admin surface mounted inside `admin-app` under\n * `/admin/ecoimpacthub` (BOFF-3118). Per fleet-wide policy the ONLY valid\n * admin surface is the shared `admin.burdenoff.com` app — this is a\n * microfrontend mounted there, not a new subdomain. It covers three\n * governance operations product owners need outside the day-to-day\n * monitoring UI:\n *\n * 1. Site / sensor governance — pause monitoring, retire hardware, archive\n * decommissioned sites.\n * 2. Carbon-ledger oversight — inspect recorded carbon entries across all\n * sites/scopes and verify DRAFT/RECORDED entries.\n * 3. Report sign-off — publish sustainability reports once their line items\n * are complete.\n *\n * Reuses the real `wspace-ecoimpacthub-svc` GraphQL operations already\n * consumed by the workspace-facing pages (`ecoListSites`, `ecoArchiveSite`,\n * `ecoListSensors`, `ecoSetSensorStatus`, `ecoListCarbonEntries`,\n * `ecoVerifyCarbonEntry`, `ecoListReports`, `ecoPublishReport`) — no new\n * backend surface. Every mutation still carries its own `@rbac` directive at\n * the gateway; this panel does not re-implement authorization, it is a\n * governance-focused view over the same RBAC-enforced API.\n *\n * Remaining gap (documented, not built here): report-approval workflow\n * routing through wspace-workflow-svc (depends on the C2 event/workflow\n * wiring landing first) — today \"publish\" is a direct status transition,\n * not a multi-step approval chain.\n */\n\nimport type { FC } from 'react';\nimport { useMemo, useState } from 'react';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { FeatureFlagProvider } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { PermissionProvider } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { MapPin, Radio, Factory, FileText, ShieldCheck } from 'lucide-react';\nimport { EcoImpactHubProvider } from './context/EcoImpactHubContext';\nimport { PageLayout } from './components/PageLayout';\nimport { Tabs, type TabItem } from './components/Tabs';\nimport { DataTable, type Column } from './components/DataTable';\nimport { StatusBadge } from './components/StatusBadge';\nimport { LoadingView, ErrorView, Section } from './components/StateViews';\nimport { EmptyState } from './components/EmptyState';\nimport { Pagination } from './components/Pagination';\nimport { FilterTabs, type FilterOption } from './components/FilterTabs';\nimport {\n useEcoSites,\n useEcoArchiveSite,\n useEcoSensors,\n useEcoSetSensorStatus,\n useEcoCarbonEntries,\n useEcoVerifyCarbonEntry,\n useEcoReports,\n useEcoPublishReport,\n} from './hooks/useEcoImpactHubApi';\nimport { formatDate, formatCo2e, formatEnumLabel } from './utils';\nimport type {\n EcoImpactHubRootProps,\n EcoSite,\n EcoSiteStatus,\n EcoSensor,\n EcoSensorStatus,\n EcoCarbonEntry,\n EcoCarbonEntryStatus,\n EcoReport,\n EcoReportStatus,\n} from './types';\n\nexport interface EcoImpactHubAdminRootProps extends EcoImpactHubRootProps {\n /** Workspace token is supplied by admin-app for workspace-scoped MFEs. */\n workspaceToken?: string;\n}\n\ntype AdminTab = 'sites' | 'sensors' | 'carbon' | 'reports';\n\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: 30 * 1000,\n retry: 1,\n refetchOnWindowFocus: false,\n },\n },\n});\n\nconst PAGE_SIZE = 12;\n\nconst SITE_STATUS_OPTIONS: FilterOption<'ALL' | EcoSiteStatus>[] = [\n { value: 'ALL', label: 'All' },\n { value: 'ACTIVE', label: 'Active' },\n { value: 'MONITORING_PAUSED', label: 'Paused' },\n { value: 'ARCHIVED', label: 'Archived' },\n];\n\nconst SENSOR_STATUS_OPTIONS: FilterOption<'ALL' | EcoSensorStatus>[] = [\n { value: 'ALL', label: 'All' },\n { value: 'ONLINE', label: 'Online' },\n { value: 'OFFLINE', label: 'Offline' },\n { value: 'DEGRADED', label: 'Degraded' },\n { value: 'MAINTENANCE', label: 'Maintenance' },\n { value: 'RETIRED', label: 'Retired' },\n];\n\nconst CARBON_STATUS_OPTIONS: FilterOption<'ALL' | EcoCarbonEntryStatus>[] = [\n { value: 'ALL', label: 'All' },\n { value: 'DRAFT', label: 'Draft' },\n { value: 'RECORDED', label: 'Recorded' },\n { value: 'VERIFIED', label: 'Verified' },\n { value: 'ADJUSTED', label: 'Adjusted' },\n];\n\nconst REPORT_STATUS_OPTIONS: FilterOption<'ALL' | EcoReportStatus>[] = [\n { value: 'ALL', label: 'All' },\n { value: 'DRAFT', label: 'Draft' },\n { value: 'IN_REVIEW', label: 'In Review' },\n { value: 'PUBLISHED', label: 'Published' },\n { value: 'ARCHIVED', label: 'Archived' },\n];\n\n// ============================================================================\n// Sites governance\n// ============================================================================\n\nfunction SiteActions({ site }: { site: EcoSite }) {\n const archive = useEcoArchiveSite();\n if (site.status === 'ARCHIVED') {\n return <span className=\"text-xs text-text-secondary\">Archived</span>;\n }\n return (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => archive.mutate(site.id)}\n disabled={archive.isPending}\n >\n Archive\n </Button>\n );\n}\n\nfunction SitesPanel() {\n const [status, setStatus] = useState<'ALL' | EcoSiteStatus>('ALL');\n const { data, isLoading, error, refetch } = useEcoSites({\n status: status === 'ALL' ? undefined : status,\n pagination: { limit: 100 },\n });\n\n const columns = useMemo<Column<EcoSite>[]>(\n () => [\n {\n key: 'name',\n header: 'Site',\n render: (s) => (\n <div className=\"min-w-0\">\n <p className=\"font-medium text-text-primary truncate\">{s.name}</p>\n {s.code && <p className=\"text-xs text-text-secondary\">{s.code}</p>}\n </div>\n ),\n sortValue: (s) => s.name.toLowerCase(),\n },\n {\n key: 'type',\n header: 'Type',\n render: (s) => formatEnumLabel(s.type),\n },\n {\n key: 'region',\n header: 'Region',\n render: (s) => s.region ?? '—',\n hideOnMobile: true,\n },\n {\n key: 'status',\n header: 'Status',\n render: (s) => <StatusBadge status={s.status} />,\n },\n {\n key: 'created',\n header: 'Created',\n render: (s) => formatDate(s.createdAt),\n sortValue: (s) => new Date(s.createdAt).getTime(),\n hideOnMobile: true,\n },\n {\n key: 'actions',\n header: 'Actions',\n align: 'right',\n render: (s) => <SiteActions site={s} />,\n },\n ],\n []\n );\n\n if (isLoading) return <LoadingView label=\"Loading sites…\" />;\n if (error)\n return <ErrorView title=\"Could not load sites\" message={error.message} onRetry={refetch} />;\n\n const rows = data?.items ?? [];\n\n return (\n <Section title=\"Site registry\" description=\"Pause monitoring or archive decommissioned sites.\">\n <div className=\"mb-4\">\n <FilterTabs options={SITE_STATUS_OPTIONS} value={status} onChange={setStatus} />\n </div>\n {rows.length === 0 ? (\n <EmptyState\n icon={<MapPin size={40} />}\n title=\"No sites found\"\n description={`There are no ${status === 'ALL' ? '' : status.toLowerCase()} sites in this workspace.`}\n />\n ) : (\n <DataTable\n columns={columns}\n rows={rows}\n rowKey={(s) => s.id}\n defaultSort={{ key: 'created', dir: 'desc' }}\n />\n )}\n </Section>\n );\n}\n\n// ============================================================================\n// Sensor governance\n// ============================================================================\n\nconst SENSOR_STATUS_TRANSITIONS: Record<EcoSensorStatus, EcoSensorStatus | null> = {\n ONLINE: 'MAINTENANCE',\n OFFLINE: 'MAINTENANCE',\n DEGRADED: 'MAINTENANCE',\n MAINTENANCE: 'ONLINE',\n RETIRED: null,\n};\n\nfunction SensorActions({ sensor }: { sensor: EcoSensor }) {\n const setStatus = useEcoSetSensorStatus();\n const nextStatus = SENSOR_STATUS_TRANSITIONS[sensor.status];\n\n return (\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n {nextStatus && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setStatus.mutate({ id: sensor.id, status: nextStatus })}\n disabled={setStatus.isPending}\n >\n {nextStatus === 'MAINTENANCE' ? 'Send to maintenance' : 'Bring online'}\n </Button>\n )}\n {sensor.status !== 'RETIRED' && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setStatus.mutate({ id: sensor.id, status: 'RETIRED' })}\n disabled={setStatus.isPending}\n >\n Retire\n </Button>\n )}\n </div>\n );\n}\n\nfunction SensorsPanel() {\n const [status, setStatus] = useState<'ALL' | EcoSensorStatus>('ALL');\n const { data, isLoading, error, refetch } = useEcoSensors({\n status: status === 'ALL' ? undefined : status,\n });\n\n const columns = useMemo<Column<EcoSensor>[]>(\n () => [\n {\n key: 'name',\n header: 'Sensor',\n render: (s) => (\n <div className=\"min-w-0\">\n <p className=\"font-medium text-text-primary truncate\">{s.name}</p>\n {s.hardwareId && (\n <p className=\"font-mono text-xs text-text-secondary\">{s.hardwareId}</p>\n )}\n </div>\n ),\n sortValue: (s) => s.name.toLowerCase(),\n },\n {\n key: 'kind',\n header: 'Kind',\n render: (s) => formatEnumLabel(s.kind),\n },\n {\n key: 'site',\n header: 'Site ID',\n render: (s) => <span className=\"font-mono text-xs text-text-secondary\">{s.siteId}</span>,\n hideOnMobile: true,\n },\n {\n key: 'status',\n header: 'Status',\n render: (s) => <StatusBadge status={s.status} />,\n },\n {\n key: 'lastReading',\n header: 'Last Reading',\n render: (s) => (s.lastReadingAt ? formatDate(s.lastReadingAt) : '—'),\n sortValue: (s) => (s.lastReadingAt ? new Date(s.lastReadingAt).getTime() : 0),\n hideOnMobile: true,\n },\n {\n key: 'actions',\n header: 'Actions',\n align: 'right',\n render: (s) => <SensorActions sensor={s} />,\n },\n ],\n []\n );\n\n if (isLoading) return <LoadingView label=\"Loading sensors…\" />;\n if (error)\n return <ErrorView title=\"Could not load sensors\" message={error.message} onRetry={refetch} />;\n\n const rows = data?.items ?? [];\n\n return (\n <Section title=\"Sensor fleet\" description=\"Retire hardware or move sensors into maintenance.\">\n <div className=\"mb-4\">\n <FilterTabs options={SENSOR_STATUS_OPTIONS} value={status} onChange={setStatus} />\n </div>\n {rows.length === 0 ? (\n <EmptyState\n icon={<Radio size={40} />}\n title=\"No sensors found\"\n description={`There are no ${status === 'ALL' ? '' : status.toLowerCase()} sensors in this workspace.`}\n />\n ) : (\n <DataTable\n columns={columns}\n rows={rows}\n rowKey={(s) => s.id}\n defaultSort={{ key: 'lastReading', dir: 'desc' }}\n />\n )}\n </Section>\n );\n}\n\n// ============================================================================\n// Carbon-ledger oversight\n// ============================================================================\n\nfunction CarbonEntryActions({ entry }: { entry: EcoCarbonEntry }) {\n const verify = useEcoVerifyCarbonEntry();\n if (entry.status === 'VERIFIED') {\n return <span className=\"text-xs text-text-secondary\">Verified</span>;\n }\n return (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => verify.mutate(entry.id)}\n disabled={verify.isPending}\n >\n Verify\n </Button>\n );\n}\n\nfunction CarbonLedgerPanel() {\n const [status, setStatus] = useState<'ALL' | EcoCarbonEntryStatus>('ALL');\n const [page, setPage] = useState(0);\n const [cursors, setCursors] = useState<string[]>([]);\n\n const cursor = page > 0 ? cursors[page - 1] : undefined;\n const { data, isLoading, error, refetch } = useEcoCarbonEntries({\n status: status === 'ALL' ? undefined : status,\n pagination: { limit: PAGE_SIZE, cursor },\n });\n\n const columns = useMemo<Column<EcoCarbonEntry>[]>(\n () => [\n {\n key: 'category',\n header: 'Category',\n render: (c) => (\n <div className=\"min-w-0\">\n <p className=\"font-medium text-text-primary truncate\">{c.category}</p>\n {c.factor && <p className=\"text-xs text-text-secondary\">{c.factor.name}</p>}\n </div>\n ),\n },\n {\n key: 'scope',\n header: 'Scope',\n render: (c) => formatEnumLabel(c.scope),\n },\n {\n key: 'co2e',\n header: 'CO₂e',\n align: 'right',\n render: (c) => formatCo2e(c.co2eKg),\n sortValue: (c) => c.co2eKg,\n },\n {\n key: 'period',\n header: 'Period',\n render: (c) => formatDate(c.periodStart),\n sortValue: (c) => new Date(c.periodStart).getTime(),\n hideOnMobile: true,\n },\n {\n key: 'status',\n header: 'Status',\n render: (c) => <StatusBadge status={c.status} />,\n },\n {\n key: 'actions',\n header: 'Actions',\n align: 'right',\n render: (c) => <CarbonEntryActions entry={c} />,\n },\n ],\n []\n );\n\n const handlePageChange = (nextPage: number) => {\n if (nextPage > page && data?.pageInfo.cursor) {\n setCursors((prev) => [...prev, data.pageInfo.cursor as string]);\n } else if (nextPage < page) {\n setCursors((prev) => prev.slice(0, -1));\n }\n setPage(nextPage);\n };\n\n if (isLoading) return <LoadingView label=\"Loading carbon entries…\" />;\n if (error)\n return (\n <ErrorView title=\"Could not load carbon entries\" message={error.message} onRetry={refetch} />\n );\n\n const rows = data?.items ?? [];\n\n return (\n <Section\n title=\"Carbon ledger\"\n description=\"Verify DRAFT/RECORDED entries across all sites and scopes.\"\n >\n <div className=\"mb-4\">\n <FilterTabs\n options={CARBON_STATUS_OPTIONS}\n value={status}\n onChange={(v) => {\n setStatus(v);\n setPage(0);\n setCursors([]);\n }}\n />\n </div>\n {rows.length === 0 ? (\n <EmptyState\n icon={<Factory size={40} />}\n title=\"No carbon entries found\"\n description={`There are no ${status === 'ALL' ? '' : status.toLowerCase()} entries in this workspace.`}\n />\n ) : (\n <>\n <DataTable\n columns={columns}\n rows={rows}\n rowKey={(c) => c.id}\n defaultSort={{ key: 'period', dir: 'desc' }}\n />\n <Pagination\n page={page}\n pageSize={PAGE_SIZE}\n itemCount={rows.length}\n hasMore={data?.pageInfo.hasMore ?? false}\n onPageChange={handlePageChange}\n />\n </>\n )}\n </Section>\n );\n}\n\n// ============================================================================\n// Report sign-off\n// ============================================================================\n\nfunction ReportActions({ report }: { report: EcoReport }) {\n const publish = useEcoPublishReport();\n if (report.status === 'PUBLISHED' || report.status === 'ARCHIVED') {\n return <span className=\"text-xs text-text-secondary\">{formatEnumLabel(report.status)}</span>;\n }\n return (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => publish.mutate({ id: report.id, fileId: report.file?.id ?? null })}\n disabled={publish.isPending}\n >\n Publish\n </Button>\n );\n}\n\nfunction ReportsPanel() {\n const [status, setStatus] = useState<'ALL' | EcoReportStatus>('ALL');\n const { data, isLoading, error, refetch } = useEcoReports(status === 'ALL' ? undefined : status, {\n limit: 100,\n });\n\n const columns = useMemo<Column<EcoReport>[]>(\n () => [\n {\n key: 'title',\n header: 'Report',\n render: (r) => <p className=\"font-medium text-text-primary truncate\">{r.title}</p>,\n sortValue: (r) => r.title.toLowerCase(),\n },\n {\n key: 'framework',\n header: 'Framework',\n render: (r) => formatEnumLabel(r.framework),\n },\n {\n key: 'period',\n header: 'Period',\n render: (r) => `${formatDate(r.periodStart)} – ${formatDate(r.periodEnd)}`,\n hideOnMobile: true,\n },\n {\n key: 'status',\n header: 'Status',\n render: (r) => <StatusBadge status={r.status} />,\n },\n {\n key: 'published',\n header: 'Published',\n render: (r) => (r.publishedAt ? formatDate(r.publishedAt) : '—'),\n sortValue: (r) => (r.publishedAt ? new Date(r.publishedAt).getTime() : 0),\n hideOnMobile: true,\n },\n {\n key: 'actions',\n header: 'Actions',\n align: 'right',\n render: (r) => <ReportActions report={r} />,\n },\n ],\n []\n );\n\n if (isLoading) return <LoadingView label=\"Loading reports…\" />;\n if (error)\n return <ErrorView title=\"Could not load reports\" message={error.message} onRetry={refetch} />;\n\n const rows = data?.items ?? [];\n\n return (\n <Section\n title=\"Sustainability reports\"\n description=\"Publish reports once their line items are complete.\"\n >\n <div className=\"mb-4\">\n <FilterTabs options={REPORT_STATUS_OPTIONS} value={status} onChange={setStatus} />\n </div>\n {rows.length === 0 ? (\n <EmptyState\n icon={<FileText size={40} />}\n title=\"No reports found\"\n description={`There are no ${status === 'ALL' ? '' : status.toLowerCase()} reports in this workspace.`}\n />\n ) : (\n <DataTable\n columns={columns}\n rows={rows}\n rowKey={(r) => r.id}\n defaultSort={{ key: 'period', dir: 'desc' }}\n />\n )}\n </Section>\n );\n}\n\n// ============================================================================\n// Root\n// ============================================================================\n\nfunction EcoImpactHubAdminDashboard() {\n const [activeTab, setActiveTab] = useState<AdminTab>('sites');\n\n const tabs = useMemo<TabItem<AdminTab>[]>(\n () => [\n { value: 'sites', label: 'Sites', icon: <MapPin size={18} /> },\n { value: 'sensors', label: 'Sensors', icon: <Radio size={18} /> },\n { value: 'carbon', label: 'Carbon Ledger', icon: <Factory size={18} /> },\n { value: 'reports', label: 'Reports', icon: <FileText size={18} /> },\n ],\n []\n );\n\n return (\n <PageLayout\n title=\"EcoImpactHub Admin\"\n description=\"Site, sensor, carbon-ledger and report governance.\"\n actions={\n <span className=\"inline-flex items-center gap-2 text-sm text-text-secondary\">\n <ShieldCheck size={18} />\n Workspace-scoped\n </span>\n }\n >\n <Tabs items={tabs} value={activeTab} onChange={setActiveTab} />\n <div className=\"mt-6\">\n {activeTab === 'sites' && <SitesPanel />}\n {activeTab === 'sensors' && <SensorsPanel />}\n {activeTab === 'carbon' && <CarbonLedgerPanel />}\n {activeTab === 'reports' && <ReportsPanel />}\n </div>\n </PageLayout>\n );\n}\n\nexport const EcoImpactHubAdminRoot: FC<EcoImpactHubAdminRootProps> = (props) => {\n return (\n <QueryClientProvider client={queryClient}>\n <FeatureFlagProvider\n workspaceId={props.workspaceId ?? null}\n gateway=\"global\"\n defaultEnabled={true}\n >\n {/* Workspace-scoped RBAC so the admin panel's archive/verify/publish\n controls are gated client-side too. Gateway @rbac remains\n authoritative — this is a UX nicety, not a security control. */}\n <PermissionProvider scopeId={props.workspaceId ?? null} gateway=\"workspace\">\n <EcoImpactHubProvider {...props}>\n <EcoImpactHubAdminDashboard />\n </EcoImpactHubProvider>\n </PermissionProvider>\n </FeatureFlagProvider>\n </QueryClientProvider>\n );\n};\n\nexport { EcoImpactHubAdminRoot as AdminRoot };\n"],"mappings":"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"}
1
+ {"version":3,"file":"EcoImpactHubAdminRoot.js","names":[],"sources":["../../src/ecoimpacthub/EcoImpactHubAdminRoot.tsx"],"sourcesContent":["/**\n * EcoImpactHub Admin Root\n * @module ecoimpacthub\n *\n * Product-specific admin surface mounted inside `admin-app` under\n * `/admin/ecoimpacthub` (BOFF-3118). Per fleet-wide policy the ONLY valid\n * admin surface is the shared `admin.burdenoff.com` app — this is a\n * microfrontend mounted there, not a new subdomain. It covers three\n * governance operations product owners need outside the day-to-day\n * monitoring UI:\n *\n * 1. Site / sensor governance — pause monitoring, retire hardware, archive\n * decommissioned sites.\n * 2. Carbon-ledger oversight — inspect recorded carbon entries across all\n * sites/scopes and verify DRAFT/RECORDED entries.\n * 3. Report sign-off — submit draft reports for approval, approve or reject\n * reports in review, and publish approved reports. The approval lifecycle\n * is gated by a wspace-workflow-svc sign-off workflow (BOFF-3118).\n *\n * Reuses the real `wspace-ecoimpacthub-svc` GraphQL operations already\n * consumed by the workspace-facing pages (`ecoListSites`, `ecoArchiveSite`,\n * `ecoListSensors`, `ecoSetSensorStatus`, `ecoListCarbonEntries`,\n * `ecoVerifyCarbonEntry`, `ecoListReports`, `ecoPublishReport`,\n * `ecoSubmitReportForApproval`, `ecoApproveReport`, `ecoRejectReport`) —\n * the new sign-off mutations are a backend addition consumed here. Every\n * mutation still carries its own `@rbac` directive at the gateway; this panel\n * does not re-implement authorization, it is a governance-focused view over\n * the same RBAC-enforced API.\n */\n\nimport type { FC } from 'react';\nimport { useMemo, useState } from 'react';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { FeatureFlagProvider } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { PermissionProvider } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { MapPin, Radio, Factory, FileText, ShieldCheck } from 'lucide-react';\nimport { EcoImpactHubProvider } from './context/EcoImpactHubContext';\nimport { PageLayout } from './components/PageLayout';\nimport { Tabs, type TabItem } from './components/Tabs';\nimport { DataTable, type Column } from './components/DataTable';\nimport { StatusBadge } from './components/StatusBadge';\nimport { LoadingView, ErrorView, Section } from './components/StateViews';\nimport { EmptyState } from './components/EmptyState';\nimport { Pagination } from './components/Pagination';\nimport { FilterTabs, type FilterOption } from './components/FilterTabs';\nimport {\n useEcoSites,\n useEcoArchiveSite,\n useEcoSensors,\n useEcoSetSensorStatus,\n useEcoCarbonEntries,\n useEcoVerifyCarbonEntry,\n useEcoReports,\n useEcoPublishReport,\n useEcoSubmitReportForApproval,\n useEcoApproveReport,\n useEcoRejectReport,\n} from './hooks/useEcoImpactHubApi';\nimport { formatDate, formatCo2e, formatEnumLabel } from './utils';\nimport type {\n EcoImpactHubRootProps,\n EcoSite,\n EcoSiteStatus,\n EcoSensor,\n EcoSensorStatus,\n EcoCarbonEntry,\n EcoCarbonEntryStatus,\n EcoReport,\n EcoReportStatus,\n} from './types';\n\nexport interface EcoImpactHubAdminRootProps extends EcoImpactHubRootProps {\n /** Workspace token is supplied by admin-app for workspace-scoped MFEs. */\n workspaceToken?: string;\n}\n\ntype AdminTab = 'sites' | 'sensors' | 'carbon' | 'reports';\n\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: 30 * 1000,\n retry: 1,\n refetchOnWindowFocus: false,\n },\n },\n});\n\nconst PAGE_SIZE = 12;\n\nconst SITE_STATUS_OPTIONS: FilterOption<'ALL' | EcoSiteStatus>[] = [\n { value: 'ALL', label: 'All' },\n { value: 'ACTIVE', label: 'Active' },\n { value: 'MONITORING_PAUSED', label: 'Paused' },\n { value: 'ARCHIVED', label: 'Archived' },\n];\n\nconst SENSOR_STATUS_OPTIONS: FilterOption<'ALL' | EcoSensorStatus>[] = [\n { value: 'ALL', label: 'All' },\n { value: 'ONLINE', label: 'Online' },\n { value: 'OFFLINE', label: 'Offline' },\n { value: 'DEGRADED', label: 'Degraded' },\n { value: 'MAINTENANCE', label: 'Maintenance' },\n { value: 'RETIRED', label: 'Retired' },\n];\n\nconst CARBON_STATUS_OPTIONS: FilterOption<'ALL' | EcoCarbonEntryStatus>[] = [\n { value: 'ALL', label: 'All' },\n { value: 'DRAFT', label: 'Draft' },\n { value: 'RECORDED', label: 'Recorded' },\n { value: 'VERIFIED', label: 'Verified' },\n { value: 'ADJUSTED', label: 'Adjusted' },\n];\n\nconst REPORT_STATUS_OPTIONS: FilterOption<'ALL' | EcoReportStatus>[] = [\n { value: 'ALL', label: 'All' },\n { value: 'DRAFT', label: 'Draft' },\n { value: 'IN_REVIEW', label: 'In Review' },\n { value: 'PUBLISHED', label: 'Published' },\n { value: 'ARCHIVED', label: 'Archived' },\n];\n\n// ============================================================================\n// Sites governance\n// ============================================================================\n\nfunction SiteActions({ site }: { site: EcoSite }) {\n const archive = useEcoArchiveSite();\n if (site.status === 'ARCHIVED') {\n return <span className=\"text-xs text-text-secondary\">Archived</span>;\n }\n return (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => archive.mutate(site.id)}\n disabled={archive.isPending}\n >\n Archive\n </Button>\n );\n}\n\nfunction SitesPanel() {\n const [status, setStatus] = useState<'ALL' | EcoSiteStatus>('ALL');\n const { data, isLoading, error, refetch } = useEcoSites({\n status: status === 'ALL' ? undefined : status,\n pagination: { limit: 100 },\n });\n\n const columns = useMemo<Column<EcoSite>[]>(\n () => [\n {\n key: 'name',\n header: 'Site',\n render: (s) => (\n <div className=\"min-w-0\">\n <p className=\"font-medium text-text-primary truncate\">{s.name}</p>\n {s.code && <p className=\"text-xs text-text-secondary\">{s.code}</p>}\n </div>\n ),\n sortValue: (s) => s.name.toLowerCase(),\n },\n {\n key: 'type',\n header: 'Type',\n render: (s) => formatEnumLabel(s.type),\n },\n {\n key: 'region',\n header: 'Region',\n render: (s) => s.region ?? '—',\n hideOnMobile: true,\n },\n {\n key: 'status',\n header: 'Status',\n render: (s) => <StatusBadge status={s.status} />,\n },\n {\n key: 'created',\n header: 'Created',\n render: (s) => formatDate(s.createdAt),\n sortValue: (s) => new Date(s.createdAt).getTime(),\n hideOnMobile: true,\n },\n {\n key: 'actions',\n header: 'Actions',\n align: 'right',\n render: (s) => <SiteActions site={s} />,\n },\n ],\n []\n );\n\n if (isLoading) return <LoadingView label=\"Loading sites…\" />;\n if (error)\n return <ErrorView title=\"Could not load sites\" message={error.message} onRetry={refetch} />;\n\n const rows = data?.items ?? [];\n\n return (\n <Section title=\"Site registry\" description=\"Pause monitoring or archive decommissioned sites.\">\n <div className=\"mb-4\">\n <FilterTabs options={SITE_STATUS_OPTIONS} value={status} onChange={setStatus} />\n </div>\n {rows.length === 0 ? (\n <EmptyState\n icon={<MapPin size={40} />}\n title=\"No sites found\"\n description={`There are no ${status === 'ALL' ? '' : status.toLowerCase()} sites in this workspace.`}\n />\n ) : (\n <DataTable\n columns={columns}\n rows={rows}\n rowKey={(s) => s.id}\n defaultSort={{ key: 'created', dir: 'desc' }}\n />\n )}\n </Section>\n );\n}\n\n// ============================================================================\n// Sensor governance\n// ============================================================================\n\nconst SENSOR_STATUS_TRANSITIONS: Record<EcoSensorStatus, EcoSensorStatus | null> = {\n ONLINE: 'MAINTENANCE',\n OFFLINE: 'MAINTENANCE',\n DEGRADED: 'MAINTENANCE',\n MAINTENANCE: 'ONLINE',\n RETIRED: null,\n};\n\nfunction SensorActions({ sensor }: { sensor: EcoSensor }) {\n const setStatus = useEcoSetSensorStatus();\n const nextStatus = SENSOR_STATUS_TRANSITIONS[sensor.status];\n\n return (\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n {nextStatus && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setStatus.mutate({ id: sensor.id, status: nextStatus })}\n disabled={setStatus.isPending}\n >\n {nextStatus === 'MAINTENANCE' ? 'Send to maintenance' : 'Bring online'}\n </Button>\n )}\n {sensor.status !== 'RETIRED' && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setStatus.mutate({ id: sensor.id, status: 'RETIRED' })}\n disabled={setStatus.isPending}\n >\n Retire\n </Button>\n )}\n </div>\n );\n}\n\nfunction SensorsPanel() {\n const [status, setStatus] = useState<'ALL' | EcoSensorStatus>('ALL');\n const { data, isLoading, error, refetch } = useEcoSensors({\n status: status === 'ALL' ? undefined : status,\n });\n\n const columns = useMemo<Column<EcoSensor>[]>(\n () => [\n {\n key: 'name',\n header: 'Sensor',\n render: (s) => (\n <div className=\"min-w-0\">\n <p className=\"font-medium text-text-primary truncate\">{s.name}</p>\n {s.hardwareId && (\n <p className=\"font-mono text-xs text-text-secondary\">{s.hardwareId}</p>\n )}\n </div>\n ),\n sortValue: (s) => s.name.toLowerCase(),\n },\n {\n key: 'kind',\n header: 'Kind',\n render: (s) => formatEnumLabel(s.kind),\n },\n {\n key: 'site',\n header: 'Site ID',\n render: (s) => <span className=\"font-mono text-xs text-text-secondary\">{s.siteId}</span>,\n hideOnMobile: true,\n },\n {\n key: 'status',\n header: 'Status',\n render: (s) => <StatusBadge status={s.status} />,\n },\n {\n key: 'lastReading',\n header: 'Last Reading',\n render: (s) => (s.lastReadingAt ? formatDate(s.lastReadingAt) : '—'),\n sortValue: (s) => (s.lastReadingAt ? new Date(s.lastReadingAt).getTime() : 0),\n hideOnMobile: true,\n },\n {\n key: 'actions',\n header: 'Actions',\n align: 'right',\n render: (s) => <SensorActions sensor={s} />,\n },\n ],\n []\n );\n\n if (isLoading) return <LoadingView label=\"Loading sensors…\" />;\n if (error)\n return <ErrorView title=\"Could not load sensors\" message={error.message} onRetry={refetch} />;\n\n const rows = data?.items ?? [];\n\n return (\n <Section title=\"Sensor fleet\" description=\"Retire hardware or move sensors into maintenance.\">\n <div className=\"mb-4\">\n <FilterTabs options={SENSOR_STATUS_OPTIONS} value={status} onChange={setStatus} />\n </div>\n {rows.length === 0 ? (\n <EmptyState\n icon={<Radio size={40} />}\n title=\"No sensors found\"\n description={`There are no ${status === 'ALL' ? '' : status.toLowerCase()} sensors in this workspace.`}\n />\n ) : (\n <DataTable\n columns={columns}\n rows={rows}\n rowKey={(s) => s.id}\n defaultSort={{ key: 'lastReading', dir: 'desc' }}\n />\n )}\n </Section>\n );\n}\n\n// ============================================================================\n// Carbon-ledger oversight\n// ============================================================================\n\nfunction CarbonEntryActions({ entry }: { entry: EcoCarbonEntry }) {\n const verify = useEcoVerifyCarbonEntry();\n if (entry.status === 'VERIFIED') {\n return <span className=\"text-xs text-text-secondary\">Verified</span>;\n }\n return (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => verify.mutate(entry.id)}\n disabled={verify.isPending}\n >\n Verify\n </Button>\n );\n}\n\nfunction CarbonLedgerPanel() {\n const [status, setStatus] = useState<'ALL' | EcoCarbonEntryStatus>('ALL');\n const [page, setPage] = useState(0);\n const [cursors, setCursors] = useState<string[]>([]);\n\n const cursor = page > 0 ? cursors[page - 1] : undefined;\n const { data, isLoading, error, refetch } = useEcoCarbonEntries({\n status: status === 'ALL' ? undefined : status,\n pagination: { limit: PAGE_SIZE, cursor },\n });\n\n const columns = useMemo<Column<EcoCarbonEntry>[]>(\n () => [\n {\n key: 'category',\n header: 'Category',\n render: (c) => (\n <div className=\"min-w-0\">\n <p className=\"font-medium text-text-primary truncate\">{c.category}</p>\n {c.factor && <p className=\"text-xs text-text-secondary\">{c.factor.name}</p>}\n </div>\n ),\n },\n {\n key: 'scope',\n header: 'Scope',\n render: (c) => formatEnumLabel(c.scope),\n },\n {\n key: 'co2e',\n header: 'CO₂e',\n align: 'right',\n render: (c) => formatCo2e(c.co2eKg),\n sortValue: (c) => c.co2eKg,\n },\n {\n key: 'period',\n header: 'Period',\n render: (c) => formatDate(c.periodStart),\n sortValue: (c) => new Date(c.periodStart).getTime(),\n hideOnMobile: true,\n },\n {\n key: 'status',\n header: 'Status',\n render: (c) => <StatusBadge status={c.status} />,\n },\n {\n key: 'actions',\n header: 'Actions',\n align: 'right',\n render: (c) => <CarbonEntryActions entry={c} />,\n },\n ],\n []\n );\n\n const handlePageChange = (nextPage: number) => {\n if (nextPage > page && data?.pageInfo.cursor) {\n setCursors((prev) => [...prev, data.pageInfo.cursor as string]);\n } else if (nextPage < page) {\n setCursors((prev) => prev.slice(0, -1));\n }\n setPage(nextPage);\n };\n\n if (isLoading) return <LoadingView label=\"Loading carbon entries…\" />;\n if (error)\n return (\n <ErrorView title=\"Could not load carbon entries\" message={error.message} onRetry={refetch} />\n );\n\n const rows = data?.items ?? [];\n\n return (\n <Section\n title=\"Carbon ledger\"\n description=\"Verify DRAFT/RECORDED entries across all sites and scopes.\"\n >\n <div className=\"mb-4\">\n <FilterTabs\n options={CARBON_STATUS_OPTIONS}\n value={status}\n onChange={(v) => {\n setStatus(v);\n setPage(0);\n setCursors([]);\n }}\n />\n </div>\n {rows.length === 0 ? (\n <EmptyState\n icon={<Factory size={40} />}\n title=\"No carbon entries found\"\n description={`There are no ${status === 'ALL' ? '' : status.toLowerCase()} entries in this workspace.`}\n />\n ) : (\n <>\n <DataTable\n columns={columns}\n rows={rows}\n rowKey={(c) => c.id}\n defaultSort={{ key: 'period', dir: 'desc' }}\n />\n <Pagination\n page={page}\n pageSize={PAGE_SIZE}\n itemCount={rows.length}\n hasMore={data?.pageInfo.hasMore ?? false}\n onPageChange={handlePageChange}\n />\n </>\n )}\n </Section>\n );\n}\n\n// ============================================================================\n// Report sign-off\n// ============================================================================\n\nfunction ReportActions({ report }: { report: EcoReport }) {\n const submit = useEcoSubmitReportForApproval();\n const approve = useEcoApproveReport();\n const reject = useEcoRejectReport();\n const publish = useEcoPublishReport();\n\n const anyPending = submit.isPending || approve.isPending || reject.isPending || publish.isPending;\n\n if (report.status === 'PUBLISHED' || report.status === 'ARCHIVED') {\n return <span className=\"text-xs text-text-secondary\">{formatEnumLabel(report.status)}</span>;\n }\n\n if (report.status === 'DRAFT') {\n return (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => submit.mutate(report.id)}\n disabled={anyPending}\n >\n Submit for approval\n </Button>\n );\n }\n\n // IN_REVIEW\n return (\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n <Button\n variant=\"default\"\n size=\"sm\"\n onClick={() => approve.mutate(report.id)}\n disabled={anyPending}\n >\n Approve\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => reject.mutate({ reportId: report.id, reason: 'Rejected from admin panel' })}\n disabled={anyPending}\n >\n Reject\n </Button>\n </div>\n );\n}\n\nfunction ReportsPanel() {\n const [status, setStatus] = useState<'ALL' | EcoReportStatus>('ALL');\n const { data, isLoading, error, refetch } = useEcoReports(status === 'ALL' ? undefined : status, {\n limit: 100,\n });\n\n const columns = useMemo<Column<EcoReport>[]>(\n () => [\n {\n key: 'title',\n header: 'Report',\n render: (r) => <p className=\"font-medium text-text-primary truncate\">{r.title}</p>,\n sortValue: (r) => r.title.toLowerCase(),\n },\n {\n key: 'framework',\n header: 'Framework',\n render: (r) => formatEnumLabel(r.framework),\n },\n {\n key: 'period',\n header: 'Period',\n render: (r) => `${formatDate(r.periodStart)} – ${formatDate(r.periodEnd)}`,\n hideOnMobile: true,\n },\n {\n key: 'status',\n header: 'Status',\n render: (r) => <StatusBadge status={r.status} />,\n },\n {\n key: 'published',\n header: 'Published',\n render: (r) => (r.publishedAt ? formatDate(r.publishedAt) : '—'),\n sortValue: (r) => (r.publishedAt ? new Date(r.publishedAt).getTime() : 0),\n hideOnMobile: true,\n },\n {\n key: 'actions',\n header: 'Actions',\n align: 'right',\n render: (r) => <ReportActions report={r} />,\n },\n ],\n []\n );\n\n if (isLoading) return <LoadingView label=\"Loading reports…\" />;\n if (error)\n return <ErrorView title=\"Could not load reports\" message={error.message} onRetry={refetch} />;\n\n const rows = data?.items ?? [];\n\n return (\n <Section\n title=\"Sustainability reports\"\n description=\"Submit draft reports for approval, then approve, reject, or publish them.\"\n >\n <div className=\"mb-4\">\n <FilterTabs options={REPORT_STATUS_OPTIONS} value={status} onChange={setStatus} />\n </div>\n {rows.length === 0 ? (\n <EmptyState\n icon={<FileText size={40} />}\n title=\"No reports found\"\n description={`There are no ${status === 'ALL' ? '' : status.toLowerCase()} reports in this workspace.`}\n />\n ) : (\n <DataTable\n columns={columns}\n rows={rows}\n rowKey={(r) => r.id}\n defaultSort={{ key: 'period', dir: 'desc' }}\n />\n )}\n </Section>\n );\n}\n\n// ============================================================================\n// Root\n// ============================================================================\n\nfunction EcoImpactHubAdminDashboard() {\n const [activeTab, setActiveTab] = useState<AdminTab>('sites');\n\n const tabs = useMemo<TabItem<AdminTab>[]>(\n () => [\n { value: 'sites', label: 'Sites', icon: <MapPin size={18} /> },\n { value: 'sensors', label: 'Sensors', icon: <Radio size={18} /> },\n { value: 'carbon', label: 'Carbon Ledger', icon: <Factory size={18} /> },\n { value: 'reports', label: 'Reports', icon: <FileText size={18} /> },\n ],\n []\n );\n\n return (\n <PageLayout\n title=\"EcoImpactHub Admin\"\n description=\"Site, sensor, carbon-ledger and report governance.\"\n actions={\n <span className=\"inline-flex items-center gap-2 text-sm text-text-secondary\">\n <ShieldCheck size={18} />\n Workspace-scoped\n </span>\n }\n >\n <Tabs items={tabs} value={activeTab} onChange={setActiveTab} />\n <div className=\"mt-6\">\n {activeTab === 'sites' && <SitesPanel />}\n {activeTab === 'sensors' && <SensorsPanel />}\n {activeTab === 'carbon' && <CarbonLedgerPanel />}\n {activeTab === 'reports' && <ReportsPanel />}\n </div>\n </PageLayout>\n );\n}\n\nexport const EcoImpactHubAdminRoot: FC<EcoImpactHubAdminRootProps> = (props) => {\n return (\n <QueryClientProvider client={queryClient}>\n <FeatureFlagProvider\n workspaceId={props.workspaceId ?? null}\n gateway=\"global\"\n defaultEnabled={true}\n >\n {/* Workspace-scoped RBAC so the admin panel's archive/verify/publish\n controls are gated client-side too. Gateway @rbac remains\n authoritative — this is a UX nicety, not a security control. */}\n <PermissionProvider scopeId={props.workspaceId ?? null} gateway=\"workspace\">\n <EcoImpactHubProvider {...props}>\n <EcoImpactHubAdminDashboard />\n </EcoImpactHubProvider>\n </PermissionProvider>\n </FeatureFlagProvider>\n </QueryClientProvider>\n );\n};\n\nexport { EcoImpactHubAdminRoot as AdminRoot };\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { EcoConnection, EcoSite, EcoSiteStatus, EcoSiteType, EcoSensor, EcoSensorKind, EcoSensorStatus, EcoMeasurement, EcoAlertThreshold, EcoSpecies, EcoTaxonGroup, EcoConservationStatus, EcoObservation, EcoHabitatProject, EcoHabitatProjectStatus, EcoRestorationActivity, EcoEmissionFactor, EcoEmissionScope, EcoCarbonEntry, EcoCarbonEntryStatus, EcoReductionTarget, EcoReductionTargetStatus, EcoReport, EcoReportStatus, EcoReportLineItem, EcoCreateSiteInput, EcoUpdateSiteInput, EcoCreateSensorInput, EcoRecordMeasurementInput, EcoCreateThresholdInput, EcoCreateSpeciesInput, EcoUpdateSpeciesInput, EcoRecordObservationInput, EcoCreateHabitatProjectInput, EcoLogRestorationActivityInput, EcoCreateEmissionFactorInput, EcoRecordCarbonEntryInput, EcoCreateReductionTargetInput, EcoCreateReportInput, EcoAddReportLineItemInput, PaginationInput } from '../types';
1
+ import { EcoConnection, EcoSite, EcoSiteStatus, EcoSiteType, EcoSensor, EcoSensorKind, EcoSensorStatus, EcoMeasurement, EcoAlertThreshold, EcoSpecies, EcoTaxonGroup, EcoConservationStatus, EcoObservation, EcoHabitatProject, EcoHabitatProjectStatus, EcoRestorationActivity, EcoEmissionFactor, EcoEmissionScope, EcoCarbonEntry, EcoCarbonEntryStatus, EcoReductionTarget, EcoReductionTargetStatus, EcoReport, EcoReportStatus, EcoReportLineItem, EcoCreateSiteInput, EcoUpdateSiteInput, EcoCreateSensorInput, EcoRecordMeasurementInput, EcoCreateThresholdInput, EcoCreateSpeciesInput, EcoUpdateSpeciesInput, EcoRecordObservationInput, EcoCreateHabitatProjectInput, EcoLogRestorationActivityInput, EcoCreateEmissionFactorInput, EcoRecordCarbonEntryInput, EcoCreateReductionTargetInput, EcoCreateReportInput, EcoAddReportLineItemInput, EcoRejectReportInput, PaginationInput } from '../types';
2
2
 
3
3
  export interface SiteFilters {
4
4
  status?: EcoSiteStatus;
@@ -101,4 +101,7 @@ export declare const useEcoPublishReport: () => import('@tanstack/react-query').
101
101
  id: string;
102
102
  fileId?: string | null;
103
103
  }, unknown>;
104
+ export declare const useEcoSubmitReportForApproval: () => import('@tanstack/react-query').UseMutationResult<EcoReport, Error, string, unknown>;
105
+ export declare const useEcoApproveReport: () => import('@tanstack/react-query').UseMutationResult<EcoReport, Error, string, unknown>;
106
+ export declare const useEcoRejectReport: () => import('@tanstack/react-query').UseMutationResult<EcoReport, Error, EcoRejectReportInput, unknown>;
104
107
  //# sourceMappingURL=useEcoImpactHubApi.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useEcoImpactHubApi.d.ts","sourceRoot":"","sources":["../../../src/ecoimpacthub/hooks/useEcoImpactHubApi.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useEcoImpactHubApi.d.ts","sourceRoot":"","sources":["../../../src/ecoimpacthub/hooks/useEcoImpactHubApi.ts"],"names":[],"mappings":"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"}
@@ -53,7 +53,7 @@ var a = () => {
53
53
  }, c = {
54
54
  limit: 50,
55
55
  offset: 0
56
- }, l = "\n id workspaceId name code type status description latitude longitude\n areaHectares country region createdAt updatedAt\n", u = "\n id workspaceId siteId name kind status hardwareId unit lastReadingAt installedAt\n createdAt updatedAt\n", d = "\n id workspaceId siteId sensorId parameter value unit source recordedAt isBreach notes\n createdAt updatedAt\n", f = "\n id workspaceId siteId parameter direction severity limitValue minValue maxValue unit\n isActive createdAt updatedAt\n", p = "\n id workspaceId commonName scientificName taxonGroup conservationStatus isPriority\n description createdAt updatedAt\n", m = "\n id workspaceId speciesId siteId method count observedAt latitude longitude observerId\n notes evidence { id } createdAt updatedAt\n", h = "\n id workspaceId name status description siteId targetHectares budgetAmount currency\n managerId startDate endDate completedAt createdAt updatedAt\n", g = "\n id workspaceId projectId type summary details quantity unit performedAt createdAt updatedAt\n", _ = "\n id workspaceId name scope activityUnit factorKgco2e source validYear isActive\n createdAt updatedAt\n", v = "\n id workspaceId siteId factorId scope status category activityValue activityUnit co2eKg\n periodStart notes createdAt updatedAt\n", y = "\n id workspaceId name status metric baselineYear baselineValue targetYear targetValue unit\n description createdAt updatedAt\n", b = "\n id workspaceId title framework status periodStart periodEnd summary publishedAt\n file { id } createdAt updatedAt\n", x = "\n id workspaceId reportId carbonEntryId label value unit category createdAt updatedAt\n", S = (t = {}) => {
56
+ }, l = "\n id workspaceId name code type status description latitude longitude\n areaHectares country region createdAt updatedAt\n", u = "\n id workspaceId siteId name kind status hardwareId unit lastReadingAt installedAt\n createdAt updatedAt\n", d = "\n id workspaceId siteId sensorId parameter value unit source recordedAt isBreach notes\n createdAt updatedAt\n", f = "\n id workspaceId siteId parameter direction severity limitValue minValue maxValue unit\n isActive createdAt updatedAt\n", p = "\n id workspaceId commonName scientificName taxonGroup conservationStatus isPriority\n description createdAt updatedAt\n", m = "\n id workspaceId speciesId siteId method count observedAt latitude longitude observerId\n notes evidence { id } createdAt updatedAt\n", h = "\n id workspaceId name status description siteId targetHectares budgetAmount currency\n managerId startDate endDate completedAt createdAt updatedAt\n", g = "\n id workspaceId projectId type summary details quantity unit performedAt createdAt updatedAt\n", _ = "\n id workspaceId name scope activityUnit factorKgco2e source validYear isActive\n createdAt updatedAt\n", v = "\n id workspaceId siteId factorId scope status category activityValue activityUnit co2eKg\n periodStart notes createdAt updatedAt\n", y = "\n id workspaceId name status metric baselineYear baselineValue targetYear targetValue unit\n description createdAt updatedAt\n", b = "\n id workspaceId title framework status periodStart periodEnd summary publishedAt\n workflowRunId approvedBy approvedAt rejectedAt rejectionReason\n file { id } createdAt updatedAt\n", x = "\n id workspaceId reportId carbonEntryId label value unit category createdAt updatedAt\n", S = (t = {}) => {
57
57
  let { apiGatewayUrl: r } = e();
58
58
  return n({
59
59
  queryKey: [...s.sites, t],
@@ -230,13 +230,13 @@ var a = () => {
230
230
  i.invalidateQueries({ queryKey: s.species }), i.invalidateQueries({ queryKey: s.speciesOne(e.id) });
231
231
  }
232
232
  });
233
- }, ee = () => {
233
+ }, R = () => {
234
234
  let { apiGatewayUrl: n } = e(), i = r();
235
235
  return t({
236
236
  mutationFn: async (e) => (await o("mutation EcoArchiveSpecies($id: ID!) { ecoArchiveSpecies(id: $id) }", { id: e }, n)).ecoArchiveSpecies,
237
237
  onSuccess: () => i.invalidateQueries({ queryKey: s.species })
238
238
  });
239
- }, R = (t = {}) => {
239
+ }, z = (t = {}) => {
240
240
  let { apiGatewayUrl: r } = e();
241
241
  return n({
242
242
  queryKey: [...s.observations, t],
@@ -251,7 +251,7 @@ var a = () => {
251
251
  pagination: t.pagination ?? c
252
252
  }, r)).ecoListObservations
253
253
  });
254
- }, z = () => {
254
+ }, B = () => {
255
255
  let { apiGatewayUrl: n } = e(), i = r();
256
256
  return t({
257
257
  mutationFn: async (e) => (await o(`mutation EcoRecordObservation($input: EcoRecordObservationInput!) {
@@ -261,7 +261,7 @@ var a = () => {
261
261
  i.invalidateQueries({ queryKey: s.observations }), i.invalidateQueries({ queryKey: s.speciesOne(e.speciesId) });
262
262
  }
263
263
  });
264
- }, B = (t) => {
264
+ }, V = (t) => {
265
265
  let { apiGatewayUrl: r } = e();
266
266
  return n({
267
267
  queryKey: [...s.habitatProjects, t ?? "all"],
@@ -272,7 +272,7 @@ var a = () => {
272
272
  }
273
273
  }`, { status: t }, r)).ecoListHabitatProjects
274
274
  });
275
- }, V = (t) => {
275
+ }, ee = (t) => {
276
276
  let { apiGatewayUrl: r } = e();
277
277
  return n({
278
278
  queryKey: s.habitatProject(t ?? ""),
@@ -461,8 +461,38 @@ var a = () => {
461
461
  i.invalidateQueries({ queryKey: s.reports }), i.invalidateQueries({ queryKey: s.report(e.id) });
462
462
  }
463
463
  });
464
+ }, oe = () => {
465
+ let { apiGatewayUrl: n } = e(), i = r();
466
+ return t({
467
+ mutationFn: async (e) => (await o(`mutation EcoSubmitReportForApproval($id: ID!) {
468
+ ecoSubmitReportForApproval(id: $id) { ${b} }
469
+ }`, { id: e }, n)).ecoSubmitReportForApproval,
470
+ onSuccess: (e) => {
471
+ i.invalidateQueries({ queryKey: s.reports }), i.invalidateQueries({ queryKey: s.report(e.id) });
472
+ }
473
+ });
474
+ }, se = () => {
475
+ let { apiGatewayUrl: n } = e(), i = r();
476
+ return t({
477
+ mutationFn: async (e) => (await o(`mutation EcoApproveReport($id: ID!) {
478
+ ecoApproveReport(id: $id) { ${b} }
479
+ }`, { id: e }, n)).ecoApproveReport,
480
+ onSuccess: (e) => {
481
+ i.invalidateQueries({ queryKey: s.reports }), i.invalidateQueries({ queryKey: s.report(e.id) });
482
+ }
483
+ });
484
+ }, ce = () => {
485
+ let { apiGatewayUrl: n } = e(), i = r();
486
+ return t({
487
+ mutationFn: async (e) => (await o(`mutation EcoRejectReport($input: EcoRejectReportInput!) {
488
+ ecoRejectReport(input: $input) { ${b} }
489
+ }`, { input: e }, n)).ecoRejectReport,
490
+ onSuccess: (e) => {
491
+ i.invalidateQueries({ queryKey: s.reports }), i.invalidateQueries({ queryKey: s.report(e.id) });
492
+ }
493
+ });
464
494
  };
465
495
  //#endregion
466
- export { ie as useEcoAddReportLineItem, T as useEcoArchiveSite, ee as useEcoArchiveSpecies, q as useEcoCarbonEntries, J as useEcoCarbonTotals, K as useEcoCreateEmissionFactor, H as useEcoCreateHabitatProject, Q as useEcoCreateReductionTarget, re as useEcoCreateReport, D as useEcoCreateSensor, w as useEcoCreateSite, I as useEcoCreateSpecies, M as useEcoCreateThreshold, G as useEcoEmissionFactors, V as useEcoHabitatProject, B as useEcoHabitatProjects, W as useEcoLogRestorationActivity, k as useEcoMeasurements, R as useEcoObservations, ae as useEcoPublishReport, Y as useEcoRecordCarbonEntry, A as useEcoRecordMeasurement, z as useEcoRecordObservation, Z as useEcoReductionTargets, ne as useEcoReport, te as useEcoReports, E as useEcoSensors, $ as useEcoSetReductionTargetStatus, O as useEcoSetSensorStatus, N as useEcoSetThresholdActive, C as useEcoSite, S as useEcoSites, P as useEcoSpecies, F as useEcoSpeciesDetail, j as useEcoThresholds, U as useEcoTransitionHabitatProject, L as useEcoUpdateSpecies, X as useEcoVerifyCarbonEntry };
496
+ export { ie as useEcoAddReportLineItem, se as useEcoApproveReport, T as useEcoArchiveSite, R as useEcoArchiveSpecies, q as useEcoCarbonEntries, J as useEcoCarbonTotals, K as useEcoCreateEmissionFactor, H as useEcoCreateHabitatProject, Q as useEcoCreateReductionTarget, re as useEcoCreateReport, D as useEcoCreateSensor, w as useEcoCreateSite, I as useEcoCreateSpecies, M as useEcoCreateThreshold, G as useEcoEmissionFactors, ee as useEcoHabitatProject, V as useEcoHabitatProjects, W as useEcoLogRestorationActivity, k as useEcoMeasurements, z as useEcoObservations, ae as useEcoPublishReport, Y as useEcoRecordCarbonEntry, A as useEcoRecordMeasurement, B as useEcoRecordObservation, Z as useEcoReductionTargets, ce as useEcoRejectReport, ne as useEcoReport, te as useEcoReports, E as useEcoSensors, $ as useEcoSetReductionTargetStatus, O as useEcoSetSensorStatus, N as useEcoSetThresholdActive, C as useEcoSite, S as useEcoSites, P as useEcoSpecies, F as useEcoSpeciesDetail, oe as useEcoSubmitReportForApproval, j as useEcoThresholds, U as useEcoTransitionHabitatProject, L as useEcoUpdateSpecies, X as useEcoVerifyCarbonEntry };
467
497
 
468
498
  //# sourceMappingURL=useEcoImpactHubApi.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useEcoImpactHubApi.js","names":[],"sources":["../../../src/ecoimpacthub/hooks/useEcoImpactHubApi.ts"],"sourcesContent":["/**\n * EcoImpactHub API hooks\n * @module ecoimpacthub/hooks\n *\n * React-Query hooks wired DIRECTLY to the real `wspace-ecoimpacthub-svc`\n * federated GraphQL contract (the `eco*` operations). Every query/mutation\n * below uses an inline gql string whose fields match the svc\n * `.hive-schema.graphql` exactly. No mock data.\n *\n * Transport: `graphqlFetch({ gateway: 'workspace', workspaceToken: true })` —\n * the host shell supplies the gateway base URL + a workspace-scoped token.\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\n\nimport { useEcoImpactHub } from '../context';\nimport type {\n EcoConnection,\n EcoSite,\n EcoSiteStatus,\n EcoSiteType,\n EcoSensor,\n EcoSensorKind,\n EcoSensorStatus,\n EcoMeasurement,\n EcoAlertThreshold,\n EcoSpecies,\n EcoTaxonGroup,\n EcoConservationStatus,\n EcoObservation,\n EcoHabitatProject,\n EcoHabitatProjectStatus,\n EcoRestorationActivity,\n EcoEmissionFactor,\n EcoEmissionScope,\n EcoCarbonEntry,\n EcoCarbonEntryStatus,\n EcoReductionTarget,\n EcoReductionTargetStatus,\n EcoReport,\n EcoReportStatus,\n EcoReportLineItem,\n EcoCreateSiteInput,\n EcoUpdateSiteInput,\n EcoCreateSensorInput,\n EcoRecordMeasurementInput,\n EcoCreateThresholdInput,\n EcoCreateSpeciesInput,\n EcoUpdateSpeciesInput,\n EcoRecordObservationInput,\n EcoCreateHabitatProjectInput,\n EcoLogRestorationActivityInput,\n EcoCreateEmissionFactorInput,\n EcoRecordCarbonEntryInput,\n EcoCreateReductionTargetInput,\n EcoCreateReportInput,\n EcoAddReportLineItemInput,\n PaginationInput,\n} from '../types';\n\n// ============================================================================\n// Transport\n// ============================================================================\n\n/**\n * fe-libs `graphqlFetch` coalesces `query` responses in an in-memory cache keyed\n * by operationName+variables for ~15s (mutations are never cached). A read\n * issued right after a write (e.g. React-Query refetch triggered by our\n * `invalidateQueries`) would otherwise return the PRE-mutation response until the\n * TTL expires — making just-created/updated rows invisible until a full reload.\n * fe-libs' documented remedy is that write-performing callers clear those caches;\n * we do exactly that (the same maps `clearGraphqlFetchResponseCache` clears)\n * after every eco mutation so every follow-up read is fresh.\n */\ntype GraphqlReadCacheGlobals = {\n __graphqlFetchResponseCache?: { clear: () => void };\n __graphqlFetchPendingResponses?: { clear: () => void };\n __boffGraphQLResponseCache?: { clear: () => void };\n};\n\nconst clearGraphqlReadCaches = (): void => {\n const g = globalThis as GraphqlReadCacheGlobals;\n g.__graphqlFetchResponseCache?.clear();\n g.__graphqlFetchPendingResponses?.clear();\n g.__boffGraphQLResponseCache?.clear();\n};\n\nconst ecoQuery = async <TData>(\n query: string,\n variables: Record<string, unknown>,\n baseUrl?: string\n): Promise<TData> => {\n const response = await graphqlFetch<TData>({\n gateway: 'workspace',\n baseUrl,\n query,\n variables,\n workspaceToken: true,\n });\n\n if (response.errors?.length) {\n throw new Error(response.errors[0]?.message ?? 'GraphQL request failed');\n }\n if (!response.data) {\n throw new Error('GraphQL response did not include data');\n }\n // After a write, drop fe-libs' short-lived read caches so the invalidation\n // refetch that follows reads fresh data instead of the pre-mutation snapshot.\n if (/^\\s*mutation\\b/.test(query)) {\n clearGraphqlReadCaches();\n }\n return response.data;\n};\n\n// React-Query key roots (one namespace per domain entity).\nconst KEY = {\n sites: ['ecoimpacthub', 'sites'] as const,\n site: (id: string) => ['ecoimpacthub', 'site', id] as const,\n sensors: ['ecoimpacthub', 'sensors'] as const,\n measurements: ['ecoimpacthub', 'measurements'] as const,\n thresholds: ['ecoimpacthub', 'thresholds'] as const,\n species: ['ecoimpacthub', 'species'] as const,\n speciesOne: (id: string) => ['ecoimpacthub', 'species', id] as const,\n observations: ['ecoimpacthub', 'observations'] as const,\n habitatProjects: ['ecoimpacthub', 'habitat-projects'] as const,\n habitatProject: (id: string) => ['ecoimpacthub', 'habitat-project', id] as const,\n emissionFactors: ['ecoimpacthub', 'emission-factors'] as const,\n carbonEntries: ['ecoimpacthub', 'carbon-entries'] as const,\n carbonTotals: ['ecoimpacthub', 'carbon-totals'] as const,\n reductionTargets: ['ecoimpacthub', 'reduction-targets'] as const,\n reports: ['ecoimpacthub', 'reports'] as const,\n report: (id: string) => ['ecoimpacthub', 'report', id] as const,\n};\n\nconst DEFAULT_PAGE: PaginationInput = { limit: 50, offset: 0 };\n\n// ============================================================================\n// Reusable gql field selections (codegen-free strictness)\n// ============================================================================\n\nconst SITE_FIELDS = `\n id workspaceId name code type status description latitude longitude\n areaHectares country region createdAt updatedAt\n`;\n\nconst SENSOR_FIELDS = `\n id workspaceId siteId name kind status hardwareId unit lastReadingAt installedAt\n createdAt updatedAt\n`;\n\nconst MEASUREMENT_FIELDS = `\n id workspaceId siteId sensorId parameter value unit source recordedAt isBreach notes\n createdAt updatedAt\n`;\n\nconst THRESHOLD_FIELDS = `\n id workspaceId siteId parameter direction severity limitValue minValue maxValue unit\n isActive createdAt updatedAt\n`;\n\nconst SPECIES_FIELDS = `\n id workspaceId commonName scientificName taxonGroup conservationStatus isPriority\n description createdAt updatedAt\n`;\n\nconst OBSERVATION_FIELDS = `\n id workspaceId speciesId siteId method count observedAt latitude longitude observerId\n notes evidence { id } createdAt updatedAt\n`;\n\nconst HABITAT_FIELDS = `\n id workspaceId name status description siteId targetHectares budgetAmount currency\n managerId startDate endDate completedAt createdAt updatedAt\n`;\n\nconst ACTIVITY_FIELDS = `\n id workspaceId projectId type summary details quantity unit performedAt createdAt updatedAt\n`;\n\nconst FACTOR_FIELDS = `\n id workspaceId name scope activityUnit factorKgco2e source validYear isActive\n createdAt updatedAt\n`;\n\nconst CARBON_FIELDS = `\n id workspaceId siteId factorId scope status category activityValue activityUnit co2eKg\n periodStart notes createdAt updatedAt\n`;\n\nconst TARGET_FIELDS = `\n id workspaceId name status metric baselineYear baselineValue targetYear targetValue unit\n description createdAt updatedAt\n`;\n\nconst REPORT_FIELDS = `\n id workspaceId title framework status periodStart periodEnd summary publishedAt\n file { id } createdAt updatedAt\n`;\n\nconst LINE_ITEM_FIELDS = `\n id workspaceId reportId carbonEntryId label value unit category createdAt updatedAt\n`;\n\n// ============================================================================\n// Sites (Environmental Monitoring)\n// ============================================================================\n\nexport interface SiteFilters {\n status?: EcoSiteStatus;\n type?: EcoSiteType;\n pagination?: PaginationInput;\n}\n\nexport const useEcoSites = (filters: SiteFilters = {}) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.sites, filters],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListSites: EcoConnection<EcoSite> }>(\n `query EcoListSites($status: EcoSiteStatus, $type: EcoSiteType, $pagination: PaginationInput) {\n ecoListSites(status: $status, type: $type, pagination: $pagination) {\n items { ${SITE_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n status: filters.status,\n type: filters.type,\n pagination: filters.pagination ?? DEFAULT_PAGE,\n },\n apiGatewayUrl\n );\n return result.ecoListSites;\n },\n });\n};\n\nexport const useEcoSite = (id: string | undefined) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: KEY.site(id ?? ''),\n enabled: Boolean(id),\n queryFn: async () => {\n const result = await ecoQuery<{ ecoSite: EcoSite | null }>(\n `query EcoSite($id: ID!) {\n ecoSite(id: $id) {\n ${SITE_FIELDS}\n sensors { ${SENSOR_FIELDS} }\n thresholds { ${THRESHOLD_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.ecoSite;\n },\n });\n};\n\nexport const useEcoCreateSite = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoCreateSiteInput) => {\n const result = await ecoQuery<{ ecoCreateSite: EcoSite }>(\n `mutation EcoCreateSite($input: EcoCreateSiteInput!) {\n ecoCreateSite(input: $input) { ${SITE_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoCreateSite;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.sites }),\n });\n};\n\nexport const useEcoUpdateSite = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; input: EcoUpdateSiteInput }) => {\n const result = await ecoQuery<{ ecoUpdateSite: EcoSite }>(\n `mutation EcoUpdateSite($id: ID!, $input: EcoUpdateSiteInput!) {\n ecoUpdateSite(id: $id, input: $input) { ${SITE_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.ecoUpdateSite;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.sites });\n qc.invalidateQueries({ queryKey: KEY.site(data.id) });\n },\n });\n};\n\nexport const useEcoArchiveSite = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await ecoQuery<{ ecoArchiveSite: boolean }>(\n `mutation EcoArchiveSite($id: ID!) { ecoArchiveSite(id: $id) }`,\n { id },\n apiGatewayUrl\n );\n return result.ecoArchiveSite;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.sites }),\n });\n};\n\n// ============================================================================\n// Sensors / Measurements / Thresholds (Environmental Monitoring)\n// ============================================================================\n\nexport interface SensorFilters {\n siteId?: string;\n kind?: EcoSensorKind;\n status?: EcoSensorStatus;\n}\n\nexport const useEcoSensors = (filters: SensorFilters = {}) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.sensors, filters],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListSensors: EcoConnection<EcoSensor> }>(\n `query EcoListSensors($siteId: ID, $kind: EcoSensorKind, $status: EcoSensorStatus) {\n ecoListSensors(siteId: $siteId, kind: $kind, status: $status) {\n items { ${SENSOR_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { siteId: filters.siteId, kind: filters.kind, status: filters.status },\n apiGatewayUrl\n );\n return result.ecoListSensors;\n },\n });\n};\n\nexport const useEcoCreateSensor = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoCreateSensorInput) => {\n const result = await ecoQuery<{ ecoCreateSensor: EcoSensor }>(\n `mutation EcoCreateSensor($input: EcoCreateSensorInput!) {\n ecoCreateSensor(input: $input) { ${SENSOR_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoCreateSensor;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.sensors });\n qc.invalidateQueries({ queryKey: KEY.site(data.siteId) });\n },\n });\n};\n\nexport const useEcoSetSensorStatus = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; status: EcoSensorStatus }) => {\n const result = await ecoQuery<{ ecoSetSensorStatus: EcoSensor }>(\n `mutation EcoSetSensorStatus($id: ID!, $status: EcoSensorStatus!) {\n ecoSetSensorStatus(id: $id, status: $status) { ${SENSOR_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.ecoSetSensorStatus;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.sensors });\n qc.invalidateQueries({ queryKey: KEY.site(data.siteId) });\n },\n });\n};\n\nexport interface MeasurementFilters {\n siteId?: string;\n sensorId?: string;\n parameter?: string;\n breachesOnly?: boolean;\n pagination?: PaginationInput;\n}\n\nexport const useEcoMeasurements = (filters: MeasurementFilters = {}) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.measurements, filters],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListMeasurements: EcoConnection<EcoMeasurement> }>(\n `query EcoListMeasurements($siteId: ID, $sensorId: ID, $parameter: String, $breachesOnly: Boolean, $pagination: PaginationInput) {\n ecoListMeasurements(siteId: $siteId, sensorId: $sensorId, parameter: $parameter, breachesOnly: $breachesOnly, pagination: $pagination) {\n items { ${MEASUREMENT_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n siteId: filters.siteId,\n sensorId: filters.sensorId,\n parameter: filters.parameter,\n breachesOnly: filters.breachesOnly,\n pagination: filters.pagination ?? DEFAULT_PAGE,\n },\n apiGatewayUrl\n );\n return result.ecoListMeasurements;\n },\n });\n};\n\nexport const useEcoRecordMeasurement = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoRecordMeasurementInput) => {\n const result = await ecoQuery<{ ecoRecordMeasurement: EcoMeasurement }>(\n `mutation EcoRecordMeasurement($input: EcoRecordMeasurementInput!) {\n ecoRecordMeasurement(input: $input) { ${MEASUREMENT_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoRecordMeasurement;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.measurements }),\n });\n};\n\nexport const useEcoThresholds = (siteId?: string) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.thresholds, siteId ?? 'all'],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListThresholds: EcoConnection<EcoAlertThreshold> }>(\n `query EcoListThresholds($siteId: ID) {\n ecoListThresholds(siteId: $siteId) {\n items { ${THRESHOLD_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { siteId },\n apiGatewayUrl\n );\n return result.ecoListThresholds;\n },\n });\n};\n\nexport const useEcoCreateThreshold = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoCreateThresholdInput) => {\n const result = await ecoQuery<{ ecoCreateThreshold: EcoAlertThreshold }>(\n `mutation EcoCreateThreshold($input: EcoCreateThresholdInput!) {\n ecoCreateThreshold(input: $input) { ${THRESHOLD_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoCreateThreshold;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.thresholds });\n qc.invalidateQueries({ queryKey: KEY.site(data.siteId) });\n },\n });\n};\n\nexport const useEcoSetThresholdActive = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; isActive: boolean }) => {\n const result = await ecoQuery<{ ecoSetThresholdActive: EcoAlertThreshold }>(\n `mutation EcoSetThresholdActive($id: ID!, $isActive: Boolean!) {\n ecoSetThresholdActive(id: $id, isActive: $isActive) { ${THRESHOLD_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.ecoSetThresholdActive;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.thresholds }),\n });\n};\n\n// ============================================================================\n// Species / Observations / Habitat (Conservation)\n// ============================================================================\n\nexport interface SpeciesFilters {\n taxonGroup?: EcoTaxonGroup;\n conservationStatus?: EcoConservationStatus;\n priorityOnly?: boolean;\n pagination?: PaginationInput;\n}\n\nexport const useEcoSpecies = (filters: SpeciesFilters = {}) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.species, filters],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListSpecies: EcoConnection<EcoSpecies> }>(\n `query EcoListSpecies($taxonGroup: EcoTaxonGroup, $conservationStatus: EcoConservationStatus, $priorityOnly: Boolean, $pagination: PaginationInput) {\n ecoListSpecies(taxonGroup: $taxonGroup, conservationStatus: $conservationStatus, priorityOnly: $priorityOnly, pagination: $pagination) {\n items { ${SPECIES_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n taxonGroup: filters.taxonGroup,\n conservationStatus: filters.conservationStatus,\n priorityOnly: filters.priorityOnly,\n pagination: filters.pagination ?? DEFAULT_PAGE,\n },\n apiGatewayUrl\n );\n return result.ecoListSpecies;\n },\n });\n};\n\nexport const useEcoSpeciesDetail = (id: string | undefined) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: KEY.speciesOne(id ?? ''),\n enabled: Boolean(id),\n queryFn: async () => {\n const result = await ecoQuery<{ ecoSpecies: EcoSpecies | null }>(\n `query EcoSpeciesDetail($id: ID!) {\n ecoSpecies(id: $id) {\n ${SPECIES_FIELDS}\n observations { ${OBSERVATION_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.ecoSpecies;\n },\n });\n};\n\nexport const useEcoCreateSpecies = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoCreateSpeciesInput) => {\n const result = await ecoQuery<{ ecoCreateSpecies: EcoSpecies }>(\n `mutation EcoCreateSpecies($input: EcoCreateSpeciesInput!) {\n ecoCreateSpecies(input: $input) { ${SPECIES_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoCreateSpecies;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.species }),\n });\n};\n\nexport const useEcoUpdateSpecies = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; input: EcoUpdateSpeciesInput }) => {\n const result = await ecoQuery<{ ecoUpdateSpecies: EcoSpecies }>(\n `mutation EcoUpdateSpecies($id: ID!, $input: EcoUpdateSpeciesInput!) {\n ecoUpdateSpecies(id: $id, input: $input) { ${SPECIES_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.ecoUpdateSpecies;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.species });\n qc.invalidateQueries({ queryKey: KEY.speciesOne(data.id) });\n },\n });\n};\n\nexport const useEcoArchiveSpecies = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await ecoQuery<{ ecoArchiveSpecies: boolean }>(\n `mutation EcoArchiveSpecies($id: ID!) { ecoArchiveSpecies(id: $id) }`,\n { id },\n apiGatewayUrl\n );\n return result.ecoArchiveSpecies;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.species }),\n });\n};\n\nexport interface ObservationFilters {\n speciesId?: string;\n siteId?: string;\n pagination?: PaginationInput;\n}\n\nexport const useEcoObservations = (filters: ObservationFilters = {}) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.observations, filters],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListObservations: EcoConnection<EcoObservation> }>(\n `query EcoListObservations($speciesId: ID, $siteId: ID, $pagination: PaginationInput) {\n ecoListObservations(speciesId: $speciesId, siteId: $siteId, pagination: $pagination) {\n items { ${OBSERVATION_FIELDS} species { id commonName scientificName taxonGroup } }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n speciesId: filters.speciesId,\n siteId: filters.siteId,\n pagination: filters.pagination ?? DEFAULT_PAGE,\n },\n apiGatewayUrl\n );\n return result.ecoListObservations;\n },\n });\n};\n\nexport const useEcoRecordObservation = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoRecordObservationInput) => {\n const result = await ecoQuery<{ ecoRecordObservation: EcoObservation }>(\n `mutation EcoRecordObservation($input: EcoRecordObservationInput!) {\n ecoRecordObservation(input: $input) { ${OBSERVATION_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoRecordObservation;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.observations });\n qc.invalidateQueries({ queryKey: KEY.speciesOne(data.speciesId) });\n },\n });\n};\n\nexport const useEcoHabitatProjects = (status?: EcoHabitatProjectStatus) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.habitatProjects, status ?? 'all'],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListHabitatProjects: EcoConnection<EcoHabitatProject> }>(\n `query EcoListHabitatProjects($status: EcoHabitatProjectStatus) {\n ecoListHabitatProjects(status: $status) {\n items { ${HABITAT_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { status },\n apiGatewayUrl\n );\n return result.ecoListHabitatProjects;\n },\n });\n};\n\nexport const useEcoHabitatProject = (id: string | undefined) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: KEY.habitatProject(id ?? ''),\n enabled: Boolean(id),\n queryFn: async () => {\n const result = await ecoQuery<{ ecoHabitatProject: EcoHabitatProject | null }>(\n `query EcoHabitatProject($id: ID!) {\n ecoHabitatProject(id: $id) {\n ${HABITAT_FIELDS}\n activities { ${ACTIVITY_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.ecoHabitatProject;\n },\n });\n};\n\nexport const useEcoCreateHabitatProject = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoCreateHabitatProjectInput) => {\n const result = await ecoQuery<{ ecoCreateHabitatProject: EcoHabitatProject }>(\n `mutation EcoCreateHabitatProject($input: EcoCreateHabitatProjectInput!) {\n ecoCreateHabitatProject(input: $input) { ${HABITAT_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoCreateHabitatProject;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.habitatProjects }),\n });\n};\n\nexport const useEcoTransitionHabitatProject = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; status: EcoHabitatProjectStatus }) => {\n const result = await ecoQuery<{ ecoTransitionHabitatProject: EcoHabitatProject }>(\n `mutation EcoTransitionHabitatProject($id: ID!, $status: EcoHabitatProjectStatus!) {\n ecoTransitionHabitatProject(id: $id, status: $status) { ${HABITAT_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.ecoTransitionHabitatProject;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.habitatProjects });\n qc.invalidateQueries({ queryKey: KEY.habitatProject(data.id) });\n },\n });\n};\n\nexport const useEcoLogRestorationActivity = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoLogRestorationActivityInput) => {\n const result = await ecoQuery<{ ecoLogRestorationActivity: EcoRestorationActivity }>(\n `mutation EcoLogRestorationActivity($input: EcoLogRestorationActivityInput!) {\n ecoLogRestorationActivity(input: $input) { ${ACTIVITY_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoLogRestorationActivity;\n },\n onSuccess: (data) => qc.invalidateQueries({ queryKey: KEY.habitatProject(data.projectId) }),\n });\n};\n\n// ============================================================================\n// Carbon ledger / Emission factors / Reduction targets (Sustainability)\n// ============================================================================\n\nexport const useEcoEmissionFactors = (scope?: EcoEmissionScope, activeOnly?: boolean) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.emissionFactors, scope ?? 'all', activeOnly ?? false],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListEmissionFactors: EcoConnection<EcoEmissionFactor> }>(\n `query EcoListEmissionFactors($scope: EcoEmissionScope, $activeOnly: Boolean) {\n ecoListEmissionFactors(scope: $scope, activeOnly: $activeOnly) {\n items { ${FACTOR_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { scope, activeOnly },\n apiGatewayUrl\n );\n return result.ecoListEmissionFactors;\n },\n });\n};\n\nexport const useEcoCreateEmissionFactor = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoCreateEmissionFactorInput) => {\n const result = await ecoQuery<{ ecoCreateEmissionFactor: EcoEmissionFactor }>(\n `mutation EcoCreateEmissionFactor($input: EcoCreateEmissionFactorInput!) {\n ecoCreateEmissionFactor(input: $input) { ${FACTOR_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoCreateEmissionFactor;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.emissionFactors }),\n });\n};\n\nexport interface CarbonEntryFilters {\n scope?: EcoEmissionScope;\n siteId?: string;\n status?: EcoCarbonEntryStatus;\n pagination?: PaginationInput;\n}\n\nexport const useEcoCarbonEntries = (filters: CarbonEntryFilters = {}) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.carbonEntries, filters],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListCarbonEntries: EcoConnection<EcoCarbonEntry> }>(\n `query EcoListCarbonEntries($scope: EcoEmissionScope, $siteId: ID, $status: EcoCarbonEntryStatus, $pagination: PaginationInput) {\n ecoListCarbonEntries(scope: $scope, siteId: $siteId, status: $status, pagination: $pagination) {\n items { ${CARBON_FIELDS} factor { id name factorKgco2e activityUnit } }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n scope: filters.scope,\n siteId: filters.siteId,\n status: filters.status,\n pagination: filters.pagination ?? DEFAULT_PAGE,\n },\n apiGatewayUrl\n );\n return result.ecoListCarbonEntries;\n },\n });\n};\n\n/** Total CO2e by scope + grand total, in one aliased query. */\nexport interface EcoCarbonTotals {\n total: number;\n scope1: number;\n scope2: number;\n scope3: number;\n}\n\nexport const useEcoCarbonTotals = (siteId?: string) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.carbonTotals, siteId ?? 'all'],\n queryFn: async (): Promise<EcoCarbonTotals> => {\n const result = await ecoQuery<{\n total: number;\n scope1: number;\n scope2: number;\n scope3: number;\n }>(\n `query EcoCarbonTotals($siteId: ID) {\n total: ecoCarbonTotalKg(siteId: $siteId)\n scope1: ecoCarbonTotalKg(scope: SCOPE_1, siteId: $siteId)\n scope2: ecoCarbonTotalKg(scope: SCOPE_2, siteId: $siteId)\n scope3: ecoCarbonTotalKg(scope: SCOPE_3, siteId: $siteId)\n }`,\n { siteId },\n apiGatewayUrl\n );\n return result;\n },\n });\n};\n\nexport const useEcoRecordCarbonEntry = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoRecordCarbonEntryInput) => {\n const result = await ecoQuery<{ ecoRecordCarbonEntry: EcoCarbonEntry }>(\n `mutation EcoRecordCarbonEntry($input: EcoRecordCarbonEntryInput!) {\n ecoRecordCarbonEntry(input: $input) { ${CARBON_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoRecordCarbonEntry;\n },\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: KEY.carbonEntries });\n qc.invalidateQueries({ queryKey: KEY.carbonTotals });\n },\n });\n};\n\nexport const useEcoVerifyCarbonEntry = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await ecoQuery<{ ecoVerifyCarbonEntry: EcoCarbonEntry }>(\n `mutation EcoVerifyCarbonEntry($id: ID!) {\n ecoVerifyCarbonEntry(id: $id) { ${CARBON_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.ecoVerifyCarbonEntry;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.carbonEntries }),\n });\n};\n\nexport const useEcoReductionTargets = (status?: EcoReductionTargetStatus) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.reductionTargets, status ?? 'all'],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListReductionTargets: EcoConnection<EcoReductionTarget> }>(\n `query EcoListReductionTargets($status: EcoReductionTargetStatus) {\n ecoListReductionTargets(status: $status) {\n items { ${TARGET_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { status },\n apiGatewayUrl\n );\n return result.ecoListReductionTargets;\n },\n });\n};\n\nexport const useEcoCreateReductionTarget = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoCreateReductionTargetInput) => {\n const result = await ecoQuery<{ ecoCreateReductionTarget: EcoReductionTarget }>(\n `mutation EcoCreateReductionTarget($input: EcoCreateReductionTargetInput!) {\n ecoCreateReductionTarget(input: $input) { ${TARGET_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoCreateReductionTarget;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.reductionTargets }),\n });\n};\n\nexport const useEcoSetReductionTargetStatus = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; status: EcoReductionTargetStatus }) => {\n const result = await ecoQuery<{ ecoSetReductionTargetStatus: EcoReductionTarget }>(\n `mutation EcoSetReductionTargetStatus($id: ID!, $status: EcoReductionTargetStatus!) {\n ecoSetReductionTargetStatus(id: $id, status: $status) { ${TARGET_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.ecoSetReductionTargetStatus;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.reductionTargets }),\n });\n};\n\n// ============================================================================\n// Reports (Sustainability & Reporting)\n// ============================================================================\n\nexport const useEcoReports = (status?: EcoReportStatus, pagination?: PaginationInput) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.reports, status ?? 'all', pagination ?? DEFAULT_PAGE],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListReports: EcoConnection<EcoReport> }>(\n `query EcoListReports($status: EcoReportStatus, $pagination: PaginationInput) {\n ecoListReports(status: $status, pagination: $pagination) {\n items { ${REPORT_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { status, pagination: pagination ?? DEFAULT_PAGE },\n apiGatewayUrl\n );\n return result.ecoListReports;\n },\n });\n};\n\nexport const useEcoReport = (id: string | undefined) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: KEY.report(id ?? ''),\n enabled: Boolean(id),\n queryFn: async () => {\n const result = await ecoQuery<{ ecoReport: EcoReport | null }>(\n `query EcoReport($id: ID!) {\n ecoReport(id: $id) {\n ${REPORT_FIELDS}\n lineItems { ${LINE_ITEM_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.ecoReport;\n },\n });\n};\n\nexport const useEcoCreateReport = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoCreateReportInput) => {\n const result = await ecoQuery<{ ecoCreateReport: EcoReport }>(\n `mutation EcoCreateReport($input: EcoCreateReportInput!) {\n ecoCreateReport(input: $input) { ${REPORT_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoCreateReport;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.reports }),\n });\n};\n\nexport const useEcoAddReportLineItem = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoAddReportLineItemInput) => {\n const result = await ecoQuery<{ ecoAddReportLineItem: EcoReportLineItem }>(\n `mutation EcoAddReportLineItem($input: EcoAddReportLineItemInput!) {\n ecoAddReportLineItem(input: $input) { ${LINE_ITEM_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoAddReportLineItem;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.reports });\n qc.invalidateQueries({ queryKey: KEY.report(data.reportId) });\n },\n });\n};\n\nexport const useEcoPublishReport = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; fileId?: string | null }) => {\n const result = await ecoQuery<{ ecoPublishReport: EcoReport }>(\n `mutation EcoPublishReport($id: ID!, $fileId: ID) {\n ecoPublishReport(id: $id, fileId: $fileId) { ${REPORT_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.ecoPublishReport;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.reports });\n qc.invalidateQueries({ queryKey: KEY.report(data.id) });\n },\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"useEcoImpactHubApi.js","names":[],"sources":["../../../src/ecoimpacthub/hooks/useEcoImpactHubApi.ts"],"sourcesContent":["/**\n * EcoImpactHub API hooks\n * @module ecoimpacthub/hooks\n *\n * React-Query hooks wired DIRECTLY to the real `wspace-ecoimpacthub-svc`\n * federated GraphQL contract (the `eco*` operations). Every query/mutation\n * below uses an inline gql string whose fields match the svc\n * `.hive-schema.graphql` exactly. No mock data.\n *\n * Transport: `graphqlFetch({ gateway: 'workspace', workspaceToken: true })` —\n * the host shell supplies the gateway base URL + a workspace-scoped token.\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\n\nimport { useEcoImpactHub } from '../context';\nimport type {\n EcoConnection,\n EcoSite,\n EcoSiteStatus,\n EcoSiteType,\n EcoSensor,\n EcoSensorKind,\n EcoSensorStatus,\n EcoMeasurement,\n EcoAlertThreshold,\n EcoSpecies,\n EcoTaxonGroup,\n EcoConservationStatus,\n EcoObservation,\n EcoHabitatProject,\n EcoHabitatProjectStatus,\n EcoRestorationActivity,\n EcoEmissionFactor,\n EcoEmissionScope,\n EcoCarbonEntry,\n EcoCarbonEntryStatus,\n EcoReductionTarget,\n EcoReductionTargetStatus,\n EcoReport,\n EcoReportStatus,\n EcoReportLineItem,\n EcoCreateSiteInput,\n EcoUpdateSiteInput,\n EcoCreateSensorInput,\n EcoRecordMeasurementInput,\n EcoCreateThresholdInput,\n EcoCreateSpeciesInput,\n EcoUpdateSpeciesInput,\n EcoRecordObservationInput,\n EcoCreateHabitatProjectInput,\n EcoLogRestorationActivityInput,\n EcoCreateEmissionFactorInput,\n EcoRecordCarbonEntryInput,\n EcoCreateReductionTargetInput,\n EcoCreateReportInput,\n EcoAddReportLineItemInput,\n EcoRejectReportInput,\n PaginationInput,\n} from '../types';\n\n// ============================================================================\n// Transport\n// ============================================================================\n\n/**\n * fe-libs `graphqlFetch` coalesces `query` responses in an in-memory cache keyed\n * by operationName+variables for ~15s (mutations are never cached). A read\n * issued right after a write (e.g. React-Query refetch triggered by our\n * `invalidateQueries`) would otherwise return the PRE-mutation response until the\n * TTL expires — making just-created/updated rows invisible until a full reload.\n * fe-libs' documented remedy is that write-performing callers clear those caches;\n * we do exactly that (the same maps `clearGraphqlFetchResponseCache` clears)\n * after every eco mutation so every follow-up read is fresh.\n */\ntype GraphqlReadCacheGlobals = {\n __graphqlFetchResponseCache?: { clear: () => void };\n __graphqlFetchPendingResponses?: { clear: () => void };\n __boffGraphQLResponseCache?: { clear: () => void };\n};\n\nconst clearGraphqlReadCaches = (): void => {\n const g = globalThis as GraphqlReadCacheGlobals;\n g.__graphqlFetchResponseCache?.clear();\n g.__graphqlFetchPendingResponses?.clear();\n g.__boffGraphQLResponseCache?.clear();\n};\n\nconst ecoQuery = async <TData>(\n query: string,\n variables: Record<string, unknown>,\n baseUrl?: string\n): Promise<TData> => {\n const response = await graphqlFetch<TData>({\n gateway: 'workspace',\n baseUrl,\n query,\n variables,\n workspaceToken: true,\n });\n\n if (response.errors?.length) {\n throw new Error(response.errors[0]?.message ?? 'GraphQL request failed');\n }\n if (!response.data) {\n throw new Error('GraphQL response did not include data');\n }\n // After a write, drop fe-libs' short-lived read caches so the invalidation\n // refetch that follows reads fresh data instead of the pre-mutation snapshot.\n if (/^\\s*mutation\\b/.test(query)) {\n clearGraphqlReadCaches();\n }\n return response.data;\n};\n\n// React-Query key roots (one namespace per domain entity).\nconst KEY = {\n sites: ['ecoimpacthub', 'sites'] as const,\n site: (id: string) => ['ecoimpacthub', 'site', id] as const,\n sensors: ['ecoimpacthub', 'sensors'] as const,\n measurements: ['ecoimpacthub', 'measurements'] as const,\n thresholds: ['ecoimpacthub', 'thresholds'] as const,\n species: ['ecoimpacthub', 'species'] as const,\n speciesOne: (id: string) => ['ecoimpacthub', 'species', id] as const,\n observations: ['ecoimpacthub', 'observations'] as const,\n habitatProjects: ['ecoimpacthub', 'habitat-projects'] as const,\n habitatProject: (id: string) => ['ecoimpacthub', 'habitat-project', id] as const,\n emissionFactors: ['ecoimpacthub', 'emission-factors'] as const,\n carbonEntries: ['ecoimpacthub', 'carbon-entries'] as const,\n carbonTotals: ['ecoimpacthub', 'carbon-totals'] as const,\n reductionTargets: ['ecoimpacthub', 'reduction-targets'] as const,\n reports: ['ecoimpacthub', 'reports'] as const,\n report: (id: string) => ['ecoimpacthub', 'report', id] as const,\n};\n\nconst DEFAULT_PAGE: PaginationInput = { limit: 50, offset: 0 };\n\n// ============================================================================\n// Reusable gql field selections (codegen-free strictness)\n// ============================================================================\n\nconst SITE_FIELDS = `\n id workspaceId name code type status description latitude longitude\n areaHectares country region createdAt updatedAt\n`;\n\nconst SENSOR_FIELDS = `\n id workspaceId siteId name kind status hardwareId unit lastReadingAt installedAt\n createdAt updatedAt\n`;\n\nconst MEASUREMENT_FIELDS = `\n id workspaceId siteId sensorId parameter value unit source recordedAt isBreach notes\n createdAt updatedAt\n`;\n\nconst THRESHOLD_FIELDS = `\n id workspaceId siteId parameter direction severity limitValue minValue maxValue unit\n isActive createdAt updatedAt\n`;\n\nconst SPECIES_FIELDS = `\n id workspaceId commonName scientificName taxonGroup conservationStatus isPriority\n description createdAt updatedAt\n`;\n\nconst OBSERVATION_FIELDS = `\n id workspaceId speciesId siteId method count observedAt latitude longitude observerId\n notes evidence { id } createdAt updatedAt\n`;\n\nconst HABITAT_FIELDS = `\n id workspaceId name status description siteId targetHectares budgetAmount currency\n managerId startDate endDate completedAt createdAt updatedAt\n`;\n\nconst ACTIVITY_FIELDS = `\n id workspaceId projectId type summary details quantity unit performedAt createdAt updatedAt\n`;\n\nconst FACTOR_FIELDS = `\n id workspaceId name scope activityUnit factorKgco2e source validYear isActive\n createdAt updatedAt\n`;\n\nconst CARBON_FIELDS = `\n id workspaceId siteId factorId scope status category activityValue activityUnit co2eKg\n periodStart notes createdAt updatedAt\n`;\n\nconst TARGET_FIELDS = `\n id workspaceId name status metric baselineYear baselineValue targetYear targetValue unit\n description createdAt updatedAt\n`;\n\nconst REPORT_FIELDS = `\n id workspaceId title framework status periodStart periodEnd summary publishedAt\n workflowRunId approvedBy approvedAt rejectedAt rejectionReason\n file { id } createdAt updatedAt\n`;\n\nconst LINE_ITEM_FIELDS = `\n id workspaceId reportId carbonEntryId label value unit category createdAt updatedAt\n`;\n\n// ============================================================================\n// Sites (Environmental Monitoring)\n// ============================================================================\n\nexport interface SiteFilters {\n status?: EcoSiteStatus;\n type?: EcoSiteType;\n pagination?: PaginationInput;\n}\n\nexport const useEcoSites = (filters: SiteFilters = {}) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.sites, filters],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListSites: EcoConnection<EcoSite> }>(\n `query EcoListSites($status: EcoSiteStatus, $type: EcoSiteType, $pagination: PaginationInput) {\n ecoListSites(status: $status, type: $type, pagination: $pagination) {\n items { ${SITE_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n status: filters.status,\n type: filters.type,\n pagination: filters.pagination ?? DEFAULT_PAGE,\n },\n apiGatewayUrl\n );\n return result.ecoListSites;\n },\n });\n};\n\nexport const useEcoSite = (id: string | undefined) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: KEY.site(id ?? ''),\n enabled: Boolean(id),\n queryFn: async () => {\n const result = await ecoQuery<{ ecoSite: EcoSite | null }>(\n `query EcoSite($id: ID!) {\n ecoSite(id: $id) {\n ${SITE_FIELDS}\n sensors { ${SENSOR_FIELDS} }\n thresholds { ${THRESHOLD_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.ecoSite;\n },\n });\n};\n\nexport const useEcoCreateSite = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoCreateSiteInput) => {\n const result = await ecoQuery<{ ecoCreateSite: EcoSite }>(\n `mutation EcoCreateSite($input: EcoCreateSiteInput!) {\n ecoCreateSite(input: $input) { ${SITE_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoCreateSite;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.sites }),\n });\n};\n\nexport const useEcoUpdateSite = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; input: EcoUpdateSiteInput }) => {\n const result = await ecoQuery<{ ecoUpdateSite: EcoSite }>(\n `mutation EcoUpdateSite($id: ID!, $input: EcoUpdateSiteInput!) {\n ecoUpdateSite(id: $id, input: $input) { ${SITE_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.ecoUpdateSite;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.sites });\n qc.invalidateQueries({ queryKey: KEY.site(data.id) });\n },\n });\n};\n\nexport const useEcoArchiveSite = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await ecoQuery<{ ecoArchiveSite: boolean }>(\n `mutation EcoArchiveSite($id: ID!) { ecoArchiveSite(id: $id) }`,\n { id },\n apiGatewayUrl\n );\n return result.ecoArchiveSite;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.sites }),\n });\n};\n\n// ============================================================================\n// Sensors / Measurements / Thresholds (Environmental Monitoring)\n// ============================================================================\n\nexport interface SensorFilters {\n siteId?: string;\n kind?: EcoSensorKind;\n status?: EcoSensorStatus;\n}\n\nexport const useEcoSensors = (filters: SensorFilters = {}) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.sensors, filters],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListSensors: EcoConnection<EcoSensor> }>(\n `query EcoListSensors($siteId: ID, $kind: EcoSensorKind, $status: EcoSensorStatus) {\n ecoListSensors(siteId: $siteId, kind: $kind, status: $status) {\n items { ${SENSOR_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { siteId: filters.siteId, kind: filters.kind, status: filters.status },\n apiGatewayUrl\n );\n return result.ecoListSensors;\n },\n });\n};\n\nexport const useEcoCreateSensor = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoCreateSensorInput) => {\n const result = await ecoQuery<{ ecoCreateSensor: EcoSensor }>(\n `mutation EcoCreateSensor($input: EcoCreateSensorInput!) {\n ecoCreateSensor(input: $input) { ${SENSOR_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoCreateSensor;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.sensors });\n qc.invalidateQueries({ queryKey: KEY.site(data.siteId) });\n },\n });\n};\n\nexport const useEcoSetSensorStatus = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; status: EcoSensorStatus }) => {\n const result = await ecoQuery<{ ecoSetSensorStatus: EcoSensor }>(\n `mutation EcoSetSensorStatus($id: ID!, $status: EcoSensorStatus!) {\n ecoSetSensorStatus(id: $id, status: $status) { ${SENSOR_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.ecoSetSensorStatus;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.sensors });\n qc.invalidateQueries({ queryKey: KEY.site(data.siteId) });\n },\n });\n};\n\nexport interface MeasurementFilters {\n siteId?: string;\n sensorId?: string;\n parameter?: string;\n breachesOnly?: boolean;\n pagination?: PaginationInput;\n}\n\nexport const useEcoMeasurements = (filters: MeasurementFilters = {}) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.measurements, filters],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListMeasurements: EcoConnection<EcoMeasurement> }>(\n `query EcoListMeasurements($siteId: ID, $sensorId: ID, $parameter: String, $breachesOnly: Boolean, $pagination: PaginationInput) {\n ecoListMeasurements(siteId: $siteId, sensorId: $sensorId, parameter: $parameter, breachesOnly: $breachesOnly, pagination: $pagination) {\n items { ${MEASUREMENT_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n siteId: filters.siteId,\n sensorId: filters.sensorId,\n parameter: filters.parameter,\n breachesOnly: filters.breachesOnly,\n pagination: filters.pagination ?? DEFAULT_PAGE,\n },\n apiGatewayUrl\n );\n return result.ecoListMeasurements;\n },\n });\n};\n\nexport const useEcoRecordMeasurement = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoRecordMeasurementInput) => {\n const result = await ecoQuery<{ ecoRecordMeasurement: EcoMeasurement }>(\n `mutation EcoRecordMeasurement($input: EcoRecordMeasurementInput!) {\n ecoRecordMeasurement(input: $input) { ${MEASUREMENT_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoRecordMeasurement;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.measurements }),\n });\n};\n\nexport const useEcoThresholds = (siteId?: string) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.thresholds, siteId ?? 'all'],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListThresholds: EcoConnection<EcoAlertThreshold> }>(\n `query EcoListThresholds($siteId: ID) {\n ecoListThresholds(siteId: $siteId) {\n items { ${THRESHOLD_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { siteId },\n apiGatewayUrl\n );\n return result.ecoListThresholds;\n },\n });\n};\n\nexport const useEcoCreateThreshold = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoCreateThresholdInput) => {\n const result = await ecoQuery<{ ecoCreateThreshold: EcoAlertThreshold }>(\n `mutation EcoCreateThreshold($input: EcoCreateThresholdInput!) {\n ecoCreateThreshold(input: $input) { ${THRESHOLD_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoCreateThreshold;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.thresholds });\n qc.invalidateQueries({ queryKey: KEY.site(data.siteId) });\n },\n });\n};\n\nexport const useEcoSetThresholdActive = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; isActive: boolean }) => {\n const result = await ecoQuery<{ ecoSetThresholdActive: EcoAlertThreshold }>(\n `mutation EcoSetThresholdActive($id: ID!, $isActive: Boolean!) {\n ecoSetThresholdActive(id: $id, isActive: $isActive) { ${THRESHOLD_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.ecoSetThresholdActive;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.thresholds }),\n });\n};\n\n// ============================================================================\n// Species / Observations / Habitat (Conservation)\n// ============================================================================\n\nexport interface SpeciesFilters {\n taxonGroup?: EcoTaxonGroup;\n conservationStatus?: EcoConservationStatus;\n priorityOnly?: boolean;\n pagination?: PaginationInput;\n}\n\nexport const useEcoSpecies = (filters: SpeciesFilters = {}) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.species, filters],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListSpecies: EcoConnection<EcoSpecies> }>(\n `query EcoListSpecies($taxonGroup: EcoTaxonGroup, $conservationStatus: EcoConservationStatus, $priorityOnly: Boolean, $pagination: PaginationInput) {\n ecoListSpecies(taxonGroup: $taxonGroup, conservationStatus: $conservationStatus, priorityOnly: $priorityOnly, pagination: $pagination) {\n items { ${SPECIES_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n taxonGroup: filters.taxonGroup,\n conservationStatus: filters.conservationStatus,\n priorityOnly: filters.priorityOnly,\n pagination: filters.pagination ?? DEFAULT_PAGE,\n },\n apiGatewayUrl\n );\n return result.ecoListSpecies;\n },\n });\n};\n\nexport const useEcoSpeciesDetail = (id: string | undefined) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: KEY.speciesOne(id ?? ''),\n enabled: Boolean(id),\n queryFn: async () => {\n const result = await ecoQuery<{ ecoSpecies: EcoSpecies | null }>(\n `query EcoSpeciesDetail($id: ID!) {\n ecoSpecies(id: $id) {\n ${SPECIES_FIELDS}\n observations { ${OBSERVATION_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.ecoSpecies;\n },\n });\n};\n\nexport const useEcoCreateSpecies = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoCreateSpeciesInput) => {\n const result = await ecoQuery<{ ecoCreateSpecies: EcoSpecies }>(\n `mutation EcoCreateSpecies($input: EcoCreateSpeciesInput!) {\n ecoCreateSpecies(input: $input) { ${SPECIES_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoCreateSpecies;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.species }),\n });\n};\n\nexport const useEcoUpdateSpecies = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; input: EcoUpdateSpeciesInput }) => {\n const result = await ecoQuery<{ ecoUpdateSpecies: EcoSpecies }>(\n `mutation EcoUpdateSpecies($id: ID!, $input: EcoUpdateSpeciesInput!) {\n ecoUpdateSpecies(id: $id, input: $input) { ${SPECIES_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.ecoUpdateSpecies;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.species });\n qc.invalidateQueries({ queryKey: KEY.speciesOne(data.id) });\n },\n });\n};\n\nexport const useEcoArchiveSpecies = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await ecoQuery<{ ecoArchiveSpecies: boolean }>(\n `mutation EcoArchiveSpecies($id: ID!) { ecoArchiveSpecies(id: $id) }`,\n { id },\n apiGatewayUrl\n );\n return result.ecoArchiveSpecies;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.species }),\n });\n};\n\nexport interface ObservationFilters {\n speciesId?: string;\n siteId?: string;\n pagination?: PaginationInput;\n}\n\nexport const useEcoObservations = (filters: ObservationFilters = {}) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.observations, filters],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListObservations: EcoConnection<EcoObservation> }>(\n `query EcoListObservations($speciesId: ID, $siteId: ID, $pagination: PaginationInput) {\n ecoListObservations(speciesId: $speciesId, siteId: $siteId, pagination: $pagination) {\n items { ${OBSERVATION_FIELDS} species { id commonName scientificName taxonGroup } }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n speciesId: filters.speciesId,\n siteId: filters.siteId,\n pagination: filters.pagination ?? DEFAULT_PAGE,\n },\n apiGatewayUrl\n );\n return result.ecoListObservations;\n },\n });\n};\n\nexport const useEcoRecordObservation = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoRecordObservationInput) => {\n const result = await ecoQuery<{ ecoRecordObservation: EcoObservation }>(\n `mutation EcoRecordObservation($input: EcoRecordObservationInput!) {\n ecoRecordObservation(input: $input) { ${OBSERVATION_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoRecordObservation;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.observations });\n qc.invalidateQueries({ queryKey: KEY.speciesOne(data.speciesId) });\n },\n });\n};\n\nexport const useEcoHabitatProjects = (status?: EcoHabitatProjectStatus) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.habitatProjects, status ?? 'all'],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListHabitatProjects: EcoConnection<EcoHabitatProject> }>(\n `query EcoListHabitatProjects($status: EcoHabitatProjectStatus) {\n ecoListHabitatProjects(status: $status) {\n items { ${HABITAT_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { status },\n apiGatewayUrl\n );\n return result.ecoListHabitatProjects;\n },\n });\n};\n\nexport const useEcoHabitatProject = (id: string | undefined) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: KEY.habitatProject(id ?? ''),\n enabled: Boolean(id),\n queryFn: async () => {\n const result = await ecoQuery<{ ecoHabitatProject: EcoHabitatProject | null }>(\n `query EcoHabitatProject($id: ID!) {\n ecoHabitatProject(id: $id) {\n ${HABITAT_FIELDS}\n activities { ${ACTIVITY_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.ecoHabitatProject;\n },\n });\n};\n\nexport const useEcoCreateHabitatProject = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoCreateHabitatProjectInput) => {\n const result = await ecoQuery<{ ecoCreateHabitatProject: EcoHabitatProject }>(\n `mutation EcoCreateHabitatProject($input: EcoCreateHabitatProjectInput!) {\n ecoCreateHabitatProject(input: $input) { ${HABITAT_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoCreateHabitatProject;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.habitatProjects }),\n });\n};\n\nexport const useEcoTransitionHabitatProject = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; status: EcoHabitatProjectStatus }) => {\n const result = await ecoQuery<{ ecoTransitionHabitatProject: EcoHabitatProject }>(\n `mutation EcoTransitionHabitatProject($id: ID!, $status: EcoHabitatProjectStatus!) {\n ecoTransitionHabitatProject(id: $id, status: $status) { ${HABITAT_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.ecoTransitionHabitatProject;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.habitatProjects });\n qc.invalidateQueries({ queryKey: KEY.habitatProject(data.id) });\n },\n });\n};\n\nexport const useEcoLogRestorationActivity = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoLogRestorationActivityInput) => {\n const result = await ecoQuery<{ ecoLogRestorationActivity: EcoRestorationActivity }>(\n `mutation EcoLogRestorationActivity($input: EcoLogRestorationActivityInput!) {\n ecoLogRestorationActivity(input: $input) { ${ACTIVITY_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoLogRestorationActivity;\n },\n onSuccess: (data) => qc.invalidateQueries({ queryKey: KEY.habitatProject(data.projectId) }),\n });\n};\n\n// ============================================================================\n// Carbon ledger / Emission factors / Reduction targets (Sustainability)\n// ============================================================================\n\nexport const useEcoEmissionFactors = (scope?: EcoEmissionScope, activeOnly?: boolean) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.emissionFactors, scope ?? 'all', activeOnly ?? false],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListEmissionFactors: EcoConnection<EcoEmissionFactor> }>(\n `query EcoListEmissionFactors($scope: EcoEmissionScope, $activeOnly: Boolean) {\n ecoListEmissionFactors(scope: $scope, activeOnly: $activeOnly) {\n items { ${FACTOR_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { scope, activeOnly },\n apiGatewayUrl\n );\n return result.ecoListEmissionFactors;\n },\n });\n};\n\nexport const useEcoCreateEmissionFactor = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoCreateEmissionFactorInput) => {\n const result = await ecoQuery<{ ecoCreateEmissionFactor: EcoEmissionFactor }>(\n `mutation EcoCreateEmissionFactor($input: EcoCreateEmissionFactorInput!) {\n ecoCreateEmissionFactor(input: $input) { ${FACTOR_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoCreateEmissionFactor;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.emissionFactors }),\n });\n};\n\nexport interface CarbonEntryFilters {\n scope?: EcoEmissionScope;\n siteId?: string;\n status?: EcoCarbonEntryStatus;\n pagination?: PaginationInput;\n}\n\nexport const useEcoCarbonEntries = (filters: CarbonEntryFilters = {}) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.carbonEntries, filters],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListCarbonEntries: EcoConnection<EcoCarbonEntry> }>(\n `query EcoListCarbonEntries($scope: EcoEmissionScope, $siteId: ID, $status: EcoCarbonEntryStatus, $pagination: PaginationInput) {\n ecoListCarbonEntries(scope: $scope, siteId: $siteId, status: $status, pagination: $pagination) {\n items { ${CARBON_FIELDS} factor { id name factorKgco2e activityUnit } }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n scope: filters.scope,\n siteId: filters.siteId,\n status: filters.status,\n pagination: filters.pagination ?? DEFAULT_PAGE,\n },\n apiGatewayUrl\n );\n return result.ecoListCarbonEntries;\n },\n });\n};\n\n/** Total CO2e by scope + grand total, in one aliased query. */\nexport interface EcoCarbonTotals {\n total: number;\n scope1: number;\n scope2: number;\n scope3: number;\n}\n\nexport const useEcoCarbonTotals = (siteId?: string) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.carbonTotals, siteId ?? 'all'],\n queryFn: async (): Promise<EcoCarbonTotals> => {\n const result = await ecoQuery<{\n total: number;\n scope1: number;\n scope2: number;\n scope3: number;\n }>(\n `query EcoCarbonTotals($siteId: ID) {\n total: ecoCarbonTotalKg(siteId: $siteId)\n scope1: ecoCarbonTotalKg(scope: SCOPE_1, siteId: $siteId)\n scope2: ecoCarbonTotalKg(scope: SCOPE_2, siteId: $siteId)\n scope3: ecoCarbonTotalKg(scope: SCOPE_3, siteId: $siteId)\n }`,\n { siteId },\n apiGatewayUrl\n );\n return result;\n },\n });\n};\n\nexport const useEcoRecordCarbonEntry = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoRecordCarbonEntryInput) => {\n const result = await ecoQuery<{ ecoRecordCarbonEntry: EcoCarbonEntry }>(\n `mutation EcoRecordCarbonEntry($input: EcoRecordCarbonEntryInput!) {\n ecoRecordCarbonEntry(input: $input) { ${CARBON_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoRecordCarbonEntry;\n },\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: KEY.carbonEntries });\n qc.invalidateQueries({ queryKey: KEY.carbonTotals });\n },\n });\n};\n\nexport const useEcoVerifyCarbonEntry = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await ecoQuery<{ ecoVerifyCarbonEntry: EcoCarbonEntry }>(\n `mutation EcoVerifyCarbonEntry($id: ID!) {\n ecoVerifyCarbonEntry(id: $id) { ${CARBON_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.ecoVerifyCarbonEntry;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.carbonEntries }),\n });\n};\n\nexport const useEcoReductionTargets = (status?: EcoReductionTargetStatus) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.reductionTargets, status ?? 'all'],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListReductionTargets: EcoConnection<EcoReductionTarget> }>(\n `query EcoListReductionTargets($status: EcoReductionTargetStatus) {\n ecoListReductionTargets(status: $status) {\n items { ${TARGET_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { status },\n apiGatewayUrl\n );\n return result.ecoListReductionTargets;\n },\n });\n};\n\nexport const useEcoCreateReductionTarget = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoCreateReductionTargetInput) => {\n const result = await ecoQuery<{ ecoCreateReductionTarget: EcoReductionTarget }>(\n `mutation EcoCreateReductionTarget($input: EcoCreateReductionTargetInput!) {\n ecoCreateReductionTarget(input: $input) { ${TARGET_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoCreateReductionTarget;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.reductionTargets }),\n });\n};\n\nexport const useEcoSetReductionTargetStatus = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; status: EcoReductionTargetStatus }) => {\n const result = await ecoQuery<{ ecoSetReductionTargetStatus: EcoReductionTarget }>(\n `mutation EcoSetReductionTargetStatus($id: ID!, $status: EcoReductionTargetStatus!) {\n ecoSetReductionTargetStatus(id: $id, status: $status) { ${TARGET_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.ecoSetReductionTargetStatus;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.reductionTargets }),\n });\n};\n\n// ============================================================================\n// Reports (Sustainability & Reporting)\n// ============================================================================\n\nexport const useEcoReports = (status?: EcoReportStatus, pagination?: PaginationInput) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: [...KEY.reports, status ?? 'all', pagination ?? DEFAULT_PAGE],\n queryFn: async () => {\n const result = await ecoQuery<{ ecoListReports: EcoConnection<EcoReport> }>(\n `query EcoListReports($status: EcoReportStatus, $pagination: PaginationInput) {\n ecoListReports(status: $status, pagination: $pagination) {\n items { ${REPORT_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { status, pagination: pagination ?? DEFAULT_PAGE },\n apiGatewayUrl\n );\n return result.ecoListReports;\n },\n });\n};\n\nexport const useEcoReport = (id: string | undefined) => {\n const { apiGatewayUrl } = useEcoImpactHub();\n return useQuery({\n queryKey: KEY.report(id ?? ''),\n enabled: Boolean(id),\n queryFn: async () => {\n const result = await ecoQuery<{ ecoReport: EcoReport | null }>(\n `query EcoReport($id: ID!) {\n ecoReport(id: $id) {\n ${REPORT_FIELDS}\n lineItems { ${LINE_ITEM_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.ecoReport;\n },\n });\n};\n\nexport const useEcoCreateReport = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoCreateReportInput) => {\n const result = await ecoQuery<{ ecoCreateReport: EcoReport }>(\n `mutation EcoCreateReport($input: EcoCreateReportInput!) {\n ecoCreateReport(input: $input) { ${REPORT_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoCreateReport;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.reports }),\n });\n};\n\nexport const useEcoAddReportLineItem = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoAddReportLineItemInput) => {\n const result = await ecoQuery<{ ecoAddReportLineItem: EcoReportLineItem }>(\n `mutation EcoAddReportLineItem($input: EcoAddReportLineItemInput!) {\n ecoAddReportLineItem(input: $input) { ${LINE_ITEM_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoAddReportLineItem;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.reports });\n qc.invalidateQueries({ queryKey: KEY.report(data.reportId) });\n },\n });\n};\n\nexport const useEcoPublishReport = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; fileId?: string | null }) => {\n const result = await ecoQuery<{ ecoPublishReport: EcoReport }>(\n `mutation EcoPublishReport($id: ID!, $fileId: ID) {\n ecoPublishReport(id: $id, fileId: $fileId) { ${REPORT_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.ecoPublishReport;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.reports });\n qc.invalidateQueries({ queryKey: KEY.report(data.id) });\n },\n });\n};\n\nexport const useEcoSubmitReportForApproval = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await ecoQuery<{ ecoSubmitReportForApproval: EcoReport }>(\n `mutation EcoSubmitReportForApproval($id: ID!) {\n ecoSubmitReportForApproval(id: $id) { ${REPORT_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.ecoSubmitReportForApproval;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.reports });\n qc.invalidateQueries({ queryKey: KEY.report(data.id) });\n },\n });\n};\n\nexport const useEcoApproveReport = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await ecoQuery<{ ecoApproveReport: EcoReport }>(\n `mutation EcoApproveReport($id: ID!) {\n ecoApproveReport(id: $id) { ${REPORT_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.ecoApproveReport;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.reports });\n qc.invalidateQueries({ queryKey: KEY.report(data.id) });\n },\n });\n};\n\nexport const useEcoRejectReport = () => {\n const { apiGatewayUrl } = useEcoImpactHub();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: EcoRejectReportInput) => {\n const result = await ecoQuery<{ ecoRejectReport: EcoReport }>(\n `mutation EcoRejectReport($input: EcoRejectReportInput!) {\n ecoRejectReport(input: $input) { ${REPORT_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.ecoRejectReport;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.reports });\n qc.invalidateQueries({ queryKey: KEY.report(data.id) });\n },\n });\n};\n"],"mappings":"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"}
@@ -273,6 +273,11 @@ export interface EcoReport {
273
273
  summary?: string | null;
274
274
  file?: EcoFileRef | null;
275
275
  publishedAt?: string | null;
276
+ workflowRunId?: string | null;
277
+ approvedBy?: string | null;
278
+ approvedAt?: string | null;
279
+ rejectedAt?: string | null;
280
+ rejectionReason?: string | null;
276
281
  lineItems?: EcoReportLineItem[];
277
282
  createdAt: string;
278
283
  updatedAt: string;
@@ -414,4 +419,8 @@ export interface EcoAddReportLineItemInput {
414
419
  category?: string | null;
415
420
  carbonEntryId?: string | null;
416
421
  }
422
+ export interface EcoRejectReportInput {
423
+ reportId: string;
424
+ reason: string;
425
+ }
417
426
  //# sourceMappingURL=index.d.ts.map