@burdenoff/microfe-ecoimpacthub 2026.704.4 → 2026.709.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/dist/dev/main.d.ts +2 -0
  2. package/dist/dev/main.d.ts.map +1 -0
  3. package/dist/ecoimpacthub/EcoImpactHubRoot.d.ts +5 -0
  4. package/dist/ecoimpacthub/EcoImpactHubRoot.d.ts.map +1 -0
  5. package/dist/ecoimpacthub/EcoImpactHubRoutes.d.ts +4 -0
  6. package/dist/ecoimpacthub/EcoImpactHubRoutes.d.ts.map +1 -0
  7. package/dist/ecoimpacthub/EcoImpactHubRoutes.js +48 -40
  8. package/dist/ecoimpacthub/EcoImpactHubRoutes.js.map +1 -1
  9. package/dist/ecoimpacthub/components/DataTable.d.ts +28 -0
  10. package/dist/ecoimpacthub/components/DataTable.d.ts.map +1 -0
  11. package/dist/ecoimpacthub/components/EcoDiscussion.d.ts +18 -0
  12. package/dist/ecoimpacthub/components/EcoDiscussion.d.ts.map +1 -0
  13. package/dist/ecoimpacthub/components/EcoTags.d.ts +17 -0
  14. package/dist/ecoimpacthub/components/EcoTags.d.ts.map +1 -0
  15. package/dist/ecoimpacthub/components/EmptyState.d.ts +18 -0
  16. package/dist/ecoimpacthub/components/EmptyState.d.ts.map +1 -0
  17. package/dist/ecoimpacthub/components/EvidenceUpload.d.ts +14 -0
  18. package/dist/ecoimpacthub/components/EvidenceUpload.d.ts.map +1 -0
  19. package/dist/ecoimpacthub/components/FeatureFlagGate.d.ts +10 -0
  20. package/dist/ecoimpacthub/components/FeatureFlagGate.d.ts.map +1 -0
  21. package/dist/ecoimpacthub/components/FeatureFlagGate.js +8 -0
  22. package/dist/ecoimpacthub/components/FeatureFlagGate.js.map +1 -0
  23. package/dist/ecoimpacthub/components/FileLink.d.ts +15 -0
  24. package/dist/ecoimpacthub/components/FileLink.d.ts.map +1 -0
  25. package/dist/ecoimpacthub/components/FilterTabs.d.ts +18 -0
  26. package/dist/ecoimpacthub/components/FilterTabs.d.ts.map +1 -0
  27. package/dist/ecoimpacthub/components/MetricsCard.d.ts +23 -0
  28. package/dist/ecoimpacthub/components/MetricsCard.d.ts.map +1 -0
  29. package/dist/ecoimpacthub/components/MiniBar.d.ts +16 -0
  30. package/dist/ecoimpacthub/components/MiniBar.d.ts.map +1 -0
  31. package/dist/ecoimpacthub/components/PageLayout.d.ts +16 -0
  32. package/dist/ecoimpacthub/components/PageLayout.d.ts.map +1 -0
  33. package/dist/ecoimpacthub/components/Pagination.d.ts +22 -0
  34. package/dist/ecoimpacthub/components/Pagination.d.ts.map +1 -0
  35. package/dist/ecoimpacthub/components/StateViews.d.ts +24 -0
  36. package/dist/ecoimpacthub/components/StateViews.d.ts.map +1 -0
  37. package/dist/ecoimpacthub/components/StatusBadge.d.ts +9 -0
  38. package/dist/ecoimpacthub/components/StatusBadge.d.ts.map +1 -0
  39. package/dist/ecoimpacthub/components/Tabs.d.ts +17 -0
  40. package/dist/ecoimpacthub/components/Tabs.d.ts.map +1 -0
  41. package/dist/ecoimpacthub/components/index.d.ts +19 -0
  42. package/dist/ecoimpacthub/components/index.d.ts.map +1 -0
  43. package/dist/ecoimpacthub/context/EcoImpactHubContext.d.ts +16 -0
  44. package/dist/ecoimpacthub/context/EcoImpactHubContext.d.ts.map +1 -0
  45. package/dist/ecoimpacthub/context/index.d.ts +6 -0
  46. package/dist/ecoimpacthub/context/index.d.ts.map +1 -0
  47. package/dist/ecoimpacthub/hooks/index.d.ts +10 -0
  48. package/dist/ecoimpacthub/hooks/index.d.ts.map +1 -0
  49. package/dist/ecoimpacthub/hooks/useCursorPager.d.ts +33 -0
  50. package/dist/ecoimpacthub/hooks/useCursorPager.d.ts.map +1 -0
  51. package/dist/ecoimpacthub/hooks/useEcoComments.d.ts +36 -0
  52. package/dist/ecoimpacthub/hooks/useEcoComments.d.ts.map +1 -0
  53. package/dist/ecoimpacthub/hooks/useEcoFiles.d.ts +47 -0
  54. package/dist/ecoimpacthub/hooks/useEcoFiles.d.ts.map +1 -0
  55. package/dist/ecoimpacthub/hooks/useEcoImpactHubApi.d.ts +104 -0
  56. package/dist/ecoimpacthub/hooks/useEcoImpactHubApi.d.ts.map +1 -0
  57. package/dist/ecoimpacthub/hooks/useEcoTags.d.ts +44 -0
  58. package/dist/ecoimpacthub/hooks/useEcoTags.d.ts.map +1 -0
  59. package/dist/ecoimpacthub/index.d.ts +10 -0
  60. package/dist/ecoimpacthub/index.d.ts.map +1 -0
  61. package/dist/ecoimpacthub/index.js +2 -0
  62. package/dist/ecoimpacthub/pages/DashboardPage.d.ts +10 -0
  63. package/dist/ecoimpacthub/pages/DashboardPage.d.ts.map +1 -0
  64. package/dist/ecoimpacthub/pages/DashboardPage.js +345 -189
  65. package/dist/ecoimpacthub/pages/DashboardPage.js.map +1 -1
  66. package/dist/ecoimpacthub/pages/_shared/ConservationBadge.d.ts +9 -0
  67. package/dist/ecoimpacthub/pages/_shared/ConservationBadge.d.ts.map +1 -0
  68. package/dist/ecoimpacthub/pages/_shared/ConservationBadge.js +58 -0
  69. package/dist/ecoimpacthub/pages/_shared/ConservationBadge.js.map +1 -0
  70. package/dist/ecoimpacthub/pages/_shared/EvidenceThumb.d.ts +23 -0
  71. package/dist/ecoimpacthub/pages/_shared/EvidenceThumb.d.ts.map +1 -0
  72. package/dist/ecoimpacthub/pages/_shared/EvidenceThumb.js +70 -0
  73. package/dist/ecoimpacthub/pages/_shared/EvidenceThumb.js.map +1 -0
  74. package/dist/ecoimpacthub/pages/_shared/MethodBadge.d.ts +9 -0
  75. package/dist/ecoimpacthub/pages/_shared/MethodBadge.d.ts.map +1 -0
  76. package/dist/ecoimpacthub/pages/_shared/MethodBadge.js +51 -0
  77. package/dist/ecoimpacthub/pages/_shared/MethodBadge.js.map +1 -0
  78. package/dist/ecoimpacthub/pages/_shared/TaxonChip.d.ts +9 -0
  79. package/dist/ecoimpacthub/pages/_shared/TaxonChip.d.ts.map +1 -0
  80. package/dist/ecoimpacthub/pages/_shared/TaxonChip.js +29 -0
  81. package/dist/ecoimpacthub/pages/_shared/TaxonChip.js.map +1 -0
  82. package/dist/ecoimpacthub/pages/badges.d.ts +27 -0
  83. package/dist/ecoimpacthub/pages/badges.d.ts.map +1 -0
  84. package/dist/ecoimpacthub/pages/badges.js +71 -0
  85. package/dist/ecoimpacthub/pages/badges.js.map +1 -0
  86. package/dist/ecoimpacthub/pages/carbon/CarbonPage.d.ts +15 -0
  87. package/dist/ecoimpacthub/pages/carbon/CarbonPage.d.ts.map +1 -0
  88. package/dist/ecoimpacthub/pages/carbon/CarbonPage.js +337 -300
  89. package/dist/ecoimpacthub/pages/carbon/CarbonPage.js.map +1 -1
  90. package/dist/ecoimpacthub/pages/carbonVisuals.d.ts +47 -0
  91. package/dist/ecoimpacthub/pages/carbonVisuals.d.ts.map +1 -0
  92. package/dist/ecoimpacthub/pages/carbonVisuals.js +89 -0
  93. package/dist/ecoimpacthub/pages/carbonVisuals.js.map +1 -0
  94. package/dist/ecoimpacthub/pages/habitat/HabitatProjectDetailPage.d.ts +12 -0
  95. package/dist/ecoimpacthub/pages/habitat/HabitatProjectDetailPage.d.ts.map +1 -0
  96. package/dist/ecoimpacthub/pages/habitat/HabitatProjectDetailPage.js +252 -218
  97. package/dist/ecoimpacthub/pages/habitat/HabitatProjectDetailPage.js.map +1 -1
  98. package/dist/ecoimpacthub/pages/habitat/HabitatProjectsPage.d.ts +8 -0
  99. package/dist/ecoimpacthub/pages/habitat/HabitatProjectsPage.d.ts.map +1 -0
  100. package/dist/ecoimpacthub/pages/habitat/HabitatProjectsPage.js +15 -12
  101. package/dist/ecoimpacthub/pages/habitat/HabitatProjectsPage.js.map +1 -1
  102. package/dist/ecoimpacthub/pages/habitat/LifecycleProgress.d.ts +6 -0
  103. package/dist/ecoimpacthub/pages/habitat/LifecycleProgress.d.ts.map +1 -0
  104. package/dist/ecoimpacthub/pages/habitat/LifecycleProgress.js +168 -0
  105. package/dist/ecoimpacthub/pages/habitat/LifecycleProgress.js.map +1 -0
  106. package/dist/ecoimpacthub/pages/monitoring/MonitoringPage.d.ts +12 -0
  107. package/dist/ecoimpacthub/pages/monitoring/MonitoringPage.d.ts.map +1 -0
  108. package/dist/ecoimpacthub/pages/monitoring/MonitoringPage.js +30 -17
  109. package/dist/ecoimpacthub/pages/monitoring/MonitoringPage.js.map +1 -1
  110. package/dist/ecoimpacthub/pages/observations/ObservationsPage.d.ts +11 -0
  111. package/dist/ecoimpacthub/pages/observations/ObservationsPage.d.ts.map +1 -0
  112. package/dist/ecoimpacthub/pages/observations/ObservationsPage.js +236 -219
  113. package/dist/ecoimpacthub/pages/observations/ObservationsPage.js.map +1 -1
  114. package/dist/ecoimpacthub/pages/reports/ReportDetailPage.d.ts +11 -0
  115. package/dist/ecoimpacthub/pages/reports/ReportDetailPage.d.ts.map +1 -0
  116. package/dist/ecoimpacthub/pages/reports/ReportDetailPage.js +248 -212
  117. package/dist/ecoimpacthub/pages/reports/ReportDetailPage.js.map +1 -1
  118. package/dist/ecoimpacthub/pages/reports/ReportsPage.d.ts +8 -0
  119. package/dist/ecoimpacthub/pages/reports/ReportsPage.d.ts.map +1 -0
  120. package/dist/ecoimpacthub/pages/reports/ReportsPage.js +119 -118
  121. package/dist/ecoimpacthub/pages/reports/ReportsPage.js.map +1 -1
  122. package/dist/ecoimpacthub/pages/sites/SiteDetailPage.d.ts +10 -0
  123. package/dist/ecoimpacthub/pages/sites/SiteDetailPage.d.ts.map +1 -0
  124. package/dist/ecoimpacthub/pages/sites/SiteDetailPage.js +498 -370
  125. package/dist/ecoimpacthub/pages/sites/SiteDetailPage.js.map +1 -1
  126. package/dist/ecoimpacthub/pages/sites/SitesPage.d.ts +8 -0
  127. package/dist/ecoimpacthub/pages/sites/SitesPage.d.ts.map +1 -0
  128. package/dist/ecoimpacthub/pages/sites/SitesPage.js +109 -99
  129. package/dist/ecoimpacthub/pages/sites/SitesPage.js.map +1 -1
  130. package/dist/ecoimpacthub/pages/sites/siteTypeVisuals.d.ts +22 -0
  131. package/dist/ecoimpacthub/pages/sites/siteTypeVisuals.d.ts.map +1 -0
  132. package/dist/ecoimpacthub/pages/sites/siteTypeVisuals.js +64 -0
  133. package/dist/ecoimpacthub/pages/sites/siteTypeVisuals.js.map +1 -0
  134. package/dist/ecoimpacthub/pages/species/SpeciesDetailPage.d.ts +9 -0
  135. package/dist/ecoimpacthub/pages/species/SpeciesDetailPage.d.ts.map +1 -0
  136. package/dist/ecoimpacthub/pages/species/SpeciesDetailPage.js +275 -259
  137. package/dist/ecoimpacthub/pages/species/SpeciesDetailPage.js.map +1 -1
  138. package/dist/ecoimpacthub/pages/species/SpeciesPage.d.ts +8 -0
  139. package/dist/ecoimpacthub/pages/species/SpeciesPage.d.ts.map +1 -0
  140. package/dist/ecoimpacthub/pages/species/SpeciesPage.js +235 -177
  141. package/dist/ecoimpacthub/pages/species/SpeciesPage.js.map +1 -1
  142. package/dist/ecoimpacthub/services/createSandboxAssistantTransport.d.ts +33 -0
  143. package/dist/ecoimpacthub/services/createSandboxAssistantTransport.d.ts.map +1 -0
  144. package/dist/ecoimpacthub/services/createSandboxAssistantTransport.js +42 -0
  145. package/dist/ecoimpacthub/services/createSandboxAssistantTransport.js.map +1 -0
  146. package/dist/ecoimpacthub/services/index.d.ts +6 -0
  147. package/dist/ecoimpacthub/services/index.d.ts.map +1 -0
  148. package/dist/ecoimpacthub/services/index.js +1 -0
  149. package/dist/ecoimpacthub/types/index.d.ts +417 -0
  150. package/dist/ecoimpacthub/types/index.d.ts.map +1 -0
  151. package/dist/ecoimpacthub/utils/cn.d.ts +4 -0
  152. package/dist/ecoimpacthub/utils/cn.d.ts.map +1 -0
  153. package/dist/ecoimpacthub/utils/formatters.d.ts +26 -0
  154. package/dist/ecoimpacthub/utils/formatters.d.ts.map +1 -0
  155. package/dist/ecoimpacthub/utils/i18n.d.ts +6 -0
  156. package/dist/ecoimpacthub/utils/i18n.d.ts.map +1 -0
  157. package/dist/ecoimpacthub/utils/index.d.ts +9 -0
  158. package/dist/ecoimpacthub/utils/index.d.ts.map +1 -0
  159. package/dist/ecoimpacthub/utils/navigation.d.ts +14 -0
  160. package/dist/ecoimpacthub/utils/navigation.d.ts.map +1 -0
  161. package/dist/generated/global-operations.d.ts +2 -0
  162. package/dist/generated/global-operations.d.ts.map +1 -0
  163. package/dist/generated/global-types.d.ts +18199 -0
  164. package/dist/generated/global-types.d.ts.map +1 -0
  165. package/dist/generated/wspace-operations.d.ts +2 -0
  166. package/dist/generated/wspace-operations.d.ts.map +1 -0
  167. package/dist/generated/wspace-types.d.ts +43046 -0
  168. package/dist/generated/wspace-types.d.ts.map +1 -0
  169. package/dist/index.d.ts +2 -0
  170. package/dist/index.d.ts.map +1 -0
  171. package/dist/index.js +2 -1
  172. package/dist/node_modules/recharts/es6/cartesian/CartesianGrid.js +305 -0
  173. package/dist/node_modules/recharts/es6/cartesian/CartesianGrid.js.map +1 -0
  174. package/dist/node_modules/recharts/es6/context/chartLayoutContext.js +44 -33
  175. package/dist/node_modules/recharts/es6/context/chartLayoutContext.js.map +1 -1
  176. package/dist/node_modules/recharts/es6/util/ChartUtils.js +31 -23
  177. package/dist/node_modules/recharts/es6/util/ChartUtils.js.map +1 -1
  178. package/package.json +5 -1
@@ -1,20 +1,21 @@
1
1
  import { useEcoImpactHub as e } from "../../context/EcoImpactHubContext.js";
2
- import { PageLayout as ee } from "../../components/PageLayout.js";
3
- import { formatEnumLabel as t, formatNumber as n, formatRelativeTime as r } from "../../utils/formatters.js";
4
- import { StatusBadge as i } from "../../components/StatusBadge.js";
5
- import { ErrorView as te, LoadingView as ne } from "../../components/StateViews.js";
6
- import { EmptyState as a } from "../../components/EmptyState.js";
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 o, useEcoSites as s } from "../../hooks/useEcoImpactHubApi.js";
9
- import { useCursorPager as c } from "../../hooks/useCursorPager.js";
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 l } from "../../components/DataTable.js";
12
- import { Pagination as u } from "../../components/Pagination.js";
13
- import { FilterTabs as d } from "../../components/FilterTabs.js";
14
- import { useMemo as f, useState as p } from "react";
15
- import { MapPin as m, Plus as h } from "lucide-react";
16
- import { Fragment as g, jsx as _, jsxs as v } from "react/jsx-runtime";
17
- 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";
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] = p("ALL"), [V, H] = p("ALL"), U = c(), [W, G] = p(!1), [K, q] = p(L), [J, Y] = p(null), { data: X, isLoading: re, isError: ie, refetch: ae } = s({
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 = o(), Q = f(() => X?.items ?? [], [X]), oe = [
66
+ }), Z = l(), Q = _(() => X?.items ?? [], [X]), ce = [
66
67
  {
67
68
  key: "name",
68
69
  header: "Site",
69
- render: (e) => /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("p", {
70
- className: "font-semibold text-text-primary",
71
- children: e.name
72
- }), /* @__PURE__ */ _("p", {
73
- className: "text-xs text-text-tertiary",
74
- children: e.code ?? t(e.type)
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__ */ _("span", {
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) => /* @__PURE__ */ _("span", {
91
- className: "text-text-secondary",
92
- children: [e.region, e.country].filter(Boolean).join(", ") || "—"
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__ */ _("span", {
111
+ render: (e) => e.areaHectares == null ? /* @__PURE__ */ S("span", {
102
112
  className: "text-text-tertiary",
103
113
  children: "—"
104
- }) : /* @__PURE__ */ v("span", {
114
+ }) : /* @__PURE__ */ C("span", {
105
115
  className: "tabular-nums text-text-secondary",
106
- children: [n(e.areaHectares), " ha"]
116
+ children: [r(e.areaHectares), " ha"]
107
117
  })
108
118
  },
109
119
  {
110
120
  key: "status",
111
121
  header: "Status",
112
- render: (e) => /* @__PURE__ */ _(i, { status: e.status })
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__ */ _("span", {
129
+ render: (e) => /* @__PURE__ */ S("span", {
120
130
  className: "text-text-tertiary",
121
- children: r(e.updatedAt)
131
+ children: i(e.updatedAt)
122
132
  })
123
133
  }
124
134
  ], $ = () => {
125
135
  q(L), Y(null);
126
136
  };
127
- return /* @__PURE__ */ v(ee, {
137
+ return /* @__PURE__ */ C(t, {
128
138
  title: "Sites",
129
139
  description: "Monitored locations — facilities, watersheds, forests, wetlands, farms & protected areas.",
130
- actions: /* @__PURE__ */ v(y, {
140
+ actions: /* @__PURE__ */ C(w, {
131
141
  onClick: () => G(!0),
132
- children: [/* @__PURE__ */ _(h, { className: "mr-1.5 h-4 w-4" }), " New site"]
142
+ children: [/* @__PURE__ */ S(b, { className: "mr-1.5 h-4 w-4" }), " New site"]
133
143
  }),
134
144
  children: [
135
- /* @__PURE__ */ v("div", {
145
+ /* @__PURE__ */ C("div", {
136
146
  className: "mb-5 flex flex-wrap items-center gap-3",
137
- children: [/* @__PURE__ */ _(d, {
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__ */ v(O, {
153
+ }), /* @__PURE__ */ C(O, {
144
154
  value: V,
145
155
  onValueChange: (e) => {
146
156
  H(e), U.reset();
147
157
  },
148
- children: [/* @__PURE__ */ _(j, {
158
+ children: [/* @__PURE__ */ S(j, {
149
159
  className: "w-44",
150
- children: /* @__PURE__ */ _(M, { placeholder: "All types" })
151
- }), /* @__PURE__ */ v(k, { children: [/* @__PURE__ */ _(A, {
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__ */ _(A, {
164
+ }), F.map((e) => /* @__PURE__ */ S(A, {
155
165
  value: e,
156
- children: t(e)
166
+ children: n(e)
157
167
  }, e))] })]
158
168
  })]
159
169
  }),
160
- re ? /* @__PURE__ */ _(ne, { label: "Loading sites…" }) : ie ? /* @__PURE__ */ _(te, {
170
+ ae ? /* @__PURE__ */ S(s, { label: "Loading sites…" }) : oe ? /* @__PURE__ */ S(o, {
161
171
  message: "Couldn't load sites.",
162
- onRetry: () => ae()
163
- }) : Q.length === 0 ? /* @__PURE__ */ _(a, {
172
+ onRetry: () => se()
173
+ }) : Q.length === 0 ? /* @__PURE__ */ S(c, {
164
174
  illustration: "empty-data",
165
- icon: /* @__PURE__ */ _(m, { className: "h-10 w-10" }),
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__ */ v(y, {
178
+ action: /* @__PURE__ */ C(w, {
169
179
  onClick: () => G(!0),
170
- children: [/* @__PURE__ */ _(h, { className: "mr-1.5 h-4 w-4" }), " New site"]
180
+ children: [/* @__PURE__ */ S(b, { className: "mr-1.5 h-4 w-4" }), " New site"]
171
181
  })
172
- }) : /* @__PURE__ */ v(g, { children: [/* @__PURE__ */ _(l, {
173
- columns: oe,
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__ */ _(u, {
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__ */ _(S, {
194
+ /* @__PURE__ */ S(D, {
185
195
  open: W,
186
196
  onOpenChange: (e) => {
187
197
  G(e), e || $();
188
198
  },
189
- children: /* @__PURE__ */ v(C, { children: [
190
- /* @__PURE__ */ v(E, { children: [/* @__PURE__ */ _(D, { children: "New site" }), /* @__PURE__ */ _(w, { children: "Register a location to monitor and attribute environmental data to." })] }),
191
- /* @__PURE__ */ v("div", {
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__ */ v("div", {
204
+ /* @__PURE__ */ C("div", {
195
205
  className: "grid gap-2 sm:grid-cols-2",
196
- children: [/* @__PURE__ */ v("div", {
206
+ children: [/* @__PURE__ */ C("div", {
197
207
  className: "grid gap-1.5",
198
- children: [/* @__PURE__ */ _(x, {
208
+ children: [/* @__PURE__ */ S(E, {
199
209
  htmlFor: "name",
200
210
  children: "Name *"
201
- }), /* @__PURE__ */ _(b, {
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__ */ v("div", {
220
+ }), /* @__PURE__ */ C("div", {
211
221
  className: "grid gap-1.5",
212
- children: [/* @__PURE__ */ _(x, {
222
+ children: [/* @__PURE__ */ S(E, {
213
223
  htmlFor: "code",
214
224
  children: "Code"
215
- }), /* @__PURE__ */ _(b, {
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__ */ v("div", {
236
+ /* @__PURE__ */ C("div", {
227
237
  className: "grid gap-2 sm:grid-cols-2",
228
- children: [/* @__PURE__ */ v("div", {
238
+ children: [/* @__PURE__ */ C("div", {
229
239
  className: "grid gap-1.5",
230
- children: [/* @__PURE__ */ _(x, {
240
+ children: [/* @__PURE__ */ S(E, {
231
241
  htmlFor: "type",
232
242
  children: "Type"
233
- }), /* @__PURE__ */ v(O, {
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__ */ _(j, {
249
+ children: [/* @__PURE__ */ S(j, {
240
250
  id: "type",
241
- children: /* @__PURE__ */ _(M, {})
242
- }), /* @__PURE__ */ _(k, { children: F.map((e) => /* @__PURE__ */ _(A, {
251
+ children: /* @__PURE__ */ S(M, {})
252
+ }), /* @__PURE__ */ S(k, { children: F.map((e) => /* @__PURE__ */ S(A, {
243
253
  value: e,
244
- children: t(e)
254
+ children: n(e)
245
255
  }, e)) })]
246
256
  })]
247
- }), /* @__PURE__ */ v("div", {
257
+ }), /* @__PURE__ */ C("div", {
248
258
  className: "grid gap-1.5",
249
- children: [/* @__PURE__ */ _(x, {
259
+ children: [/* @__PURE__ */ S(E, {
250
260
  htmlFor: "area",
251
261
  children: "Area (hectares)"
252
- }), /* @__PURE__ */ _(b, {
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__ */ v("div", {
276
+ /* @__PURE__ */ C("div", {
267
277
  className: "grid gap-2 sm:grid-cols-2",
268
- children: [/* @__PURE__ */ v("div", {
278
+ children: [/* @__PURE__ */ C("div", {
269
279
  className: "grid gap-1.5",
270
- children: [/* @__PURE__ */ _(x, {
280
+ children: [/* @__PURE__ */ S(E, {
271
281
  htmlFor: "region",
272
282
  children: "Region"
273
- }), /* @__PURE__ */ _(b, {
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__ */ v("div", {
292
+ }), /* @__PURE__ */ C("div", {
283
293
  className: "grid gap-1.5",
284
- children: [/* @__PURE__ */ _(x, {
294
+ children: [/* @__PURE__ */ S(E, {
285
295
  htmlFor: "country",
286
296
  children: "Country"
287
- }), /* @__PURE__ */ _(b, {
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__ */ v("div", {
308
+ /* @__PURE__ */ C("div", {
299
309
  className: "grid gap-2 sm:grid-cols-2",
300
- children: [/* @__PURE__ */ v("div", {
310
+ children: [/* @__PURE__ */ C("div", {
301
311
  className: "grid gap-1.5",
302
- children: [/* @__PURE__ */ _(x, {
312
+ children: [/* @__PURE__ */ S(E, {
303
313
  htmlFor: "lat",
304
314
  children: "Latitude"
305
- }), /* @__PURE__ */ _(b, {
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__ */ v("div", {
326
+ }), /* @__PURE__ */ C("div", {
317
327
  className: "grid gap-1.5",
318
- children: [/* @__PURE__ */ _(x, {
328
+ children: [/* @__PURE__ */ S(E, {
319
329
  htmlFor: "lng",
320
330
  children: "Longitude"
321
- }), /* @__PURE__ */ _(b, {
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__ */ v("div", {
344
+ /* @__PURE__ */ C("div", {
335
345
  className: "grid gap-1.5",
336
- children: [/* @__PURE__ */ _(x, {
346
+ children: [/* @__PURE__ */ S(E, {
337
347
  htmlFor: "description",
338
348
  children: "Description"
339
- }), /* @__PURE__ */ _(N, {
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__ */ _("p", {
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__ */ v(T, { children: [/* @__PURE__ */ _(y, {
366
+ /* @__PURE__ */ C(ne, { children: [/* @__PURE__ */ S(w, {
357
367
  variant: "outline",
358
368
  onClick: () => G(!1),
359
369
  children: "Cancel"
360
- }), /* @__PURE__ */ _(y, {
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"}