@burdenoff/microfe-ecoimpacthub 2026.704.3 → 2026.704.5

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 (47) hide show
  1. package/dist/ecoimpacthub/pages/DashboardPage.js +345 -189
  2. package/dist/ecoimpacthub/pages/DashboardPage.js.map +1 -1
  3. package/dist/ecoimpacthub/pages/_shared/ConservationBadge.js +58 -0
  4. package/dist/ecoimpacthub/pages/_shared/ConservationBadge.js.map +1 -0
  5. package/dist/ecoimpacthub/pages/_shared/EvidenceThumb.js +70 -0
  6. package/dist/ecoimpacthub/pages/_shared/EvidenceThumb.js.map +1 -0
  7. package/dist/ecoimpacthub/pages/_shared/MethodBadge.js +51 -0
  8. package/dist/ecoimpacthub/pages/_shared/MethodBadge.js.map +1 -0
  9. package/dist/ecoimpacthub/pages/_shared/TaxonChip.js +29 -0
  10. package/dist/ecoimpacthub/pages/_shared/TaxonChip.js.map +1 -0
  11. package/dist/ecoimpacthub/pages/badges.js +71 -0
  12. package/dist/ecoimpacthub/pages/badges.js.map +1 -0
  13. package/dist/ecoimpacthub/pages/carbon/CarbonPage.js +341 -300
  14. package/dist/ecoimpacthub/pages/carbon/CarbonPage.js.map +1 -1
  15. package/dist/ecoimpacthub/pages/carbonVisuals.js +89 -0
  16. package/dist/ecoimpacthub/pages/carbonVisuals.js.map +1 -0
  17. package/dist/ecoimpacthub/pages/habitat/HabitatProjectDetailPage.js +252 -218
  18. package/dist/ecoimpacthub/pages/habitat/HabitatProjectDetailPage.js.map +1 -1
  19. package/dist/ecoimpacthub/pages/habitat/HabitatProjectsPage.js +15 -12
  20. package/dist/ecoimpacthub/pages/habitat/HabitatProjectsPage.js.map +1 -1
  21. package/dist/ecoimpacthub/pages/habitat/LifecycleProgress.js +168 -0
  22. package/dist/ecoimpacthub/pages/habitat/LifecycleProgress.js.map +1 -0
  23. package/dist/ecoimpacthub/pages/monitoring/MonitoringPage.js +30 -17
  24. package/dist/ecoimpacthub/pages/monitoring/MonitoringPage.js.map +1 -1
  25. package/dist/ecoimpacthub/pages/observations/ObservationsPage.js +236 -219
  26. package/dist/ecoimpacthub/pages/observations/ObservationsPage.js.map +1 -1
  27. package/dist/ecoimpacthub/pages/reports/ReportDetailPage.js +248 -212
  28. package/dist/ecoimpacthub/pages/reports/ReportDetailPage.js.map +1 -1
  29. package/dist/ecoimpacthub/pages/reports/ReportsPage.js +119 -118
  30. package/dist/ecoimpacthub/pages/reports/ReportsPage.js.map +1 -1
  31. package/dist/ecoimpacthub/pages/sites/SiteDetailPage.js +498 -370
  32. package/dist/ecoimpacthub/pages/sites/SiteDetailPage.js.map +1 -1
  33. package/dist/ecoimpacthub/pages/sites/SitesPage.js +109 -99
  34. package/dist/ecoimpacthub/pages/sites/SitesPage.js.map +1 -1
  35. package/dist/ecoimpacthub/pages/sites/siteTypeVisuals.js +64 -0
  36. package/dist/ecoimpacthub/pages/sites/siteTypeVisuals.js.map +1 -0
  37. package/dist/ecoimpacthub/pages/species/SpeciesDetailPage.js +275 -259
  38. package/dist/ecoimpacthub/pages/species/SpeciesDetailPage.js.map +1 -1
  39. package/dist/ecoimpacthub/pages/species/SpeciesPage.js +235 -177
  40. package/dist/ecoimpacthub/pages/species/SpeciesPage.js.map +1 -1
  41. package/dist/node_modules/recharts/es6/cartesian/CartesianGrid.js +305 -0
  42. package/dist/node_modules/recharts/es6/cartesian/CartesianGrid.js.map +1 -0
  43. package/dist/node_modules/recharts/es6/context/chartLayoutContext.js +44 -33
  44. package/dist/node_modules/recharts/es6/context/chartLayoutContext.js.map +1 -1
  45. package/dist/node_modules/recharts/es6/util/ChartUtils.js +31 -23
  46. package/dist/node_modules/recharts/es6/util/ChartUtils.js.map +1 -1
  47. package/package.json +1 -1
@@ -1,21 +1,23 @@
1
1
  import { useEcoImpactHub as e } from "../../context/EcoImpactHubContext.js";
2
2
  import { PageLayout as t } from "../../components/PageLayout.js";
3
- import { formatCoords as n, formatDateTime as r, formatEnumLabel as i, formatNumber as a } from "../../utils/formatters.js";
4
- import { StatusBadge as o } from "../../components/StatusBadge.js";
5
- import { ErrorView as ee, LoadingView as s, Section as c } from "../../components/StateViews.js";
6
- import { EmptyState as l } from "../../components/EmptyState.js";
3
+ import { formatCoords as ee, formatDateTime as te, formatEnumLabel as n, formatNumber as r, formatRelativeTime as ne } from "../../utils/formatters.js";
4
+ import { StatusBadge as i } from "../../components/StatusBadge.js";
5
+ import { MiniBar as re } from "../../components/MiniBar.js";
6
+ import { ErrorView as ie, LoadingView as ae, Section as a } from "../../components/StateViews.js";
7
+ import { EmptyState as o } from "../../components/EmptyState.js";
7
8
  import "../../context/index.js";
8
- import { useEcoArchiveSite as te, useEcoCreateSensor as ne, useEcoCreateThreshold as re, useEcoMeasurements as ie, useEcoRecordMeasurement as ae, useEcoSetSensorStatus as oe, useEcoSetThresholdActive as se, useEcoSite as ce } from "../../hooks/useEcoImpactHubApi.js";
9
+ import { useEcoArchiveSite as oe, useEcoCreateSensor as se, useEcoCreateThreshold as ce, useEcoMeasurements as s, useEcoRecordMeasurement as le, useEcoSetSensorStatus as ue, useEcoSetThresholdActive as de, useEcoSite as fe } from "../../hooks/useEcoImpactHubApi.js";
9
10
  import "../../hooks/index.js";
10
- import { DataTable as u } from "../../components/DataTable.js";
11
- import { EcoTags as le } from "../../components/EcoTags.js";
12
- import { useState as d } from "react";
13
- import { Activity as ue, Archive as de, ArrowLeft as fe, Gauge as pe, Plus as f, Radio as p } from "lucide-react";
14
- import { useParams as me } from "react-router-dom";
15
- import { Fragment as he, jsx as m, jsxs as h } from "react/jsx-runtime";
16
- import { Button as g, GlassCard as _, Input as v, Label as y, ResponsiveDialog as b, ResponsiveDialogContent as x, ResponsiveDialogDescription as S, ResponsiveDialogFooter as C, ResponsiveDialogHeader as w, ResponsiveDialogTitle as T, Select as E, SelectContent as D, SelectItem as O, SelectTrigger as k, SelectValue as A } from "@burdenoff/fe-libs/ui";
11
+ import { DataTable as c } from "../../components/DataTable.js";
12
+ import { EcoTags as pe } from "../../components/EcoTags.js";
13
+ import { SiteTypeBadge as me } from "./siteTypeVisuals.js";
14
+ import { useState as l } from "react";
15
+ import { Activity as he, Archive as ge, ArrowLeft as _e, Gauge as ve, Plus as u, Radio as d, ShieldCheck as ye, Zap as be } from "lucide-react";
16
+ import { useParams as xe } from "react-router-dom";
17
+ import { Fragment as Se, jsx as f, jsxs as p } from "react/jsx-runtime";
18
+ import { Button as m, GlassCard as h, Input as g, Label as _, ResponsiveDialog as v, ResponsiveDialogContent as y, ResponsiveDialogDescription as b, ResponsiveDialogFooter as x, ResponsiveDialogHeader as S, ResponsiveDialogTitle as C, Select as w, SelectContent as T, SelectItem as E, SelectTrigger as D, SelectValue as O } from "@burdenoff/fe-libs/ui";
17
19
  //#region src/ecoimpacthub/pages/sites/SiteDetailPage.tsx
18
- var ge = [
20
+ var Ce = [
19
21
  "AIR_QUALITY",
20
22
  "WATER_QUALITY",
21
23
  "WEATHER",
@@ -25,34 +27,41 @@ var ge = [
25
27
  "ACOUSTIC",
26
28
  "CAMERA_TRAP",
27
29
  "MANUAL"
28
- ], _e = [
30
+ ], we = [
29
31
  "ONLINE",
30
32
  "OFFLINE",
31
33
  "DEGRADED",
32
34
  "MAINTENANCE",
33
35
  "RETIRED"
34
- ], ve = [
36
+ ], Te = [
35
37
  "ABOVE",
36
38
  "BELOW",
37
39
  "OUTSIDE_RANGE"
38
- ], ye = [
40
+ ], Ee = [
39
41
  "INFO",
40
42
  "WARNING",
41
43
  "CRITICAL"
42
44
  ];
43
- function j() {
44
- let { id: j } = me(), { navigateTo: M } = e(), { data: N, isLoading: be, isError: xe, refetch: Se } = ce(j), P = ie({
45
- siteId: j,
45
+ function k() {
46
+ let { id: k } = xe(), { navigateTo: A } = e(), { data: j, isLoading: De, isError: Oe, refetch: ke } = fe(k), M = s({
47
+ siteId: k,
46
48
  pagination: {
47
49
  limit: 10,
48
50
  offset: 0
49
51
  }
50
- }), F = ne(), I = oe(), L = re(), Ce = se(), R = ae(), z = te(), [we, B] = d(!1), [V, H] = d({
52
+ }), Ae = s({
53
+ siteId: k,
54
+ breachesOnly: !0,
55
+ pagination: {
56
+ limit: 1,
57
+ offset: 0
58
+ }
59
+ }), N = se(), je = ue(), P = ce(), Me = de(), F = le(), I = oe(), [Ne, L] = l(!1), [R, z] = l({
51
60
  name: "",
52
61
  kind: "AIR_QUALITY",
53
62
  unit: "",
54
63
  hardwareId: ""
55
- }), [Te, U] = d(!1), [W, G] = d({
64
+ }), [Pe, B] = l(!1), [V, H] = l({
56
65
  parameter: "",
57
66
  unit: "",
58
67
  direction: "ABOVE",
@@ -60,173 +69,272 @@ function j() {
60
69
  limitValue: "",
61
70
  minValue: "",
62
71
  maxValue: ""
63
- }), [Ee, K] = d(!1), [q, J] = d({
72
+ }), [Fe, U] = l(!1), [W, G] = l({
64
73
  parameter: "",
65
74
  value: "",
66
75
  unit: "",
67
76
  sensorId: ""
68
- }), [Y, X] = d(null);
69
- if (be) return /* @__PURE__ */ m(t, {
77
+ }), [K, q] = l(null);
78
+ if (De) return /* @__PURE__ */ f(t, {
70
79
  title: "Site",
71
- children: /* @__PURE__ */ m(s, {})
80
+ children: /* @__PURE__ */ f(ae, {})
72
81
  });
73
- if (xe || !N) return /* @__PURE__ */ m(t, {
82
+ if (Oe || !j) return /* @__PURE__ */ f(t, {
74
83
  title: "Site",
75
- children: /* @__PURE__ */ m(ee, {
84
+ children: /* @__PURE__ */ f(ie, {
76
85
  message: "This site could not be loaded.",
77
- onRetry: () => Se()
86
+ onRetry: () => ke()
78
87
  })
79
88
  });
80
- let Z = N.sensors ?? [], Q = N.thresholds ?? [], $ = P.data?.items ?? [];
81
- return /* @__PURE__ */ h(t, {
82
- title: N.name,
83
- description: [N.code, i(N.type)].filter(Boolean).join(" · "),
84
- actions: /* @__PURE__ */ h(he, { children: [/* @__PURE__ */ m(o, { status: N.status }), /* @__PURE__ */ h(g, {
89
+ let J = j.sensors ?? [], Y = j.thresholds ?? [], X = M.data?.items ?? [], Z = J.filter((e) => e.status === "ONLINE").length, Q = J.filter((e) => [
90
+ "OFFLINE",
91
+ "DEGRADED",
92
+ "MAINTENANCE"
93
+ ].includes(e.status)).length, Ie = Y.filter((e) => e.isActive).length, $ = Ae.data?.items?.[0] ?? null;
94
+ return /* @__PURE__ */ p(t, {
95
+ title: j.name,
96
+ description: [j.code, n(j.type)].filter(Boolean).join(" · "),
97
+ actions: /* @__PURE__ */ p(Se, { children: [/* @__PURE__ */ f(i, { status: j.status }), /* @__PURE__ */ p(m, {
85
98
  variant: "ghost",
86
- onClick: () => M("sites"),
87
- children: [/* @__PURE__ */ m(fe, { className: "mr-1.5 h-4 w-4" }), " Back"]
99
+ onClick: () => A("sites"),
100
+ children: [/* @__PURE__ */ f(_e, { className: "mr-1.5 h-4 w-4" }), " Back"]
88
101
  })] }),
89
102
  children: [
90
- /* @__PURE__ */ h("div", {
103
+ /* @__PURE__ */ p("div", {
91
104
  className: "grid grid-cols-1 gap-4 lg:grid-cols-3",
92
- children: [/* @__PURE__ */ h(_, {
105
+ children: [/* @__PURE__ */ p(h, {
93
106
  treatment: "glass",
94
107
  className: "p-6 lg:col-span-2",
95
108
  children: [
96
- /* @__PURE__ */ h("dl", {
109
+ /* @__PURE__ */ p("dl", {
97
110
  className: "grid grid-cols-2 gap-x-6 gap-y-4 sm:grid-cols-3",
98
111
  children: [
99
- /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("dt", {
112
+ /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("dt", {
100
113
  className: "text-xs text-text-tertiary",
101
114
  children: "Type"
102
- }), /* @__PURE__ */ m("dd", {
103
- className: "mt-0.5 text-sm text-text-primary",
104
- children: i(N.type)
115
+ }), /* @__PURE__ */ f("dd", {
116
+ className: "mt-1",
117
+ children: /* @__PURE__ */ f(me, { type: j.type })
105
118
  })] }),
106
- /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("dt", {
119
+ /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("dt", {
107
120
  className: "text-xs text-text-tertiary",
108
121
  children: "Region"
109
- }), /* @__PURE__ */ m("dd", {
122
+ }), /* @__PURE__ */ f("dd", {
110
123
  className: "mt-0.5 text-sm text-text-primary",
111
- children: [N.region, N.country].filter(Boolean).join(", ") || "—"
124
+ children: [j.region, j.country].filter(Boolean).join(", ") || "—"
112
125
  })] }),
113
- /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("dt", {
126
+ /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("dt", {
114
127
  className: "text-xs text-text-tertiary",
115
128
  children: "Area"
116
- }), /* @__PURE__ */ m("dd", {
129
+ }), /* @__PURE__ */ f("dd", {
117
130
  className: "mt-0.5 text-sm text-text-primary tabular-nums",
118
- children: N.areaHectares == null ? "—" : `${a(N.areaHectares)} ha`
131
+ children: j.areaHectares == null ? "—" : `${r(j.areaHectares)} ha`
119
132
  })] }),
120
- /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("dt", {
133
+ /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("dt", {
121
134
  className: "text-xs text-text-tertiary",
122
135
  children: "Coordinates"
123
- }), /* @__PURE__ */ m("dd", {
136
+ }), /* @__PURE__ */ f("dd", {
124
137
  className: "mt-0.5 text-sm text-text-primary tabular-nums",
125
- children: n(N.latitude, N.longitude)
138
+ children: ee(j.latitude, j.longitude)
126
139
  })] }),
127
- /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("dt", {
140
+ /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("dt", {
128
141
  className: "text-xs text-text-tertiary",
129
142
  children: "Sensors"
130
- }), /* @__PURE__ */ m("dd", {
143
+ }), /* @__PURE__ */ f("dd", {
131
144
  className: "mt-0.5 text-sm text-text-primary tabular-nums",
132
- children: Z.length
145
+ children: J.length
133
146
  })] }),
134
- /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("dt", {
147
+ /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("dt", {
135
148
  className: "text-xs text-text-tertiary",
136
149
  children: "Thresholds"
137
- }), /* @__PURE__ */ m("dd", {
150
+ }), /* @__PURE__ */ f("dd", {
138
151
  className: "mt-0.5 text-sm text-text-primary tabular-nums",
139
- children: Q.length
152
+ children: Y.length
140
153
  })] })
141
154
  ]
142
155
  }),
143
- N.description && /* @__PURE__ */ m("p", {
156
+ j.description && /* @__PURE__ */ f("p", {
144
157
  className: "mt-5 rounded-lg bg-bg-sunken/60 p-3 text-sm text-text-secondary",
145
- children: N.description
158
+ children: j.description
146
159
  }),
147
- /* @__PURE__ */ m("div", {
160
+ /* @__PURE__ */ f("div", {
148
161
  className: "mt-5 border-t border-border-seam pt-4",
149
- children: /* @__PURE__ */ m(le, {
162
+ children: /* @__PURE__ */ f(pe, {
150
163
  entityType: "ecoimpacthub-site",
151
- entityId: N.id
164
+ entityId: j.id
152
165
  })
153
166
  })
154
167
  ]
155
- }), /* @__PURE__ */ h(_, {
156
- treatment: "glass",
157
- className: "flex flex-col gap-3 p-6",
158
- children: [
159
- /* @__PURE__ */ m("p", {
160
- className: "text-xs text-text-tertiary",
161
- children: "Quick actions"
162
- }),
163
- /* @__PURE__ */ h(g, {
164
- onClick: () => K(!0),
165
- children: [/* @__PURE__ */ m(ue, { className: "mr-1.5 h-4 w-4" }), " Record measurement"]
166
- }),
167
- /* @__PURE__ */ h(g, {
168
- variant: "outline",
169
- onClick: () => B(!0),
170
- children: [/* @__PURE__ */ m(p, { className: "mr-1.5 h-4 w-4" }), " Add sensor"]
171
- }),
172
- /* @__PURE__ */ h(g, {
173
- variant: "outline",
174
- onClick: () => U(!0),
175
- children: [/* @__PURE__ */ m(pe, { className: "mr-1.5 h-4 w-4" }), " Add threshold"]
176
- }),
177
- N.status !== "ARCHIVED" && /* @__PURE__ */ h(g, {
178
- variant: "ghost",
179
- onClick: async () => {
180
- if (j) {
181
- X(null);
182
- try {
183
- await z.mutateAsync(j), M("sites");
184
- } catch (e) {
185
- X(e instanceof Error ? e.message : "Failed to archive site.");
186
- }
187
- }
188
- },
189
- disabled: z.isPending,
190
- className: "text-status-error-text hover:text-status-error-text",
191
- children: [/* @__PURE__ */ m(de, { className: "mr-1.5 h-4 w-4" }), " Archive site"]
192
- })
193
- ]
168
+ }), /* @__PURE__ */ p("div", {
169
+ className: "flex flex-col gap-4",
170
+ children: [/* @__PURE__ */ p(h, {
171
+ treatment: "glass",
172
+ className: "p-6",
173
+ children: [/* @__PURE__ */ p("div", {
174
+ className: "mb-3 flex items-center gap-2",
175
+ children: [/* @__PURE__ */ f(be, { className: "h-4 w-4 text-accent" }), /* @__PURE__ */ f("h2", {
176
+ className: "text-base font-semibold text-text-primary",
177
+ children: "Quick actions"
178
+ })]
179
+ }), /* @__PURE__ */ p("div", {
180
+ className: "flex flex-col gap-2.5",
181
+ children: [
182
+ /* @__PURE__ */ p(m, {
183
+ onClick: () => U(!0),
184
+ children: [/* @__PURE__ */ f(he, { className: "mr-1.5 h-4 w-4" }), " Record measurement"]
185
+ }),
186
+ /* @__PURE__ */ p(m, {
187
+ variant: "outline",
188
+ onClick: () => L(!0),
189
+ children: [/* @__PURE__ */ f(d, { className: "mr-1.5 h-4 w-4" }), " Add sensor"]
190
+ }),
191
+ /* @__PURE__ */ p(m, {
192
+ variant: "outline",
193
+ onClick: () => B(!0),
194
+ children: [/* @__PURE__ */ f(ve, { className: "mr-1.5 h-4 w-4" }), " Add threshold"]
195
+ }),
196
+ j.status !== "ARCHIVED" && /* @__PURE__ */ p(m, {
197
+ variant: "ghost",
198
+ onClick: async () => {
199
+ if (k) {
200
+ q(null);
201
+ try {
202
+ await I.mutateAsync(k), A("sites");
203
+ } catch (e) {
204
+ q(e instanceof Error ? e.message : "Failed to archive site.");
205
+ }
206
+ }
207
+ },
208
+ disabled: I.isPending,
209
+ className: "text-status-error-text hover:text-status-error-text",
210
+ children: [/* @__PURE__ */ f(ge, { className: "mr-1.5 h-4 w-4" }), " Archive site"]
211
+ })
212
+ ]
213
+ })]
214
+ }), /* @__PURE__ */ p(h, {
215
+ treatment: "glass",
216
+ className: "p-6",
217
+ children: [
218
+ /* @__PURE__ */ p("div", {
219
+ className: "mb-4 flex items-center gap-2",
220
+ children: [/* @__PURE__ */ f(d, { className: "h-4 w-4 text-accent" }), /* @__PURE__ */ f("h2", {
221
+ className: "text-base font-semibold text-text-primary",
222
+ children: "Monitoring summary"
223
+ })]
224
+ }),
225
+ /* @__PURE__ */ p("div", {
226
+ className: "grid grid-cols-2 gap-3",
227
+ children: [/* @__PURE__ */ p("div", {
228
+ className: "rounded-xl bg-bg-sunken/60 p-3",
229
+ children: [
230
+ /* @__PURE__ */ p("p", {
231
+ className: "text-2xl font-semibold text-text-primary tabular-nums",
232
+ children: [Z, /* @__PURE__ */ p("span", {
233
+ className: "text-base text-text-tertiary",
234
+ children: ["/", J.length]
235
+ })]
236
+ }),
237
+ /* @__PURE__ */ f("p", {
238
+ className: "mt-0.5 text-xs text-text-secondary",
239
+ children: "Sensors online"
240
+ }),
241
+ /* @__PURE__ */ f(re, {
242
+ className: "mt-2",
243
+ value: J.length ? Z / J.length * 100 : 0,
244
+ barClassName: "bg-[var(--color-status-success-text)]"
245
+ })
246
+ ]
247
+ }), /* @__PURE__ */ p("div", {
248
+ className: "rounded-xl bg-bg-sunken/60 p-3",
249
+ children: [
250
+ /* @__PURE__ */ p("p", {
251
+ className: "text-2xl font-semibold text-text-primary tabular-nums",
252
+ children: [Ie, /* @__PURE__ */ p("span", {
253
+ className: "text-base text-text-tertiary",
254
+ children: ["/", Y.length]
255
+ })]
256
+ }),
257
+ /* @__PURE__ */ f("p", {
258
+ className: "mt-0.5 text-xs text-text-secondary",
259
+ children: "Active thresholds"
260
+ }),
261
+ /* @__PURE__ */ f("p", {
262
+ className: Q > 0 ? "mt-2 text-xs text-status-warning-text" : "mt-2 text-xs text-text-tertiary",
263
+ children: Q > 0 ? `${Q} sensor${Q > 1 ? "s" : ""} need attention` : "All sensors healthy"
264
+ })
265
+ ]
266
+ })]
267
+ }),
268
+ /* @__PURE__ */ p("div", {
269
+ className: "mt-4 border-t border-border-seam pt-4",
270
+ children: [/* @__PURE__ */ f("p", {
271
+ className: "mb-2 text-xs text-text-tertiary",
272
+ children: "Latest breach"
273
+ }), $ ? /* @__PURE__ */ p("div", {
274
+ className: "flex items-center justify-between gap-3",
275
+ children: [/* @__PURE__ */ p("div", {
276
+ className: "min-w-0",
277
+ children: [/* @__PURE__ */ f("p", {
278
+ className: "truncate text-sm font-medium text-text-primary",
279
+ children: $.parameter
280
+ }), /* @__PURE__ */ p("p", {
281
+ className: "text-xs text-text-tertiary tabular-nums",
282
+ children: [
283
+ r($.value),
284
+ " ",
285
+ $.unit,
286
+ " ·",
287
+ " ",
288
+ ne($.recordedAt)
289
+ ]
290
+ })]
291
+ }), /* @__PURE__ */ f(i, {
292
+ status: "BREACH",
293
+ className: "shrink-0 uppercase"
294
+ })]
295
+ }) : /* @__PURE__ */ p("div", {
296
+ className: "flex items-center gap-2 text-sm text-text-secondary",
297
+ children: [/* @__PURE__ */ f(ye, { className: "h-4 w-4 shrink-0 text-status-success-text" }), "No breaches recorded"]
298
+ })]
299
+ })
300
+ ]
301
+ })]
194
302
  })]
195
303
  }),
196
- Y && /* @__PURE__ */ m("p", {
304
+ K && /* @__PURE__ */ f("p", {
197
305
  className: "mt-4 text-sm text-status-error-text",
198
- children: Y
306
+ children: K
199
307
  }),
200
- /* @__PURE__ */ m(c, {
308
+ /* @__PURE__ */ f(a, {
201
309
  title: "Sensors",
202
310
  description: "Instruments streaming or recording readings for this site.",
203
- action: /* @__PURE__ */ h(g, {
311
+ action: /* @__PURE__ */ p(m, {
204
312
  size: "sm",
205
- onClick: () => B(!0),
206
- children: [/* @__PURE__ */ m(f, { className: "mr-1.5 h-4 w-4" }), " Add sensor"]
313
+ onClick: () => L(!0),
314
+ children: [/* @__PURE__ */ f(u, { className: "mr-1.5 h-4 w-4" }), " Add sensor"]
207
315
  }),
208
- children: Z.length === 0 ? /* @__PURE__ */ m(l, {
316
+ children: J.length === 0 ? /* @__PURE__ */ f(o, {
209
317
  illustration: "empty-data",
210
318
  title: "No sensors",
211
319
  description: "Add a sensor to begin monitoring."
212
- }) : /* @__PURE__ */ m(u, {
320
+ }) : /* @__PURE__ */ f(c, {
213
321
  columns: [
214
322
  {
215
323
  key: "name",
216
324
  header: "Sensor",
217
- render: (e) => /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("p", {
325
+ render: (e) => /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("p", {
218
326
  className: "font-medium text-text-primary",
219
327
  children: e.name
220
- }), /* @__PURE__ */ m("p", {
328
+ }), /* @__PURE__ */ f("p", {
221
329
  className: "text-xs text-text-tertiary",
222
- children: i(e.kind)
330
+ children: n(e.kind)
223
331
  })] })
224
332
  },
225
333
  {
226
334
  key: "unit",
227
335
  header: "Unit",
228
336
  hideOnMobile: !0,
229
- render: (e) => /* @__PURE__ */ m("span", {
337
+ render: (e) => /* @__PURE__ */ f("span", {
230
338
  className: "text-text-secondary",
231
339
  children: e.unit ?? "—"
232
340
  })
@@ -234,50 +342,50 @@ function j() {
234
342
  {
235
343
  key: "status",
236
344
  header: "Status",
237
- render: (e) => /* @__PURE__ */ m(o, { status: e.status })
345
+ render: (e) => /* @__PURE__ */ f(i, { status: e.status })
238
346
  },
239
347
  {
240
348
  key: "action",
241
349
  header: "",
242
350
  align: "right",
243
- render: (e) => /* @__PURE__ */ h(E, {
351
+ render: (e) => /* @__PURE__ */ p(w, {
244
352
  value: e.status,
245
- onValueChange: (t) => I.mutate({
353
+ onValueChange: (t) => je.mutate({
246
354
  id: e.id,
247
355
  status: t
248
356
  }),
249
- children: [/* @__PURE__ */ m(k, {
357
+ children: [/* @__PURE__ */ f(D, {
250
358
  className: "h-8 w-36",
251
- children: /* @__PURE__ */ m(A, {})
252
- }), /* @__PURE__ */ m(D, { children: _e.map((e) => /* @__PURE__ */ m(O, {
359
+ children: /* @__PURE__ */ f(O, {})
360
+ }), /* @__PURE__ */ f(T, { children: we.map((e) => /* @__PURE__ */ f(E, {
253
361
  value: e,
254
- children: i(e)
362
+ children: n(e)
255
363
  }, e)) })]
256
364
  })
257
365
  }
258
366
  ],
259
- rows: Z,
367
+ rows: J,
260
368
  rowKey: (e) => e.id
261
369
  })
262
370
  }),
263
- /* @__PURE__ */ m(c, {
371
+ /* @__PURE__ */ f(a, {
264
372
  title: "Alert thresholds",
265
373
  description: "Rules that flag measurements as breaches when values drift out of range.",
266
- action: /* @__PURE__ */ h(g, {
374
+ action: /* @__PURE__ */ p(m, {
267
375
  size: "sm",
268
- onClick: () => U(!0),
269
- children: [/* @__PURE__ */ m(f, { className: "mr-1.5 h-4 w-4" }), " Add threshold"]
376
+ onClick: () => B(!0),
377
+ children: [/* @__PURE__ */ f(u, { className: "mr-1.5 h-4 w-4" }), " Add threshold"]
270
378
  }),
271
- children: Q.length === 0 ? /* @__PURE__ */ m(l, {
379
+ children: Y.length === 0 ? /* @__PURE__ */ f(o, {
272
380
  illustration: "empty-data",
273
381
  title: "No thresholds",
274
382
  description: "Define a threshold to flag breaches."
275
- }) : /* @__PURE__ */ m(u, {
383
+ }) : /* @__PURE__ */ f(c, {
276
384
  columns: [
277
385
  {
278
386
  key: "parameter",
279
387
  header: "Parameter",
280
- render: (e) => /* @__PURE__ */ m("span", {
388
+ render: (e) => /* @__PURE__ */ f("span", {
281
389
  className: "font-medium text-text-primary",
282
390
  children: e.parameter
283
391
  })
@@ -285,24 +393,24 @@ function j() {
285
393
  {
286
394
  key: "rule",
287
395
  header: "Rule",
288
- render: (e) => /* @__PURE__ */ m("span", {
396
+ render: (e) => /* @__PURE__ */ f("span", {
289
397
  className: "text-text-secondary",
290
- children: e.direction === "OUTSIDE_RANGE" ? `${a(e.minValue)}–${a(e.maxValue)} ${e.unit}` : `${i(e.direction)} ${a(e.limitValue)} ${e.unit}`
398
+ children: e.direction === "OUTSIDE_RANGE" ? `${r(e.minValue)}–${r(e.maxValue)} ${e.unit}` : `${n(e.direction)} ${r(e.limitValue)} ${e.unit}`
291
399
  })
292
400
  },
293
401
  {
294
402
  key: "severity",
295
403
  header: "Severity",
296
- render: (e) => /* @__PURE__ */ m(o, { status: e.severity })
404
+ render: (e) => /* @__PURE__ */ f(i, { status: e.severity })
297
405
  },
298
406
  {
299
407
  key: "active",
300
408
  header: "Active",
301
409
  align: "right",
302
- render: (e) => /* @__PURE__ */ m(g, {
410
+ render: (e) => /* @__PURE__ */ f(m, {
303
411
  size: "sm",
304
412
  variant: e.isActive ? "outline" : "ghost",
305
- onClick: () => Ce.mutate({
413
+ onClick: () => Me.mutate({
306
414
  id: e.id,
307
415
  isActive: !e.isActive
308
416
  }),
@@ -310,23 +418,23 @@ function j() {
310
418
  })
311
419
  }
312
420
  ],
313
- rows: Q,
421
+ rows: Y,
314
422
  rowKey: (e) => e.id
315
423
  })
316
424
  }),
317
- /* @__PURE__ */ m(c, {
425
+ /* @__PURE__ */ f(a, {
318
426
  title: "Recent measurements",
319
427
  description: "The latest readings recorded at this site.",
320
- children: $.length === 0 ? /* @__PURE__ */ m(l, {
428
+ children: X.length === 0 ? /* @__PURE__ */ f(o, {
321
429
  illustration: "empty-data",
322
430
  title: "No measurements yet",
323
431
  description: "Record a measurement to see it here."
324
- }) : /* @__PURE__ */ m(u, {
432
+ }) : /* @__PURE__ */ f(c, {
325
433
  columns: [
326
434
  {
327
435
  key: "parameter",
328
436
  header: "Parameter",
329
- render: (e) => /* @__PURE__ */ m("span", {
437
+ render: (e) => /* @__PURE__ */ f("span", {
330
438
  className: "font-medium text-text-primary",
331
439
  children: e.parameter
332
440
  })
@@ -335,10 +443,10 @@ function j() {
335
443
  key: "value",
336
444
  header: "Value",
337
445
  align: "right",
338
- render: (e) => /* @__PURE__ */ h("span", {
446
+ render: (e) => /* @__PURE__ */ p("span", {
339
447
  className: "tabular-nums text-text-primary",
340
448
  children: [
341
- a(e.value),
449
+ r(e.value),
342
450
  " ",
343
451
  e.unit
344
452
  ]
@@ -348,105 +456,111 @@ function j() {
348
456
  key: "source",
349
457
  header: "Source",
350
458
  hideOnMobile: !0,
351
- render: (e) => /* @__PURE__ */ m("span", {
459
+ render: (e) => /* @__PURE__ */ f("span", {
352
460
  className: "text-text-secondary",
353
- children: i(e.source)
461
+ children: n(e.source)
354
462
  })
355
463
  },
356
464
  {
357
465
  key: "breach",
358
466
  header: "Status",
359
- render: (e) => e.isBreach ? /* @__PURE__ */ m(o, { status: "BREACH" }) : /* @__PURE__ */ m(o, { status: "OK" })
467
+ render: (e) => e.isBreach ? /* @__PURE__ */ f(i, {
468
+ status: "BREACH",
469
+ className: "uppercase"
470
+ }) : /* @__PURE__ */ f(i, {
471
+ status: "OK",
472
+ className: "uppercase"
473
+ })
360
474
  },
361
475
  {
362
476
  key: "recorded",
363
477
  header: "Recorded",
364
478
  align: "right",
365
479
  hideOnMobile: !0,
366
- render: (e) => /* @__PURE__ */ m("span", {
480
+ render: (e) => /* @__PURE__ */ f("span", {
367
481
  className: "text-text-tertiary",
368
- children: r(e.recordedAt)
482
+ children: te(e.recordedAt)
369
483
  })
370
484
  }
371
485
  ],
372
- rows: $,
486
+ rows: X,
373
487
  rowKey: (e) => e.id
374
488
  })
375
489
  }),
376
- /* @__PURE__ */ m(b, {
377
- open: we,
378
- onOpenChange: B,
379
- children: /* @__PURE__ */ h(x, { children: [
380
- /* @__PURE__ */ h(w, { children: [/* @__PURE__ */ m(T, { children: "Add sensor" }), /* @__PURE__ */ h(S, { children: [
490
+ /* @__PURE__ */ f(v, {
491
+ open: Ne,
492
+ onOpenChange: L,
493
+ children: /* @__PURE__ */ p(y, { children: [
494
+ /* @__PURE__ */ p(S, { children: [/* @__PURE__ */ f(C, { children: "Add sensor" }), /* @__PURE__ */ p(b, { children: [
381
495
  "Register a sensor at ",
382
- N.name,
496
+ j.name,
383
497
  "."
384
498
  ] })] }),
385
- /* @__PURE__ */ h("div", {
499
+ /* @__PURE__ */ p("div", {
386
500
  className: "grid gap-4 py-2",
387
501
  children: [
388
- /* @__PURE__ */ h("div", {
502
+ /* @__PURE__ */ p("div", {
389
503
  className: "grid gap-1.5",
390
- children: [/* @__PURE__ */ m(y, {
504
+ children: [/* @__PURE__ */ f(_, {
391
505
  htmlFor: "sensorName",
392
506
  children: "Name *"
393
- }), /* @__PURE__ */ m(v, {
507
+ }), /* @__PURE__ */ f(g, {
394
508
  id: "sensorName",
395
- value: V.name,
396
- onChange: (e) => H({
397
- ...V,
509
+ value: R.name,
510
+ onChange: (e) => z({
511
+ ...R,
398
512
  name: e.target.value
399
513
  }),
400
514
  placeholder: "North gate PM2.5"
401
515
  })]
402
516
  }),
403
- /* @__PURE__ */ h("div", {
517
+ /* @__PURE__ */ p("div", {
404
518
  className: "grid gap-2 sm:grid-cols-2",
405
- children: [/* @__PURE__ */ h("div", {
519
+ children: [/* @__PURE__ */ p("div", {
406
520
  className: "grid gap-1.5",
407
- children: [/* @__PURE__ */ m(y, {
521
+ children: [/* @__PURE__ */ f(_, {
408
522
  htmlFor: "sensorKind",
409
523
  children: "Kind"
410
- }), /* @__PURE__ */ h(E, {
411
- value: V.kind,
412
- onValueChange: (e) => H({
413
- ...V,
524
+ }), /* @__PURE__ */ p(w, {
525
+ value: R.kind,
526
+ onValueChange: (e) => z({
527
+ ...R,
414
528
  kind: e
415
529
  }),
416
- children: [/* @__PURE__ */ m(k, {
530
+ children: [/* @__PURE__ */ f(D, {
417
531
  id: "sensorKind",
418
- children: /* @__PURE__ */ m(A, {})
419
- }), /* @__PURE__ */ m(D, { children: ge.map((e) => /* @__PURE__ */ m(O, {
532
+ children: /* @__PURE__ */ f(O, {})
533
+ }), /* @__PURE__ */ f(T, { children: Ce.map((e) => /* @__PURE__ */ f(E, {
420
534
  value: e,
421
- children: i(e)
535
+ children: n(e)
422
536
  }, e)) })]
423
537
  })]
424
- }), /* @__PURE__ */ h("div", {
538
+ }), /* @__PURE__ */ p("div", {
425
539
  className: "grid gap-1.5",
426
- children: [/* @__PURE__ */ m(y, {
540
+ children: [/* @__PURE__ */ f(_, {
427
541
  htmlFor: "sensorUnit",
428
542
  children: "Unit"
429
- }), /* @__PURE__ */ m(v, {
543
+ }), /* @__PURE__ */ f(g, {
430
544
  id: "sensorUnit",
431
- value: V.unit,
432
- onChange: (e) => H({
433
- ...V,
545
+ value: R.unit,
546
+ onChange: (e) => z({
547
+ ...R,
434
548
  unit: e.target.value
435
549
  }),
436
550
  placeholder: "µg/m³"
437
551
  })]
438
552
  })]
439
553
  }),
440
- /* @__PURE__ */ h("div", {
554
+ /* @__PURE__ */ p("div", {
441
555
  className: "grid gap-1.5",
442
- children: [/* @__PURE__ */ m(y, {
556
+ children: [/* @__PURE__ */ f(_, {
443
557
  htmlFor: "sensorHw",
444
558
  children: "Hardware ID"
445
- }), /* @__PURE__ */ m(v, {
559
+ }), /* @__PURE__ */ f(g, {
446
560
  id: "sensorHw",
447
- value: V.hardwareId,
448
- onChange: (e) => H({
449
- ...V,
561
+ value: R.hardwareId,
562
+ onChange: (e) => z({
563
+ ...R,
450
564
  hardwareId: e.target.value
451
565
  }),
452
566
  placeholder: "Optional device identifier"
@@ -454,166 +568,166 @@ function j() {
454
568
  })
455
569
  ]
456
570
  }),
457
- /* @__PURE__ */ h(C, { children: [/* @__PURE__ */ m(g, {
571
+ /* @__PURE__ */ p(x, { children: [/* @__PURE__ */ f(m, {
458
572
  variant: "outline",
459
- onClick: () => B(!1),
573
+ onClick: () => L(!1),
460
574
  children: "Cancel"
461
- }), /* @__PURE__ */ m(g, {
575
+ }), /* @__PURE__ */ f(m, {
462
576
  onClick: async () => {
463
- if (!j || !V.name.trim()) {
464
- X("Sensor name is required.");
577
+ if (!k || !R.name.trim()) {
578
+ q("Sensor name is required.");
465
579
  return;
466
580
  }
467
- X(null);
581
+ q(null);
468
582
  try {
469
- await F.mutateAsync({
470
- name: V.name.trim(),
471
- siteId: j,
472
- kind: V.kind,
473
- unit: V.unit.trim() || null,
474
- hardwareId: V.hardwareId.trim() || null
475
- }), B(!1), H({
583
+ await N.mutateAsync({
584
+ name: R.name.trim(),
585
+ siteId: k,
586
+ kind: R.kind,
587
+ unit: R.unit.trim() || null,
588
+ hardwareId: R.hardwareId.trim() || null
589
+ }), L(!1), z({
476
590
  name: "",
477
591
  kind: "AIR_QUALITY",
478
592
  unit: "",
479
593
  hardwareId: ""
480
594
  });
481
595
  } catch (e) {
482
- X(e instanceof Error ? e.message : "Failed to add sensor.");
596
+ q(e instanceof Error ? e.message : "Failed to add sensor.");
483
597
  }
484
598
  },
485
- disabled: F.isPending,
486
- children: F.isPending ? "Adding…" : "Add sensor"
599
+ disabled: N.isPending,
600
+ children: N.isPending ? "Adding…" : "Add sensor"
487
601
  })] })
488
602
  ] })
489
603
  }),
490
- /* @__PURE__ */ m(b, {
491
- open: Te,
492
- onOpenChange: U,
493
- children: /* @__PURE__ */ h(x, { children: [
494
- /* @__PURE__ */ h(w, { children: [/* @__PURE__ */ m(T, { children: "Add alert threshold" }), /* @__PURE__ */ m(S, { children: "Flag readings that drift out of an acceptable range." })] }),
495
- /* @__PURE__ */ h("div", {
604
+ /* @__PURE__ */ f(v, {
605
+ open: Pe,
606
+ onOpenChange: B,
607
+ children: /* @__PURE__ */ p(y, { children: [
608
+ /* @__PURE__ */ p(S, { children: [/* @__PURE__ */ f(C, { children: "Add alert threshold" }), /* @__PURE__ */ f(b, { children: "Flag readings that drift out of an acceptable range." })] }),
609
+ /* @__PURE__ */ p("div", {
496
610
  className: "grid gap-4 py-2",
497
611
  children: [
498
- /* @__PURE__ */ h("div", {
612
+ /* @__PURE__ */ p("div", {
499
613
  className: "grid gap-2 sm:grid-cols-2",
500
- children: [/* @__PURE__ */ h("div", {
614
+ children: [/* @__PURE__ */ p("div", {
501
615
  className: "grid gap-1.5",
502
- children: [/* @__PURE__ */ m(y, {
616
+ children: [/* @__PURE__ */ f(_, {
503
617
  htmlFor: "thParam",
504
618
  children: "Parameter *"
505
- }), /* @__PURE__ */ m(v, {
619
+ }), /* @__PURE__ */ f(g, {
506
620
  id: "thParam",
507
- value: W.parameter,
508
- onChange: (e) => G({
509
- ...W,
621
+ value: V.parameter,
622
+ onChange: (e) => H({
623
+ ...V,
510
624
  parameter: e.target.value
511
625
  }),
512
626
  placeholder: "PM2.5"
513
627
  })]
514
- }), /* @__PURE__ */ h("div", {
628
+ }), /* @__PURE__ */ p("div", {
515
629
  className: "grid gap-1.5",
516
- children: [/* @__PURE__ */ m(y, {
630
+ children: [/* @__PURE__ */ f(_, {
517
631
  htmlFor: "thUnit",
518
632
  children: "Unit *"
519
- }), /* @__PURE__ */ m(v, {
633
+ }), /* @__PURE__ */ f(g, {
520
634
  id: "thUnit",
521
- value: W.unit,
522
- onChange: (e) => G({
523
- ...W,
635
+ value: V.unit,
636
+ onChange: (e) => H({
637
+ ...V,
524
638
  unit: e.target.value
525
639
  }),
526
640
  placeholder: "µg/m³"
527
641
  })]
528
642
  })]
529
643
  }),
530
- /* @__PURE__ */ h("div", {
644
+ /* @__PURE__ */ p("div", {
531
645
  className: "grid gap-2 sm:grid-cols-2",
532
- children: [/* @__PURE__ */ h("div", {
646
+ children: [/* @__PURE__ */ p("div", {
533
647
  className: "grid gap-1.5",
534
- children: [/* @__PURE__ */ m(y, {
648
+ children: [/* @__PURE__ */ f(_, {
535
649
  htmlFor: "thDir",
536
650
  children: "Direction"
537
- }), /* @__PURE__ */ h(E, {
538
- value: W.direction,
539
- onValueChange: (e) => G({
540
- ...W,
651
+ }), /* @__PURE__ */ p(w, {
652
+ value: V.direction,
653
+ onValueChange: (e) => H({
654
+ ...V,
541
655
  direction: e
542
656
  }),
543
- children: [/* @__PURE__ */ m(k, {
657
+ children: [/* @__PURE__ */ f(D, {
544
658
  id: "thDir",
545
- children: /* @__PURE__ */ m(A, {})
546
- }), /* @__PURE__ */ m(D, { children: ve.map((e) => /* @__PURE__ */ m(O, {
659
+ children: /* @__PURE__ */ f(O, {})
660
+ }), /* @__PURE__ */ f(T, { children: Te.map((e) => /* @__PURE__ */ f(E, {
547
661
  value: e,
548
- children: i(e)
662
+ children: n(e)
549
663
  }, e)) })]
550
664
  })]
551
- }), /* @__PURE__ */ h("div", {
665
+ }), /* @__PURE__ */ p("div", {
552
666
  className: "grid gap-1.5",
553
- children: [/* @__PURE__ */ m(y, {
667
+ children: [/* @__PURE__ */ f(_, {
554
668
  htmlFor: "thSev",
555
669
  children: "Severity"
556
- }), /* @__PURE__ */ h(E, {
557
- value: W.severity,
558
- onValueChange: (e) => G({
559
- ...W,
670
+ }), /* @__PURE__ */ p(w, {
671
+ value: V.severity,
672
+ onValueChange: (e) => H({
673
+ ...V,
560
674
  severity: e
561
675
  }),
562
- children: [/* @__PURE__ */ m(k, {
676
+ children: [/* @__PURE__ */ f(D, {
563
677
  id: "thSev",
564
- children: /* @__PURE__ */ m(A, {})
565
- }), /* @__PURE__ */ m(D, { children: ye.map((e) => /* @__PURE__ */ m(O, {
678
+ children: /* @__PURE__ */ f(O, {})
679
+ }), /* @__PURE__ */ f(T, { children: Ee.map((e) => /* @__PURE__ */ f(E, {
566
680
  value: e,
567
- children: i(e)
681
+ children: n(e)
568
682
  }, e)) })]
569
683
  })]
570
684
  })]
571
685
  }),
572
- W.direction === "OUTSIDE_RANGE" ? /* @__PURE__ */ h("div", {
686
+ V.direction === "OUTSIDE_RANGE" ? /* @__PURE__ */ p("div", {
573
687
  className: "grid gap-2 sm:grid-cols-2",
574
- children: [/* @__PURE__ */ h("div", {
688
+ children: [/* @__PURE__ */ p("div", {
575
689
  className: "grid gap-1.5",
576
- children: [/* @__PURE__ */ m(y, {
690
+ children: [/* @__PURE__ */ f(_, {
577
691
  htmlFor: "thMin",
578
692
  children: "Min value"
579
- }), /* @__PURE__ */ m(v, {
693
+ }), /* @__PURE__ */ f(g, {
580
694
  id: "thMin",
581
695
  type: "number",
582
696
  step: "any",
583
- value: W.minValue,
584
- onChange: (e) => G({
585
- ...W,
697
+ value: V.minValue,
698
+ onChange: (e) => H({
699
+ ...V,
586
700
  minValue: e.target.value
587
701
  })
588
702
  })]
589
- }), /* @__PURE__ */ h("div", {
703
+ }), /* @__PURE__ */ p("div", {
590
704
  className: "grid gap-1.5",
591
- children: [/* @__PURE__ */ m(y, {
705
+ children: [/* @__PURE__ */ f(_, {
592
706
  htmlFor: "thMax",
593
707
  children: "Max value"
594
- }), /* @__PURE__ */ m(v, {
708
+ }), /* @__PURE__ */ f(g, {
595
709
  id: "thMax",
596
710
  type: "number",
597
711
  step: "any",
598
- value: W.maxValue,
599
- onChange: (e) => G({
600
- ...W,
712
+ value: V.maxValue,
713
+ onChange: (e) => H({
714
+ ...V,
601
715
  maxValue: e.target.value
602
716
  })
603
717
  })]
604
718
  })]
605
- }) : /* @__PURE__ */ h("div", {
719
+ }) : /* @__PURE__ */ p("div", {
606
720
  className: "grid gap-1.5",
607
- children: [/* @__PURE__ */ m(y, {
721
+ children: [/* @__PURE__ */ f(_, {
608
722
  htmlFor: "thLimit",
609
723
  children: "Limit value"
610
- }), /* @__PURE__ */ m(v, {
724
+ }), /* @__PURE__ */ f(g, {
611
725
  id: "thLimit",
612
726
  type: "number",
613
727
  step: "any",
614
- value: W.limitValue,
615
- onChange: (e) => G({
616
- ...W,
728
+ value: V.limitValue,
729
+ onChange: (e) => H({
730
+ ...V,
617
731
  limitValue: e.target.value
618
732
  }),
619
733
  placeholder: "35"
@@ -621,28 +735,28 @@ function j() {
621
735
  })
622
736
  ]
623
737
  }),
624
- /* @__PURE__ */ h(C, { children: [/* @__PURE__ */ m(g, {
738
+ /* @__PURE__ */ p(x, { children: [/* @__PURE__ */ f(m, {
625
739
  variant: "outline",
626
- onClick: () => U(!1),
740
+ onClick: () => B(!1),
627
741
  children: "Cancel"
628
- }), /* @__PURE__ */ m(g, {
742
+ }), /* @__PURE__ */ f(m, {
629
743
  onClick: async () => {
630
- if (!j || !W.parameter.trim() || !W.unit.trim()) {
631
- X("Parameter and unit are required.");
744
+ if (!k || !V.parameter.trim() || !V.unit.trim()) {
745
+ q("Parameter and unit are required.");
632
746
  return;
633
747
  }
634
- X(null);
748
+ q(null);
635
749
  try {
636
- await L.mutateAsync({
637
- siteId: j,
638
- parameter: W.parameter.trim(),
639
- unit: W.unit.trim(),
640
- direction: W.direction,
641
- severity: W.severity,
642
- limitValue: W.limitValue ? Number(W.limitValue) : null,
643
- minValue: W.minValue ? Number(W.minValue) : null,
644
- maxValue: W.maxValue ? Number(W.maxValue) : null
645
- }), U(!1), G({
750
+ await P.mutateAsync({
751
+ siteId: k,
752
+ parameter: V.parameter.trim(),
753
+ unit: V.unit.trim(),
754
+ direction: V.direction,
755
+ severity: V.severity,
756
+ limitValue: V.limitValue ? Number(V.limitValue) : null,
757
+ minValue: V.minValue ? Number(V.minValue) : null,
758
+ maxValue: V.maxValue ? Number(V.maxValue) : null
759
+ }), B(!1), H({
646
760
  parameter: "",
647
761
  unit: "",
648
762
  direction: "ABOVE",
@@ -652,125 +766,139 @@ function j() {
652
766
  maxValue: ""
653
767
  });
654
768
  } catch (e) {
655
- X(e instanceof Error ? e.message : "Failed to add threshold.");
769
+ q(e instanceof Error ? e.message : "Failed to add threshold.");
656
770
  }
657
771
  },
658
- disabled: L.isPending,
659
- children: L.isPending ? "Adding…" : "Add threshold"
772
+ disabled: P.isPending,
773
+ children: P.isPending ? "Adding…" : "Add threshold"
660
774
  })] })
661
775
  ] })
662
776
  }),
663
- /* @__PURE__ */ m(b, {
664
- open: Ee,
665
- onOpenChange: K,
666
- children: /* @__PURE__ */ h(x, { children: [
667
- /* @__PURE__ */ h(w, { children: [/* @__PURE__ */ m(T, { children: "Record measurement" }), /* @__PURE__ */ m(S, { children: "Log a reading. It is checked against active thresholds and flagged if it breaches." })] }),
668
- /* @__PURE__ */ h("div", {
777
+ /* @__PURE__ */ f(v, {
778
+ open: Fe,
779
+ onOpenChange: U,
780
+ children: /* @__PURE__ */ p(y, { children: [
781
+ /* @__PURE__ */ p(S, { children: [/* @__PURE__ */ f(C, { children: "Record measurement" }), /* @__PURE__ */ f(b, { children: "Log a reading. It is checked against active thresholds and flagged if it breaches." })] }),
782
+ /* @__PURE__ */ p("div", {
669
783
  className: "grid gap-4 py-2",
670
- children: [/* @__PURE__ */ h("div", {
671
- className: "grid gap-2 sm:grid-cols-3",
672
- children: [
673
- /* @__PURE__ */ h("div", {
674
- className: "grid gap-1.5 sm:col-span-1",
675
- children: [/* @__PURE__ */ m(y, {
676
- htmlFor: "mParam",
677
- children: "Parameter *"
678
- }), /* @__PURE__ */ m(v, {
679
- id: "mParam",
680
- value: q.parameter,
681
- onChange: (e) => J({
682
- ...q,
683
- parameter: e.target.value
684
- }),
685
- placeholder: "PM2.5"
686
- })]
687
- }),
688
- /* @__PURE__ */ h("div", {
689
- className: "grid gap-1.5",
690
- children: [/* @__PURE__ */ m(y, {
691
- htmlFor: "mValue",
692
- children: "Value *"
693
- }), /* @__PURE__ */ m(v, {
694
- id: "mValue",
695
- type: "number",
696
- step: "any",
697
- value: q.value,
698
- onChange: (e) => J({
699
- ...q,
700
- value: e.target.value
701
- }),
702
- placeholder: "42"
703
- })]
704
- }),
705
- /* @__PURE__ */ h("div", {
706
- className: "grid gap-1.5",
707
- children: [/* @__PURE__ */ m(y, {
708
- htmlFor: "mUnit",
709
- children: "Unit *"
710
- }), /* @__PURE__ */ m(v, {
711
- id: "mUnit",
712
- value: q.unit,
713
- onChange: (e) => J({
714
- ...q,
715
- unit: e.target.value
784
+ children: [
785
+ /* @__PURE__ */ p("div", {
786
+ className: "grid gap-2 sm:grid-cols-3",
787
+ children: [
788
+ /* @__PURE__ */ p("div", {
789
+ className: "grid gap-1.5 sm:col-span-1",
790
+ children: [/* @__PURE__ */ f(_, {
791
+ htmlFor: "mParam",
792
+ children: "Parameter *"
793
+ }), /* @__PURE__ */ f(g, {
794
+ id: "mParam",
795
+ value: W.parameter,
796
+ onChange: (e) => G({
797
+ ...W,
798
+ parameter: e.target.value
799
+ }),
800
+ placeholder: "PM2.5"
801
+ })]
802
+ }),
803
+ /* @__PURE__ */ p("div", {
804
+ className: "grid gap-1.5",
805
+ children: [/* @__PURE__ */ f(_, {
806
+ htmlFor: "mValue",
807
+ children: "Value *"
808
+ }), /* @__PURE__ */ f(g, {
809
+ id: "mValue",
810
+ type: "number",
811
+ step: "any",
812
+ value: W.value,
813
+ onChange: (e) => G({
814
+ ...W,
815
+ value: e.target.value
816
+ }),
817
+ placeholder: "42"
818
+ })]
819
+ }),
820
+ /* @__PURE__ */ p("div", {
821
+ className: "grid gap-1.5",
822
+ children: [/* @__PURE__ */ f(_, {
823
+ htmlFor: "mUnit",
824
+ children: "Unit *"
825
+ }), /* @__PURE__ */ f(g, {
826
+ id: "mUnit",
827
+ value: W.unit,
828
+ onChange: (e) => G({
829
+ ...W,
830
+ unit: e.target.value
831
+ }),
832
+ placeholder: "µg/m³"
833
+ })]
834
+ })
835
+ ]
836
+ }),
837
+ J.length > 0 && /* @__PURE__ */ p("div", {
838
+ className: "grid gap-1.5",
839
+ children: [
840
+ /* @__PURE__ */ f(_, {
841
+ htmlFor: "mSensor",
842
+ children: "Sensor (optional)"
843
+ }),
844
+ /* @__PURE__ */ p(w, {
845
+ value: W.sensorId,
846
+ onValueChange: (e) => G({
847
+ ...W,
848
+ sensorId: e
716
849
  }),
717
- placeholder: "µg/m³"
718
- })]
719
- })
720
- ]
721
- }), Z.length > 0 && /* @__PURE__ */ h("div", {
722
- className: "grid gap-1.5",
723
- children: [/* @__PURE__ */ m(y, {
724
- htmlFor: "mSensor",
725
- children: "Sensor (optional)"
726
- }), /* @__PURE__ */ h(E, {
727
- value: q.sensorId,
728
- onValueChange: (e) => J({
729
- ...q,
730
- sensorId: e
731
- }),
732
- children: [/* @__PURE__ */ m(k, {
733
- id: "mSensor",
734
- children: /* @__PURE__ */ m(A, { placeholder: "Manual entry" })
735
- }), /* @__PURE__ */ m(D, { children: Z.map((e) => /* @__PURE__ */ m(O, {
736
- value: e.id,
737
- children: e.name
738
- }, e.id)) })]
739
- })]
740
- })]
850
+ children: [/* @__PURE__ */ f(D, {
851
+ id: "mSensor",
852
+ children: /* @__PURE__ */ f(O, { placeholder: "Manual entry" })
853
+ }), /* @__PURE__ */ f(T, { children: J.map((e) => /* @__PURE__ */ f(E, {
854
+ value: e.id,
855
+ children: e.name
856
+ }, e.id)) })]
857
+ }),
858
+ /* @__PURE__ */ f("p", {
859
+ className: "text-xs text-text-tertiary",
860
+ children: "Select a specific sensor for context, or leave blank for a site-level reading."
861
+ })
862
+ ]
863
+ }),
864
+ K && /* @__PURE__ */ f("p", {
865
+ className: "text-sm text-status-error-text",
866
+ children: K
867
+ })
868
+ ]
741
869
  }),
742
- /* @__PURE__ */ h(C, { children: [/* @__PURE__ */ m(g, {
870
+ /* @__PURE__ */ p(x, { children: [/* @__PURE__ */ f(m, {
743
871
  variant: "outline",
744
- onClick: () => K(!1),
872
+ onClick: () => U(!1),
745
873
  children: "Cancel"
746
- }), /* @__PURE__ */ m(g, {
874
+ }), /* @__PURE__ */ f(m, {
747
875
  onClick: async () => {
748
- if (!j || !q.parameter.trim() || !q.unit.trim() || !q.value) {
749
- X("Parameter, value and unit are required.");
876
+ if (!k || !W.parameter.trim() || !W.unit.trim() || !W.value) {
877
+ q("Parameter, value and unit are required.");
750
878
  return;
751
879
  }
752
- X(null);
880
+ q(null);
753
881
  try {
754
- await R.mutateAsync({
755
- siteId: j,
756
- parameter: q.parameter.trim(),
757
- value: Number(q.value),
758
- unit: q.unit.trim(),
882
+ await F.mutateAsync({
883
+ siteId: k,
884
+ parameter: W.parameter.trim(),
885
+ value: Number(W.value),
886
+ unit: W.unit.trim(),
759
887
  recordedAt: (/* @__PURE__ */ new Date()).toISOString(),
760
- sensorId: q.sensorId || null,
888
+ sensorId: W.sensorId || null,
761
889
  source: "MANUAL"
762
- }), K(!1), J({
890
+ }), U(!1), G({
763
891
  parameter: "",
764
892
  value: "",
765
893
  unit: "",
766
894
  sensorId: ""
767
- }), P.refetch();
895
+ }), M.refetch();
768
896
  } catch (e) {
769
- X(e instanceof Error ? e.message : "Failed to record measurement.");
897
+ q(e instanceof Error ? e.message : "Failed to record measurement.");
770
898
  }
771
899
  },
772
- disabled: R.isPending,
773
- children: R.isPending ? "Recording…" : "Record"
900
+ disabled: F.isPending,
901
+ children: F.isPending ? "Recording…" : "Record"
774
902
  })] })
775
903
  ] })
776
904
  })
@@ -778,6 +906,6 @@ function j() {
778
906
  });
779
907
  }
780
908
  //#endregion
781
- export { j as SiteDetailPage };
909
+ export { k as SiteDetailPage };
782
910
 
783
911
  //# sourceMappingURL=SiteDetailPage.js.map