@burdenoff/microfe-ecoimpacthub 2026.1030.1 → 2026.1030.3

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 (86) hide show
  1. package/dist/ecoimpacthub/EcoImpactHubRoutes.d.ts.map +1 -1
  2. package/dist/ecoimpacthub/EcoImpactHubRoutes.js +67 -43
  3. package/dist/ecoimpacthub/EcoImpactHubRoutes.js.map +1 -1
  4. package/dist/ecoimpacthub/components/EcoDiscussion.js +1 -1
  5. package/dist/ecoimpacthub/components/ai/AiAnomalyPanel.d.ts.map +1 -1
  6. package/dist/ecoimpacthub/components/ai/AiAnomalyPanel.js +92 -92
  7. package/dist/ecoimpacthub/components/ai/AiAnomalyPanel.js.map +1 -1
  8. package/dist/ecoimpacthub/components/ai/AiThresholdSuggest.d.ts.map +1 -1
  9. package/dist/ecoimpacthub/components/ai/AiThresholdSuggest.js +51 -51
  10. package/dist/ecoimpacthub/components/ai/AiThresholdSuggest.js.map +1 -1
  11. package/dist/ecoimpacthub/components/ai/AiTriageDialog.js +74 -74
  12. package/dist/ecoimpacthub/components/ai/AiTriageDialog.js.map +1 -1
  13. package/dist/ecoimpacthub/field/device.d.ts +26 -0
  14. package/dist/ecoimpacthub/field/device.d.ts.map +1 -0
  15. package/dist/ecoimpacthub/field/device.js +39 -0
  16. package/dist/ecoimpacthub/field/device.js.map +1 -0
  17. package/dist/ecoimpacthub/field/fieldSync.d.ts +22 -0
  18. package/dist/ecoimpacthub/field/fieldSync.d.ts.map +1 -0
  19. package/dist/ecoimpacthub/field/fieldSync.js +45 -0
  20. package/dist/ecoimpacthub/field/fieldSync.js.map +1 -0
  21. package/dist/ecoimpacthub/field/index.d.ts +8 -0
  22. package/dist/ecoimpacthub/field/index.d.ts.map +1 -0
  23. package/dist/ecoimpacthub/field/queueStore.d.ts +17 -0
  24. package/dist/ecoimpacthub/field/queueStore.d.ts.map +1 -0
  25. package/dist/ecoimpacthub/field/queueStore.js +102 -0
  26. package/dist/ecoimpacthub/field/queueStore.js.map +1 -0
  27. package/dist/ecoimpacthub/field/syncProcessor.d.ts +46 -0
  28. package/dist/ecoimpacthub/field/syncProcessor.d.ts.map +1 -0
  29. package/dist/ecoimpacthub/field/syncProcessor.js +89 -0
  30. package/dist/ecoimpacthub/field/syncProcessor.js.map +1 -0
  31. package/dist/ecoimpacthub/field/types.d.ts +72 -0
  32. package/dist/ecoimpacthub/field/types.d.ts.map +1 -0
  33. package/dist/ecoimpacthub/field/useFieldQueue.d.ts +47 -0
  34. package/dist/ecoimpacthub/field/useFieldQueue.d.ts.map +1 -0
  35. package/dist/ecoimpacthub/field/useFieldQueue.js +181 -0
  36. package/dist/ecoimpacthub/field/useFieldQueue.js.map +1 -0
  37. package/dist/ecoimpacthub/hooks/index.js +1 -1
  38. package/dist/ecoimpacthub/hooks/useEcoFiles.d.ts +12 -0
  39. package/dist/ecoimpacthub/hooks/useEcoFiles.d.ts.map +1 -1
  40. package/dist/ecoimpacthub/hooks/useEcoFiles.js +30 -23
  41. package/dist/ecoimpacthub/hooks/useEcoFiles.js.map +1 -1
  42. package/dist/ecoimpacthub/index.d.ts +1 -0
  43. package/dist/ecoimpacthub/index.d.ts.map +1 -1
  44. package/dist/ecoimpacthub/index.js +3 -1
  45. package/dist/ecoimpacthub/pages/DashboardPage.js +1 -1
  46. package/dist/ecoimpacthub/pages/_shared/EvidenceThumb.js +8 -8
  47. package/dist/ecoimpacthub/pages/carbon/DraftReviewPanel.js +78 -78
  48. package/dist/ecoimpacthub/pages/carbon/DraftReviewPanel.js.map +1 -1
  49. package/dist/ecoimpacthub/pages/carbon/DraftWithAiDialog.js +20 -20
  50. package/dist/ecoimpacthub/pages/carbon/SuggestFactorPanel.js +29 -29
  51. package/dist/ecoimpacthub/pages/carbonVisuals.js +1 -1
  52. package/dist/ecoimpacthub/pages/habitat/HabitatProjectDetailPage.js +1 -1
  53. package/dist/ecoimpacthub/pages/habitat/HabitatProjectsPage.js +1 -1
  54. package/dist/ecoimpacthub/pages/mobile/FieldQueuePanel.d.ts +11 -0
  55. package/dist/ecoimpacthub/pages/mobile/FieldQueuePanel.d.ts.map +1 -0
  56. package/dist/ecoimpacthub/pages/mobile/FieldQueuePanel.js +119 -0
  57. package/dist/ecoimpacthub/pages/mobile/FieldQueuePanel.js.map +1 -0
  58. package/dist/ecoimpacthub/pages/mobile/MobileDashboardPage.d.ts +12 -0
  59. package/dist/ecoimpacthub/pages/mobile/MobileDashboardPage.d.ts.map +1 -0
  60. package/dist/ecoimpacthub/pages/mobile/MobileDashboardPage.js +253 -0
  61. package/dist/ecoimpacthub/pages/mobile/MobileDashboardPage.js.map +1 -0
  62. package/dist/ecoimpacthub/pages/mobile/MobileRecordObservationPage.d.ts +13 -0
  63. package/dist/ecoimpacthub/pages/mobile/MobileRecordObservationPage.d.ts.map +1 -0
  64. package/dist/ecoimpacthub/pages/mobile/MobileRecordObservationPage.js +494 -0
  65. package/dist/ecoimpacthub/pages/mobile/MobileRecordObservationPage.js.map +1 -0
  66. package/dist/ecoimpacthub/pages/mobile/MobileShell.d.ts +10 -0
  67. package/dist/ecoimpacthub/pages/mobile/MobileShell.d.ts.map +1 -0
  68. package/dist/ecoimpacthub/pages/mobile/MobileShell.js +109 -0
  69. package/dist/ecoimpacthub/pages/mobile/MobileShell.js.map +1 -0
  70. package/dist/ecoimpacthub/pages/observations/ObservationsPage.d.ts.map +1 -1
  71. package/dist/ecoimpacthub/pages/observations/ObservationsPage.js +132 -126
  72. package/dist/ecoimpacthub/pages/observations/ObservationsPage.js.map +1 -1
  73. package/dist/ecoimpacthub/pages/reports/ReportDetailPage.js +1 -1
  74. package/dist/ecoimpacthub/pages/reports/ReportsPage.js +1 -1
  75. package/dist/ecoimpacthub/pages/sites/SiteDetailPage.js +1 -1
  76. package/dist/ecoimpacthub/pages/sites/SitesPage.js +1 -1
  77. package/dist/ecoimpacthub/pages/species/SpeciesDetailPage.js +9 -9
  78. package/dist/ecoimpacthub/pages/species/SpeciesPage.js +1 -1
  79. package/dist/ecoimpacthub/utils/aiMonitoring.d.ts +1 -0
  80. package/dist/ecoimpacthub/utils/aiMonitoring.d.ts.map +1 -1
  81. package/dist/ecoimpacthub/utils/aiMonitoring.js +5 -1
  82. package/dist/ecoimpacthub/utils/aiMonitoring.js.map +1 -1
  83. package/dist/ecoimpacthub/utils/graphqlErrors.js +8 -2
  84. package/dist/ecoimpacthub/utils/graphqlErrors.js.map +1 -1
  85. package/dist/index.js +8 -6
  86. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"EcoImpactHubRoutes.d.ts","sourceRoot":"","sources":["../../src/ecoimpacthub/EcoImpactHubRoutes.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,EAAE,EAAkC,MAAM,OAAO,CAAC;AAoEhE,eAAO,MAAM,kBAAkB,EAAE,EA+DhC,CAAC"}
1
+ {"version":3,"file":"EcoImpactHubRoutes.d.ts","sourceRoot":"","sources":["../../src/ecoimpacthub/EcoImpactHubRoutes.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,EAAE,EAA4C,MAAM,OAAO,CAAC;AAkH1E,eAAO,MAAM,kBAAkB,EAAE,EAyEhC,CAAC"}
@@ -1,88 +1,112 @@
1
1
  import { useEcoImpactHub as e } from "./context/EcoImpactHubContext.js";
2
2
  import { FeatureFlagGate as t } from "./components/FeatureFlagGate.js";
3
- import { DashboardPage as n } from "./pages/DashboardPage.js";
4
- import { Suspense as r, lazy as i } from "react";
5
- import { Navigate as a, Route as o, Routes as s, useLocation as c } from "react-router";
6
- import { jsx as l, jsxs as u } from "react/jsx-runtime";
7
- import { Spinner as d } from "@burdenoff/fe-libs/ui";
3
+ import { useFieldSyncBridge as n } from "./field/useFieldQueue.js";
4
+ import { DashboardPage as r } from "./pages/DashboardPage.js";
5
+ import { Suspense as i, lazy as a, useState as o } from "react";
6
+ import { Navigate as s, Route as c, Routes as l, useLocation as u } from "react-router";
7
+ import { jsx as d, jsxs as f } from "react/jsx-runtime";
8
+ import { Spinner as p } from "@burdenoff/fe-libs/ui";
8
9
  //#region src/ecoimpacthub/EcoImpactHubRoutes.tsx
9
- var f = i(() => import("./pages/sites/SitesPage.js").then((e) => ({ default: e.SitesPage }))), p = i(() => import("./pages/sites/SiteDetailPage.js").then((e) => ({ default: e.SiteDetailPage }))), m = i(() => import("./pages/monitoring/MonitoringPage.js").then((e) => ({ default: e.MonitoringPage }))), h = i(() => import("./pages/species/SpeciesPage.js").then((e) => ({ default: e.SpeciesPage }))), g = i(() => import("./pages/species/SpeciesDetailPage.js").then((e) => ({ default: e.SpeciesDetailPage }))), _ = i(() => import("./pages/observations/ObservationsPage.js").then((e) => ({ default: e.ObservationsPage }))), v = i(() => import("./pages/habitat/HabitatProjectsPage.js").then((e) => ({ default: e.HabitatProjectsPage }))), y = i(() => import("./pages/habitat/HabitatProjectDetailPage.js").then((e) => ({ default: e.HabitatProjectDetailPage }))), b = i(() => import("./pages/carbon/CarbonPage.js").then((e) => ({ default: e.CarbonPage }))), x = i(() => import("./pages/reports/ReportsPage.js").then((e) => ({ default: e.ReportsPage }))), S = i(() => import("./pages/reports/ReportDetailPage.js").then((e) => ({ default: e.ReportDetailPage }))), C = () => /* @__PURE__ */ l("div", {
10
+ var m = a(() => import("./pages/sites/SitesPage.js").then((e) => ({ default: e.SitesPage }))), h = a(() => import("./pages/sites/SiteDetailPage.js").then((e) => ({ default: e.SiteDetailPage }))), g = a(() => import("./pages/monitoring/MonitoringPage.js").then((e) => ({ default: e.MonitoringPage }))), _ = a(() => import("./pages/species/SpeciesPage.js").then((e) => ({ default: e.SpeciesPage }))), v = a(() => import("./pages/species/SpeciesDetailPage.js").then((e) => ({ default: e.SpeciesDetailPage }))), y = a(() => import("./pages/observations/ObservationsPage.js").then((e) => ({ default: e.ObservationsPage }))), b = a(() => import("./pages/habitat/HabitatProjectsPage.js").then((e) => ({ default: e.HabitatProjectsPage }))), x = a(() => import("./pages/habitat/HabitatProjectDetailPage.js").then((e) => ({ default: e.HabitatProjectDetailPage }))), S = a(() => import("./pages/carbon/CarbonPage.js").then((e) => ({ default: e.CarbonPage }))), C = a(() => import("./pages/reports/ReportsPage.js").then((e) => ({ default: e.ReportsPage }))), w = a(() => import("./pages/reports/ReportDetailPage.js").then((e) => ({ default: e.ReportDetailPage }))), T = a(() => import("./pages/mobile/MobileDashboardPage.js").then((e) => ({ default: e.MobileDashboardPage }))), E = a(() => import("./pages/mobile/MobileRecordObservationPage.js").then((e) => ({ default: e.MobileRecordObservationPage }))), D = () => (n(), null), O = "ecoimpacthub.field.nativeHomeShown";
11
+ function k() {
12
+ if (!globalThis.Capacitor?.isNativePlatform?.()) return !1;
13
+ try {
14
+ if (sessionStorage.getItem(O)) return !1;
15
+ sessionStorage.setItem(O, "1");
16
+ } catch {}
17
+ return !0;
18
+ }
19
+ var A = () => {
20
+ let [e] = o(k);
21
+ return e ? /* @__PURE__ */ d(s, {
22
+ to: "mobile",
23
+ replace: !0
24
+ }) : /* @__PURE__ */ d(r, {});
25
+ }, j = () => /* @__PURE__ */ d("div", {
10
26
  className: "flex min-h-[400px] items-center justify-center",
11
- children: /* @__PURE__ */ l(d, { size: "lg" })
27
+ children: /* @__PURE__ */ d(p, { size: "lg" })
12
28
  });
13
- function w(e, n) {
14
- return /* @__PURE__ */ l(t, {
29
+ function M(e, n) {
30
+ return /* @__PURE__ */ d(t, {
15
31
  flag: e,
16
32
  children: n
17
33
  });
18
34
  }
19
- var T = () => {
20
- let { basePath: t, isStandalone: i } = e(), d = c(), T = t === "/" ? "" : (t ?? "").replace(/\/$/, "");
21
- return T && !i && !(d.pathname === T || d.pathname.startsWith(T + "/")) ? null : /* @__PURE__ */ l("div", {
35
+ var N = () => {
36
+ let { basePath: t, isStandalone: n } = e(), r = u(), a = t === "/" ? "" : (t ?? "").replace(/\/$/, "");
37
+ return a && !n && !(r.pathname === a || r.pathname.startsWith(a + "/")) ? null : /* @__PURE__ */ f("div", {
22
38
  className: "flex min-h-full flex-col",
23
- children: /* @__PURE__ */ l(r, {
24
- fallback: /* @__PURE__ */ l(C, {}),
25
- children: /* @__PURE__ */ u(s, { children: [
26
- /* @__PURE__ */ l(o, {
39
+ children: [/* @__PURE__ */ d(D, {}), /* @__PURE__ */ d(i, {
40
+ fallback: /* @__PURE__ */ d(j, {}),
41
+ children: /* @__PURE__ */ f(l, { children: [
42
+ /* @__PURE__ */ d(c, {
27
43
  index: !0,
28
- element: w("ecoimpacthub.page.dashboard", /* @__PURE__ */ l(n, {}))
44
+ element: M("ecoimpacthub.page.dashboard", /* @__PURE__ */ d(A, {}))
29
45
  }),
30
- /* @__PURE__ */ l(o, {
46
+ /* @__PURE__ */ d(c, {
31
47
  path: "sites",
32
- element: w("ecoimpacthub.page.sites", /* @__PURE__ */ l(f, {}))
48
+ element: M("ecoimpacthub.page.sites", /* @__PURE__ */ d(m, {}))
33
49
  }),
34
- /* @__PURE__ */ l(o, {
50
+ /* @__PURE__ */ d(c, {
35
51
  path: "sites/:id",
36
- element: w("ecoimpacthub.page.sites", /* @__PURE__ */ l(p, {}))
52
+ element: M("ecoimpacthub.page.sites", /* @__PURE__ */ d(h, {}))
37
53
  }),
38
- /* @__PURE__ */ l(o, {
54
+ /* @__PURE__ */ d(c, {
39
55
  path: "monitoring",
40
- element: w("ecoimpacthub.page.monitoring", /* @__PURE__ */ l(m, {}))
56
+ element: M("ecoimpacthub.page.monitoring", /* @__PURE__ */ d(g, {}))
41
57
  }),
42
- /* @__PURE__ */ l(o, {
58
+ /* @__PURE__ */ d(c, {
43
59
  path: "species",
44
- element: w("ecoimpacthub.page.species", /* @__PURE__ */ l(h, {}))
60
+ element: M("ecoimpacthub.page.species", /* @__PURE__ */ d(_, {}))
45
61
  }),
46
- /* @__PURE__ */ l(o, {
62
+ /* @__PURE__ */ d(c, {
47
63
  path: "species/:id",
48
- element: w("ecoimpacthub.page.species", /* @__PURE__ */ l(g, {}))
64
+ element: M("ecoimpacthub.page.species", /* @__PURE__ */ d(v, {}))
49
65
  }),
50
- /* @__PURE__ */ l(o, {
66
+ /* @__PURE__ */ d(c, {
51
67
  path: "observations",
52
- element: w("ecoimpacthub.page.observations", /* @__PURE__ */ l(_, {}))
68
+ element: M("ecoimpacthub.page.observations", /* @__PURE__ */ d(y, {}))
53
69
  }),
54
- /* @__PURE__ */ l(o, {
70
+ /* @__PURE__ */ d(c, {
55
71
  path: "habitat",
56
- element: w("ecoimpacthub.page.habitat", /* @__PURE__ */ l(v, {}))
72
+ element: M("ecoimpacthub.page.habitat", /* @__PURE__ */ d(b, {}))
57
73
  }),
58
- /* @__PURE__ */ l(o, {
74
+ /* @__PURE__ */ d(c, {
59
75
  path: "habitat/:id",
60
- element: w("ecoimpacthub.page.habitat", /* @__PURE__ */ l(y, {}))
76
+ element: M("ecoimpacthub.page.habitat", /* @__PURE__ */ d(x, {}))
61
77
  }),
62
- /* @__PURE__ */ l(o, {
78
+ /* @__PURE__ */ d(c, {
63
79
  path: "carbon",
64
- element: w("ecoimpacthub.page.carbon", /* @__PURE__ */ l(b, {}))
80
+ element: M("ecoimpacthub.page.carbon", /* @__PURE__ */ d(S, {}))
65
81
  }),
66
- /* @__PURE__ */ l(o, {
82
+ /* @__PURE__ */ d(c, {
67
83
  path: "reports",
68
- element: w("ecoimpacthub.page.reports", /* @__PURE__ */ l(x, {}))
84
+ element: M("ecoimpacthub.page.reports", /* @__PURE__ */ d(C, {}))
69
85
  }),
70
- /* @__PURE__ */ l(o, {
86
+ /* @__PURE__ */ d(c, {
71
87
  path: "reports/:id",
72
- element: w("ecoimpacthub.page.reports", /* @__PURE__ */ l(S, {}))
88
+ element: M("ecoimpacthub.page.reports", /* @__PURE__ */ d(w, {}))
89
+ }),
90
+ /* @__PURE__ */ d(c, {
91
+ path: "mobile",
92
+ element: M("ecoimpacthub.page.mobile", /* @__PURE__ */ d(T, {}))
93
+ }),
94
+ /* @__PURE__ */ d(c, {
95
+ path: "mobile/record-observation",
96
+ element: M("ecoimpacthub.page.observations", /* @__PURE__ */ d(E, {}))
73
97
  }),
74
- /* @__PURE__ */ l(o, {
98
+ /* @__PURE__ */ d(c, {
75
99
  path: "*",
76
- element: /* @__PURE__ */ l(a, {
100
+ element: /* @__PURE__ */ d(s, {
77
101
  to: "",
78
102
  replace: !0
79
103
  })
80
104
  })
81
105
  ] })
82
- })
106
+ })]
83
107
  });
84
108
  };
85
109
  //#endregion
86
- export { T as EcoImpactHubRoutes };
110
+ export { N as EcoImpactHubRoutes };
87
111
 
88
112
  //# sourceMappingURL=EcoImpactHubRoutes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"EcoImpactHubRoutes.js","names":[],"sources":["../../src/ecoimpacthub/EcoImpactHubRoutes.tsx"],"sourcesContent":["/**\n * EcoImpactHub Routes\n * @module ecoimpacthub\n *\n * Domain routes. The dashboard is eager-loaded (primary landing); all other\n * pages are lazy-loaded. Every route maps to a real `eco*` backend capability.\n */\n\nimport { type FC, lazy, Suspense, type ReactNode } from 'react';\nimport { Routes, Route, Navigate, useLocation } from 'react-router';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { useEcoImpactHub } from './context/EcoImpactHubContext';\nimport { FeatureFlagGate } from './components/FeatureFlagGate';\n\n// Eager — primary landing\nimport { DashboardPage } from './pages/DashboardPage';\n\n// Sites (Environmental Monitoring)\nconst SitesPage = lazy(() =>\n import('./pages/sites/SitesPage').then((m) => ({ default: m.SitesPage }))\n);\nconst SiteDetailPage = lazy(() =>\n import('./pages/sites/SiteDetailPage').then((m) => ({ default: m.SiteDetailPage }))\n);\n\n// Monitoring (sensors / measurements / thresholds)\nconst MonitoringPage = lazy(() =>\n import('./pages/monitoring/MonitoringPage').then((m) => ({ default: m.MonitoringPage }))\n);\n\n// Species (Conservation)\nconst SpeciesPage = lazy(() =>\n import('./pages/species/SpeciesPage').then((m) => ({ default: m.SpeciesPage }))\n);\nconst SpeciesDetailPage = lazy(() =>\n import('./pages/species/SpeciesDetailPage').then((m) => ({ default: m.SpeciesDetailPage }))\n);\n\n// Observations (citizen science / field data)\nconst ObservationsPage = lazy(() =>\n import('./pages/observations/ObservationsPage').then((m) => ({ default: m.ObservationsPage }))\n);\n\n// Habitat projects & restoration\nconst HabitatProjectsPage = lazy(() =>\n import('./pages/habitat/HabitatProjectsPage').then((m) => ({ default: m.HabitatProjectsPage }))\n);\nconst HabitatProjectDetailPage = lazy(() =>\n import('./pages/habitat/HabitatProjectDetailPage').then((m) => ({\n default: m.HabitatProjectDetailPage,\n }))\n);\n\n// Carbon ledger / emission factors / reduction targets (Sustainability)\nconst CarbonPage = lazy(() =>\n import('./pages/carbon/CarbonPage').then((m) => ({ default: m.CarbonPage }))\n);\n\n// ESG Reports\nconst ReportsPage = lazy(() =>\n import('./pages/reports/ReportsPage').then((m) => ({ default: m.ReportsPage }))\n);\nconst ReportDetailPage = lazy(() =>\n import('./pages/reports/ReportDetailPage').then((m) => ({ default: m.ReportDetailPage }))\n);\n\nconst PageLoader: FC = () => (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n);\n\nfunction gated(flag: string, element: ReactNode): ReactNode {\n return <FeatureFlagGate flag={flag}>{element}</FeatureFlagGate>;\n}\n\nexport const EcoImpactHubRoutes: FC = () => {\n const { basePath, isStandalone } = useEcoImpactHub();\n const location = useLocation();\n\n const normalizedBasePath = basePath === '/' ? '' : (basePath ?? '').replace(/\\/$/, '');\n\n // Guard: only render if the current path matches basePath (integrated mode).\n if (normalizedBasePath && !isStandalone) {\n const pathMatches =\n location.pathname === normalizedBasePath ||\n location.pathname.startsWith(normalizedBasePath + '/');\n if (!pathMatches) {\n return null;\n }\n }\n\n return (\n <div className=\"flex min-h-full flex-col\">\n <Suspense fallback={<PageLoader />}>\n <Routes>\n <Route index element={gated('ecoimpacthub.page.dashboard', <DashboardPage />)} />\n\n <Route path=\"sites\" element={gated('ecoimpacthub.page.sites', <SitesPage />)} />\n <Route path=\"sites/:id\" element={gated('ecoimpacthub.page.sites', <SiteDetailPage />)} />\n\n <Route\n path=\"monitoring\"\n element={gated('ecoimpacthub.page.monitoring', <MonitoringPage />)}\n />\n\n <Route path=\"species\" element={gated('ecoimpacthub.page.species', <SpeciesPage />)} />\n <Route\n path=\"species/:id\"\n element={gated('ecoimpacthub.page.species', <SpeciesDetailPage />)}\n />\n\n <Route\n path=\"observations\"\n element={gated('ecoimpacthub.page.observations', <ObservationsPage />)}\n />\n\n <Route\n path=\"habitat\"\n element={gated('ecoimpacthub.page.habitat', <HabitatProjectsPage />)}\n />\n <Route\n path=\"habitat/:id\"\n element={gated('ecoimpacthub.page.habitat', <HabitatProjectDetailPage />)}\n />\n\n <Route path=\"carbon\" element={gated('ecoimpacthub.page.carbon', <CarbonPage />)} />\n\n <Route path=\"reports\" element={gated('ecoimpacthub.page.reports', <ReportsPage />)} />\n <Route\n path=\"reports/:id\"\n element={gated('ecoimpacthub.page.reports', <ReportDetailPage />)}\n />\n\n <Route path=\"*\" element={<Navigate to=\"\" replace />} />\n </Routes>\n </Suspense>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"EcoImpactHubRoutes.js","names":[],"sources":["../../src/ecoimpacthub/EcoImpactHubRoutes.tsx"],"sourcesContent":["/**\n * EcoImpactHub Routes\n * @module ecoimpacthub\n *\n * Domain routes. The dashboard is eager-loaded (primary landing); all other\n * pages are lazy-loaded. Every route maps to a real `eco*` backend capability.\n */\n\nimport { type FC, lazy, Suspense, type ReactNode, useState } from 'react';\nimport { Routes, Route, Navigate, useLocation } from 'react-router';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { useEcoImpactHub } from './context/EcoImpactHubContext';\nimport { FeatureFlagGate } from './components/FeatureFlagGate';\nimport { useFieldSyncBridge } from './field/useFieldQueue';\n\n// Eager — primary landing\nimport { DashboardPage } from './pages/DashboardPage';\n\n// Sites (Environmental Monitoring)\nconst SitesPage = lazy(() =>\n import('./pages/sites/SitesPage').then((m) => ({ default: m.SitesPage }))\n);\nconst SiteDetailPage = lazy(() =>\n import('./pages/sites/SiteDetailPage').then((m) => ({ default: m.SiteDetailPage }))\n);\n\n// Monitoring (sensors / measurements / thresholds)\nconst MonitoringPage = lazy(() =>\n import('./pages/monitoring/MonitoringPage').then((m) => ({ default: m.MonitoringPage }))\n);\n\n// Species (Conservation)\nconst SpeciesPage = lazy(() =>\n import('./pages/species/SpeciesPage').then((m) => ({ default: m.SpeciesPage }))\n);\nconst SpeciesDetailPage = lazy(() =>\n import('./pages/species/SpeciesDetailPage').then((m) => ({ default: m.SpeciesDetailPage }))\n);\n\n// Observations (citizen science / field data)\nconst ObservationsPage = lazy(() =>\n import('./pages/observations/ObservationsPage').then((m) => ({ default: m.ObservationsPage }))\n);\n\n// Habitat projects & restoration\nconst HabitatProjectsPage = lazy(() =>\n import('./pages/habitat/HabitatProjectsPage').then((m) => ({ default: m.HabitatProjectsPage }))\n);\nconst HabitatProjectDetailPage = lazy(() =>\n import('./pages/habitat/HabitatProjectDetailPage').then((m) => ({\n default: m.HabitatProjectDetailPage,\n }))\n);\n\n// Carbon ledger / emission factors / reduction targets (Sustainability)\nconst CarbonPage = lazy(() =>\n import('./pages/carbon/CarbonPage').then((m) => ({ default: m.CarbonPage }))\n);\n\n// ESG Reports\nconst ReportsPage = lazy(() =>\n import('./pages/reports/ReportsPage').then((m) => ({ default: m.ReportsPage }))\n);\nconst ReportDetailPage = lazy(() =>\n import('./pages/reports/ReportDetailPage').then((m) => ({ default: m.ReportDetailPage }))\n);\n\n// Mobile field app (Capacitor iOS/Android home + offline field capture)\nconst MobileDashboardPage = lazy(() =>\n import('./pages/mobile/MobileDashboardPage').then((m) => ({ default: m.MobileDashboardPage }))\n);\nconst MobileRecordObservationPage = lazy(() =>\n import('./pages/mobile/MobileRecordObservationPage').then((m) => ({\n default: m.MobileRecordObservationPage,\n }))\n);\n\n/**\n * Drains the offline field-observation queue for the active workspace while\n * the MFE is mounted, whichever page is showing (see `field/fieldSync.ts`).\n */\nconst FieldSyncBridge: FC = () => {\n useFieldSyncBridge();\n return null;\n};\n\nconst NATIVE_HOME_KEY = 'ecoimpacthub.field.nativeHomeShown';\n\n/**\n * Inside the installed iOS/Android app the first screen of each launch is the\n * field app's mobile dashboard; after that the regular dashboard stays one tap\n * away (sidebar \"Dashboard\"). Capacitor injects `window.Capacitor`, so the MFE\n * needs no Capacitor dependency to detect it.\n */\nfunction shouldOpenNativeHome(): boolean {\n const cap = (globalThis as { Capacitor?: { isNativePlatform?: () => boolean } }).Capacitor;\n if (!cap?.isNativePlatform?.()) return false;\n try {\n if (sessionStorage.getItem(NATIVE_HOME_KEY)) return false;\n sessionStorage.setItem(NATIVE_HOME_KEY, '1');\n } catch {\n // Storage unavailable: still open the field home this time.\n }\n return true;\n}\n\nconst DashboardIndex: FC = () => {\n const [openNativeHome] = useState(shouldOpenNativeHome);\n if (openNativeHome) return <Navigate to=\"mobile\" replace />;\n return <DashboardPage />;\n};\n\nconst PageLoader: FC = () => (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n);\n\nfunction gated(flag: string, element: ReactNode): ReactNode {\n return <FeatureFlagGate flag={flag}>{element}</FeatureFlagGate>;\n}\n\nexport const EcoImpactHubRoutes: FC = () => {\n const { basePath, isStandalone } = useEcoImpactHub();\n const location = useLocation();\n\n const normalizedBasePath = basePath === '/' ? '' : (basePath ?? '').replace(/\\/$/, '');\n\n // Guard: only render if the current path matches basePath (integrated mode).\n if (normalizedBasePath && !isStandalone) {\n const pathMatches =\n location.pathname === normalizedBasePath ||\n location.pathname.startsWith(normalizedBasePath + '/');\n if (!pathMatches) {\n return null;\n }\n }\n\n return (\n <div className=\"flex min-h-full flex-col\">\n <FieldSyncBridge />\n <Suspense fallback={<PageLoader />}>\n <Routes>\n <Route index element={gated('ecoimpacthub.page.dashboard', <DashboardIndex />)} />\n\n <Route path=\"sites\" element={gated('ecoimpacthub.page.sites', <SitesPage />)} />\n <Route path=\"sites/:id\" element={gated('ecoimpacthub.page.sites', <SiteDetailPage />)} />\n\n <Route\n path=\"monitoring\"\n element={gated('ecoimpacthub.page.monitoring', <MonitoringPage />)}\n />\n\n <Route path=\"species\" element={gated('ecoimpacthub.page.species', <SpeciesPage />)} />\n <Route\n path=\"species/:id\"\n element={gated('ecoimpacthub.page.species', <SpeciesDetailPage />)}\n />\n\n <Route\n path=\"observations\"\n element={gated('ecoimpacthub.page.observations', <ObservationsPage />)}\n />\n\n <Route\n path=\"habitat\"\n element={gated('ecoimpacthub.page.habitat', <HabitatProjectsPage />)}\n />\n <Route\n path=\"habitat/:id\"\n element={gated('ecoimpacthub.page.habitat', <HabitatProjectDetailPage />)}\n />\n\n <Route path=\"carbon\" element={gated('ecoimpacthub.page.carbon', <CarbonPage />)} />\n\n <Route path=\"reports\" element={gated('ecoimpacthub.page.reports', <ReportsPage />)} />\n <Route\n path=\"reports/:id\"\n element={gated('ecoimpacthub.page.reports', <ReportDetailPage />)}\n />\n\n <Route\n path=\"mobile\"\n element={gated('ecoimpacthub.page.mobile', <MobileDashboardPage />)}\n />\n <Route\n path=\"mobile/record-observation\"\n element={gated('ecoimpacthub.page.observations', <MobileRecordObservationPage />)}\n />\n\n <Route path=\"*\" element={<Navigate to=\"\" replace />} />\n </Routes>\n </Suspense>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { useEcoImpactHub as e } from "../context/EcoImpactHubContext.js";
2
+ import "../context/index.js";
2
3
  import { formatDateTime as t } from "../utils/formatters.js";
3
4
  import { ErrorView as n, LoadingView as r, Section as i } from "./StateViews.js";
4
5
  import { EmptyState as a } from "./EmptyState.js";
5
- import "../context/index.js";
6
6
  import { useEcoComments as o, useEcoCreateComment as s } from "../hooks/useEcoComments.js";
7
7
  import "../hooks/index.js";
8
8
  import { useState as c } from "react";
@@ -1 +1 @@
1
- {"version":3,"file":"AiAnomalyPanel.d.ts","sourceRoot":"","sources":["../../../../src/ecoimpacthub/components/ai/AiAnomalyPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAqB,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAyBnD,OAAO,KAAK,EAA6B,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxE,UAAU,mBAAmB;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,EAAE,CAAC;CACvB;AAeD,eAAO,MAAM,cAAc,EAAE,EAAE,CAAC,mBAAmB,CAsPlD,CAAC"}
1
+ {"version":3,"file":"AiAnomalyPanel.d.ts","sourceRoot":"","sources":["../../../../src/ecoimpacthub/components/ai/AiAnomalyPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAqB,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AA0BnD,OAAO,KAAK,EAA6B,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxE,UAAU,mBAAmB;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,EAAE,CAAC;CACvB;AAeD,eAAO,MAAM,cAAc,EAAE,EAAE,CAAC,mBAAmB,CAuPlD,CAAC"}
@@ -2,153 +2,153 @@ import { formatDateTime as e, formatNumber as t } from "../../utils/formatters.j
2
2
  import { StatusBadge as n } from "../StatusBadge.js";
3
3
  import { useEcoMeasurements as r } from "../../hooks/useEcoImpactHubApi.js";
4
4
  import { useTr as i } from "../../hooks/useTr.js";
5
- import { ANOMALY_PERIOD_PRESETS as a, groupAnomalies as o, periodRange as s, resolveCitedReadings as c } from "../../utils/aiMonitoring.js";
6
- import { useEcoAiDetectAnomalies as l, useEcoAiErrorReporter as u } from "../../hooks/useEcoAiMonitoring.js";
5
+ import { ANOMALY_PERIOD_PRESETS as a, groupAnomalies as o, periodRange as s, resolveCitedReadings as c, userFacingAiNotes as l } from "../../utils/aiMonitoring.js";
6
+ import { useEcoAiDetectAnomalies as u, useEcoAiErrorReporter as d } from "../../hooks/useEcoAiMonitoring.js";
7
7
  import "../../hooks/index.js";
8
- import { AiCreditHint as d, AiErrorNotice as f, CitedReadingsList as p } from "./AiShared.js";
9
- import { useMemo as m, useState as h } from "react";
10
- import { Activity as g, ScanSearch as _ } from "lucide-react";
11
- import { Fragment as v, jsx as y, jsxs as b } from "react/jsx-runtime";
12
- import { Button as x, GlassCard as S, Label as C, Select as w, SelectContent as T, SelectItem as E, SelectTrigger as D, SelectValue as O } from "@burdenoff/fe-libs/ui";
8
+ import { AiCreditHint as f, AiErrorNotice as p, CitedReadingsList as m } from "./AiShared.js";
9
+ import { useMemo as h, useState as g } from "react";
10
+ import { Activity as _, ScanSearch as v } from "lucide-react";
11
+ import { Fragment as y, jsx as b, jsxs as x } from "react/jsx-runtime";
12
+ import { Button as S, GlassCard as C, Label as w, Select as T, SelectContent as E, SelectItem as D, SelectTrigger as O, SelectValue as k } from "@burdenoff/fe-libs/ui";
13
13
  //#region src/ecoimpacthub/components/ai/AiAnomalyPanel.tsx
14
- var k = {
14
+ var A = {
15
15
  "7d": ["ecoAi.anomalies.period7d", "Last 7 days"],
16
16
  "30d": ["ecoAi.anomalies.period30d", "Last 30 days"],
17
17
  "90d": ["ecoAi.anomalies.period90d", "Last 90 days"],
18
18
  "365d": ["ecoAi.anomalies.period365d", "Last 12 months"]
19
- }, A = {
19
+ }, j = {
20
20
  SPIKE: ["ecoAi.anomalies.kindSpike", "Spikes"],
21
21
  DROP: ["ecoAi.anomalies.kindDrop", "Drops"],
22
22
  FLATLINE: ["ecoAi.anomalies.kindFlatline", "Flatlines"]
23
- }, j = ({ siteId: j, parameters: M, sensors: N = [] }) => {
24
- let P = i(), [F, I] = h(""), [L, R] = h("30d"), z = F || M[0] || "", B = l(), V = u(), [H, U] = h(null), [W, G] = h(null), [K, q] = h(null), J = r({
25
- siteId: j,
26
- parameter: H?.parameter ?? z,
23
+ }, M = ({ siteId: M, parameters: N, sensors: P = [] }) => {
24
+ let F = i(), [I, L] = g(""), [R, z] = g("30d"), B = I || N[0] || "", V = u(), H = d(), [U, W] = g(null), [G, K] = g(null), [q, J] = g(null), Y = r({
25
+ siteId: M,
26
+ parameter: U?.parameter ?? B,
27
27
  pagination: {
28
28
  limit: 100,
29
29
  offset: 0
30
30
  }
31
- }), Y = m(() => J.data?.items ?? [], [J.data]), X = m(() => H ? o(H.anomalies) : [], [H]), Z = (e) => e && N.find((t) => t.id === e)?.name || null;
32
- return /* @__PURE__ */ y("div", {
31
+ }), X = h(() => Y.data?.items ?? [], [Y.data]), Z = h(() => U ? o(U.anomalies) : [], [U]), Q = h(() => l(U?.notes), [U]), $ = (e) => e && P.find((t) => t.id === e)?.name || null;
32
+ return /* @__PURE__ */ b("div", {
33
33
  "data-testid": "eco-ai-anomalies",
34
- children: /* @__PURE__ */ b(S, {
34
+ children: /* @__PURE__ */ x(C, {
35
35
  treatment: "plain",
36
36
  className: "p-5",
37
37
  children: [
38
- M.length === 0 ? /* @__PURE__ */ y("p", {
38
+ N.length === 0 ? /* @__PURE__ */ b("p", {
39
39
  className: "text-sm text-text-secondary",
40
- children: P("ecoAi.anomalies.noParameters", "Record measurements at this site to analyse them for anomalies.")
41
- }) : /* @__PURE__ */ b(v, { children: [/* @__PURE__ */ b("div", {
40
+ children: F("ecoAi.anomalies.noParameters", "Record measurements at this site to analyse them for anomalies.")
41
+ }) : /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ x("div", {
42
42
  className: "flex flex-wrap items-end gap-3",
43
43
  children: [
44
- /* @__PURE__ */ b("div", {
44
+ /* @__PURE__ */ x("div", {
45
45
  className: "grid gap-1.5",
46
- children: [/* @__PURE__ */ y(C, {
46
+ children: [/* @__PURE__ */ b(w, {
47
47
  htmlFor: "ecoAiAnomalyParam",
48
- children: P("ecoAi.anomalies.parameter", "Parameter")
49
- }), /* @__PURE__ */ b(w, {
50
- value: z,
48
+ children: F("ecoAi.anomalies.parameter", "Parameter")
49
+ }), /* @__PURE__ */ x(T, {
50
+ value: B,
51
51
  onValueChange: (e) => {
52
- I(e), U(null), G(null);
52
+ L(e), W(null), K(null);
53
53
  },
54
- children: [/* @__PURE__ */ y(D, {
54
+ children: [/* @__PURE__ */ b(O, {
55
55
  id: "ecoAiAnomalyParam",
56
56
  className: "w-48",
57
- children: /* @__PURE__ */ y(O, {})
58
- }), /* @__PURE__ */ y(T, { children: M.map((e) => /* @__PURE__ */ y(E, {
57
+ children: /* @__PURE__ */ b(k, {})
58
+ }), /* @__PURE__ */ b(E, { children: N.map((e) => /* @__PURE__ */ b(D, {
59
59
  value: e,
60
60
  children: e
61
61
  }, e)) })]
62
62
  })]
63
63
  }),
64
- /* @__PURE__ */ b("div", {
64
+ /* @__PURE__ */ x("div", {
65
65
  className: "grid gap-1.5",
66
- children: [/* @__PURE__ */ y(C, {
66
+ children: [/* @__PURE__ */ b(w, {
67
67
  htmlFor: "ecoAiAnomalyPeriod",
68
- children: P("ecoAi.anomalies.period", "Period")
69
- }), /* @__PURE__ */ b(w, {
70
- value: L,
68
+ children: F("ecoAi.anomalies.period", "Period")
69
+ }), /* @__PURE__ */ x(T, {
70
+ value: R,
71
71
  onValueChange: (e) => {
72
- R(e), U(null), G(null);
72
+ z(e), W(null), K(null);
73
73
  },
74
- children: [/* @__PURE__ */ y(D, {
74
+ children: [/* @__PURE__ */ b(O, {
75
75
  id: "ecoAiAnomalyPeriod",
76
76
  className: "w-44",
77
- children: /* @__PURE__ */ y(O, {})
78
- }), /* @__PURE__ */ y(T, { children: a.map((e) => /* @__PURE__ */ y(E, {
77
+ children: /* @__PURE__ */ b(k, {})
78
+ }), /* @__PURE__ */ b(E, { children: a.map((e) => /* @__PURE__ */ b(D, {
79
79
  value: e,
80
- children: P(k[e][0], k[e][1])
80
+ children: F(A[e][0], A[e][1])
81
81
  }, e)) })]
82
82
  })]
83
83
  }),
84
- /* @__PURE__ */ b(x, {
84
+ /* @__PURE__ */ x(S, {
85
85
  onClick: async () => {
86
- if (z) {
87
- G(null), q(null);
86
+ if (B) {
87
+ K(null), J(null);
88
88
  try {
89
- U(await B.mutateAsync({
90
- siteId: j,
91
- parameter: z,
92
- ...s(L)
89
+ W(await V.mutateAsync({
90
+ siteId: M,
91
+ parameter: B,
92
+ ...s(R)
93
93
  }));
94
94
  } catch (e) {
95
- U(null), G(V(e, "EcoAiDetectAnomalies", P("ecoAi.anomalies.failed", "Anomaly detection failed.")));
95
+ W(null), K(H(e, "EcoAiDetectAnomalies", F("ecoAi.anomalies.failed", "Anomaly detection failed.")));
96
96
  }
97
97
  }
98
98
  },
99
- disabled: !z || B.isPending,
99
+ disabled: !B || V.isPending,
100
100
  "data-testid": "eco-ai-anomalies-run",
101
- children: [/* @__PURE__ */ y(_, { className: "mr-1.5 h-4 w-4" }), B.isPending ? P("ecoAi.anomalies.running", "Analysing…") : P("ecoAi.anomalies.run", "Detect anomalies")]
101
+ children: [/* @__PURE__ */ b(v, { className: "mr-1.5 h-4 w-4" }), V.isPending ? F("ecoAi.anomalies.running", "Analysing…") : F("ecoAi.anomalies.run", "Detect anomalies")]
102
102
  })
103
103
  ]
104
- }), /* @__PURE__ */ y(d, { className: "mt-2" })] }),
105
- W && /* @__PURE__ */ y(f, {
106
- error: W,
104
+ }), /* @__PURE__ */ b(f, { className: "mt-2" })] }),
105
+ G && /* @__PURE__ */ b(p, {
106
+ error: G,
107
107
  className: "mt-4"
108
108
  }),
109
- H && H.status === "INSUFFICIENT_DATA" && /* @__PURE__ */ b("div", {
109
+ U && U.status === "INSUFFICIENT_DATA" && /* @__PURE__ */ x("div", {
110
110
  className: "mt-4 rounded-lg bg-bg-sunken/60 p-4",
111
111
  "data-testid": "eco-ai-anomalies-insufficient",
112
112
  children: [
113
- /* @__PURE__ */ y("p", {
113
+ /* @__PURE__ */ b("p", {
114
114
  className: "text-sm font-semibold text-text-primary",
115
- children: P("ecoAi.anomalies.notEnoughData", "Not enough data")
115
+ children: F("ecoAi.anomalies.notEnoughData", "Not enough data")
116
116
  }),
117
- /* @__PURE__ */ y("p", {
117
+ /* @__PURE__ */ b("p", {
118
118
  className: "mt-1 text-sm text-text-secondary",
119
- children: P("ecoAi.anomalies.notEnoughDataBody", "Only {{count}} reading(s) of {{parameter}} in this period, too few to judge what is normal. No trend is shown.", {
120
- count: H.readingsAnalysed,
121
- parameter: H.parameter
119
+ children: F("ecoAi.anomalies.notEnoughDataBody", "Only {{count}} reading(s) of {{parameter}} in this period, too few to judge what is normal. No trend is shown.", {
120
+ count: U.readingsAnalysed,
121
+ parameter: U.parameter
122
122
  })
123
123
  }),
124
- H.notes.length > 0 && /* @__PURE__ */ y("ul", {
124
+ Q.length > 0 && /* @__PURE__ */ b("ul", {
125
125
  className: "mt-2 list-disc space-y-0.5 pl-5 text-xs text-text-tertiary",
126
- children: H.notes.map((e, t) => /* @__PURE__ */ y("li", { children: e }, `${t}:${e}`))
126
+ children: Q.map((e, t) => /* @__PURE__ */ b("li", { children: e }, `${t}:${e}`))
127
127
  })
128
128
  ]
129
129
  }),
130
- H && H.status === "OK" && /* @__PURE__ */ b("div", {
130
+ U && U.status === "OK" && /* @__PURE__ */ x("div", {
131
131
  className: "mt-4 grid gap-4",
132
132
  "data-testid": "eco-ai-anomalies-result",
133
133
  children: [
134
- /* @__PURE__ */ b("p", {
134
+ /* @__PURE__ */ x("p", {
135
135
  className: "text-xs text-text-tertiary",
136
- children: [P("ecoAi.anomalies.summary", "{{count}} reading(s) analysed · baseline median {{median}} {{unit}}", {
137
- count: H.readingsAnalysed,
138
- median: t(H.baseline?.median ?? null),
139
- unit: H.unit ?? ""
140
- }), H.truncated && ` · ${P("ecoAi.anomalies.truncated", "the series was truncated to the most recent readings")}`]
136
+ children: [F("ecoAi.anomalies.summary", "{{count}} reading(s) analysed · baseline median {{median}} {{unit}}", {
137
+ count: U.readingsAnalysed,
138
+ median: t(U.baseline?.median ?? null),
139
+ unit: U.unit ?? ""
140
+ }), U.truncated && ` · ${F("ecoAi.anomalies.truncated", "the series was truncated to the most recent readings")}`]
141
141
  }),
142
- X.length === 0 ? /* @__PURE__ */ b("p", {
142
+ Z.length === 0 ? /* @__PURE__ */ x("p", {
143
143
  className: "flex items-center gap-2 text-sm text-text-secondary",
144
144
  "data-testid": "eco-ai-anomalies-none",
145
- children: [/* @__PURE__ */ y(g, { className: "h-4 w-4 text-status-success-text" }), P("ecoAi.anomalies.none", "No spikes, drops or flatlines in this period.")]
146
- }) : X.map((r) => /* @__PURE__ */ b("div", { children: [/* @__PURE__ */ b("h3", {
145
+ children: [/* @__PURE__ */ b(_, { className: "h-4 w-4 text-status-success-text" }), F("ecoAi.anomalies.none", "No spikes, drops or flatlines in this period.")]
146
+ }) : Z.map((r) => /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ x("h3", {
147
147
  className: "mb-2 flex items-center gap-2 text-sm font-semibold text-text-primary",
148
148
  children: [
149
- /* @__PURE__ */ y(n, { status: r.kind }),
150
- P(A[r.kind]?.[0] ?? r.kind, A[r.kind]?.[1] ?? r.kind),
151
- /* @__PURE__ */ b("span", {
149
+ /* @__PURE__ */ b(n, { status: r.kind }),
150
+ F(j[r.kind]?.[0] ?? r.kind, j[r.kind]?.[1] ?? r.kind),
151
+ /* @__PURE__ */ x("span", {
152
152
  className: "text-text-tertiary",
153
153
  children: [
154
154
  "(",
@@ -157,49 +157,49 @@ var k = {
157
157
  ]
158
158
  })
159
159
  ]
160
- }), /* @__PURE__ */ y("ul", {
160
+ }), /* @__PURE__ */ b("ul", {
161
161
  className: "divide-y divide-border-seam/60 rounded-lg border border-border-seam",
162
162
  children: r.items.map((n) => {
163
- let r = K === n.measurementId;
164
- return /* @__PURE__ */ b("li", {
163
+ let r = q === n.measurementId;
164
+ return /* @__PURE__ */ x("li", {
165
165
  "data-testid": "eco-ai-anomaly",
166
- children: [/* @__PURE__ */ b("button", {
166
+ children: [/* @__PURE__ */ x("button", {
167
167
  type: "button",
168
168
  className: "flex w-full items-center justify-between gap-3 px-3 py-2 text-left text-sm hover:bg-bg-sunken/60",
169
169
  "aria-expanded": r,
170
- onClick: () => q(r ? null : n.measurementId),
171
- children: [/* @__PURE__ */ b("span", {
170
+ onClick: () => J(r ? null : n.measurementId),
171
+ children: [/* @__PURE__ */ x("span", {
172
172
  className: "tabular-nums text-text-primary",
173
173
  children: [
174
174
  t(n.value),
175
175
  " ",
176
- H.unit ?? "",
177
- Z(n.sensorId) && /* @__PURE__ */ y("span", {
176
+ U.unit ?? "",
177
+ $(n.sensorId) && /* @__PURE__ */ b("span", {
178
178
  className: "ml-2 text-xs text-text-tertiary",
179
- children: Z(n.sensorId)
179
+ children: $(n.sensorId)
180
180
  })
181
181
  ]
182
- }), /* @__PURE__ */ b("span", {
182
+ }), /* @__PURE__ */ x("span", {
183
183
  className: "flex items-center gap-3 text-xs text-text-tertiary",
184
184
  children: [
185
- /* @__PURE__ */ y("span", { children: n.kind === "FLATLINE" ? P("ecoAi.anomalies.runLength", "run of {{n}}", { n: t(n.score, { maximumFractionDigits: 1 }) }) : P("ecoAi.anomalies.score", "z {{z}}", { z: t(n.score, { maximumFractionDigits: 1 }) }) }),
186
- /* @__PURE__ */ y("span", { children: e(n.recordedAt) }),
187
- /* @__PURE__ */ y("span", { children: P("ecoAi.anomalies.citedCount", "{{n}} cited", { n: n.evidenceMeasurementIds.length }) })
185
+ /* @__PURE__ */ b("span", { children: n.kind === "FLATLINE" ? F("ecoAi.anomalies.runLength", "run of {{n}}", { n: t(n.score, { maximumFractionDigits: 1 }) }) : F("ecoAi.anomalies.score", "z {{z}}", { z: t(n.score, { maximumFractionDigits: 1 }) }) }),
186
+ /* @__PURE__ */ b("span", { children: e(n.recordedAt) }),
187
+ /* @__PURE__ */ b("span", { children: F("ecoAi.anomalies.citedCount", "{{n}} cited", { n: n.evidenceMeasurementIds.length }) })
188
188
  ]
189
189
  })]
190
- }), r && /* @__PURE__ */ y("div", {
190
+ }), r && /* @__PURE__ */ b("div", {
191
191
  className: "px-3 pb-3",
192
- children: /* @__PURE__ */ y(p, {
193
- readings: c(n.evidenceMeasurementIds, Y),
192
+ children: /* @__PURE__ */ b(m, {
193
+ readings: c(n.evidenceMeasurementIds, X),
194
194
  focusId: n.measurementId
195
195
  })
196
196
  })]
197
197
  }, n.measurementId);
198
198
  })
199
199
  })] }, r.kind)),
200
- H.notes.length > 0 && /* @__PURE__ */ y("ul", {
200
+ Q.length > 0 && /* @__PURE__ */ b("ul", {
201
201
  className: "list-disc space-y-0.5 pl-5 text-xs text-text-tertiary",
202
- children: H.notes.map((e, t) => /* @__PURE__ */ y("li", { children: e }, `${t}:${e}`))
202
+ children: Q.map((e, t) => /* @__PURE__ */ b("li", { children: e }, `${t}:${e}`))
203
203
  })
204
204
  ]
205
205
  })
@@ -208,6 +208,6 @@ var k = {
208
208
  });
209
209
  };
210
210
  //#endregion
211
- export { j as AiAnomalyPanel };
211
+ export { M as AiAnomalyPanel };
212
212
 
213
213
  //# sourceMappingURL=AiAnomalyPanel.js.map