@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.
- package/dist/dev/main.d.ts +2 -0
- package/dist/dev/main.d.ts.map +1 -0
- package/dist/ecoimpacthub/EcoImpactHubRoot.d.ts +5 -0
- package/dist/ecoimpacthub/EcoImpactHubRoot.d.ts.map +1 -0
- package/dist/ecoimpacthub/EcoImpactHubRoutes.d.ts +4 -0
- package/dist/ecoimpacthub/EcoImpactHubRoutes.d.ts.map +1 -0
- package/dist/ecoimpacthub/EcoImpactHubRoutes.js +48 -40
- package/dist/ecoimpacthub/EcoImpactHubRoutes.js.map +1 -1
- package/dist/ecoimpacthub/components/DataTable.d.ts +28 -0
- package/dist/ecoimpacthub/components/DataTable.d.ts.map +1 -0
- package/dist/ecoimpacthub/components/EcoDiscussion.d.ts +18 -0
- package/dist/ecoimpacthub/components/EcoDiscussion.d.ts.map +1 -0
- package/dist/ecoimpacthub/components/EcoTags.d.ts +17 -0
- package/dist/ecoimpacthub/components/EcoTags.d.ts.map +1 -0
- package/dist/ecoimpacthub/components/EmptyState.d.ts +18 -0
- package/dist/ecoimpacthub/components/EmptyState.d.ts.map +1 -0
- package/dist/ecoimpacthub/components/EvidenceUpload.d.ts +14 -0
- package/dist/ecoimpacthub/components/EvidenceUpload.d.ts.map +1 -0
- package/dist/ecoimpacthub/components/FeatureFlagGate.d.ts +10 -0
- package/dist/ecoimpacthub/components/FeatureFlagGate.d.ts.map +1 -0
- package/dist/ecoimpacthub/components/FeatureFlagGate.js +8 -0
- package/dist/ecoimpacthub/components/FeatureFlagGate.js.map +1 -0
- package/dist/ecoimpacthub/components/FileLink.d.ts +15 -0
- package/dist/ecoimpacthub/components/FileLink.d.ts.map +1 -0
- package/dist/ecoimpacthub/components/FilterTabs.d.ts +18 -0
- package/dist/ecoimpacthub/components/FilterTabs.d.ts.map +1 -0
- package/dist/ecoimpacthub/components/MetricsCard.d.ts +23 -0
- package/dist/ecoimpacthub/components/MetricsCard.d.ts.map +1 -0
- package/dist/ecoimpacthub/components/MiniBar.d.ts +16 -0
- package/dist/ecoimpacthub/components/MiniBar.d.ts.map +1 -0
- package/dist/ecoimpacthub/components/PageLayout.d.ts +16 -0
- package/dist/ecoimpacthub/components/PageLayout.d.ts.map +1 -0
- package/dist/ecoimpacthub/components/Pagination.d.ts +22 -0
- package/dist/ecoimpacthub/components/Pagination.d.ts.map +1 -0
- package/dist/ecoimpacthub/components/StateViews.d.ts +24 -0
- package/dist/ecoimpacthub/components/StateViews.d.ts.map +1 -0
- package/dist/ecoimpacthub/components/StatusBadge.d.ts +9 -0
- package/dist/ecoimpacthub/components/StatusBadge.d.ts.map +1 -0
- package/dist/ecoimpacthub/components/Tabs.d.ts +17 -0
- package/dist/ecoimpacthub/components/Tabs.d.ts.map +1 -0
- package/dist/ecoimpacthub/components/index.d.ts +19 -0
- package/dist/ecoimpacthub/components/index.d.ts.map +1 -0
- package/dist/ecoimpacthub/context/EcoImpactHubContext.d.ts +16 -0
- package/dist/ecoimpacthub/context/EcoImpactHubContext.d.ts.map +1 -0
- package/dist/ecoimpacthub/context/index.d.ts +6 -0
- package/dist/ecoimpacthub/context/index.d.ts.map +1 -0
- package/dist/ecoimpacthub/hooks/index.d.ts +10 -0
- package/dist/ecoimpacthub/hooks/index.d.ts.map +1 -0
- package/dist/ecoimpacthub/hooks/useCursorPager.d.ts +33 -0
- package/dist/ecoimpacthub/hooks/useCursorPager.d.ts.map +1 -0
- package/dist/ecoimpacthub/hooks/useEcoComments.d.ts +36 -0
- package/dist/ecoimpacthub/hooks/useEcoComments.d.ts.map +1 -0
- package/dist/ecoimpacthub/hooks/useEcoFiles.d.ts +47 -0
- package/dist/ecoimpacthub/hooks/useEcoFiles.d.ts.map +1 -0
- package/dist/ecoimpacthub/hooks/useEcoImpactHubApi.d.ts +104 -0
- package/dist/ecoimpacthub/hooks/useEcoImpactHubApi.d.ts.map +1 -0
- package/dist/ecoimpacthub/hooks/useEcoTags.d.ts +44 -0
- package/dist/ecoimpacthub/hooks/useEcoTags.d.ts.map +1 -0
- package/dist/ecoimpacthub/index.d.ts +10 -0
- package/dist/ecoimpacthub/index.d.ts.map +1 -0
- package/dist/ecoimpacthub/index.js +2 -0
- package/dist/ecoimpacthub/pages/DashboardPage.d.ts +10 -0
- package/dist/ecoimpacthub/pages/DashboardPage.d.ts.map +1 -0
- package/dist/ecoimpacthub/pages/DashboardPage.js +345 -189
- package/dist/ecoimpacthub/pages/DashboardPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/_shared/ConservationBadge.d.ts +9 -0
- package/dist/ecoimpacthub/pages/_shared/ConservationBadge.d.ts.map +1 -0
- package/dist/ecoimpacthub/pages/_shared/ConservationBadge.js +58 -0
- package/dist/ecoimpacthub/pages/_shared/ConservationBadge.js.map +1 -0
- package/dist/ecoimpacthub/pages/_shared/EvidenceThumb.d.ts +23 -0
- package/dist/ecoimpacthub/pages/_shared/EvidenceThumb.d.ts.map +1 -0
- package/dist/ecoimpacthub/pages/_shared/EvidenceThumb.js +70 -0
- package/dist/ecoimpacthub/pages/_shared/EvidenceThumb.js.map +1 -0
- package/dist/ecoimpacthub/pages/_shared/MethodBadge.d.ts +9 -0
- package/dist/ecoimpacthub/pages/_shared/MethodBadge.d.ts.map +1 -0
- package/dist/ecoimpacthub/pages/_shared/MethodBadge.js +51 -0
- package/dist/ecoimpacthub/pages/_shared/MethodBadge.js.map +1 -0
- package/dist/ecoimpacthub/pages/_shared/TaxonChip.d.ts +9 -0
- package/dist/ecoimpacthub/pages/_shared/TaxonChip.d.ts.map +1 -0
- package/dist/ecoimpacthub/pages/_shared/TaxonChip.js +29 -0
- package/dist/ecoimpacthub/pages/_shared/TaxonChip.js.map +1 -0
- package/dist/ecoimpacthub/pages/badges.d.ts +27 -0
- package/dist/ecoimpacthub/pages/badges.d.ts.map +1 -0
- package/dist/ecoimpacthub/pages/badges.js +71 -0
- package/dist/ecoimpacthub/pages/badges.js.map +1 -0
- package/dist/ecoimpacthub/pages/carbon/CarbonPage.d.ts +15 -0
- package/dist/ecoimpacthub/pages/carbon/CarbonPage.d.ts.map +1 -0
- package/dist/ecoimpacthub/pages/carbon/CarbonPage.js +337 -300
- package/dist/ecoimpacthub/pages/carbon/CarbonPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/carbonVisuals.d.ts +47 -0
- package/dist/ecoimpacthub/pages/carbonVisuals.d.ts.map +1 -0
- package/dist/ecoimpacthub/pages/carbonVisuals.js +89 -0
- package/dist/ecoimpacthub/pages/carbonVisuals.js.map +1 -0
- package/dist/ecoimpacthub/pages/habitat/HabitatProjectDetailPage.d.ts +12 -0
- package/dist/ecoimpacthub/pages/habitat/HabitatProjectDetailPage.d.ts.map +1 -0
- package/dist/ecoimpacthub/pages/habitat/HabitatProjectDetailPage.js +252 -218
- package/dist/ecoimpacthub/pages/habitat/HabitatProjectDetailPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/habitat/HabitatProjectsPage.d.ts +8 -0
- package/dist/ecoimpacthub/pages/habitat/HabitatProjectsPage.d.ts.map +1 -0
- package/dist/ecoimpacthub/pages/habitat/HabitatProjectsPage.js +15 -12
- package/dist/ecoimpacthub/pages/habitat/HabitatProjectsPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/habitat/LifecycleProgress.d.ts +6 -0
- package/dist/ecoimpacthub/pages/habitat/LifecycleProgress.d.ts.map +1 -0
- package/dist/ecoimpacthub/pages/habitat/LifecycleProgress.js +168 -0
- package/dist/ecoimpacthub/pages/habitat/LifecycleProgress.js.map +1 -0
- package/dist/ecoimpacthub/pages/monitoring/MonitoringPage.d.ts +12 -0
- package/dist/ecoimpacthub/pages/monitoring/MonitoringPage.d.ts.map +1 -0
- package/dist/ecoimpacthub/pages/monitoring/MonitoringPage.js +30 -17
- package/dist/ecoimpacthub/pages/monitoring/MonitoringPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/observations/ObservationsPage.d.ts +11 -0
- package/dist/ecoimpacthub/pages/observations/ObservationsPage.d.ts.map +1 -0
- package/dist/ecoimpacthub/pages/observations/ObservationsPage.js +236 -219
- package/dist/ecoimpacthub/pages/observations/ObservationsPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/reports/ReportDetailPage.d.ts +11 -0
- package/dist/ecoimpacthub/pages/reports/ReportDetailPage.d.ts.map +1 -0
- package/dist/ecoimpacthub/pages/reports/ReportDetailPage.js +248 -212
- package/dist/ecoimpacthub/pages/reports/ReportDetailPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/reports/ReportsPage.d.ts +8 -0
- package/dist/ecoimpacthub/pages/reports/ReportsPage.d.ts.map +1 -0
- package/dist/ecoimpacthub/pages/reports/ReportsPage.js +119 -118
- package/dist/ecoimpacthub/pages/reports/ReportsPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/sites/SiteDetailPage.d.ts +10 -0
- package/dist/ecoimpacthub/pages/sites/SiteDetailPage.d.ts.map +1 -0
- package/dist/ecoimpacthub/pages/sites/SiteDetailPage.js +498 -370
- package/dist/ecoimpacthub/pages/sites/SiteDetailPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/sites/SitesPage.d.ts +8 -0
- package/dist/ecoimpacthub/pages/sites/SitesPage.d.ts.map +1 -0
- package/dist/ecoimpacthub/pages/sites/SitesPage.js +109 -99
- package/dist/ecoimpacthub/pages/sites/SitesPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/sites/siteTypeVisuals.d.ts +22 -0
- package/dist/ecoimpacthub/pages/sites/siteTypeVisuals.d.ts.map +1 -0
- package/dist/ecoimpacthub/pages/sites/siteTypeVisuals.js +64 -0
- package/dist/ecoimpacthub/pages/sites/siteTypeVisuals.js.map +1 -0
- package/dist/ecoimpacthub/pages/species/SpeciesDetailPage.d.ts +9 -0
- package/dist/ecoimpacthub/pages/species/SpeciesDetailPage.d.ts.map +1 -0
- package/dist/ecoimpacthub/pages/species/SpeciesDetailPage.js +275 -259
- package/dist/ecoimpacthub/pages/species/SpeciesDetailPage.js.map +1 -1
- package/dist/ecoimpacthub/pages/species/SpeciesPage.d.ts +8 -0
- package/dist/ecoimpacthub/pages/species/SpeciesPage.d.ts.map +1 -0
- package/dist/ecoimpacthub/pages/species/SpeciesPage.js +235 -177
- package/dist/ecoimpacthub/pages/species/SpeciesPage.js.map +1 -1
- package/dist/ecoimpacthub/services/createSandboxAssistantTransport.d.ts +33 -0
- package/dist/ecoimpacthub/services/createSandboxAssistantTransport.d.ts.map +1 -0
- package/dist/ecoimpacthub/services/createSandboxAssistantTransport.js +42 -0
- package/dist/ecoimpacthub/services/createSandboxAssistantTransport.js.map +1 -0
- package/dist/ecoimpacthub/services/index.d.ts +6 -0
- package/dist/ecoimpacthub/services/index.d.ts.map +1 -0
- package/dist/ecoimpacthub/services/index.js +1 -0
- package/dist/ecoimpacthub/types/index.d.ts +417 -0
- package/dist/ecoimpacthub/types/index.d.ts.map +1 -0
- package/dist/ecoimpacthub/utils/cn.d.ts +4 -0
- package/dist/ecoimpacthub/utils/cn.d.ts.map +1 -0
- package/dist/ecoimpacthub/utils/formatters.d.ts +26 -0
- package/dist/ecoimpacthub/utils/formatters.d.ts.map +1 -0
- package/dist/ecoimpacthub/utils/i18n.d.ts +6 -0
- package/dist/ecoimpacthub/utils/i18n.d.ts.map +1 -0
- package/dist/ecoimpacthub/utils/index.d.ts +9 -0
- package/dist/ecoimpacthub/utils/index.d.ts.map +1 -0
- package/dist/ecoimpacthub/utils/navigation.d.ts +14 -0
- package/dist/ecoimpacthub/utils/navigation.d.ts.map +1 -0
- package/dist/generated/global-operations.d.ts +2 -0
- package/dist/generated/global-operations.d.ts.map +1 -0
- package/dist/generated/global-types.d.ts +18199 -0
- package/dist/generated/global-types.d.ts.map +1 -0
- package/dist/generated/wspace-operations.d.ts +2 -0
- package/dist/generated/wspace-operations.d.ts.map +1 -0
- package/dist/generated/wspace-types.d.ts +43046 -0
- package/dist/generated/wspace-types.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -1
- package/dist/node_modules/recharts/es6/cartesian/CartesianGrid.js +305 -0
- package/dist/node_modules/recharts/es6/cartesian/CartesianGrid.js.map +1 -0
- package/dist/node_modules/recharts/es6/context/chartLayoutContext.js +44 -33
- package/dist/node_modules/recharts/es6/context/chartLayoutContext.js.map +1 -1
- package/dist/node_modules/recharts/es6/util/ChartUtils.js +31 -23
- package/dist/node_modules/recharts/es6/util/ChartUtils.js.map +1 -1
- 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
|
|
4
|
-
import { StatusBadge as
|
|
5
|
-
import { ErrorView as
|
|
6
|
-
import { EmptyState as
|
|
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
|
|
9
|
-
import { useCursorPager as
|
|
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
|
|
12
|
-
import { Pagination as
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
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
|
|
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
|
-
],
|
|
41
|
+
], F = [
|
|
41
42
|
"GHG_PROTOCOL",
|
|
42
43
|
"GRI",
|
|
43
44
|
"TCFD",
|
|
44
45
|
"CDP",
|
|
45
46
|
"SASB",
|
|
46
47
|
"CUSTOM"
|
|
47
|
-
],
|
|
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
|
|
55
|
-
let { navigateTo:
|
|
56
|
-
limit:
|
|
57
|
-
cursor:
|
|
58
|
-
}), Z =
|
|
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__ */
|
|
63
|
+
render: (e) => /* @__PURE__ */ _("p", {
|
|
63
64
|
className: "font-semibold text-text-primary",
|
|
64
65
|
children: e.title
|
|
65
|
-
})
|
|
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__ */
|
|
72
|
+
render: (e) => /* @__PURE__ */ _(u, { framework: e.framework })
|
|
75
73
|
},
|
|
76
74
|
{
|
|
77
75
|
key: "status",
|
|
78
76
|
header: "Status",
|
|
79
|
-
render: (e) => /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
109
|
+
render: (e) => /* @__PURE__ */ _("span", {
|
|
109
110
|
className: "text-text-tertiary",
|
|
110
|
-
children:
|
|
111
|
+
children: r(e.updatedAt)
|
|
111
112
|
})
|
|
112
113
|
}
|
|
113
114
|
], $ = () => {
|
|
114
|
-
|
|
115
|
+
G(L), q(null);
|
|
115
116
|
};
|
|
116
|
-
return /* @__PURE__ */
|
|
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
|
|
120
|
-
onClick: () =>
|
|
121
|
-
children: [/* @__PURE__ */
|
|
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__ */
|
|
125
|
+
/* @__PURE__ */ _("div", {
|
|
125
126
|
className: "mb-5 flex flex-wrap items-center gap-3",
|
|
126
|
-
children: /* @__PURE__ */
|
|
127
|
-
options:
|
|
128
|
-
value:
|
|
127
|
+
children: /* @__PURE__ */ _(d, {
|
|
128
|
+
options: P,
|
|
129
|
+
value: z,
|
|
129
130
|
onChange: (e) => {
|
|
130
|
-
|
|
131
|
+
B(e), V.reset();
|
|
131
132
|
}
|
|
132
133
|
})
|
|
133
134
|
}),
|
|
134
|
-
|
|
135
|
+
Y ? /* @__PURE__ */ _(o, { label: "Loading reports…" }) : X ? /* @__PURE__ */ _(a, {
|
|
135
136
|
message: "Couldn't load reports.",
|
|
136
|
-
onRetry: () =>
|
|
137
|
-
}) : Q.length === 0 ? /* @__PURE__ */
|
|
137
|
+
onRetry: () => ie()
|
|
138
|
+
}) : Q.length === 0 ? /* @__PURE__ */ _(s, {
|
|
138
139
|
illustration: "empty-data",
|
|
139
|
-
icon: /* @__PURE__ */
|
|
140
|
+
icon: /* @__PURE__ */ _(m, { className: "h-10 w-10" }),
|
|
140
141
|
title: "No reports yet",
|
|
141
|
-
description:
|
|
142
|
-
action: /* @__PURE__ */ y
|
|
143
|
-
onClick: () =>
|
|
144
|
-
children: [/* @__PURE__ */
|
|
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__ */
|
|
147
|
-
columns:
|
|
147
|
+
}) : /* @__PURE__ */ v(g, { children: [/* @__PURE__ */ _(l, {
|
|
148
|
+
columns: ae,
|
|
148
149
|
rows: Q,
|
|
149
150
|
rowKey: (e) => e.id,
|
|
150
|
-
onRowClick: (e) =>
|
|
151
|
-
}), /* @__PURE__ */
|
|
152
|
-
page:
|
|
153
|
-
pageSize:
|
|
151
|
+
onRowClick: (e) => R(`reports/${e.id}`)
|
|
152
|
+
}), /* @__PURE__ */ _(re, {
|
|
153
|
+
page: V.page,
|
|
154
|
+
pageSize: I,
|
|
154
155
|
itemCount: Q.length,
|
|
155
|
-
hasMore:
|
|
156
|
-
onPageChange: (e) =>
|
|
156
|
+
hasMore: J?.pageInfo?.hasMore ?? !1,
|
|
157
|
+
onPageChange: (e) => V.onPageChange(e, J?.pageInfo?.cursor)
|
|
157
158
|
})] }),
|
|
158
|
-
/* @__PURE__ */
|
|
159
|
-
open:
|
|
159
|
+
/* @__PURE__ */ _(S, {
|
|
160
|
+
open: H,
|
|
160
161
|
onOpenChange: (e) => {
|
|
161
|
-
|
|
162
|
+
U(e), e || $();
|
|
162
163
|
},
|
|
163
|
-
children: /* @__PURE__ */
|
|
164
|
-
/* @__PURE__ */
|
|
165
|
-
/* @__PURE__ */
|
|
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__ */
|
|
169
|
+
/* @__PURE__ */ v("div", {
|
|
169
170
|
className: "grid gap-1.5",
|
|
170
|
-
children: [/* @__PURE__ */
|
|
171
|
+
children: [/* @__PURE__ */ _(x, {
|
|
171
172
|
htmlFor: "title",
|
|
172
173
|
children: "Title *"
|
|
173
|
-
}), /* @__PURE__ */
|
|
174
|
+
}), /* @__PURE__ */ _(b, {
|
|
174
175
|
id: "title",
|
|
175
|
-
value:
|
|
176
|
-
onChange: (e) =>
|
|
177
|
-
...
|
|
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__ */
|
|
184
|
+
/* @__PURE__ */ v("div", {
|
|
184
185
|
className: "grid gap-1.5",
|
|
185
|
-
children: [/* @__PURE__ */
|
|
186
|
+
children: [/* @__PURE__ */ _(x, {
|
|
186
187
|
htmlFor: "framework",
|
|
187
188
|
children: "Framework"
|
|
188
|
-
}), /* @__PURE__ */
|
|
189
|
-
value:
|
|
190
|
-
onValueChange: (e) =>
|
|
191
|
-
...
|
|
189
|
+
}), /* @__PURE__ */ v(O, {
|
|
190
|
+
value: W.framework,
|
|
191
|
+
onValueChange: (e) => G({
|
|
192
|
+
...W,
|
|
192
193
|
framework: e
|
|
193
194
|
}),
|
|
194
|
-
children: [/* @__PURE__ */
|
|
195
|
+
children: [/* @__PURE__ */ _(j, {
|
|
195
196
|
id: "framework",
|
|
196
|
-
children: /* @__PURE__ */
|
|
197
|
-
}), /* @__PURE__ */
|
|
197
|
+
children: /* @__PURE__ */ _(M, {})
|
|
198
|
+
}), /* @__PURE__ */ _(k, { children: F.map((e) => /* @__PURE__ */ _(A, {
|
|
198
199
|
value: e,
|
|
199
|
-
children:
|
|
200
|
+
children: ee(e)
|
|
200
201
|
}, e)) })]
|
|
201
202
|
})]
|
|
202
203
|
}),
|
|
203
|
-
/* @__PURE__ */
|
|
204
|
+
/* @__PURE__ */ v("div", {
|
|
204
205
|
className: "grid gap-2 sm:grid-cols-2",
|
|
205
|
-
children: [/* @__PURE__ */
|
|
206
|
+
children: [/* @__PURE__ */ v("div", {
|
|
206
207
|
className: "grid gap-1.5",
|
|
207
|
-
children: [/* @__PURE__ */
|
|
208
|
+
children: [/* @__PURE__ */ _(x, {
|
|
208
209
|
htmlFor: "periodStart",
|
|
209
210
|
children: "Period start *"
|
|
210
|
-
}), /* @__PURE__ */
|
|
211
|
+
}), /* @__PURE__ */ _(b, {
|
|
211
212
|
id: "periodStart",
|
|
212
213
|
type: "date",
|
|
213
|
-
value:
|
|
214
|
-
onChange: (e) =>
|
|
215
|
-
...
|
|
214
|
+
value: W.periodStart,
|
|
215
|
+
onChange: (e) => G({
|
|
216
|
+
...W,
|
|
216
217
|
periodStart: e.target.value
|
|
217
218
|
})
|
|
218
219
|
})]
|
|
219
|
-
}), /* @__PURE__ */
|
|
220
|
+
}), /* @__PURE__ */ v("div", {
|
|
220
221
|
className: "grid gap-1.5",
|
|
221
|
-
children: [/* @__PURE__ */
|
|
222
|
+
children: [/* @__PURE__ */ _(x, {
|
|
222
223
|
htmlFor: "periodEnd",
|
|
223
224
|
children: "Period end *"
|
|
224
|
-
}), /* @__PURE__ */
|
|
225
|
+
}), /* @__PURE__ */ _(b, {
|
|
225
226
|
id: "periodEnd",
|
|
226
227
|
type: "date",
|
|
227
|
-
value:
|
|
228
|
-
onChange: (e) =>
|
|
229
|
-
...
|
|
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__ */
|
|
236
|
+
/* @__PURE__ */ v("div", {
|
|
236
237
|
className: "grid gap-1.5",
|
|
237
|
-
children: [/* @__PURE__ */
|
|
238
|
+
children: [/* @__PURE__ */ _(x, {
|
|
238
239
|
htmlFor: "summary",
|
|
239
240
|
children: "Summary"
|
|
240
|
-
}), /* @__PURE__ */
|
|
241
|
+
}), /* @__PURE__ */ _(N, {
|
|
241
242
|
id: "summary",
|
|
242
|
-
value:
|
|
243
|
-
onChange: (e) =>
|
|
244
|
-
...
|
|
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
|
-
|
|
252
|
+
K && /* @__PURE__ */ _("p", {
|
|
252
253
|
className: "text-sm text-status-error-text",
|
|
253
|
-
children:
|
|
254
|
+
children: K
|
|
254
255
|
})
|
|
255
256
|
]
|
|
256
257
|
}),
|
|
257
|
-
/* @__PURE__ */
|
|
258
|
+
/* @__PURE__ */ v(T, { children: [/* @__PURE__ */ _(y, {
|
|
258
259
|
variant: "outline",
|
|
259
|
-
onClick: () =>
|
|
260
|
+
onClick: () => U(!1),
|
|
260
261
|
children: "Cancel"
|
|
261
|
-
}), /* @__PURE__ */
|
|
262
|
+
}), /* @__PURE__ */ _(y, {
|
|
262
263
|
onClick: async () => {
|
|
263
|
-
if (!
|
|
264
|
-
|
|
264
|
+
if (!W.title.trim()) {
|
|
265
|
+
q("Report title is required.");
|
|
265
266
|
return;
|
|
266
267
|
}
|
|
267
|
-
if (!
|
|
268
|
-
|
|
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:
|
|
274
|
-
framework:
|
|
275
|
-
periodStart:
|
|
276
|
-
periodEnd:
|
|
277
|
-
summary:
|
|
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
|
-
|
|
280
|
+
U(!1), $(), R(`reports/${e.id}`);
|
|
280
281
|
} catch (e) {
|
|
281
|
-
|
|
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 {
|
|
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":"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"}
|
|
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"}
|