@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,20 +1,21 @@
|
|
|
1
1
|
import { useEcoImpactHub as e } from "../../context/EcoImpactHubContext.js";
|
|
2
|
-
import { PageLayout as
|
|
3
|
-
import { formatEnumLabel as
|
|
4
|
-
import { StatusBadge as
|
|
5
|
-
import { ErrorView as
|
|
6
|
-
import { EmptyState as
|
|
2
|
+
import { PageLayout as t } from "../../components/PageLayout.js";
|
|
3
|
+
import { formatEnumLabel as n, formatNumber 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";
|
|
7
7
|
import "../../context/index.js";
|
|
8
|
-
import { useEcoCreateSite as
|
|
9
|
-
import { useCursorPager as
|
|
8
|
+
import { useEcoCreateSite as l, useEcoSites as u } from "../../hooks/useEcoImpactHubApi.js";
|
|
9
|
+
import { useCursorPager as d } from "../../hooks/useCursorPager.js";
|
|
10
10
|
import "../../hooks/index.js";
|
|
11
|
-
import { DataTable as
|
|
12
|
-
import { Pagination as
|
|
13
|
-
import { FilterTabs as
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
11
|
+
import { DataTable as f } from "../../components/DataTable.js";
|
|
12
|
+
import { Pagination as p } from "../../components/Pagination.js";
|
|
13
|
+
import { FilterTabs as m } from "../../components/FilterTabs.js";
|
|
14
|
+
import { SiteTypeBadge as h, SiteTypeIcon as g } from "./siteTypeVisuals.js";
|
|
15
|
+
import { useMemo as _, useState as v } from "react";
|
|
16
|
+
import { MapPin as y, Plus as b } from "lucide-react";
|
|
17
|
+
import { Fragment as x, jsx as S, jsxs as C } from "react/jsx-runtime";
|
|
18
|
+
import { Button as w, Input as T, Label as E, ResponsiveDialog as D, ResponsiveDialogContent as ee, ResponsiveDialogDescription as te, ResponsiveDialogFooter as ne, ResponsiveDialogHeader as re, ResponsiveDialogTitle as ie, 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/sites/SitesPage.tsx
|
|
19
20
|
var P = [
|
|
20
21
|
{
|
|
@@ -55,42 +56,51 @@ var P = [
|
|
|
55
56
|
description: ""
|
|
56
57
|
};
|
|
57
58
|
function R() {
|
|
58
|
-
let { navigateTo: R } = e(), [z, B] =
|
|
59
|
+
let { navigateTo: R } = e(), [z, B] = v("ALL"), [V, H] = v("ALL"), U = d(), [W, G] = v(!1), [K, q] = v(L), [J, Y] = v(null), { data: X, isLoading: ae, isError: oe, refetch: se } = u({
|
|
59
60
|
status: z === "ALL" ? void 0 : z,
|
|
60
61
|
type: V === "ALL" ? void 0 : V,
|
|
61
62
|
pagination: {
|
|
62
63
|
limit: I,
|
|
63
64
|
cursor: U.cursor
|
|
64
65
|
}
|
|
65
|
-
}), Z =
|
|
66
|
+
}), Z = l(), Q = _(() => X?.items ?? [], [X]), ce = [
|
|
66
67
|
{
|
|
67
68
|
key: "name",
|
|
68
69
|
header: "Site",
|
|
69
|
-
render: (e) => /* @__PURE__ */
|
|
70
|
-
className: "
|
|
71
|
-
children: e.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
70
|
+
render: (e) => /* @__PURE__ */ C("div", {
|
|
71
|
+
className: "flex items-center gap-3",
|
|
72
|
+
children: [/* @__PURE__ */ S(g, { type: e.type }), /* @__PURE__ */ C("div", {
|
|
73
|
+
className: "min-w-0",
|
|
74
|
+
children: [/* @__PURE__ */ S("p", {
|
|
75
|
+
className: "truncate font-semibold text-text-primary",
|
|
76
|
+
children: e.name
|
|
77
|
+
}), e.code && /* @__PURE__ */ S("p", {
|
|
78
|
+
className: "truncate text-xs text-text-tertiary",
|
|
79
|
+
children: e.code
|
|
80
|
+
})]
|
|
81
|
+
})]
|
|
82
|
+
})
|
|
76
83
|
},
|
|
77
84
|
{
|
|
78
85
|
key: "type",
|
|
79
86
|
header: "Type",
|
|
80
87
|
hideOnMobile: !0,
|
|
81
|
-
render: (e) => /* @__PURE__ */
|
|
82
|
-
className: "text-text-secondary",
|
|
83
|
-
children: t(e.type)
|
|
84
|
-
})
|
|
88
|
+
render: (e) => /* @__PURE__ */ S(h, { type: e.type })
|
|
85
89
|
},
|
|
86
90
|
{
|
|
87
91
|
key: "location",
|
|
88
92
|
header: "Location",
|
|
89
93
|
hideOnMobile: !0,
|
|
90
|
-
render: (e) =>
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
+
render: (e) => {
|
|
95
|
+
let t = [e.region, e.country].filter(Boolean).join(", ");
|
|
96
|
+
return t ? /* @__PURE__ */ C("span", {
|
|
97
|
+
className: "inline-flex items-center gap-1.5 text-text-secondary",
|
|
98
|
+
children: [/* @__PURE__ */ S(y, { className: "h-3.5 w-3.5 shrink-0 text-text-tertiary" }), t]
|
|
99
|
+
}) : /* @__PURE__ */ S("span", {
|
|
100
|
+
className: "text-text-tertiary",
|
|
101
|
+
children: "—"
|
|
102
|
+
});
|
|
103
|
+
}
|
|
94
104
|
},
|
|
95
105
|
{
|
|
96
106
|
key: "area",
|
|
@@ -98,107 +108,107 @@ function R() {
|
|
|
98
108
|
align: "right",
|
|
99
109
|
hideOnMobile: !0,
|
|
100
110
|
sortValue: (e) => e.areaHectares ?? 0,
|
|
101
|
-
render: (e) => e.areaHectares == null ? /* @__PURE__ */
|
|
111
|
+
render: (e) => e.areaHectares == null ? /* @__PURE__ */ S("span", {
|
|
102
112
|
className: "text-text-tertiary",
|
|
103
113
|
children: "—"
|
|
104
|
-
}) : /* @__PURE__ */
|
|
114
|
+
}) : /* @__PURE__ */ C("span", {
|
|
105
115
|
className: "tabular-nums text-text-secondary",
|
|
106
|
-
children: [
|
|
116
|
+
children: [r(e.areaHectares), " ha"]
|
|
107
117
|
})
|
|
108
118
|
},
|
|
109
119
|
{
|
|
110
120
|
key: "status",
|
|
111
121
|
header: "Status",
|
|
112
|
-
render: (e) => /* @__PURE__ */
|
|
122
|
+
render: (e) => /* @__PURE__ */ S(a, { status: e.status })
|
|
113
123
|
},
|
|
114
124
|
{
|
|
115
125
|
key: "updated",
|
|
116
126
|
header: "Updated",
|
|
117
127
|
align: "right",
|
|
118
128
|
hideOnMobile: !0,
|
|
119
|
-
render: (e) => /* @__PURE__ */
|
|
129
|
+
render: (e) => /* @__PURE__ */ S("span", {
|
|
120
130
|
className: "text-text-tertiary",
|
|
121
|
-
children:
|
|
131
|
+
children: i(e.updatedAt)
|
|
122
132
|
})
|
|
123
133
|
}
|
|
124
134
|
], $ = () => {
|
|
125
135
|
q(L), Y(null);
|
|
126
136
|
};
|
|
127
|
-
return /* @__PURE__ */
|
|
137
|
+
return /* @__PURE__ */ C(t, {
|
|
128
138
|
title: "Sites",
|
|
129
139
|
description: "Monitored locations — facilities, watersheds, forests, wetlands, farms & protected areas.",
|
|
130
|
-
actions: /* @__PURE__ */
|
|
140
|
+
actions: /* @__PURE__ */ C(w, {
|
|
131
141
|
onClick: () => G(!0),
|
|
132
|
-
children: [/* @__PURE__ */
|
|
142
|
+
children: [/* @__PURE__ */ S(b, { className: "mr-1.5 h-4 w-4" }), " New site"]
|
|
133
143
|
}),
|
|
134
144
|
children: [
|
|
135
|
-
/* @__PURE__ */
|
|
145
|
+
/* @__PURE__ */ C("div", {
|
|
136
146
|
className: "mb-5 flex flex-wrap items-center gap-3",
|
|
137
|
-
children: [/* @__PURE__ */
|
|
147
|
+
children: [/* @__PURE__ */ S(m, {
|
|
138
148
|
options: P,
|
|
139
149
|
value: z,
|
|
140
150
|
onChange: (e) => {
|
|
141
151
|
B(e), U.reset();
|
|
142
152
|
}
|
|
143
|
-
}), /* @__PURE__ */
|
|
153
|
+
}), /* @__PURE__ */ C(O, {
|
|
144
154
|
value: V,
|
|
145
155
|
onValueChange: (e) => {
|
|
146
156
|
H(e), U.reset();
|
|
147
157
|
},
|
|
148
|
-
children: [/* @__PURE__ */
|
|
158
|
+
children: [/* @__PURE__ */ S(j, {
|
|
149
159
|
className: "w-44",
|
|
150
|
-
children: /* @__PURE__ */
|
|
151
|
-
}), /* @__PURE__ */
|
|
160
|
+
children: /* @__PURE__ */ S(M, { placeholder: "All types" })
|
|
161
|
+
}), /* @__PURE__ */ C(k, { children: [/* @__PURE__ */ S(A, {
|
|
152
162
|
value: "ALL",
|
|
153
163
|
children: "All types"
|
|
154
|
-
}), F.map((e) => /* @__PURE__ */
|
|
164
|
+
}), F.map((e) => /* @__PURE__ */ S(A, {
|
|
155
165
|
value: e,
|
|
156
|
-
children:
|
|
166
|
+
children: n(e)
|
|
157
167
|
}, e))] })]
|
|
158
168
|
})]
|
|
159
169
|
}),
|
|
160
|
-
|
|
170
|
+
ae ? /* @__PURE__ */ S(s, { label: "Loading sites…" }) : oe ? /* @__PURE__ */ S(o, {
|
|
161
171
|
message: "Couldn't load sites.",
|
|
162
|
-
onRetry: () =>
|
|
163
|
-
}) : Q.length === 0 ? /* @__PURE__ */
|
|
172
|
+
onRetry: () => se()
|
|
173
|
+
}) : Q.length === 0 ? /* @__PURE__ */ S(c, {
|
|
164
174
|
illustration: "empty-data",
|
|
165
|
-
icon: /* @__PURE__ */
|
|
175
|
+
icon: /* @__PURE__ */ S(y, { className: "h-10 w-10" }),
|
|
166
176
|
title: "No sites yet",
|
|
167
177
|
description: z === "ALL" && V === "ALL" ? "Create your first monitored site to start collecting environmental data." : "No sites match these filters.",
|
|
168
|
-
action: /* @__PURE__ */
|
|
178
|
+
action: /* @__PURE__ */ C(w, {
|
|
169
179
|
onClick: () => G(!0),
|
|
170
|
-
children: [/* @__PURE__ */
|
|
180
|
+
children: [/* @__PURE__ */ S(b, { className: "mr-1.5 h-4 w-4" }), " New site"]
|
|
171
181
|
})
|
|
172
|
-
}) : /* @__PURE__ */
|
|
173
|
-
columns:
|
|
182
|
+
}) : /* @__PURE__ */ C(x, { children: [/* @__PURE__ */ S(f, {
|
|
183
|
+
columns: ce,
|
|
174
184
|
rows: Q,
|
|
175
185
|
rowKey: (e) => e.id,
|
|
176
186
|
onRowClick: (e) => R(`sites/${e.id}`)
|
|
177
|
-
}), /* @__PURE__ */
|
|
187
|
+
}), /* @__PURE__ */ S(p, {
|
|
178
188
|
page: U.page,
|
|
179
189
|
pageSize: I,
|
|
180
190
|
itemCount: Q.length,
|
|
181
191
|
hasMore: X?.pageInfo?.hasMore ?? !1,
|
|
182
192
|
onPageChange: (e) => U.onPageChange(e, X?.pageInfo?.cursor)
|
|
183
193
|
})] }),
|
|
184
|
-
/* @__PURE__ */
|
|
194
|
+
/* @__PURE__ */ S(D, {
|
|
185
195
|
open: W,
|
|
186
196
|
onOpenChange: (e) => {
|
|
187
197
|
G(e), e || $();
|
|
188
198
|
},
|
|
189
|
-
children: /* @__PURE__ */
|
|
190
|
-
/* @__PURE__ */
|
|
191
|
-
/* @__PURE__ */
|
|
199
|
+
children: /* @__PURE__ */ C(ee, { children: [
|
|
200
|
+
/* @__PURE__ */ C(re, { children: [/* @__PURE__ */ S(ie, { children: "New site" }), /* @__PURE__ */ S(te, { children: "Register a location to monitor and attribute environmental data to." })] }),
|
|
201
|
+
/* @__PURE__ */ C("div", {
|
|
192
202
|
className: "grid gap-4 py-2",
|
|
193
203
|
children: [
|
|
194
|
-
/* @__PURE__ */
|
|
204
|
+
/* @__PURE__ */ C("div", {
|
|
195
205
|
className: "grid gap-2 sm:grid-cols-2",
|
|
196
|
-
children: [/* @__PURE__ */
|
|
206
|
+
children: [/* @__PURE__ */ C("div", {
|
|
197
207
|
className: "grid gap-1.5",
|
|
198
|
-
children: [/* @__PURE__ */
|
|
208
|
+
children: [/* @__PURE__ */ S(E, {
|
|
199
209
|
htmlFor: "name",
|
|
200
210
|
children: "Name *"
|
|
201
|
-
}), /* @__PURE__ */
|
|
211
|
+
}), /* @__PURE__ */ S(T, {
|
|
202
212
|
id: "name",
|
|
203
213
|
value: K.name,
|
|
204
214
|
onChange: (e) => q({
|
|
@@ -207,12 +217,12 @@ function R() {
|
|
|
207
217
|
}),
|
|
208
218
|
placeholder: "Palar Wetland Reserve"
|
|
209
219
|
})]
|
|
210
|
-
}), /* @__PURE__ */
|
|
220
|
+
}), /* @__PURE__ */ C("div", {
|
|
211
221
|
className: "grid gap-1.5",
|
|
212
|
-
children: [/* @__PURE__ */
|
|
222
|
+
children: [/* @__PURE__ */ S(E, {
|
|
213
223
|
htmlFor: "code",
|
|
214
224
|
children: "Code"
|
|
215
|
-
}), /* @__PURE__ */
|
|
225
|
+
}), /* @__PURE__ */ S(T, {
|
|
216
226
|
id: "code",
|
|
217
227
|
value: K.code,
|
|
218
228
|
onChange: (e) => q({
|
|
@@ -223,33 +233,33 @@ function R() {
|
|
|
223
233
|
})]
|
|
224
234
|
})]
|
|
225
235
|
}),
|
|
226
|
-
/* @__PURE__ */
|
|
236
|
+
/* @__PURE__ */ C("div", {
|
|
227
237
|
className: "grid gap-2 sm:grid-cols-2",
|
|
228
|
-
children: [/* @__PURE__ */
|
|
238
|
+
children: [/* @__PURE__ */ C("div", {
|
|
229
239
|
className: "grid gap-1.5",
|
|
230
|
-
children: [/* @__PURE__ */
|
|
240
|
+
children: [/* @__PURE__ */ S(E, {
|
|
231
241
|
htmlFor: "type",
|
|
232
242
|
children: "Type"
|
|
233
|
-
}), /* @__PURE__ */
|
|
243
|
+
}), /* @__PURE__ */ C(O, {
|
|
234
244
|
value: K.type,
|
|
235
245
|
onValueChange: (e) => q({
|
|
236
246
|
...K,
|
|
237
247
|
type: e
|
|
238
248
|
}),
|
|
239
|
-
children: [/* @__PURE__ */
|
|
249
|
+
children: [/* @__PURE__ */ S(j, {
|
|
240
250
|
id: "type",
|
|
241
|
-
children: /* @__PURE__ */
|
|
242
|
-
}), /* @__PURE__ */
|
|
251
|
+
children: /* @__PURE__ */ S(M, {})
|
|
252
|
+
}), /* @__PURE__ */ S(k, { children: F.map((e) => /* @__PURE__ */ S(A, {
|
|
243
253
|
value: e,
|
|
244
|
-
children:
|
|
254
|
+
children: n(e)
|
|
245
255
|
}, e)) })]
|
|
246
256
|
})]
|
|
247
|
-
}), /* @__PURE__ */
|
|
257
|
+
}), /* @__PURE__ */ C("div", {
|
|
248
258
|
className: "grid gap-1.5",
|
|
249
|
-
children: [/* @__PURE__ */
|
|
259
|
+
children: [/* @__PURE__ */ S(E, {
|
|
250
260
|
htmlFor: "area",
|
|
251
261
|
children: "Area (hectares)"
|
|
252
|
-
}), /* @__PURE__ */
|
|
262
|
+
}), /* @__PURE__ */ S(T, {
|
|
253
263
|
id: "area",
|
|
254
264
|
type: "number",
|
|
255
265
|
min: "0",
|
|
@@ -263,14 +273,14 @@ function R() {
|
|
|
263
273
|
})]
|
|
264
274
|
})]
|
|
265
275
|
}),
|
|
266
|
-
/* @__PURE__ */
|
|
276
|
+
/* @__PURE__ */ C("div", {
|
|
267
277
|
className: "grid gap-2 sm:grid-cols-2",
|
|
268
|
-
children: [/* @__PURE__ */
|
|
278
|
+
children: [/* @__PURE__ */ C("div", {
|
|
269
279
|
className: "grid gap-1.5",
|
|
270
|
-
children: [/* @__PURE__ */
|
|
280
|
+
children: [/* @__PURE__ */ S(E, {
|
|
271
281
|
htmlFor: "region",
|
|
272
282
|
children: "Region"
|
|
273
|
-
}), /* @__PURE__ */
|
|
283
|
+
}), /* @__PURE__ */ S(T, {
|
|
274
284
|
id: "region",
|
|
275
285
|
value: K.region,
|
|
276
286
|
onChange: (e) => q({
|
|
@@ -279,12 +289,12 @@ function R() {
|
|
|
279
289
|
}),
|
|
280
290
|
placeholder: "Tamil Nadu"
|
|
281
291
|
})]
|
|
282
|
-
}), /* @__PURE__ */
|
|
292
|
+
}), /* @__PURE__ */ C("div", {
|
|
283
293
|
className: "grid gap-1.5",
|
|
284
|
-
children: [/* @__PURE__ */
|
|
294
|
+
children: [/* @__PURE__ */ S(E, {
|
|
285
295
|
htmlFor: "country",
|
|
286
296
|
children: "Country"
|
|
287
|
-
}), /* @__PURE__ */
|
|
297
|
+
}), /* @__PURE__ */ S(T, {
|
|
288
298
|
id: "country",
|
|
289
299
|
value: K.country,
|
|
290
300
|
onChange: (e) => q({
|
|
@@ -295,14 +305,14 @@ function R() {
|
|
|
295
305
|
})]
|
|
296
306
|
})]
|
|
297
307
|
}),
|
|
298
|
-
/* @__PURE__ */
|
|
308
|
+
/* @__PURE__ */ C("div", {
|
|
299
309
|
className: "grid gap-2 sm:grid-cols-2",
|
|
300
|
-
children: [/* @__PURE__ */
|
|
310
|
+
children: [/* @__PURE__ */ C("div", {
|
|
301
311
|
className: "grid gap-1.5",
|
|
302
|
-
children: [/* @__PURE__ */
|
|
312
|
+
children: [/* @__PURE__ */ S(E, {
|
|
303
313
|
htmlFor: "lat",
|
|
304
314
|
children: "Latitude"
|
|
305
|
-
}), /* @__PURE__ */
|
|
315
|
+
}), /* @__PURE__ */ S(T, {
|
|
306
316
|
id: "lat",
|
|
307
317
|
type: "number",
|
|
308
318
|
step: "any",
|
|
@@ -313,12 +323,12 @@ function R() {
|
|
|
313
323
|
}),
|
|
314
324
|
placeholder: "12.9716"
|
|
315
325
|
})]
|
|
316
|
-
}), /* @__PURE__ */
|
|
326
|
+
}), /* @__PURE__ */ C("div", {
|
|
317
327
|
className: "grid gap-1.5",
|
|
318
|
-
children: [/* @__PURE__ */
|
|
328
|
+
children: [/* @__PURE__ */ S(E, {
|
|
319
329
|
htmlFor: "lng",
|
|
320
330
|
children: "Longitude"
|
|
321
|
-
}), /* @__PURE__ */
|
|
331
|
+
}), /* @__PURE__ */ S(T, {
|
|
322
332
|
id: "lng",
|
|
323
333
|
type: "number",
|
|
324
334
|
step: "any",
|
|
@@ -331,12 +341,12 @@ function R() {
|
|
|
331
341
|
})]
|
|
332
342
|
})]
|
|
333
343
|
}),
|
|
334
|
-
/* @__PURE__ */
|
|
344
|
+
/* @__PURE__ */ C("div", {
|
|
335
345
|
className: "grid gap-1.5",
|
|
336
|
-
children: [/* @__PURE__ */
|
|
346
|
+
children: [/* @__PURE__ */ S(E, {
|
|
337
347
|
htmlFor: "description",
|
|
338
348
|
children: "Description"
|
|
339
|
-
}), /* @__PURE__ */
|
|
349
|
+
}), /* @__PURE__ */ S(N, {
|
|
340
350
|
id: "description",
|
|
341
351
|
value: K.description,
|
|
342
352
|
onChange: (e) => q({
|
|
@@ -347,17 +357,17 @@ function R() {
|
|
|
347
357
|
rows: 2
|
|
348
358
|
})]
|
|
349
359
|
}),
|
|
350
|
-
J && /* @__PURE__ */
|
|
360
|
+
J && /* @__PURE__ */ S("p", {
|
|
351
361
|
className: "text-sm text-status-error-text",
|
|
352
362
|
children: J
|
|
353
363
|
})
|
|
354
364
|
]
|
|
355
365
|
}),
|
|
356
|
-
/* @__PURE__ */
|
|
366
|
+
/* @__PURE__ */ C(ne, { children: [/* @__PURE__ */ S(w, {
|
|
357
367
|
variant: "outline",
|
|
358
368
|
onClick: () => G(!1),
|
|
359
369
|
children: "Cancel"
|
|
360
|
-
}), /* @__PURE__ */
|
|
370
|
+
}), /* @__PURE__ */ S(w, {
|
|
361
371
|
onClick: async () => {
|
|
362
372
|
if (!K.name.trim()) {
|
|
363
373
|
Y("Site name is required.");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SitesPage.js","names":[],"sources":["../../../../src/ecoimpacthub/pages/sites/SitesPage.tsx"],"sourcesContent":["/**\n * Sites — list, filter, and create monitored locations.\n * @module ecoimpacthub/pages/sites\n *\n * Reads `ecoListSites`; writes `ecoCreateSite`.\n */\n\nimport { useMemo, useState } from 'react';\nimport { Plus, MapPin } 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 { useEcoSites, useEcoCreateSite, useCursorPager } from '../../hooks';\nimport { formatEnumLabel, formatNumber, formatRelativeTime } from '../../utils/formatters';\nimport type { EcoSite, EcoSiteStatus, EcoSiteType } from '../../types';\n\nconst STATUS_FILTERS: FilterOption<EcoSiteStatus | 'ALL'>[] = [\n { value: 'ALL', label: 'All' },\n { value: 'ACTIVE', label: 'Active' },\n { value: 'MONITORING_PAUSED', label: 'Paused' },\n { value: 'ARCHIVED', label: 'Archived' },\n];\n\nconst SITE_TYPES: EcoSiteType[] = [\n 'FACILITY',\n 'WATERSHED',\n 'FOREST',\n 'WETLAND',\n 'FARM',\n 'PROTECTED_AREA',\n 'AIRSHED',\n 'COASTAL',\n 'OTHER',\n];\n\nconst PAGE_SIZE = 25;\n\ninterface CreateFormState {\n name: string;\n code: string;\n type: EcoSiteType;\n region: string;\n country: string;\n areaHectares: string;\n latitude: string;\n longitude: string;\n description: string;\n}\n\nconst EMPTY_FORM: CreateFormState = {\n name: '',\n code: '',\n type: 'FACILITY',\n region: '',\n country: '',\n areaHectares: '',\n latitude: '',\n longitude: '',\n description: '',\n};\n\nexport function SitesPage() {\n const { navigateTo } = useEcoImpactHub();\n const [status, setStatus] = useState<EcoSiteStatus | 'ALL'>('ALL');\n const [type, setType] = useState<EcoSiteType | '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 } = useEcoSites({\n status: status === 'ALL' ? undefined : status,\n type: type === 'ALL' ? undefined : type,\n pagination: { limit: PAGE_SIZE, cursor: pager.cursor },\n });\n const createSite = useEcoCreateSite();\n\n const rows = useMemo(() => data?.items ?? [], [data]);\n\n const columns: Column<EcoSite>[] = [\n {\n key: 'name',\n header: 'Site',\n render: (s) => (\n <div>\n <p className=\"font-semibold text-text-primary\">{s.name}</p>\n <p className=\"text-xs text-text-tertiary\">{s.code ?? formatEnumLabel(s.type)}</p>\n </div>\n ),\n },\n {\n key: 'type',\n header: 'Type',\n hideOnMobile: true,\n render: (s) => <span className=\"text-text-secondary\">{formatEnumLabel(s.type)}</span>,\n },\n {\n key: 'location',\n header: 'Location',\n hideOnMobile: true,\n render: (s) => (\n <span className=\"text-text-secondary\">\n {[s.region, s.country].filter(Boolean).join(', ') || '—'}\n </span>\n ),\n },\n {\n key: 'area',\n header: 'Area',\n align: 'right',\n hideOnMobile: true,\n sortValue: (s) => s.areaHectares ?? 0,\n render: (s) =>\n s.areaHectares != null ? (\n <span className=\"tabular-nums text-text-secondary\">\n {formatNumber(s.areaHectares)} ha\n </span>\n ) : (\n <span className=\"text-text-tertiary\">—</span>\n ),\n },\n {\n key: 'status',\n header: 'Status',\n render: (s) => <StatusBadge status={s.status} />,\n },\n {\n key: 'updated',\n header: 'Updated',\n align: 'right',\n hideOnMobile: true,\n render: (s) => <span className=\"text-text-tertiary\">{formatRelativeTime(s.updatedAt)}</span>,\n },\n ];\n\n const resetForm = () => {\n setForm(EMPTY_FORM);\n setFormError(null);\n };\n\n const handleCreate = async () => {\n if (!form.name.trim()) {\n setFormError('Site name is required.');\n return;\n }\n try {\n const created = await createSite.mutateAsync({\n name: form.name.trim(),\n code: form.code.trim() || null,\n type: form.type,\n region: form.region.trim() || null,\n country: form.country.trim() || null,\n areaHectares: form.areaHectares ? Number(form.areaHectares) : null,\n latitude: form.latitude ? Number(form.latitude) : null,\n longitude: form.longitude ? Number(form.longitude) : null,\n description: form.description.trim() || null,\n });\n setDialogOpen(false);\n resetForm();\n navigateTo(`sites/${created.id}`);\n } catch (err) {\n setFormError(err instanceof Error ? err.message : 'Failed to create site.');\n }\n };\n\n return (\n <PageLayout\n title=\"Sites\"\n description=\"Monitored locations — facilities, watersheds, forests, wetlands, farms & protected areas.\"\n actions={\n <Button onClick={() => setDialogOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New site\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 <Select\n value={type}\n onValueChange={(v) => {\n setType(v as EcoSiteType | 'ALL');\n pager.reset();\n }}\n >\n <SelectTrigger className=\"w-44\">\n <SelectValue placeholder=\"All types\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">All types</SelectItem>\n {SITE_TYPES.map((t) => (\n <SelectItem key={t} value={t}>\n {formatEnumLabel(t)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {isLoading ? (\n <LoadingView label=\"Loading sites…\" />\n ) : isError ? (\n <ErrorView message=\"Couldn't load sites.\" onRetry={() => refetch()} />\n ) : rows.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<MapPin className=\"h-10 w-10\" />}\n title=\"No sites yet\"\n description={\n status === 'ALL' && type === 'ALL'\n ? 'Create your first monitored site to start collecting environmental data.'\n : 'No sites match these filters.'\n }\n action={\n <Button onClick={() => setDialogOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New site\n </Button>\n }\n />\n ) : (\n <>\n <DataTable\n columns={columns}\n rows={rows}\n rowKey={(s) => s.id}\n onRowClick={(s) => navigateTo(`sites/${s.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 site</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Register a location to monitor and attribute environmental data to.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"grid gap-4 py-2\">\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"name\">Name *</Label>\n <Input\n id=\"name\"\n value={form.name}\n onChange={(e) => setForm({ ...form, name: e.target.value })}\n placeholder=\"Palar Wetland Reserve\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"code\">Code</Label>\n <Input\n id=\"code\"\n value={form.code}\n onChange={(e) => setForm({ ...form, code: e.target.value })}\n placeholder=\"SITE-PWR\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"type\">Type</Label>\n <Select\n value={form.type}\n onValueChange={(v) => setForm({ ...form, type: v as EcoSiteType })}\n >\n <SelectTrigger id=\"type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SITE_TYPES.map((t) => (\n <SelectItem key={t} value={t}>\n {formatEnumLabel(t)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"area\">Area (hectares)</Label>\n <Input\n id=\"area\"\n type=\"number\"\n min=\"0\"\n step=\"any\"\n value={form.areaHectares}\n onChange={(e) => setForm({ ...form, areaHectares: e.target.value })}\n placeholder=\"42.5\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"region\">Region</Label>\n <Input\n id=\"region\"\n value={form.region}\n onChange={(e) => setForm({ ...form, region: e.target.value })}\n placeholder=\"Tamil Nadu\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"country\">Country</Label>\n <Input\n id=\"country\"\n value={form.country}\n onChange={(e) => setForm({ ...form, country: e.target.value })}\n placeholder=\"India\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"lat\">Latitude</Label>\n <Input\n id=\"lat\"\n type=\"number\"\n step=\"any\"\n value={form.latitude}\n onChange={(e) => setForm({ ...form, latitude: e.target.value })}\n placeholder=\"12.9716\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"lng\">Longitude</Label>\n <Input\n id=\"lng\"\n type=\"number\"\n step=\"any\"\n value={form.longitude}\n onChange={(e) => setForm({ ...form, longitude: e.target.value })}\n placeholder=\"77.5946\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"description\">Description</Label>\n <Textarea\n id=\"description\"\n value={form.description}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n placeholder=\"Optional context about this site.\"\n rows={2}\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={createSite.isPending}>\n {createSite.isPending ? 'Creating…' : 'Create site'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SitesPage.js","names":[],"sources":["../../../../src/ecoimpacthub/pages/sites/SitesPage.tsx"],"sourcesContent":["/**\n * Sites — list, filter, and create monitored locations.\n * @module ecoimpacthub/pages/sites\n *\n * Reads `ecoListSites`; writes `ecoCreateSite`.\n */\n\nimport { useMemo, useState } from 'react';\nimport { Plus, MapPin } 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 { SiteTypeBadge, SiteTypeIcon } from './siteTypeVisuals';\nimport { useEcoImpactHub } from '../../context';\nimport { useEcoSites, useEcoCreateSite, useCursorPager } from '../../hooks';\nimport { formatEnumLabel, formatNumber, formatRelativeTime } from '../../utils/formatters';\nimport type { EcoSite, EcoSiteStatus, EcoSiteType } from '../../types';\n\nconst STATUS_FILTERS: FilterOption<EcoSiteStatus | 'ALL'>[] = [\n { value: 'ALL', label: 'All' },\n { value: 'ACTIVE', label: 'Active' },\n { value: 'MONITORING_PAUSED', label: 'Paused' },\n { value: 'ARCHIVED', label: 'Archived' },\n];\n\nconst SITE_TYPES: EcoSiteType[] = [\n 'FACILITY',\n 'WATERSHED',\n 'FOREST',\n 'WETLAND',\n 'FARM',\n 'PROTECTED_AREA',\n 'AIRSHED',\n 'COASTAL',\n 'OTHER',\n];\n\nconst PAGE_SIZE = 25;\n\ninterface CreateFormState {\n name: string;\n code: string;\n type: EcoSiteType;\n region: string;\n country: string;\n areaHectares: string;\n latitude: string;\n longitude: string;\n description: string;\n}\n\nconst EMPTY_FORM: CreateFormState = {\n name: '',\n code: '',\n type: 'FACILITY',\n region: '',\n country: '',\n areaHectares: '',\n latitude: '',\n longitude: '',\n description: '',\n};\n\nexport function SitesPage() {\n const { navigateTo } = useEcoImpactHub();\n const [status, setStatus] = useState<EcoSiteStatus | 'ALL'>('ALL');\n const [type, setType] = useState<EcoSiteType | '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 } = useEcoSites({\n status: status === 'ALL' ? undefined : status,\n type: type === 'ALL' ? undefined : type,\n pagination: { limit: PAGE_SIZE, cursor: pager.cursor },\n });\n const createSite = useEcoCreateSite();\n\n const rows = useMemo(() => data?.items ?? [], [data]);\n\n const columns: Column<EcoSite>[] = [\n {\n key: 'name',\n header: 'Site',\n render: (s) => (\n <div className=\"flex items-center gap-3\">\n <SiteTypeIcon type={s.type} />\n <div className=\"min-w-0\">\n <p className=\"truncate font-semibold text-text-primary\">{s.name}</p>\n {s.code && <p className=\"truncate text-xs text-text-tertiary\">{s.code}</p>}\n </div>\n </div>\n ),\n },\n {\n key: 'type',\n header: 'Type',\n hideOnMobile: true,\n render: (s) => <SiteTypeBadge type={s.type} />,\n },\n {\n key: 'location',\n header: 'Location',\n hideOnMobile: true,\n render: (s) => {\n const loc = [s.region, s.country].filter(Boolean).join(', ');\n return loc ? (\n <span className=\"inline-flex items-center gap-1.5 text-text-secondary\">\n <MapPin className=\"h-3.5 w-3.5 shrink-0 text-text-tertiary\" />\n {loc}\n </span>\n ) : (\n <span className=\"text-text-tertiary\">—</span>\n );\n },\n },\n {\n key: 'area',\n header: 'Area',\n align: 'right',\n hideOnMobile: true,\n sortValue: (s) => s.areaHectares ?? 0,\n render: (s) =>\n s.areaHectares != null ? (\n <span className=\"tabular-nums text-text-secondary\">\n {formatNumber(s.areaHectares)} ha\n </span>\n ) : (\n <span className=\"text-text-tertiary\">—</span>\n ),\n },\n {\n key: 'status',\n header: 'Status',\n render: (s) => <StatusBadge status={s.status} />,\n },\n {\n key: 'updated',\n header: 'Updated',\n align: 'right',\n hideOnMobile: true,\n render: (s) => <span className=\"text-text-tertiary\">{formatRelativeTime(s.updatedAt)}</span>,\n },\n ];\n\n const resetForm = () => {\n setForm(EMPTY_FORM);\n setFormError(null);\n };\n\n const handleCreate = async () => {\n if (!form.name.trim()) {\n setFormError('Site name is required.');\n return;\n }\n try {\n const created = await createSite.mutateAsync({\n name: form.name.trim(),\n code: form.code.trim() || null,\n type: form.type,\n region: form.region.trim() || null,\n country: form.country.trim() || null,\n areaHectares: form.areaHectares ? Number(form.areaHectares) : null,\n latitude: form.latitude ? Number(form.latitude) : null,\n longitude: form.longitude ? Number(form.longitude) : null,\n description: form.description.trim() || null,\n });\n setDialogOpen(false);\n resetForm();\n navigateTo(`sites/${created.id}`);\n } catch (err) {\n setFormError(err instanceof Error ? err.message : 'Failed to create site.');\n }\n };\n\n return (\n <PageLayout\n title=\"Sites\"\n description=\"Monitored locations — facilities, watersheds, forests, wetlands, farms & protected areas.\"\n actions={\n <Button onClick={() => setDialogOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New site\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 <Select\n value={type}\n onValueChange={(v) => {\n setType(v as EcoSiteType | 'ALL');\n pager.reset();\n }}\n >\n <SelectTrigger className=\"w-44\">\n <SelectValue placeholder=\"All types\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">All types</SelectItem>\n {SITE_TYPES.map((t) => (\n <SelectItem key={t} value={t}>\n {formatEnumLabel(t)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {isLoading ? (\n <LoadingView label=\"Loading sites…\" />\n ) : isError ? (\n <ErrorView message=\"Couldn't load sites.\" onRetry={() => refetch()} />\n ) : rows.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<MapPin className=\"h-10 w-10\" />}\n title=\"No sites yet\"\n description={\n status === 'ALL' && type === 'ALL'\n ? 'Create your first monitored site to start collecting environmental data.'\n : 'No sites match these filters.'\n }\n action={\n <Button onClick={() => setDialogOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New site\n </Button>\n }\n />\n ) : (\n <>\n <DataTable\n columns={columns}\n rows={rows}\n rowKey={(s) => s.id}\n onRowClick={(s) => navigateTo(`sites/${s.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 site</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Register a location to monitor and attribute environmental data to.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"grid gap-4 py-2\">\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"name\">Name *</Label>\n <Input\n id=\"name\"\n value={form.name}\n onChange={(e) => setForm({ ...form, name: e.target.value })}\n placeholder=\"Palar Wetland Reserve\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"code\">Code</Label>\n <Input\n id=\"code\"\n value={form.code}\n onChange={(e) => setForm({ ...form, code: e.target.value })}\n placeholder=\"SITE-PWR\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"type\">Type</Label>\n <Select\n value={form.type}\n onValueChange={(v) => setForm({ ...form, type: v as EcoSiteType })}\n >\n <SelectTrigger id=\"type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SITE_TYPES.map((t) => (\n <SelectItem key={t} value={t}>\n {formatEnumLabel(t)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"area\">Area (hectares)</Label>\n <Input\n id=\"area\"\n type=\"number\"\n min=\"0\"\n step=\"any\"\n value={form.areaHectares}\n onChange={(e) => setForm({ ...form, areaHectares: e.target.value })}\n placeholder=\"42.5\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"region\">Region</Label>\n <Input\n id=\"region\"\n value={form.region}\n onChange={(e) => setForm({ ...form, region: e.target.value })}\n placeholder=\"Tamil Nadu\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"country\">Country</Label>\n <Input\n id=\"country\"\n value={form.country}\n onChange={(e) => setForm({ ...form, country: e.target.value })}\n placeholder=\"India\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-2 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"lat\">Latitude</Label>\n <Input\n id=\"lat\"\n type=\"number\"\n step=\"any\"\n value={form.latitude}\n onChange={(e) => setForm({ ...form, latitude: e.target.value })}\n placeholder=\"12.9716\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"lng\">Longitude</Label>\n <Input\n id=\"lng\"\n type=\"number\"\n step=\"any\"\n value={form.longitude}\n onChange={(e) => setForm({ ...form, longitude: e.target.value })}\n placeholder=\"77.5946\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"description\">Description</Label>\n <Textarea\n id=\"description\"\n value={form.description}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n placeholder=\"Optional context about this site.\"\n rows={2}\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={createSite.isPending}>\n {createSite.isPending ? 'Creating…' : 'Create site'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { LucideIcon } from 'lucide-react';
|
|
3
|
+
import { EcoSiteType } from '../../types';
|
|
4
|
+
|
|
5
|
+
interface TypeVisual {
|
|
6
|
+
Icon: LucideIcon;
|
|
7
|
+
/** Shared bg + text classes for both the pill and the leading icon tile. */
|
|
8
|
+
tone: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function siteTypeVisual(type: EcoSiteType): TypeVisual;
|
|
11
|
+
/** A leading rounded icon tile keyed to the site type. */
|
|
12
|
+
export declare const SiteTypeIcon: FC<{
|
|
13
|
+
type: EcoSiteType;
|
|
14
|
+
className?: string;
|
|
15
|
+
}>;
|
|
16
|
+
/** A coloured pill: icon + human label for a site type. */
|
|
17
|
+
export declare const SiteTypeBadge: FC<{
|
|
18
|
+
type: EcoSiteType;
|
|
19
|
+
className?: string;
|
|
20
|
+
}>;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=siteTypeVisuals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"siteTypeVisuals.d.ts","sourceRoot":"","sources":["../../../../src/ecoimpacthub/pages/sites/siteTypeVisuals.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAUL,KAAK,UAAU,EAChB,MAAM,cAAc,CAAC;AAGtB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,UAAU,UAAU;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;CACd;AAkCD,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,CAE5D;AAED,0DAA0D;AAC1D,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAiBtE,CAAC;AAEF,2DAA2D;AAC3D,eAAO,MAAM,aAAa,EAAE,EAAE,CAAC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAiBvE,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { cn as e } from "../../utils/cn.js";
|
|
2
|
+
import { formatEnumLabel as t } from "../../utils/formatters.js";
|
|
3
|
+
import { Droplets as n, Factory as r, MapPin as i, Sailboat as a, ShieldCheck as o, Sprout as s, Trees as c, Waves as l, Wind as u } from "lucide-react";
|
|
4
|
+
import { jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
5
|
+
//#region src/ecoimpacthub/pages/sites/siteTypeVisuals.tsx
|
|
6
|
+
var p = "bg-bg-sunken text-text-secondary", m = {
|
|
7
|
+
FACILITY: {
|
|
8
|
+
Icon: r,
|
|
9
|
+
tone: p
|
|
10
|
+
},
|
|
11
|
+
WATERSHED: {
|
|
12
|
+
Icon: l,
|
|
13
|
+
tone: "bg-[var(--color-accent-teal-subtle)] text-[var(--color-accent-teal)]"
|
|
14
|
+
},
|
|
15
|
+
FOREST: {
|
|
16
|
+
Icon: c,
|
|
17
|
+
tone: "bg-status-success-bg-subtle text-status-success-text"
|
|
18
|
+
},
|
|
19
|
+
WETLAND: {
|
|
20
|
+
Icon: n,
|
|
21
|
+
tone: "bg-[var(--color-accent-blue-subtle)] text-[var(--color-accent-blue)]"
|
|
22
|
+
},
|
|
23
|
+
FARM: {
|
|
24
|
+
Icon: s,
|
|
25
|
+
tone: "bg-status-warning-bg-subtle text-status-warning-text"
|
|
26
|
+
},
|
|
27
|
+
PROTECTED_AREA: {
|
|
28
|
+
Icon: o,
|
|
29
|
+
tone: "bg-[var(--color-accent-purple-subtle)] text-[var(--color-accent-purple)]"
|
|
30
|
+
},
|
|
31
|
+
AIRSHED: {
|
|
32
|
+
Icon: u,
|
|
33
|
+
tone: p
|
|
34
|
+
},
|
|
35
|
+
COASTAL: {
|
|
36
|
+
Icon: a,
|
|
37
|
+
tone: "bg-[var(--color-accent-indigo-subtle)] text-[var(--color-accent-indigo)]"
|
|
38
|
+
},
|
|
39
|
+
OTHER: {
|
|
40
|
+
Icon: i,
|
|
41
|
+
tone: p
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
function h(e) {
|
|
45
|
+
return m[e] ?? m.OTHER;
|
|
46
|
+
}
|
|
47
|
+
var g = ({ type: t, className: n }) => {
|
|
48
|
+
let { Icon: r, tone: i } = h(t);
|
|
49
|
+
return /* @__PURE__ */ d("span", {
|
|
50
|
+
className: e("inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-lg", i, n),
|
|
51
|
+
"aria-hidden": "true",
|
|
52
|
+
children: /* @__PURE__ */ d(r, { className: "h-[1.15rem] w-[1.15rem]" })
|
|
53
|
+
});
|
|
54
|
+
}, _ = ({ type: n, className: r }) => {
|
|
55
|
+
let { Icon: i, tone: a } = h(n);
|
|
56
|
+
return /* @__PURE__ */ f("span", {
|
|
57
|
+
className: e("inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-medium", a, r),
|
|
58
|
+
children: [/* @__PURE__ */ d(i, { className: "h-3.5 w-3.5" }), t(n)]
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
//#endregion
|
|
62
|
+
export { _ as SiteTypeBadge, g as SiteTypeIcon };
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=siteTypeVisuals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"siteTypeVisuals.js","names":[],"sources":["../../../../src/ecoimpacthub/pages/sites/siteTypeVisuals.tsx"],"sourcesContent":["/**\n * Per-site-type visual language — a lucide icon + a semantic-token colour tone\n * that makes the Sites list & Site detail scannable at a glance.\n * @module ecoimpacthub/pages/sites\n *\n * Tokens only (CSS variables) — no raw colours. Hue tones map to the fe-libs\n * `accent-*` / `status-*` families so each site type reads distinctly while\n * still inheriting the active product theme.\n */\n\nimport type { FC } from 'react';\nimport {\n Factory,\n Waves,\n Trees,\n Droplets,\n Sprout,\n ShieldCheck,\n Wind,\n Sailboat,\n MapPin,\n type LucideIcon,\n} from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { formatEnumLabel } from '../../utils/formatters';\nimport type { EcoSiteType } from '../../types';\n\ninterface TypeVisual {\n Icon: LucideIcon;\n /** Shared bg + text classes for both the pill and the leading icon tile. */\n tone: string;\n}\n\nconst NEUTRAL = 'bg-bg-sunken text-text-secondary';\n\nconst VISUALS: Record<EcoSiteType, TypeVisual> = {\n FACILITY: { Icon: Factory, tone: NEUTRAL },\n WATERSHED: {\n Icon: Waves,\n tone: 'bg-[var(--color-accent-teal-subtle)] text-[var(--color-accent-teal)]',\n },\n FOREST: {\n Icon: Trees,\n tone: 'bg-status-success-bg-subtle text-status-success-text',\n },\n WETLAND: {\n Icon: Droplets,\n tone: 'bg-[var(--color-accent-blue-subtle)] text-[var(--color-accent-blue)]',\n },\n FARM: {\n Icon: Sprout,\n tone: 'bg-status-warning-bg-subtle text-status-warning-text',\n },\n PROTECTED_AREA: {\n Icon: ShieldCheck,\n tone: 'bg-[var(--color-accent-purple-subtle)] text-[var(--color-accent-purple)]',\n },\n AIRSHED: { Icon: Wind, tone: NEUTRAL },\n COASTAL: {\n Icon: Sailboat,\n tone: 'bg-[var(--color-accent-indigo-subtle)] text-[var(--color-accent-indigo)]',\n },\n OTHER: { Icon: MapPin, tone: NEUTRAL },\n};\n\nexport function siteTypeVisual(type: EcoSiteType): TypeVisual {\n return VISUALS[type] ?? VISUALS.OTHER;\n}\n\n/** A leading rounded icon tile keyed to the site type. */\nexport const SiteTypeIcon: FC<{ type: EcoSiteType; className?: string }> = ({\n type,\n className,\n}) => {\n const { Icon, tone } = siteTypeVisual(type);\n return (\n <span\n className={cn(\n 'inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-lg',\n tone,\n className\n )}\n aria-hidden=\"true\"\n >\n <Icon className=\"h-[1.15rem] w-[1.15rem]\" />\n </span>\n );\n};\n\n/** A coloured pill: icon + human label for a site type. */\nexport const SiteTypeBadge: FC<{ type: EcoSiteType; className?: string }> = ({\n type,\n className,\n}) => {\n const { Icon, tone } = siteTypeVisual(type);\n return (\n <span\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-medium',\n tone,\n className\n )}\n >\n <Icon className=\"h-3.5 w-3.5\" />\n {formatEnumLabel(type)}\n </span>\n );\n};\n"],"mappings":";;;;;AAiCA,IAAM,IAAU,oCAEV,IAA2C;CAC/C,UAAU;EAAE,MAAM;EAAS,MAAM;EAAS;CAC1C,WAAW;EACT,MAAM;EACN,MAAM;EACP;CACD,QAAQ;EACN,MAAM;EACN,MAAM;EACP;CACD,SAAS;EACP,MAAM;EACN,MAAM;EACP;CACD,MAAM;EACJ,MAAM;EACN,MAAM;EACP;CACD,gBAAgB;EACd,MAAM;EACN,MAAM;EACP;CACD,SAAS;EAAE,MAAM;EAAM,MAAM;EAAS;CACtC,SAAS;EACP,MAAM;EACN,MAAM;EACP;CACD,OAAO;EAAE,MAAM;EAAQ,MAAM;EAAS;CACvC;AAED,SAAgB,EAAe,GAA+B;AAC5D,QAAO,EAAQ,MAAS,EAAQ;;AAIlC,IAAa,KAA+D,EAC1E,SACA,mBACI;CACJ,IAAM,EAAE,SAAM,YAAS,EAAe,EAAK;AAC3C,QACE,kBAAC,QAAD;EACE,WAAW,EACT,uEACA,GACA,EACD;EACD,eAAY;YAEZ,kBAAC,GAAD,EAAM,WAAU,2BAA4B,CAAA;EACvC,CAAA;GAKE,KAAgE,EAC3E,SACA,mBACI;CACJ,IAAM,EAAE,SAAM,YAAS,EAAe,EAAK;AAC3C,QACE,kBAAC,QAAD;EACE,WAAW,EACT,mFACA,GACA,EACD;YALH,CAOE,kBAAC,GAAD,EAAM,WAAU,eAAgB,CAAA,EAC/B,EAAgB,EAAK,CACjB"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Species detail — overview, field observations & species actions.
|
|
3
|
+
* @module ecoimpacthub/pages/species
|
|
4
|
+
*
|
|
5
|
+
* Reads `ecoSpecies` (+ nested observations); writes `ecoRecordObservation`,
|
|
6
|
+
* `ecoUpdateSpecies`, `ecoArchiveSpecies`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function SpeciesDetailPage(): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
//# sourceMappingURL=SpeciesDetailPage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SpeciesDetailPage.d.ts","sourceRoot":"","sources":["../../../../src/ecoimpacthub/pages/species/SpeciesDetailPage.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAoGH,wBAAgB,iBAAiB,4CAmgBhC"}
|