@burdenoff/microfe-ecoimpacthub 2026.704.4 → 2026.709.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/dist/dev/main.d.ts +2 -0
  2. package/dist/dev/main.d.ts.map +1 -0
  3. package/dist/ecoimpacthub/EcoImpactHubRoot.d.ts +5 -0
  4. package/dist/ecoimpacthub/EcoImpactHubRoot.d.ts.map +1 -0
  5. package/dist/ecoimpacthub/EcoImpactHubRoutes.d.ts +4 -0
  6. package/dist/ecoimpacthub/EcoImpactHubRoutes.d.ts.map +1 -0
  7. package/dist/ecoimpacthub/EcoImpactHubRoutes.js +48 -40
  8. package/dist/ecoimpacthub/EcoImpactHubRoutes.js.map +1 -1
  9. package/dist/ecoimpacthub/components/DataTable.d.ts +28 -0
  10. package/dist/ecoimpacthub/components/DataTable.d.ts.map +1 -0
  11. package/dist/ecoimpacthub/components/EcoDiscussion.d.ts +18 -0
  12. package/dist/ecoimpacthub/components/EcoDiscussion.d.ts.map +1 -0
  13. package/dist/ecoimpacthub/components/EcoTags.d.ts +17 -0
  14. package/dist/ecoimpacthub/components/EcoTags.d.ts.map +1 -0
  15. package/dist/ecoimpacthub/components/EmptyState.d.ts +18 -0
  16. package/dist/ecoimpacthub/components/EmptyState.d.ts.map +1 -0
  17. package/dist/ecoimpacthub/components/EvidenceUpload.d.ts +14 -0
  18. package/dist/ecoimpacthub/components/EvidenceUpload.d.ts.map +1 -0
  19. package/dist/ecoimpacthub/components/FeatureFlagGate.d.ts +10 -0
  20. package/dist/ecoimpacthub/components/FeatureFlagGate.d.ts.map +1 -0
  21. package/dist/ecoimpacthub/components/FeatureFlagGate.js +8 -0
  22. package/dist/ecoimpacthub/components/FeatureFlagGate.js.map +1 -0
  23. package/dist/ecoimpacthub/components/FileLink.d.ts +15 -0
  24. package/dist/ecoimpacthub/components/FileLink.d.ts.map +1 -0
  25. package/dist/ecoimpacthub/components/FilterTabs.d.ts +18 -0
  26. package/dist/ecoimpacthub/components/FilterTabs.d.ts.map +1 -0
  27. package/dist/ecoimpacthub/components/MetricsCard.d.ts +23 -0
  28. package/dist/ecoimpacthub/components/MetricsCard.d.ts.map +1 -0
  29. package/dist/ecoimpacthub/components/MiniBar.d.ts +16 -0
  30. package/dist/ecoimpacthub/components/MiniBar.d.ts.map +1 -0
  31. package/dist/ecoimpacthub/components/PageLayout.d.ts +16 -0
  32. package/dist/ecoimpacthub/components/PageLayout.d.ts.map +1 -0
  33. package/dist/ecoimpacthub/components/Pagination.d.ts +22 -0
  34. package/dist/ecoimpacthub/components/Pagination.d.ts.map +1 -0
  35. package/dist/ecoimpacthub/components/StateViews.d.ts +24 -0
  36. package/dist/ecoimpacthub/components/StateViews.d.ts.map +1 -0
  37. package/dist/ecoimpacthub/components/StatusBadge.d.ts +9 -0
  38. package/dist/ecoimpacthub/components/StatusBadge.d.ts.map +1 -0
  39. package/dist/ecoimpacthub/components/Tabs.d.ts +17 -0
  40. package/dist/ecoimpacthub/components/Tabs.d.ts.map +1 -0
  41. package/dist/ecoimpacthub/components/index.d.ts +19 -0
  42. package/dist/ecoimpacthub/components/index.d.ts.map +1 -0
  43. package/dist/ecoimpacthub/context/EcoImpactHubContext.d.ts +16 -0
  44. package/dist/ecoimpacthub/context/EcoImpactHubContext.d.ts.map +1 -0
  45. package/dist/ecoimpacthub/context/index.d.ts +6 -0
  46. package/dist/ecoimpacthub/context/index.d.ts.map +1 -0
  47. package/dist/ecoimpacthub/hooks/index.d.ts +10 -0
  48. package/dist/ecoimpacthub/hooks/index.d.ts.map +1 -0
  49. package/dist/ecoimpacthub/hooks/useCursorPager.d.ts +33 -0
  50. package/dist/ecoimpacthub/hooks/useCursorPager.d.ts.map +1 -0
  51. package/dist/ecoimpacthub/hooks/useEcoComments.d.ts +36 -0
  52. package/dist/ecoimpacthub/hooks/useEcoComments.d.ts.map +1 -0
  53. package/dist/ecoimpacthub/hooks/useEcoFiles.d.ts +47 -0
  54. package/dist/ecoimpacthub/hooks/useEcoFiles.d.ts.map +1 -0
  55. package/dist/ecoimpacthub/hooks/useEcoImpactHubApi.d.ts +104 -0
  56. package/dist/ecoimpacthub/hooks/useEcoImpactHubApi.d.ts.map +1 -0
  57. package/dist/ecoimpacthub/hooks/useEcoTags.d.ts +44 -0
  58. package/dist/ecoimpacthub/hooks/useEcoTags.d.ts.map +1 -0
  59. package/dist/ecoimpacthub/index.d.ts +10 -0
  60. package/dist/ecoimpacthub/index.d.ts.map +1 -0
  61. package/dist/ecoimpacthub/index.js +2 -0
  62. package/dist/ecoimpacthub/pages/DashboardPage.d.ts +10 -0
  63. package/dist/ecoimpacthub/pages/DashboardPage.d.ts.map +1 -0
  64. package/dist/ecoimpacthub/pages/DashboardPage.js +345 -189
  65. package/dist/ecoimpacthub/pages/DashboardPage.js.map +1 -1
  66. package/dist/ecoimpacthub/pages/_shared/ConservationBadge.d.ts +9 -0
  67. package/dist/ecoimpacthub/pages/_shared/ConservationBadge.d.ts.map +1 -0
  68. package/dist/ecoimpacthub/pages/_shared/ConservationBadge.js +58 -0
  69. package/dist/ecoimpacthub/pages/_shared/ConservationBadge.js.map +1 -0
  70. package/dist/ecoimpacthub/pages/_shared/EvidenceThumb.d.ts +23 -0
  71. package/dist/ecoimpacthub/pages/_shared/EvidenceThumb.d.ts.map +1 -0
  72. package/dist/ecoimpacthub/pages/_shared/EvidenceThumb.js +70 -0
  73. package/dist/ecoimpacthub/pages/_shared/EvidenceThumb.js.map +1 -0
  74. package/dist/ecoimpacthub/pages/_shared/MethodBadge.d.ts +9 -0
  75. package/dist/ecoimpacthub/pages/_shared/MethodBadge.d.ts.map +1 -0
  76. package/dist/ecoimpacthub/pages/_shared/MethodBadge.js +51 -0
  77. package/dist/ecoimpacthub/pages/_shared/MethodBadge.js.map +1 -0
  78. package/dist/ecoimpacthub/pages/_shared/TaxonChip.d.ts +9 -0
  79. package/dist/ecoimpacthub/pages/_shared/TaxonChip.d.ts.map +1 -0
  80. package/dist/ecoimpacthub/pages/_shared/TaxonChip.js +29 -0
  81. package/dist/ecoimpacthub/pages/_shared/TaxonChip.js.map +1 -0
  82. package/dist/ecoimpacthub/pages/badges.d.ts +27 -0
  83. package/dist/ecoimpacthub/pages/badges.d.ts.map +1 -0
  84. package/dist/ecoimpacthub/pages/badges.js +71 -0
  85. package/dist/ecoimpacthub/pages/badges.js.map +1 -0
  86. package/dist/ecoimpacthub/pages/carbon/CarbonPage.d.ts +15 -0
  87. package/dist/ecoimpacthub/pages/carbon/CarbonPage.d.ts.map +1 -0
  88. package/dist/ecoimpacthub/pages/carbon/CarbonPage.js +337 -300
  89. package/dist/ecoimpacthub/pages/carbon/CarbonPage.js.map +1 -1
  90. package/dist/ecoimpacthub/pages/carbonVisuals.d.ts +47 -0
  91. package/dist/ecoimpacthub/pages/carbonVisuals.d.ts.map +1 -0
  92. package/dist/ecoimpacthub/pages/carbonVisuals.js +89 -0
  93. package/dist/ecoimpacthub/pages/carbonVisuals.js.map +1 -0
  94. package/dist/ecoimpacthub/pages/habitat/HabitatProjectDetailPage.d.ts +12 -0
  95. package/dist/ecoimpacthub/pages/habitat/HabitatProjectDetailPage.d.ts.map +1 -0
  96. package/dist/ecoimpacthub/pages/habitat/HabitatProjectDetailPage.js +252 -218
  97. package/dist/ecoimpacthub/pages/habitat/HabitatProjectDetailPage.js.map +1 -1
  98. package/dist/ecoimpacthub/pages/habitat/HabitatProjectsPage.d.ts +8 -0
  99. package/dist/ecoimpacthub/pages/habitat/HabitatProjectsPage.d.ts.map +1 -0
  100. package/dist/ecoimpacthub/pages/habitat/HabitatProjectsPage.js +15 -12
  101. package/dist/ecoimpacthub/pages/habitat/HabitatProjectsPage.js.map +1 -1
  102. package/dist/ecoimpacthub/pages/habitat/LifecycleProgress.d.ts +6 -0
  103. package/dist/ecoimpacthub/pages/habitat/LifecycleProgress.d.ts.map +1 -0
  104. package/dist/ecoimpacthub/pages/habitat/LifecycleProgress.js +168 -0
  105. package/dist/ecoimpacthub/pages/habitat/LifecycleProgress.js.map +1 -0
  106. package/dist/ecoimpacthub/pages/monitoring/MonitoringPage.d.ts +12 -0
  107. package/dist/ecoimpacthub/pages/monitoring/MonitoringPage.d.ts.map +1 -0
  108. package/dist/ecoimpacthub/pages/monitoring/MonitoringPage.js +30 -17
  109. package/dist/ecoimpacthub/pages/monitoring/MonitoringPage.js.map +1 -1
  110. package/dist/ecoimpacthub/pages/observations/ObservationsPage.d.ts +11 -0
  111. package/dist/ecoimpacthub/pages/observations/ObservationsPage.d.ts.map +1 -0
  112. package/dist/ecoimpacthub/pages/observations/ObservationsPage.js +236 -219
  113. package/dist/ecoimpacthub/pages/observations/ObservationsPage.js.map +1 -1
  114. package/dist/ecoimpacthub/pages/reports/ReportDetailPage.d.ts +11 -0
  115. package/dist/ecoimpacthub/pages/reports/ReportDetailPage.d.ts.map +1 -0
  116. package/dist/ecoimpacthub/pages/reports/ReportDetailPage.js +248 -212
  117. package/dist/ecoimpacthub/pages/reports/ReportDetailPage.js.map +1 -1
  118. package/dist/ecoimpacthub/pages/reports/ReportsPage.d.ts +8 -0
  119. package/dist/ecoimpacthub/pages/reports/ReportsPage.d.ts.map +1 -0
  120. package/dist/ecoimpacthub/pages/reports/ReportsPage.js +119 -118
  121. package/dist/ecoimpacthub/pages/reports/ReportsPage.js.map +1 -1
  122. package/dist/ecoimpacthub/pages/sites/SiteDetailPage.d.ts +10 -0
  123. package/dist/ecoimpacthub/pages/sites/SiteDetailPage.d.ts.map +1 -0
  124. package/dist/ecoimpacthub/pages/sites/SiteDetailPage.js +498 -370
  125. package/dist/ecoimpacthub/pages/sites/SiteDetailPage.js.map +1 -1
  126. package/dist/ecoimpacthub/pages/sites/SitesPage.d.ts +8 -0
  127. package/dist/ecoimpacthub/pages/sites/SitesPage.d.ts.map +1 -0
  128. package/dist/ecoimpacthub/pages/sites/SitesPage.js +109 -99
  129. package/dist/ecoimpacthub/pages/sites/SitesPage.js.map +1 -1
  130. package/dist/ecoimpacthub/pages/sites/siteTypeVisuals.d.ts +22 -0
  131. package/dist/ecoimpacthub/pages/sites/siteTypeVisuals.d.ts.map +1 -0
  132. package/dist/ecoimpacthub/pages/sites/siteTypeVisuals.js +64 -0
  133. package/dist/ecoimpacthub/pages/sites/siteTypeVisuals.js.map +1 -0
  134. package/dist/ecoimpacthub/pages/species/SpeciesDetailPage.d.ts +9 -0
  135. package/dist/ecoimpacthub/pages/species/SpeciesDetailPage.d.ts.map +1 -0
  136. package/dist/ecoimpacthub/pages/species/SpeciesDetailPage.js +275 -259
  137. package/dist/ecoimpacthub/pages/species/SpeciesDetailPage.js.map +1 -1
  138. package/dist/ecoimpacthub/pages/species/SpeciesPage.d.ts +8 -0
  139. package/dist/ecoimpacthub/pages/species/SpeciesPage.d.ts.map +1 -0
  140. package/dist/ecoimpacthub/pages/species/SpeciesPage.js +235 -177
  141. package/dist/ecoimpacthub/pages/species/SpeciesPage.js.map +1 -1
  142. package/dist/ecoimpacthub/services/createSandboxAssistantTransport.d.ts +33 -0
  143. package/dist/ecoimpacthub/services/createSandboxAssistantTransport.d.ts.map +1 -0
  144. package/dist/ecoimpacthub/services/createSandboxAssistantTransport.js +42 -0
  145. package/dist/ecoimpacthub/services/createSandboxAssistantTransport.js.map +1 -0
  146. package/dist/ecoimpacthub/services/index.d.ts +6 -0
  147. package/dist/ecoimpacthub/services/index.d.ts.map +1 -0
  148. package/dist/ecoimpacthub/services/index.js +1 -0
  149. package/dist/ecoimpacthub/types/index.d.ts +417 -0
  150. package/dist/ecoimpacthub/types/index.d.ts.map +1 -0
  151. package/dist/ecoimpacthub/utils/cn.d.ts +4 -0
  152. package/dist/ecoimpacthub/utils/cn.d.ts.map +1 -0
  153. package/dist/ecoimpacthub/utils/formatters.d.ts +26 -0
  154. package/dist/ecoimpacthub/utils/formatters.d.ts.map +1 -0
  155. package/dist/ecoimpacthub/utils/i18n.d.ts +6 -0
  156. package/dist/ecoimpacthub/utils/i18n.d.ts.map +1 -0
  157. package/dist/ecoimpacthub/utils/index.d.ts +9 -0
  158. package/dist/ecoimpacthub/utils/index.d.ts.map +1 -0
  159. package/dist/ecoimpacthub/utils/navigation.d.ts +14 -0
  160. package/dist/ecoimpacthub/utils/navigation.d.ts.map +1 -0
  161. package/dist/generated/global-operations.d.ts +2 -0
  162. package/dist/generated/global-operations.d.ts.map +1 -0
  163. package/dist/generated/global-types.d.ts +18199 -0
  164. package/dist/generated/global-types.d.ts.map +1 -0
  165. package/dist/generated/wspace-operations.d.ts +2 -0
  166. package/dist/generated/wspace-operations.d.ts.map +1 -0
  167. package/dist/generated/wspace-types.d.ts +43046 -0
  168. package/dist/generated/wspace-types.d.ts.map +1 -0
  169. package/dist/index.d.ts +2 -0
  170. package/dist/index.d.ts.map +1 -0
  171. package/dist/index.js +2 -1
  172. package/dist/node_modules/recharts/es6/cartesian/CartesianGrid.js +305 -0
  173. package/dist/node_modules/recharts/es6/cartesian/CartesianGrid.js.map +1 -0
  174. package/dist/node_modules/recharts/es6/context/chartLayoutContext.js +44 -33
  175. package/dist/node_modules/recharts/es6/context/chartLayoutContext.js.map +1 -1
  176. package/dist/node_modules/recharts/es6/util/ChartUtils.js +31 -23
  177. package/dist/node_modules/recharts/es6/util/ChartUtils.js.map +1 -1
  178. package/package.json +5 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ReportDetailPage.js","names":[],"sources":["../../../../src/ecoimpacthub/pages/reports/ReportDetailPage.tsx"],"sourcesContent":["/**\n * Report detail — overview, line items & disclosure actions.\n * @module ecoimpacthub/pages/reports\n *\n * Reads `ecoReport` (+ nested lineItems); writes `ecoAddReportLineItem`,\n * `ecoPublishReport`.\n */\n\nimport { useMemo, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { ArrowLeft, Plus, ListPlus, Send } from 'lucide-react';\nimport {\n Button,\n Input,\n Label,\n GlassCard,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { DataTable, type Column } from '../../components/DataTable';\nimport { LoadingView, ErrorView, Section } from '../../components/StateViews';\nimport { EmptyState } from '../../components/EmptyState';\nimport { EvidenceUpload } from '../../components/EvidenceUpload';\nimport { FileLink } from '../../components/FileLink';\nimport { EcoDiscussion } from '../../components/EcoDiscussion';\nimport { useEcoImpactHub } from '../../context';\nimport {\n useEcoReport,\n useEcoAddReportLineItem,\n useEcoPublishReport,\n type UploadedEcoFile,\n} from '../../hooks';\nimport { formatDate, formatEnumLabel, formatNumber } from '../../utils/formatters';\nimport type { EcoReportLineItem } from '../../types';\n\nexport function ReportDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useEcoImpactHub();\n const { data: report, isLoading, isError, refetch } = useEcoReport(id);\n\n const addLineItem = useEcoAddReportLineItem();\n const publishReport = useEcoPublishReport();\n\n const [lineItemOpen, setLineItemOpen] = useState(false);\n const [lineItemForm, setLineItemForm] = useState({\n label: '',\n value: '',\n unit: '',\n category: '',\n carbonEntryId: '',\n });\n const [error, setError] = useState<string | null>(null);\n const [attachment, setAttachment] = useState<UploadedEcoFile | null>(null);\n\n const lineItems = useMemo(() => report?.lineItems ?? [], [report]);\n const total = useMemo(() => lineItems.reduce((sum, li) => sum + li.value, 0), [lineItems]);\n\n if (isLoading) {\n return (\n <PageLayout title=\"Report\">\n <LoadingView />\n </PageLayout>\n );\n }\n if (isError || !report) {\n return (\n <PageLayout title=\"Report\">\n <ErrorView message=\"This report could not be loaded.\" onRetry={() => refetch()} />\n </PageLayout>\n );\n }\n\n const handleAddLineItem = async () => {\n if (!id) return;\n if (!lineItemForm.label.trim() || !lineItemForm.value || !lineItemForm.unit.trim()) {\n setError('Label, value and unit are required.');\n return;\n }\n setError(null);\n try {\n await addLineItem.mutateAsync({\n reportId: id,\n label: lineItemForm.label.trim(),\n value: Number(lineItemForm.value),\n unit: lineItemForm.unit.trim(),\n category: lineItemForm.category.trim() || null,\n carbonEntryId: lineItemForm.carbonEntryId.trim() || null,\n });\n setLineItemOpen(false);\n setLineItemForm({ label: '', value: '', unit: '', category: '', carbonEntryId: '' });\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to add line item.');\n }\n };\n\n const handlePublish = async () => {\n if (!id) return;\n setError(null);\n try {\n await publishReport.mutateAsync({ id, fileId: attachment?.fileId ?? null });\n setAttachment(null);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to publish report.');\n }\n };\n\n const lineItemColumns: Column<EcoReportLineItem>[] = [\n {\n key: 'label',\n header: 'Line item',\n render: (li) => <span className=\"font-semibold text-text-primary\">{li.label}</span>,\n },\n {\n key: 'category',\n header: 'Category',\n hideOnMobile: true,\n render: (li) => <span className=\"text-text-secondary\">{li.category ?? '—'}</span>,\n },\n {\n key: 'value',\n header: 'Value',\n align: 'right',\n sortValue: (li) => li.value,\n render: (li) => (\n <span className=\"tabular-nums text-text-primary\">\n {formatNumber(li.value)} {li.unit}\n </span>\n ),\n },\n ];\n\n return (\n <PageLayout\n title={report.title}\n description={[formatEnumLabel(report.framework), formatEnumLabel(report.status)]\n .filter(Boolean)\n .join(' · ')}\n actions={\n <>\n <StatusBadge status={report.status} />\n <Button variant=\"ghost\" onClick={() => navigateTo('reports')}>\n <ArrowLeft className=\"mr-1.5 h-4 w-4\" /> Back\n </Button>\n </>\n }\n >\n {/* Overview */}\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-3\">\n <GlassCard treatment=\"glass\" className=\"p-6 lg:col-span-2\">\n <dl className=\"grid grid-cols-2 gap-x-6 gap-y-4 sm:grid-cols-3\">\n <div>\n <dt className=\"text-xs text-text-tertiary\">Framework</dt>\n <dd className=\"mt-0.5\">\n <StatusBadge status={report.framework} />\n </dd>\n </div>\n <div>\n <dt className=\"text-xs text-text-tertiary\">Status</dt>\n <dd className=\"mt-0.5\">\n <StatusBadge status={report.status} />\n </dd>\n </div>\n <div>\n <dt className=\"text-xs text-text-tertiary\">Period</dt>\n <dd className=\"mt-0.5 text-sm text-text-primary tabular-nums\">\n {formatDate(report.periodStart)} – {formatDate(report.periodEnd)}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs text-text-tertiary\">Published</dt>\n <dd className=\"mt-0.5 text-sm text-text-primary\">{formatDate(report.publishedAt)}</dd>\n </div>\n <div>\n <dt className=\"text-xs text-text-tertiary\">Line items</dt>\n <dd className=\"mt-0.5 text-sm text-text-primary tabular-nums\">{lineItems.length}</dd>\n </div>\n <div>\n <dt className=\"text-xs text-text-tertiary\">Attachment</dt>\n <dd className=\"mt-0.5 text-sm\">\n {report.file?.id ? (\n <FileLink fileId={report.file.id} />\n ) : (\n <span className=\"text-text-tertiary\">—</span>\n )}\n </dd>\n </div>\n </dl>\n {report.summary && (\n <p className=\"mt-5 rounded-lg bg-bg-sunken/60 p-3 text-sm text-text-secondary\">\n {report.summary}\n </p>\n )}\n </GlassCard>\n\n <GlassCard treatment=\"glass\" className=\"flex flex-col gap-3 p-6\">\n <p className=\"text-xs text-text-tertiary\">Quick actions</p>\n <Button onClick={() => setLineItemOpen(true)}>\n <ListPlus className=\"mr-1.5 h-4 w-4\" /> Add line item\n </Button>\n {report.status !== 'PUBLISHED' && (\n <>\n <EvidenceUpload\n id=\"reportAttachment\"\n label=\"Attach file (optional)\"\n value={attachment}\n onChange={setAttachment}\n hint=\"Attach the signed report PDF or supporting document, then publish.\"\n />\n <Button variant=\"outline\" onClick={handlePublish} disabled={publishReport.isPending}>\n <Send className=\"mr-1.5 h-4 w-4\" />\n {publishReport.isPending ? 'Publishing…' : 'Publish report'}\n </Button>\n </>\n )}\n </GlassCard>\n </div>\n\n {error && <p className=\"mt-4 text-sm text-status-error-text\">{error}</p>}\n\n {/* Line items */}\n <Section\n title=\"Line items\"\n description=\"Quantified disclosures that make up this report.\"\n action={\n <Button size=\"sm\" onClick={() => setLineItemOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Add line item\n </Button>\n }\n >\n {lineItems.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n title=\"No line items\"\n description=\"Add a line item to record a quantified disclosure for this report.\"\n />\n ) : (\n <>\n <div className=\"mb-3 flex items-center justify-end gap-2 text-sm\">\n <span className=\"text-text-tertiary\">Total value</span>\n <span className=\"font-semibold text-text-primary tabular-nums\">\n {formatNumber(total)}\n </span>\n </div>\n <DataTable columns={lineItemColumns} rows={lineItems} rowKey={(li) => li.id} />\n </>\n )}\n </Section>\n\n {/* Discussion — reuses the platform EntityComment API (no eco-svc change) */}\n <EcoDiscussion\n entityType=\"ecoimpacthub-report\"\n entityId={report.id}\n description=\"Coordinate review and sign-off on this disclosure with your team.\"\n />\n\n {/* Add line item dialog */}\n <ResponsiveDialog open={lineItemOpen} onOpenChange={setLineItemOpen}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Add line item</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Record a quantified disclosure for {report.title}.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"grid gap-4 py-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"liLabel\">Label *</Label>\n <Input\n id=\"liLabel\"\n value={lineItemForm.label}\n onChange={(e) => setLineItemForm({ ...lineItemForm, label: e.target.value })}\n placeholder=\"Scope 1 emissions\"\n />\n </div>\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"liValue\">Value *</Label>\n <Input\n id=\"liValue\"\n type=\"number\"\n step=\"any\"\n value={lineItemForm.value}\n onChange={(e) => setLineItemForm({ ...lineItemForm, value: e.target.value })}\n placeholder=\"1250\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"liUnit\">Unit *</Label>\n <Input\n id=\"liUnit\"\n value={lineItemForm.unit}\n onChange={(e) => setLineItemForm({ ...lineItemForm, unit: e.target.value })}\n placeholder=\"t CO₂e\"\n />\n </div>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"liCategory\">Category</Label>\n <Input\n id=\"liCategory\"\n value={lineItemForm.category}\n onChange={(e) => setLineItemForm({ ...lineItemForm, category: e.target.value })}\n placeholder=\"Optional grouping, e.g. Energy\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"liCarbonEntry\">Carbon entry ID</Label>\n <Input\n id=\"liCarbonEntry\"\n value={lineItemForm.carbonEntryId}\n onChange={(e) =>\n setLineItemForm({ ...lineItemForm, carbonEntryId: e.target.value })\n }\n placeholder=\"Optional linked carbon-ledger entry\"\n />\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => setLineItemOpen(false)}>\n Cancel\n </Button>\n <Button onClick={handleAddLineItem} disabled={addLineItem.isPending}>\n {addLineItem.isPending ? 'Adding…' : 'Add line item'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ReportDetailPage.js","names":[],"sources":["../../../../src/ecoimpacthub/pages/reports/ReportDetailPage.tsx"],"sourcesContent":["/**\n * Report detail — overview, line items (with total) & disclosure actions.\n * @module ecoimpacthub/pages/reports\n *\n * Reads `ecoReport` (+ nested lineItems); writes `ecoAddReportLineItem`,\n * `ecoPublishReport`. The hero pairs a fact-rich overview with an actions card;\n * line items render as a crisp table whose footer carries the running TOTAL, and\n * a discussion thread (platform EntityComment API) sits below.\n */\n\nimport { useMemo, useState, type ReactNode } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { ArrowLeft, ListPlus, Send } from 'lucide-react';\nimport {\n Button,\n Input,\n Label,\n GlassCard,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { LoadingView, ErrorView, Section } from '../../components/StateViews';\nimport { EmptyState } from '../../components/EmptyState';\nimport { EvidenceUpload } from '../../components/EvidenceUpload';\nimport { FileLink } from '../../components/FileLink';\nimport { EcoDiscussion } from '../../components/EcoDiscussion';\nimport { useEcoImpactHub } from '../../context';\nimport {\n useEcoReport,\n useEcoAddReportLineItem,\n useEcoPublishReport,\n type UploadedEcoFile,\n} from '../../hooks';\nimport { formatDate, formatNumber } from '../../utils/formatters';\nimport { FrameworkBadge } from '../badges';\n\n/** A labelled key/value cell for the overview grid. */\nfunction Fact({ label, children }: { label: string; children: ReactNode }) {\n return (\n <div>\n <dt className=\"text-xs text-text-tertiary\">{label}</dt>\n <dd className=\"mt-1 text-sm text-text-primary\">{children}</dd>\n </div>\n );\n}\n\nexport function ReportDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useEcoImpactHub();\n const { data: report, isLoading, isError, refetch } = useEcoReport(id);\n\n const addLineItem = useEcoAddReportLineItem();\n const publishReport = useEcoPublishReport();\n\n const [lineItemOpen, setLineItemOpen] = useState(false);\n const [lineItemForm, setLineItemForm] = useState({\n label: '',\n value: '',\n unit: '',\n category: '',\n carbonEntryId: '',\n });\n const [error, setError] = useState<string | null>(null);\n const [attachment, setAttachment] = useState<UploadedEcoFile | null>(null);\n\n const lineItems = useMemo(() => report?.lineItems ?? [], [report]);\n const total = useMemo(() => lineItems.reduce((sum, li) => sum + li.value, 0), [lineItems]);\n const totalUnit = useMemo(() => {\n const units = new Set(lineItems.map((li) => li.unit));\n return units.size === 1 ? [...units][0] : null;\n }, [lineItems]);\n\n if (isLoading) {\n return (\n <PageLayout title=\"Report\">\n <LoadingView />\n </PageLayout>\n );\n }\n if (isError || !report) {\n return (\n <PageLayout title=\"Report\">\n <ErrorView message=\"This report could not be loaded.\" onRetry={() => refetch()} />\n </PageLayout>\n );\n }\n\n const isPublished = report.status === 'PUBLISHED';\n\n const handleAddLineItem = async () => {\n if (!id) return;\n if (!lineItemForm.label.trim() || !lineItemForm.value || !lineItemForm.unit.trim()) {\n setError('Label, value and unit are required.');\n return;\n }\n setError(null);\n try {\n await addLineItem.mutateAsync({\n reportId: id,\n label: lineItemForm.label.trim(),\n value: Number(lineItemForm.value),\n unit: lineItemForm.unit.trim(),\n category: lineItemForm.category.trim() || null,\n carbonEntryId: lineItemForm.carbonEntryId.trim() || null,\n });\n setLineItemOpen(false);\n setLineItemForm({ label: '', value: '', unit: '', category: '', carbonEntryId: '' });\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to add line item.');\n }\n };\n\n const handlePublish = async () => {\n if (!id) return;\n setError(null);\n try {\n await publishReport.mutateAsync({ id, fileId: attachment?.fileId ?? null });\n setAttachment(null);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to publish report.');\n }\n };\n\n return (\n <PageLayout\n title={\n <span className=\"flex flex-wrap items-center gap-x-3 gap-y-2\">\n <span className=\"text-text-primary\">{report.title}</span>\n <FrameworkBadge framework={report.framework} />\n </span>\n }\n description={`Reporting period ${formatDate(report.periodStart)} – ${formatDate(report.periodEnd)}`}\n actions={\n <>\n <StatusBadge status={report.status} />\n <Button variant=\"ghost\" onClick={() => navigateTo('reports')}>\n <ArrowLeft className=\"mr-1.5 h-4 w-4\" /> Back\n </Button>\n </>\n }\n >\n {/* Overview + actions */}\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-3\">\n <GlassCard treatment=\"glass\" className=\"p-6 lg:col-span-2\">\n <dl className=\"grid grid-cols-2 gap-x-6 gap-y-4 sm:grid-cols-3\">\n <Fact label=\"Framework\">\n <FrameworkBadge framework={report.framework} />\n </Fact>\n <Fact label=\"Status\">\n <StatusBadge status={report.status} />\n </Fact>\n <Fact label=\"Period\">\n <span className=\"tabular-nums\">\n {formatDate(report.periodStart)} – {formatDate(report.periodEnd)}\n </span>\n </Fact>\n <Fact label=\"Published\">{formatDate(report.publishedAt)}</Fact>\n <Fact label=\"Line items\">\n <span className=\"tabular-nums\">{lineItems.length}</span>\n </Fact>\n <Fact label=\"Attachment\">\n {report.file?.id ? (\n <FileLink fileId={report.file.id} />\n ) : (\n <span className=\"text-text-tertiary\">—</span>\n )}\n </Fact>\n </dl>\n {report.summary && (\n <p className=\"mt-5 rounded-lg bg-bg-sunken/60 p-3 text-sm text-text-secondary\">\n {report.summary}\n </p>\n )}\n </GlassCard>\n\n <GlassCard treatment=\"glass\" className=\"flex flex-col gap-3 p-6\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-tertiary\">Actions</p>\n <Button onClick={() => setLineItemOpen(true)}>\n <ListPlus className=\"mr-1.5 h-4 w-4\" /> Add line item\n </Button>\n {isPublished ? (\n <p className=\"mt-1 text-sm text-text-secondary\">\n Published {formatDate(report.publishedAt)}. This disclosure is finalised.\n </p>\n ) : (\n <>\n <EvidenceUpload\n id=\"reportAttachment\"\n label=\"Attach file (optional)\"\n value={attachment}\n onChange={setAttachment}\n hint=\"Attach the signed report PDF or supporting document, then publish.\"\n />\n <Button variant=\"outline\" onClick={handlePublish} disabled={publishReport.isPending}>\n <Send className=\"mr-1.5 h-4 w-4\" />\n {publishReport.isPending ? 'Publishing…' : 'Publish report'}\n </Button>\n </>\n )}\n </GlassCard>\n </div>\n\n {error && <p className=\"mt-4 text-sm text-status-error-text\">{error}</p>}\n\n {/* Line items */}\n <Section\n title=\"Line items\"\n description=\"Quantified disclosures that make up this report.\"\n action={\n <Button size=\"sm\" onClick={() => setLineItemOpen(true)}>\n <ListPlus className=\"mr-1.5 h-4 w-4\" /> Add line item\n </Button>\n }\n >\n {lineItems.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n title=\"No line items\"\n description=\"Add a line item to record a quantified disclosure for this report.\"\n action={\n <Button size=\"sm\" onClick={() => setLineItemOpen(true)}>\n <ListPlus className=\"mr-1.5 h-4 w-4\" /> Add line item\n </Button>\n }\n />\n ) : (\n <GlassCard treatment=\"plain\" className=\"overflow-hidden\">\n <div className=\"overflow-x-auto\">\n <table className=\"w-full border-collapse text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam text-left\">\n <th className=\"px-4 py-3 font-medium text-text-secondary\">Line item</th>\n <th className=\"hidden px-4 py-3 font-medium text-text-secondary md:table-cell\">\n Category\n </th>\n <th className=\"px-4 py-3 text-right font-medium text-text-secondary\">Value</th>\n </tr>\n </thead>\n <tbody>\n {lineItems.map((li) => (\n <tr key={li.id} className=\"border-b border-border-seam/60\">\n <td className=\"px-4 py-3 font-medium text-text-primary\">{li.label}</td>\n <td className=\"hidden px-4 py-3 text-text-secondary md:table-cell\">\n {li.category ?? '—'}\n </td>\n <td className=\"px-4 py-3 text-right text-text-primary tabular-nums\">\n {formatNumber(li.value)} {li.unit}\n </td>\n </tr>\n ))}\n </tbody>\n <tfoot>\n <tr className=\"border-t-2 border-border-seam bg-bg-sunken/40\">\n <td className=\"px-4 py-3 text-sm font-semibold text-text-primary\" colSpan={2}>\n Total\n </td>\n <td className=\"px-4 py-3 text-right text-base font-bold text-text-primary tabular-nums\">\n {formatNumber(total)}\n {totalUnit ? ` ${totalUnit}` : ''}\n </td>\n </tr>\n </tfoot>\n </table>\n </div>\n </GlassCard>\n )}\n </Section>\n\n {/* Discussion — reuses the platform EntityComment API (no eco-svc change) */}\n <EcoDiscussion\n entityType=\"ecoimpacthub-report\"\n entityId={report.id}\n description=\"Coordinate review and sign-off on this disclosure with your team.\"\n />\n\n {/* Add line item dialog */}\n <ResponsiveDialog open={lineItemOpen} onOpenChange={setLineItemOpen}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Add line item</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Record a quantified disclosure for {report.title}.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"grid gap-4 py-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"liLabel\">Label *</Label>\n <Input\n id=\"liLabel\"\n value={lineItemForm.label}\n onChange={(e) => setLineItemForm({ ...lineItemForm, label: e.target.value })}\n placeholder=\"Scope 1 emissions\"\n />\n </div>\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"liValue\">Value *</Label>\n <Input\n id=\"liValue\"\n type=\"number\"\n step=\"any\"\n value={lineItemForm.value}\n onChange={(e) => setLineItemForm({ ...lineItemForm, value: e.target.value })}\n placeholder=\"1250\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"liUnit\">Unit *</Label>\n <Input\n id=\"liUnit\"\n value={lineItemForm.unit}\n onChange={(e) => setLineItemForm({ ...lineItemForm, unit: e.target.value })}\n placeholder=\"t CO₂e\"\n />\n </div>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"liCategory\">Category</Label>\n <Input\n id=\"liCategory\"\n value={lineItemForm.category}\n onChange={(e) => setLineItemForm({ ...lineItemForm, category: e.target.value })}\n placeholder=\"Optional grouping, e.g. Energy\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"liCarbonEntry\">Carbon entry ID</Label>\n <Input\n id=\"liCarbonEntry\"\n value={lineItemForm.carbonEntryId}\n onChange={(e) =>\n setLineItemForm({ ...lineItemForm, carbonEntryId: e.target.value })\n }\n placeholder=\"Optional linked carbon-ledger entry\"\n />\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => setLineItemOpen(false)}>\n Cancel\n </Button>\n <Button onClick={handleAddLineItem} disabled={addLineItem.isPending}>\n {addLineItem.isPending ? 'Adding…' : 'Add line item'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * ESG Reports — list, filter, and draft sustainability disclosures.
3
+ * @module ecoimpacthub/pages/reports
4
+ *
5
+ * Reads `ecoListReports`; writes `ecoCreateReport`.
6
+ */
7
+ export declare function ReportsPage(): import("react/jsx-runtime").JSX.Element;
8
+ //# sourceMappingURL=ReportsPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReportsPage.d.ts","sourceRoot":"","sources":["../../../../src/ecoimpacthub/pages/reports/ReportsPage.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AA8DH,wBAAgB,WAAW,4CAoP1B"}
@@ -1,22 +1,23 @@
1
1
  import { useEcoImpactHub as e } from "../../context/EcoImpactHubContext.js";
2
2
  import { PageLayout as t } from "../../components/PageLayout.js";
3
- import { formatDate as n, formatEnumLabel as r, formatRelativeTime as i } from "../../utils/formatters.js";
4
- import { StatusBadge as a } from "../../components/StatusBadge.js";
5
- import { ErrorView as o, LoadingView as s } from "../../components/StateViews.js";
6
- import { EmptyState as c } from "../../components/EmptyState.js";
3
+ import { formatDate as n, formatEnumLabel as ee, formatRelativeTime as r } from "../../utils/formatters.js";
4
+ import { StatusBadge as i } from "../../components/StatusBadge.js";
5
+ import { ErrorView as a, LoadingView as o } from "../../components/StateViews.js";
6
+ import { EmptyState as s } from "../../components/EmptyState.js";
7
7
  import "../../context/index.js";
8
- import { useEcoCreateReport as l, useEcoReports as ee } from "../../hooks/useEcoImpactHubApi.js";
9
- import { useCursorPager as u } from "../../hooks/useCursorPager.js";
8
+ import { useEcoCreateReport as c, useEcoReports as te } from "../../hooks/useEcoImpactHubApi.js";
9
+ import { useCursorPager as ne } from "../../hooks/useCursorPager.js";
10
10
  import "../../hooks/index.js";
11
- import { DataTable as d } from "../../components/DataTable.js";
12
- import { Pagination as f } from "../../components/Pagination.js";
13
- import { FilterTabs as p } from "../../components/FilterTabs.js";
14
- import { useMemo as m, useState as h } from "react";
15
- import { FileText as g, Plus as _ } from "lucide-react";
16
- import { Fragment as te, jsx as v, jsxs as y } from "react/jsx-runtime";
17
- import { Button as b, Input as x, Label as S, ResponsiveDialog as ne, ResponsiveDialogContent as re, ResponsiveDialogDescription as C, ResponsiveDialogFooter as w, ResponsiveDialogHeader as T, ResponsiveDialogTitle as E, Select as D, SelectContent as O, SelectItem as k, SelectTrigger as A, SelectValue as j, Textarea as M } from "@burdenoff/fe-libs/ui";
11
+ import { DataTable as l } from "../../components/DataTable.js";
12
+ import { Pagination as re } from "../../components/Pagination.js";
13
+ import { FrameworkBadge as u } from "../badges.js";
14
+ import { FilterTabs as d } from "../../components/FilterTabs.js";
15
+ import { useMemo as f, useState as p } from "react";
16
+ import { FileText as m, Plus as h } from "lucide-react";
17
+ import { Fragment as g, jsx as _, jsxs as v } from "react/jsx-runtime";
18
+ import { Button as y, Input as b, Label as x, ResponsiveDialog as S, ResponsiveDialogContent as C, ResponsiveDialogDescription as w, ResponsiveDialogFooter as T, ResponsiveDialogHeader as E, ResponsiveDialogTitle as D, Select as O, SelectContent as k, SelectItem as A, SelectTrigger as j, SelectValue as M, Textarea as N } from "@burdenoff/fe-libs/ui";
18
19
  //#region src/ecoimpacthub/pages/reports/ReportsPage.tsx
19
- var N = [
20
+ var P = [
20
21
  {
21
22
  value: "ALL",
22
23
  label: "All"
@@ -37,53 +38,50 @@ var N = [
37
38
  value: "ARCHIVED",
38
39
  label: "Archived"
39
40
  }
40
- ], P = [
41
+ ], F = [
41
42
  "GHG_PROTOCOL",
42
43
  "GRI",
43
44
  "TCFD",
44
45
  "CDP",
45
46
  "SASB",
46
47
  "CUSTOM"
47
- ], F = 25, I = {
48
+ ], I = 25, L = {
48
49
  title: "",
49
50
  framework: "GHG_PROTOCOL",
50
51
  periodStart: "",
51
52
  periodEnd: "",
52
53
  summary: ""
53
54
  };
54
- function L() {
55
- let { navigateTo: L } = e(), [R, z] = h("ALL"), B = u(), [V, H] = h(!1), [U, W] = h(I), [G, K] = h(null), { data: q, isLoading: J, isError: Y, refetch: X } = ee(R === "ALL" ? void 0 : R, {
56
- limit: F,
57
- cursor: B.cursor
58
- }), Z = l(), Q = m(() => q?.items ?? [], [q]), ie = [
55
+ function R() {
56
+ let { navigateTo: R } = e(), [z, B] = p("ALL"), V = ne(), [H, U] = p(!1), [W, G] = p(L), [K, q] = p(null), { data: J, isLoading: Y, isError: X, refetch: ie } = te(z === "ALL" ? void 0 : z, {
57
+ limit: I,
58
+ cursor: V.cursor
59
+ }), Z = c(), Q = f(() => J?.items ?? [], [J]), ae = [
59
60
  {
60
61
  key: "title",
61
62
  header: "Report",
62
- render: (e) => /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("p", {
63
+ render: (e) => /* @__PURE__ */ _("p", {
63
64
  className: "font-semibold text-text-primary",
64
65
  children: e.title
65
- }), /* @__PURE__ */ v("p", {
66
- className: "text-xs text-text-tertiary",
67
- children: r(e.framework)
68
- })] })
66
+ })
69
67
  },
70
68
  {
71
69
  key: "framework",
72
70
  header: "Framework",
73
71
  hideOnMobile: !0,
74
- render: (e) => /* @__PURE__ */ v(a, { status: e.framework })
72
+ render: (e) => /* @__PURE__ */ _(u, { framework: e.framework })
75
73
  },
76
74
  {
77
75
  key: "status",
78
76
  header: "Status",
79
- render: (e) => /* @__PURE__ */ v(a, { status: e.status })
77
+ render: (e) => /* @__PURE__ */ _(i, { status: e.status })
80
78
  },
81
79
  {
82
80
  key: "period",
83
81
  header: "Period",
84
82
  hideOnMobile: !0,
85
- render: (e) => /* @__PURE__ */ y("span", {
86
- className: "text-text-secondary tabular-nums",
83
+ render: (e) => /* @__PURE__ */ v("span", {
84
+ className: "whitespace-nowrap text-text-secondary tabular-nums",
87
85
  children: [
88
86
  n(e.periodStart),
89
87
  " – ",
@@ -95,9 +93,12 @@ function L() {
95
93
  key: "published",
96
94
  header: "Published",
97
95
  hideOnMobile: !0,
98
- render: (e) => /* @__PURE__ */ v("span", {
99
- className: "text-text-secondary",
96
+ render: (e) => e.publishedAt ? /* @__PURE__ */ _("span", {
97
+ className: "whitespace-nowrap text-text-secondary",
100
98
  children: n(e.publishedAt)
99
+ }) : /* @__PURE__ */ _("span", {
100
+ className: "text-text-tertiary",
101
+ children: "—"
101
102
  })
102
103
  },
103
104
  {
@@ -105,180 +106,180 @@ function L() {
105
106
  header: "Updated",
106
107
  align: "right",
107
108
  hideOnMobile: !0,
108
- render: (e) => /* @__PURE__ */ v("span", {
109
+ render: (e) => /* @__PURE__ */ _("span", {
109
110
  className: "text-text-tertiary",
110
- children: i(e.updatedAt)
111
+ children: r(e.updatedAt)
111
112
  })
112
113
  }
113
114
  ], $ = () => {
114
- W(I), K(null);
115
+ G(L), q(null);
115
116
  };
116
- return /* @__PURE__ */ y(t, {
117
+ return /* @__PURE__ */ v(t, {
117
118
  title: "ESG Reports",
118
119
  description: "Sustainability disclosures — draft, review & publish GHG Protocol, GRI, TCFD, CDP & SASB reports.",
119
- actions: /* @__PURE__ */ y(b, {
120
- onClick: () => H(!0),
121
- children: [/* @__PURE__ */ v(_, { className: "mr-1.5 h-4 w-4" }), " New report"]
120
+ actions: /* @__PURE__ */ v(y, {
121
+ onClick: () => U(!0),
122
+ children: [/* @__PURE__ */ _(h, { className: "mr-1.5 h-4 w-4" }), " New report"]
122
123
  }),
123
124
  children: [
124
- /* @__PURE__ */ v("div", {
125
+ /* @__PURE__ */ _("div", {
125
126
  className: "mb-5 flex flex-wrap items-center gap-3",
126
- children: /* @__PURE__ */ v(p, {
127
- options: N,
128
- value: R,
127
+ children: /* @__PURE__ */ _(d, {
128
+ options: P,
129
+ value: z,
129
130
  onChange: (e) => {
130
- z(e), B.reset();
131
+ B(e), V.reset();
131
132
  }
132
133
  })
133
134
  }),
134
- J ? /* @__PURE__ */ v(s, { label: "Loading reports…" }) : Y ? /* @__PURE__ */ v(o, {
135
+ Y ? /* @__PURE__ */ _(o, { label: "Loading reports…" }) : X ? /* @__PURE__ */ _(a, {
135
136
  message: "Couldn't load reports.",
136
- onRetry: () => X()
137
- }) : Q.length === 0 ? /* @__PURE__ */ v(c, {
137
+ onRetry: () => ie()
138
+ }) : Q.length === 0 ? /* @__PURE__ */ _(s, {
138
139
  illustration: "empty-data",
139
- icon: /* @__PURE__ */ v(g, { className: "h-10 w-10" }),
140
+ icon: /* @__PURE__ */ _(m, { className: "h-10 w-10" }),
140
141
  title: "No reports yet",
141
- description: R === "ALL" ? "Draft your first ESG report to compile disclosures against a reporting framework." : "No reports match this filter.",
142
- action: /* @__PURE__ */ y(b, {
143
- onClick: () => H(!0),
144
- children: [/* @__PURE__ */ v(_, { className: "mr-1.5 h-4 w-4" }), " New report"]
142
+ description: z === "ALL" ? "Draft your first ESG report to compile disclosures against a reporting framework." : "No reports match this filter.",
143
+ action: /* @__PURE__ */ v(y, {
144
+ onClick: () => U(!0),
145
+ children: [/* @__PURE__ */ _(h, { className: "mr-1.5 h-4 w-4" }), " New report"]
145
146
  })
146
- }) : /* @__PURE__ */ y(te, { children: [/* @__PURE__ */ v(d, {
147
- columns: ie,
147
+ }) : /* @__PURE__ */ v(g, { children: [/* @__PURE__ */ _(l, {
148
+ columns: ae,
148
149
  rows: Q,
149
150
  rowKey: (e) => e.id,
150
- onRowClick: (e) => L(`reports/${e.id}`)
151
- }), /* @__PURE__ */ v(f, {
152
- page: B.page,
153
- pageSize: F,
151
+ onRowClick: (e) => R(`reports/${e.id}`)
152
+ }), /* @__PURE__ */ _(re, {
153
+ page: V.page,
154
+ pageSize: I,
154
155
  itemCount: Q.length,
155
- hasMore: q?.pageInfo?.hasMore ?? !1,
156
- onPageChange: (e) => B.onPageChange(e, q?.pageInfo?.cursor)
156
+ hasMore: J?.pageInfo?.hasMore ?? !1,
157
+ onPageChange: (e) => V.onPageChange(e, J?.pageInfo?.cursor)
157
158
  })] }),
158
- /* @__PURE__ */ v(ne, {
159
- open: V,
159
+ /* @__PURE__ */ _(S, {
160
+ open: H,
160
161
  onOpenChange: (e) => {
161
- H(e), e || $();
162
+ U(e), e || $();
162
163
  },
163
- children: /* @__PURE__ */ y(re, { children: [
164
- /* @__PURE__ */ y(T, { children: [/* @__PURE__ */ v(E, { children: "New report" }), /* @__PURE__ */ v(C, { children: "Start a sustainability disclosure for a reporting period and framework." })] }),
165
- /* @__PURE__ */ y("div", {
164
+ children: /* @__PURE__ */ v(C, { children: [
165
+ /* @__PURE__ */ v(E, { children: [/* @__PURE__ */ _(D, { children: "New report" }), /* @__PURE__ */ _(w, { children: "Start a sustainability disclosure for a reporting period and framework." })] }),
166
+ /* @__PURE__ */ v("div", {
166
167
  className: "grid gap-4 py-2",
167
168
  children: [
168
- /* @__PURE__ */ y("div", {
169
+ /* @__PURE__ */ v("div", {
169
170
  className: "grid gap-1.5",
170
- children: [/* @__PURE__ */ v(S, {
171
+ children: [/* @__PURE__ */ _(x, {
171
172
  htmlFor: "title",
172
173
  children: "Title *"
173
- }), /* @__PURE__ */ v(x, {
174
+ }), /* @__PURE__ */ _(b, {
174
175
  id: "title",
175
- value: U.title,
176
- onChange: (e) => W({
177
- ...U,
176
+ value: W.title,
177
+ onChange: (e) => G({
178
+ ...W,
178
179
  title: e.target.value
179
180
  }),
180
181
  placeholder: "FY2026 Sustainability Report"
181
182
  })]
182
183
  }),
183
- /* @__PURE__ */ y("div", {
184
+ /* @__PURE__ */ v("div", {
184
185
  className: "grid gap-1.5",
185
- children: [/* @__PURE__ */ v(S, {
186
+ children: [/* @__PURE__ */ _(x, {
186
187
  htmlFor: "framework",
187
188
  children: "Framework"
188
- }), /* @__PURE__ */ y(D, {
189
- value: U.framework,
190
- onValueChange: (e) => W({
191
- ...U,
189
+ }), /* @__PURE__ */ v(O, {
190
+ value: W.framework,
191
+ onValueChange: (e) => G({
192
+ ...W,
192
193
  framework: e
193
194
  }),
194
- children: [/* @__PURE__ */ v(A, {
195
+ children: [/* @__PURE__ */ _(j, {
195
196
  id: "framework",
196
- children: /* @__PURE__ */ v(j, {})
197
- }), /* @__PURE__ */ v(O, { children: P.map((e) => /* @__PURE__ */ v(k, {
197
+ children: /* @__PURE__ */ _(M, {})
198
+ }), /* @__PURE__ */ _(k, { children: F.map((e) => /* @__PURE__ */ _(A, {
198
199
  value: e,
199
- children: r(e)
200
+ children: ee(e)
200
201
  }, e)) })]
201
202
  })]
202
203
  }),
203
- /* @__PURE__ */ y("div", {
204
+ /* @__PURE__ */ v("div", {
204
205
  className: "grid gap-2 sm:grid-cols-2",
205
- children: [/* @__PURE__ */ y("div", {
206
+ children: [/* @__PURE__ */ v("div", {
206
207
  className: "grid gap-1.5",
207
- children: [/* @__PURE__ */ v(S, {
208
+ children: [/* @__PURE__ */ _(x, {
208
209
  htmlFor: "periodStart",
209
210
  children: "Period start *"
210
- }), /* @__PURE__ */ v(x, {
211
+ }), /* @__PURE__ */ _(b, {
211
212
  id: "periodStart",
212
213
  type: "date",
213
- value: U.periodStart,
214
- onChange: (e) => W({
215
- ...U,
214
+ value: W.periodStart,
215
+ onChange: (e) => G({
216
+ ...W,
216
217
  periodStart: e.target.value
217
218
  })
218
219
  })]
219
- }), /* @__PURE__ */ y("div", {
220
+ }), /* @__PURE__ */ v("div", {
220
221
  className: "grid gap-1.5",
221
- children: [/* @__PURE__ */ v(S, {
222
+ children: [/* @__PURE__ */ _(x, {
222
223
  htmlFor: "periodEnd",
223
224
  children: "Period end *"
224
- }), /* @__PURE__ */ v(x, {
225
+ }), /* @__PURE__ */ _(b, {
225
226
  id: "periodEnd",
226
227
  type: "date",
227
- value: U.periodEnd,
228
- onChange: (e) => W({
229
- ...U,
228
+ value: W.periodEnd,
229
+ onChange: (e) => G({
230
+ ...W,
230
231
  periodEnd: e.target.value
231
232
  })
232
233
  })]
233
234
  })]
234
235
  }),
235
- /* @__PURE__ */ y("div", {
236
+ /* @__PURE__ */ v("div", {
236
237
  className: "grid gap-1.5",
237
- children: [/* @__PURE__ */ v(S, {
238
+ children: [/* @__PURE__ */ _(x, {
238
239
  htmlFor: "summary",
239
240
  children: "Summary"
240
- }), /* @__PURE__ */ v(M, {
241
+ }), /* @__PURE__ */ _(N, {
241
242
  id: "summary",
242
- value: U.summary,
243
- onChange: (e) => W({
244
- ...U,
243
+ value: W.summary,
244
+ onChange: (e) => G({
245
+ ...W,
245
246
  summary: e.target.value
246
247
  }),
247
248
  placeholder: "Optional executive summary or scope note for this report.",
248
249
  rows: 3
249
250
  })]
250
251
  }),
251
- G && /* @__PURE__ */ v("p", {
252
+ K && /* @__PURE__ */ _("p", {
252
253
  className: "text-sm text-status-error-text",
253
- children: G
254
+ children: K
254
255
  })
255
256
  ]
256
257
  }),
257
- /* @__PURE__ */ y(w, { children: [/* @__PURE__ */ v(b, {
258
+ /* @__PURE__ */ v(T, { children: [/* @__PURE__ */ _(y, {
258
259
  variant: "outline",
259
- onClick: () => H(!1),
260
+ onClick: () => U(!1),
260
261
  children: "Cancel"
261
- }), /* @__PURE__ */ v(b, {
262
+ }), /* @__PURE__ */ _(y, {
262
263
  onClick: async () => {
263
- if (!U.title.trim()) {
264
- K("Report title is required.");
264
+ if (!W.title.trim()) {
265
+ q("Report title is required.");
265
266
  return;
266
267
  }
267
- if (!U.periodStart || !U.periodEnd) {
268
- K("Reporting period start and end are required.");
268
+ if (!W.periodStart || !W.periodEnd) {
269
+ q("Reporting period start and end are required.");
269
270
  return;
270
271
  }
271
272
  try {
272
273
  let e = await Z.mutateAsync({
273
- title: U.title.trim(),
274
- framework: U.framework,
275
- periodStart: U.periodStart,
276
- periodEnd: U.periodEnd,
277
- summary: U.summary.trim() || null
274
+ title: W.title.trim(),
275
+ framework: W.framework,
276
+ periodStart: W.periodStart,
277
+ periodEnd: W.periodEnd,
278
+ summary: W.summary.trim() || null
278
279
  });
279
- H(!1), $(), L(`reports/${e.id}`);
280
+ U(!1), $(), R(`reports/${e.id}`);
280
281
  } catch (e) {
281
- K(e instanceof Error ? e.message : "Failed to create report.");
282
+ q(e instanceof Error ? e.message : "Failed to create report.");
282
283
  }
283
284
  },
284
285
  disabled: Z.isPending,
@@ -290,6 +291,6 @@ function L() {
290
291
  });
291
292
  }
292
293
  //#endregion
293
- export { L as ReportsPage };
294
+ export { R as ReportsPage };
294
295
 
295
296
  //# sourceMappingURL=ReportsPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ReportsPage.js","names":[],"sources":["../../../../src/ecoimpacthub/pages/reports/ReportsPage.tsx"],"sourcesContent":["/**\n * ESG Reports — list, filter, and draft sustainability disclosures.\n * @module ecoimpacthub/pages/reports\n *\n * Reads `ecoListReports`; writes `ecoCreateReport`.\n */\n\nimport { useMemo, useState } from 'react';\nimport { Plus, FileText } from 'lucide-react';\nimport {\n Button,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { DataTable, type Column } from '../../components/DataTable';\nimport { FilterTabs, type FilterOption } from '../../components/FilterTabs';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { EmptyState } from '../../components/EmptyState';\nimport { Pagination } from '../../components/Pagination';\nimport { useEcoImpactHub } from '../../context';\nimport { useEcoReports, useEcoCreateReport, useCursorPager } from '../../hooks';\nimport { formatDate, formatEnumLabel, formatRelativeTime } from '../../utils/formatters';\nimport type { EcoReport, EcoReportStatus, EcoReportFramework } from '../../types';\n\nconst STATUS_FILTERS: FilterOption<EcoReportStatus | 'ALL'>[] = [\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\nconst FRAMEWORKS: EcoReportFramework[] = ['GHG_PROTOCOL', 'GRI', 'TCFD', 'CDP', 'SASB', 'CUSTOM'];\n\nconst PAGE_SIZE = 25;\n\ninterface CreateFormState {\n title: string;\n framework: EcoReportFramework;\n periodStart: string;\n periodEnd: string;\n summary: string;\n}\n\nconst EMPTY_FORM: CreateFormState = {\n title: '',\n framework: 'GHG_PROTOCOL',\n periodStart: '',\n periodEnd: '',\n summary: '',\n};\n\nexport function ReportsPage() {\n const { navigateTo } = useEcoImpactHub();\n const [status, setStatus] = useState<EcoReportStatus | 'ALL'>('ALL');\n const pager = useCursorPager();\n const [dialogOpen, setDialogOpen] = useState(false);\n const [form, setForm] = useState<CreateFormState>(EMPTY_FORM);\n const [formError, setFormError] = useState<string | null>(null);\n\n const { data, isLoading, isError, refetch } = useEcoReports(\n status === 'ALL' ? undefined : status,\n { limit: PAGE_SIZE, cursor: pager.cursor }\n );\n const createReport = useEcoCreateReport();\n\n const rows = useMemo(() => data?.items ?? [], [data]);\n\n const columns: Column<EcoReport>[] = [\n {\n key: 'title',\n header: 'Report',\n render: (r) => (\n <div>\n <p className=\"font-semibold text-text-primary\">{r.title}</p>\n <p className=\"text-xs text-text-tertiary\">{formatEnumLabel(r.framework)}</p>\n </div>\n ),\n },\n {\n key: 'framework',\n header: 'Framework',\n hideOnMobile: true,\n render: (r) => <StatusBadge status={r.framework} />,\n },\n {\n key: 'status',\n header: 'Status',\n render: (r) => <StatusBadge status={r.status} />,\n },\n {\n key: 'period',\n header: 'Period',\n hideOnMobile: true,\n render: (r) => (\n <span className=\"text-text-secondary tabular-nums\">\n {formatDate(r.periodStart)} – {formatDate(r.periodEnd)}\n </span>\n ),\n },\n {\n key: 'published',\n header: 'Published',\n hideOnMobile: true,\n render: (r) => <span className=\"text-text-secondary\">{formatDate(r.publishedAt)}</span>,\n },\n {\n key: 'updated',\n header: 'Updated',\n align: 'right',\n hideOnMobile: true,\n render: (r) => <span className=\"text-text-tertiary\">{formatRelativeTime(r.updatedAt)}</span>,\n },\n ];\n\n const resetForm = () => {\n setForm(EMPTY_FORM);\n setFormError(null);\n };\n\n const handleCreate = async () => {\n if (!form.title.trim()) {\n setFormError('Report title is required.');\n return;\n }\n if (!form.periodStart || !form.periodEnd) {\n setFormError('Reporting period start and end are required.');\n return;\n }\n try {\n const created = await createReport.mutateAsync({\n title: form.title.trim(),\n framework: form.framework,\n periodStart: form.periodStart,\n periodEnd: form.periodEnd,\n summary: form.summary.trim() || null,\n });\n setDialogOpen(false);\n resetForm();\n navigateTo(`reports/${created.id}`);\n } catch (err) {\n setFormError(err instanceof Error ? err.message : 'Failed to create report.');\n }\n };\n\n return (\n <PageLayout\n title=\"ESG Reports\"\n description=\"Sustainability disclosures — draft, review & publish GHG Protocol, GRI, TCFD, CDP & SASB reports.\"\n actions={\n <Button onClick={() => setDialogOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New report\n </Button>\n }\n >\n <div className=\"mb-5 flex flex-wrap items-center gap-3\">\n <FilterTabs\n options={STATUS_FILTERS}\n value={status}\n onChange={(v) => {\n setStatus(v);\n pager.reset();\n }}\n />\n </div>\n\n {isLoading ? (\n <LoadingView label=\"Loading reports…\" />\n ) : isError ? (\n <ErrorView message=\"Couldn't load reports.\" onRetry={() => refetch()} />\n ) : rows.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<FileText className=\"h-10 w-10\" />}\n title=\"No reports yet\"\n description={\n status === 'ALL'\n ? 'Draft your first ESG report to compile disclosures against a reporting framework.'\n : 'No reports match this filter.'\n }\n action={\n <Button onClick={() => setDialogOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New report\n </Button>\n }\n />\n ) : (\n <>\n <DataTable\n columns={columns}\n rows={rows}\n rowKey={(r) => r.id}\n onRowClick={(r) => navigateTo(`reports/${r.id}`)}\n />\n <Pagination\n page={pager.page}\n pageSize={PAGE_SIZE}\n itemCount={rows.length}\n hasMore={data?.pageInfo?.hasMore ?? false}\n onPageChange={(target) => pager.onPageChange(target, data?.pageInfo?.cursor)}\n />\n </>\n )}\n\n <ResponsiveDialog\n open={dialogOpen}\n onOpenChange={(open) => {\n setDialogOpen(open);\n if (!open) resetForm();\n }}\n >\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New report</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Start a sustainability disclosure for a reporting period and framework.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"grid gap-4 py-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"title\">Title *</Label>\n <Input\n id=\"title\"\n value={form.title}\n onChange={(e) => setForm({ ...form, title: e.target.value })}\n placeholder=\"FY2026 Sustainability Report\"\n />\n </div>\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"framework\">Framework</Label>\n <Select\n value={form.framework}\n onValueChange={(v) => setForm({ ...form, framework: v as EcoReportFramework })}\n >\n <SelectTrigger id=\"framework\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {FRAMEWORKS.map((f) => (\n <SelectItem key={f} value={f}>\n {formatEnumLabel(f)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"periodStart\">Period start *</Label>\n <Input\n id=\"periodStart\"\n type=\"date\"\n value={form.periodStart}\n onChange={(e) => setForm({ ...form, periodStart: e.target.value })}\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"periodEnd\">Period end *</Label>\n <Input\n id=\"periodEnd\"\n type=\"date\"\n value={form.periodEnd}\n onChange={(e) => setForm({ ...form, periodEnd: e.target.value })}\n />\n </div>\n </div>\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"summary\">Summary</Label>\n <Textarea\n id=\"summary\"\n value={form.summary}\n onChange={(e) => setForm({ ...form, summary: e.target.value })}\n placeholder=\"Optional executive summary or scope note for this report.\"\n rows={3}\n />\n </div>\n\n {formError && <p className=\"text-sm text-status-error-text\">{formError}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => setDialogOpen(false)}>\n Cancel\n </Button>\n <Button onClick={handleCreate} disabled={createReport.isPending}>\n {createReport.isPending ? 'Creating…' : 'Create report'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAsCA,IAAM,IAA0D;CAC9D;EAAE,OAAO;EAAO,OAAO;EAAO;CAC9B;EAAE,OAAO;EAAS,OAAO;EAAS;CAClC;EAAE,OAAO;EAAa,OAAO;EAAa;CAC1C;EAAE,OAAO;EAAa,OAAO;EAAa;CAC1C;EAAE,OAAO;EAAY,OAAO;EAAY;CACzC,EAEK,IAAmC;CAAC;CAAgB;CAAO;CAAQ;CAAO;CAAQ;CAAS,EAE3F,IAAY,IAUZ,IAA8B;CAClC,OAAO;CACP,WAAW;CACX,aAAa;CACb,WAAW;CACX,SAAS;CACV;AAED,SAAgB,IAAc;CAC5B,IAAM,EAAE,kBAAe,GAAiB,EAClC,CAAC,GAAQ,KAAa,EAAkC,MAAM,EAC9D,IAAQ,GAAgB,EACxB,CAAC,GAAY,KAAiB,EAAS,GAAM,EAC7C,CAAC,GAAM,KAAW,EAA0B,EAAW,EACvD,CAAC,GAAW,KAAgB,EAAwB,KAAK,EAEzD,EAAE,SAAM,cAAW,YAAS,eAAY,GAC5C,MAAW,QAAQ,KAAA,IAAY,GAC/B;EAAE,OAAO;EAAW,QAAQ,EAAM;EAAQ,CAC3C,EACK,IAAe,GAAoB,EAEnC,IAAO,QAAc,GAAM,SAAS,EAAE,EAAE,CAAC,EAAK,CAAC,EAE/C,KAA+B;EACnC;GACE,KAAK;GACL,QAAQ;GACR,SAAS,MACP,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;IAAG,WAAU;cAAmC,EAAE;IAAU,CAAA,EAC5D,kBAAC,KAAD;IAAG,WAAU;cAA8B,EAAgB,EAAE,UAAU;IAAK,CAAA,CACxE,EAAA,CAAA;GAET;EACD;GACE,KAAK;GACL,QAAQ;GACR,cAAc;GACd,SAAS,MAAM,kBAAC,GAAD,EAAa,QAAQ,EAAE,WAAa,CAAA;GACpD;EACD;GACE,KAAK;GACL,QAAQ;GACR,SAAS,MAAM,kBAAC,GAAD,EAAa,QAAQ,EAAE,QAAU,CAAA;GACjD;EACD;GACE,KAAK;GACL,QAAQ;GACR,cAAc;GACd,SAAS,MACP,kBAAC,QAAD;IAAM,WAAU;cAAhB;KACG,EAAW,EAAE,YAAY;KAAC;KAAI,EAAW,EAAE,UAAU;KACjD;;GAEV;EACD;GACE,KAAK;GACL,QAAQ;GACR,cAAc;GACd,SAAS,MAAM,kBAAC,QAAD;IAAM,WAAU;cAAuB,EAAW,EAAE,YAAY;IAAQ,CAAA;GACxF;EACD;GACE,KAAK;GACL,QAAQ;GACR,OAAO;GACP,cAAc;GACd,SAAS,MAAM,kBAAC,QAAD;IAAM,WAAU;cAAsB,EAAmB,EAAE,UAAU;IAAQ,CAAA;GAC7F;EACF,EAEK,UAAkB;AAEtB,EADA,EAAQ,EAAW,EACnB,EAAa,KAAK;;AA4BpB,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;EACZ,SACE,kBAAC,GAAD;GAAQ,eAAe,EAAc,GAAK;aAA1C,CACE,kBAAC,GAAD,EAAM,WAAU,kBAAmB,CAAA,EAAA,cAC5B;;YANb;GASE,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD;KACE,SAAS;KACT,OAAO;KACP,WAAW,MAAM;AAEf,MADA,EAAU,EAAE,EACZ,EAAM,OAAO;;KAEf,CAAA;IACE,CAAA;GAEL,IACC,kBAAC,GAAD,EAAa,OAAM,oBAAqB,CAAA,GACtC,IACF,kBAAC,GAAD;IAAW,SAAQ;IAAyB,eAAe,GAAS;IAAI,CAAA,GACtE,EAAK,WAAW,IAClB,kBAAC,GAAD;IACE,cAAa;IACb,MAAM,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA;IACxC,OAAM;IACN,aACE,MAAW,QACP,sFACA;IAEN,QACE,kBAAC,GAAD;KAAQ,eAAe,EAAc,GAAK;eAA1C,CACE,kBAAC,GAAD,EAAM,WAAU,kBAAmB,CAAA,EAAA,cAC5B;;IAEX,CAAA,GAEF,kBAAA,IAAA,EAAA,UAAA,CACE,kBAAC,GAAD;IACW;IACH;IACN,SAAS,MAAM,EAAE;IACjB,aAAa,MAAM,EAAW,WAAW,EAAE,KAAK;IAChD,CAAA,EACF,kBAAC,GAAD;IACE,MAAM,EAAM;IACZ,UAAU;IACV,WAAW,EAAK;IAChB,SAAS,GAAM,UAAU,WAAW;IACpC,eAAe,MAAW,EAAM,aAAa,GAAQ,GAAM,UAAU,OAAO;IAC5E,CAAA,CACD,EAAA,CAAA;GAGL,kBAAC,IAAD;IACE,MAAM;IACN,eAAe,MAAS;AAEtB,KADA,EAAc,EAAK,EACd,KAAM,GAAW;;cAGxB,kBAAC,IAAD,EAAA,UAAA;KACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAuB,cAAkC,CAAA,EACzD,kBAAC,GAAD,EAAA,UAA6B,2EAEC,CAAA,CACP,EAAA,CAAA;KAEzB,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD;SAAO,SAAQ;mBAAQ;SAAe,CAAA,EACtC,kBAAC,GAAD;SACE,IAAG;SACH,OAAO,EAAK;SACZ,WAAW,MAAM,EAAQ;UAAE,GAAG;UAAM,OAAO,EAAE,OAAO;UAAO,CAAC;SAC5D,aAAY;SACZ,CAAA,CACE;;OAEN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD;SAAO,SAAQ;mBAAY;SAAiB,CAAA,EAC5C,kBAAC,GAAD;SACE,OAAO,EAAK;SACZ,gBAAgB,MAAM,EAAQ;UAAE,GAAG;UAAM,WAAW;UAAyB,CAAC;mBAFhF,CAIE,kBAAC,GAAD;UAAe,IAAG;oBAChB,kBAAC,GAAD,EAAe,CAAA;UACD,CAAA,EAChB,kBAAC,GAAD,EAAA,UACG,EAAW,KAAK,MACf,kBAAC,GAAD;UAAoB,OAAO;oBACxB,EAAgB,EAAE;UACR,EAFI,EAEJ,CACb,EACY,CAAA,CACT;WACL;;OAEN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UAAO,SAAQ;oBAAc;UAAsB,CAAA,EACnD,kBAAC,GAAD;UACE,IAAG;UACH,MAAK;UACL,OAAO,EAAK;UACZ,WAAW,MAAM,EAAQ;WAAE,GAAG;WAAM,aAAa,EAAE,OAAO;WAAO,CAAC;UAClE,CAAA,CACE;YACN,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UAAO,SAAQ;oBAAY;UAAoB,CAAA,EAC/C,kBAAC,GAAD;UACE,IAAG;UACH,MAAK;UACL,OAAO,EAAK;UACZ,WAAW,MAAM,EAAQ;WAAE,GAAG;WAAM,WAAW,EAAE,OAAO;WAAO,CAAC;UAChE,CAAA,CACE;WACF;;OAEN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD;SAAO,SAAQ;mBAAU;SAAe,CAAA,EACxC,kBAAC,GAAD;SACE,IAAG;SACH,OAAO,EAAK;SACZ,WAAW,MAAM,EAAQ;UAAE,GAAG;UAAM,SAAS,EAAE,OAAO;UAAO,CAAC;SAC9D,aAAY;SACZ,MAAM;SACN,CAAA,CACE;;OAEL,KAAa,kBAAC,KAAD;QAAG,WAAU;kBAAkC;QAAc,CAAA;OACvE;;KAEN,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;MAAQ,SAAQ;MAAU,eAAe,EAAc,GAAM;gBAAE;MAEtD,CAAA,EACT,kBAAC,GAAD;MAAQ,SAxKG,YAAY;AAC/B,WAAI,CAAC,EAAK,MAAM,MAAM,EAAE;AACtB,UAAa,4BAA4B;AACzC;;AAEF,WAAI,CAAC,EAAK,eAAe,CAAC,EAAK,WAAW;AACxC,UAAa,+CAA+C;AAC5D;;AAEF,WAAI;QACF,IAAM,IAAU,MAAM,EAAa,YAAY;SAC7C,OAAO,EAAK,MAAM,MAAM;SACxB,WAAW,EAAK;SAChB,aAAa,EAAK;SAClB,WAAW,EAAK;SAChB,SAAS,EAAK,QAAQ,MAAM,IAAI;SACjC,CAAC;AAGF,QAFA,EAAc,GAAM,EACpB,GAAW,EACX,EAAW,WAAW,EAAQ,KAAK;gBAC5B,GAAK;AACZ,UAAa,aAAe,QAAQ,EAAI,UAAU,2BAA2B;;;MAmJxC,UAAU,EAAa;gBACnD,EAAa,YAAY,cAAc;MACjC,CAAA,CACc,EAAA,CAAA;KACD,EAAA,CAAA;IACT,CAAA;GACR"}
1
+ {"version":3,"file":"ReportsPage.js","names":[],"sources":["../../../../src/ecoimpacthub/pages/reports/ReportsPage.tsx"],"sourcesContent":["/**\n * ESG Reports — list, filter, and draft sustainability disclosures.\n * @module ecoimpacthub/pages/reports\n *\n * Reads `ecoListReports`; writes `ecoCreateReport`.\n */\n\nimport { useMemo, useState } from 'react';\nimport { Plus, FileText } from 'lucide-react';\nimport {\n Button,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { DataTable, type Column } from '../../components/DataTable';\nimport { FilterTabs, type FilterOption } from '../../components/FilterTabs';\nimport { FrameworkBadge } from '../badges';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { EmptyState } from '../../components/EmptyState';\nimport { Pagination } from '../../components/Pagination';\nimport { useEcoImpactHub } from '../../context';\nimport { useEcoReports, useEcoCreateReport, useCursorPager } from '../../hooks';\nimport { formatDate, formatEnumLabel, formatRelativeTime } from '../../utils/formatters';\nimport type { EcoReport, EcoReportStatus, EcoReportFramework } from '../../types';\n\nconst STATUS_FILTERS: FilterOption<EcoReportStatus | 'ALL'>[] = [\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\nconst FRAMEWORKS: EcoReportFramework[] = ['GHG_PROTOCOL', 'GRI', 'TCFD', 'CDP', 'SASB', 'CUSTOM'];\n\nconst PAGE_SIZE = 25;\n\ninterface CreateFormState {\n title: string;\n framework: EcoReportFramework;\n periodStart: string;\n periodEnd: string;\n summary: string;\n}\n\nconst EMPTY_FORM: CreateFormState = {\n title: '',\n framework: 'GHG_PROTOCOL',\n periodStart: '',\n periodEnd: '',\n summary: '',\n};\n\nexport function ReportsPage() {\n const { navigateTo } = useEcoImpactHub();\n const [status, setStatus] = useState<EcoReportStatus | 'ALL'>('ALL');\n const pager = useCursorPager();\n const [dialogOpen, setDialogOpen] = useState(false);\n const [form, setForm] = useState<CreateFormState>(EMPTY_FORM);\n const [formError, setFormError] = useState<string | null>(null);\n\n const { data, isLoading, isError, refetch } = useEcoReports(\n status === 'ALL' ? undefined : status,\n { limit: PAGE_SIZE, cursor: pager.cursor }\n );\n const createReport = useEcoCreateReport();\n\n const rows = useMemo(() => data?.items ?? [], [data]);\n\n const columns: Column<EcoReport>[] = [\n {\n key: 'title',\n header: 'Report',\n render: (r) => <p className=\"font-semibold text-text-primary\">{r.title}</p>,\n },\n {\n key: 'framework',\n header: 'Framework',\n hideOnMobile: true,\n render: (r) => <FrameworkBadge framework={r.framework} />,\n },\n {\n key: 'status',\n header: 'Status',\n render: (r) => <StatusBadge status={r.status} />,\n },\n {\n key: 'period',\n header: 'Period',\n hideOnMobile: true,\n render: (r) => (\n <span className=\"whitespace-nowrap text-text-secondary tabular-nums\">\n {formatDate(r.periodStart)} – {formatDate(r.periodEnd)}\n </span>\n ),\n },\n {\n key: 'published',\n header: 'Published',\n hideOnMobile: true,\n render: (r) =>\n r.publishedAt ? (\n <span className=\"whitespace-nowrap text-text-secondary\">{formatDate(r.publishedAt)}</span>\n ) : (\n <span className=\"text-text-tertiary\">—</span>\n ),\n },\n {\n key: 'updated',\n header: 'Updated',\n align: 'right',\n hideOnMobile: true,\n render: (r) => <span className=\"text-text-tertiary\">{formatRelativeTime(r.updatedAt)}</span>,\n },\n ];\n\n const resetForm = () => {\n setForm(EMPTY_FORM);\n setFormError(null);\n };\n\n const handleCreate = async () => {\n if (!form.title.trim()) {\n setFormError('Report title is required.');\n return;\n }\n if (!form.periodStart || !form.periodEnd) {\n setFormError('Reporting period start and end are required.');\n return;\n }\n try {\n const created = await createReport.mutateAsync({\n title: form.title.trim(),\n framework: form.framework,\n periodStart: form.periodStart,\n periodEnd: form.periodEnd,\n summary: form.summary.trim() || null,\n });\n setDialogOpen(false);\n resetForm();\n navigateTo(`reports/${created.id}`);\n } catch (err) {\n setFormError(err instanceof Error ? err.message : 'Failed to create report.');\n }\n };\n\n return (\n <PageLayout\n title=\"ESG Reports\"\n description=\"Sustainability disclosures — draft, review & publish GHG Protocol, GRI, TCFD, CDP & SASB reports.\"\n actions={\n <Button onClick={() => setDialogOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New report\n </Button>\n }\n >\n <div className=\"mb-5 flex flex-wrap items-center gap-3\">\n <FilterTabs\n options={STATUS_FILTERS}\n value={status}\n onChange={(v) => {\n setStatus(v);\n pager.reset();\n }}\n />\n </div>\n\n {isLoading ? (\n <LoadingView label=\"Loading reports…\" />\n ) : isError ? (\n <ErrorView message=\"Couldn't load reports.\" onRetry={() => refetch()} />\n ) : rows.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<FileText className=\"h-10 w-10\" />}\n title=\"No reports yet\"\n description={\n status === 'ALL'\n ? 'Draft your first ESG report to compile disclosures against a reporting framework.'\n : 'No reports match this filter.'\n }\n action={\n <Button onClick={() => setDialogOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New report\n </Button>\n }\n />\n ) : (\n <>\n <DataTable\n columns={columns}\n rows={rows}\n rowKey={(r) => r.id}\n onRowClick={(r) => navigateTo(`reports/${r.id}`)}\n />\n <Pagination\n page={pager.page}\n pageSize={PAGE_SIZE}\n itemCount={rows.length}\n hasMore={data?.pageInfo?.hasMore ?? false}\n onPageChange={(target) => pager.onPageChange(target, data?.pageInfo?.cursor)}\n />\n </>\n )}\n\n <ResponsiveDialog\n open={dialogOpen}\n onOpenChange={(open) => {\n setDialogOpen(open);\n if (!open) resetForm();\n }}\n >\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New report</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Start a sustainability disclosure for a reporting period and framework.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"grid gap-4 py-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"title\">Title *</Label>\n <Input\n id=\"title\"\n value={form.title}\n onChange={(e) => setForm({ ...form, title: e.target.value })}\n placeholder=\"FY2026 Sustainability Report\"\n />\n </div>\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"framework\">Framework</Label>\n <Select\n value={form.framework}\n onValueChange={(v) => setForm({ ...form, framework: v as EcoReportFramework })}\n >\n <SelectTrigger id=\"framework\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {FRAMEWORKS.map((f) => (\n <SelectItem key={f} value={f}>\n {formatEnumLabel(f)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"periodStart\">Period start *</Label>\n <Input\n id=\"periodStart\"\n type=\"date\"\n value={form.periodStart}\n onChange={(e) => setForm({ ...form, periodStart: e.target.value })}\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"periodEnd\">Period end *</Label>\n <Input\n id=\"periodEnd\"\n type=\"date\"\n value={form.periodEnd}\n onChange={(e) => setForm({ ...form, periodEnd: e.target.value })}\n />\n </div>\n </div>\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"summary\">Summary</Label>\n <Textarea\n id=\"summary\"\n value={form.summary}\n onChange={(e) => setForm({ ...form, summary: e.target.value })}\n placeholder=\"Optional executive summary or scope note for this report.\"\n rows={3}\n />\n </div>\n\n {formError && <p className=\"text-sm text-status-error-text\">{formError}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => setDialogOpen(false)}>\n Cancel\n </Button>\n <Button onClick={handleCreate} disabled={createReport.isPending}>\n {createReport.isPending ? 'Creating…' : 'Create report'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Site detail — sensors, alert thresholds, recent measurements & site actions.
3
+ * @module ecoimpacthub/pages/sites
4
+ *
5
+ * Reads `ecoSite` (+ nested sensors/thresholds) and `ecoListMeasurements`;
6
+ * writes `ecoCreateSensor`, `ecoSetSensorStatus`, `ecoCreateThreshold`,
7
+ * `ecoSetThresholdActive`, `ecoRecordMeasurement`, `ecoArchiveSite`.
8
+ */
9
+ export declare function SiteDetailPage(): import("react/jsx-runtime").JSX.Element;
10
+ //# sourceMappingURL=SiteDetailPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SiteDetailPage.d.ts","sourceRoot":"","sources":["../../../../src/ecoimpacthub/pages/sites/SiteDetailPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA+EH,wBAAgB,cAAc,4CA0vB7B"}