@burdenoff/microfe-ecoimpacthub 2026.720.5 → 2026.720.6

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 (29) hide show
  1. package/dist/ecoimpacthub/EcoImpactHubAdminRoot.d.ts +10 -0
  2. package/dist/ecoimpacthub/EcoImpactHubAdminRoot.d.ts.map +1 -0
  3. package/dist/ecoimpacthub/EcoImpactHubAdminRoot.js +579 -0
  4. package/dist/ecoimpacthub/EcoImpactHubAdminRoot.js.map +1 -0
  5. package/dist/ecoimpacthub/index.d.ts +1 -0
  6. package/dist/ecoimpacthub/index.d.ts.map +1 -1
  7. package/dist/ecoimpacthub/index.js +1 -0
  8. package/dist/ecoimpacthub/pages/carbon/CarbonPage.js +1 -1
  9. package/dist/ecoimpacthub/pages/habitat/HabitatProjectsPage.js +4 -4
  10. package/dist/ecoimpacthub/pages/monitoring/MonitoringPage.js +1 -1
  11. package/dist/ecoimpacthub/pages/reports/ReportsPage.js +4 -4
  12. package/dist/index.js +3 -2
  13. package/dist/stories/DashboardCustomizerDialog.stories.d.ts +9 -0
  14. package/dist/stories/DashboardCustomizerDialog.stories.d.ts.map +1 -0
  15. package/dist/stories/DataTable.stories.d.ts +11 -0
  16. package/dist/stories/DataTable.stories.d.ts.map +1 -0
  17. package/dist/stories/FeatureFlagGate.stories.d.ts +19 -0
  18. package/dist/stories/FeatureFlagGate.stories.d.ts.map +1 -0
  19. package/dist/stories/FilterTabs.stories.d.ts +9 -0
  20. package/dist/stories/FilterTabs.stories.d.ts.map +1 -0
  21. package/dist/stories/PageLayout.stories.d.ts +10 -0
  22. package/dist/stories/PageLayout.stories.d.ts.map +1 -0
  23. package/dist/stories/Pagination.stories.d.ts +11 -0
  24. package/dist/stories/Pagination.stories.d.ts.map +1 -0
  25. package/dist/stories/StateViews.stories.d.ts +10 -0
  26. package/dist/stories/StateViews.stories.d.ts.map +1 -0
  27. package/dist/stories/Tabs.stories.d.ts +9 -0
  28. package/dist/stories/Tabs.stories.d.ts.map +1 -0
  29. package/package.json +1 -1
@@ -0,0 +1,10 @@
1
+ import { FC } from 'react';
2
+ import { EcoImpactHubRootProps } from './types';
3
+
4
+ export interface EcoImpactHubAdminRootProps extends EcoImpactHubRootProps {
5
+ /** Workspace token is supplied by admin-app for workspace-scoped MFEs. */
6
+ workspaceToken?: string;
7
+ }
8
+ export declare const EcoImpactHubAdminRoot: FC<EcoImpactHubAdminRootProps>;
9
+ export { EcoImpactHubAdminRoot as AdminRoot };
10
+ //# sourceMappingURL=EcoImpactHubAdminRoot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EcoImpactHubAdminRoot.d.ts","sourceRoot":"","sources":["../../src/ecoimpacthub/EcoImpactHubAdminRoot.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AA2BhC,OAAO,KAAK,EACV,qBAAqB,EAStB,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,0BAA2B,SAAQ,qBAAqB;IACvE,0EAA0E;IAC1E,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAyiBD,eAAO,MAAM,qBAAqB,EAAE,EAAE,CAAC,0BAA0B,CAmBhE,CAAC;AAEF,OAAO,EAAE,qBAAqB,IAAI,SAAS,EAAE,CAAC"}
@@ -0,0 +1,579 @@
1
+ import { EcoImpactHubProvider as e } from "./context/EcoImpactHubContext.js";
2
+ import { PageLayout as t } from "./components/PageLayout.js";
3
+ import { formatCo2e as n, formatDate as r, formatEnumLabel as i } from "./utils/formatters.js";
4
+ import { StatusBadge as a } from "./components/StatusBadge.js";
5
+ import { ErrorView as o, LoadingView as s, Section as c } from "./components/StateViews.js";
6
+ import { EmptyState as l } from "./components/EmptyState.js";
7
+ import { useEcoArchiveSite as u, useEcoCarbonEntries as d, useEcoPublishReport as f, useEcoReports as p, useEcoSensors as m, useEcoSetSensorStatus as h, useEcoSites as g, useEcoVerifyCarbonEntry as _ } from "./hooks/useEcoImpactHubApi.js";
8
+ import { Tabs as v } from "./components/Tabs.js";
9
+ import { DataTable as y } from "./components/DataTable.js";
10
+ import { Pagination as b } from "./components/Pagination.js";
11
+ import { FilterTabs as x } from "./components/FilterTabs.js";
12
+ import { useMemo as S, useState as C } from "react";
13
+ import { QueryClient as w, QueryClientProvider as T } from "@tanstack/react-query";
14
+ import { FeatureFlagProvider as E } from "@burdenoff/fe-libs/shared/feature-flags";
15
+ import { Factory as D, FileText as O, MapPin as k, Radio as A, ShieldCheck as j } from "lucide-react";
16
+ import { Fragment as M, jsx as N, jsxs as P } from "react/jsx-runtime";
17
+ import { Button as F } from "@burdenoff/fe-libs/ui";
18
+ import { PermissionProvider as I } from "@burdenoff/fe-libs/shared/providers/shell";
19
+ //#region src/ecoimpacthub/EcoImpactHubAdminRoot.tsx
20
+ var L = new w({ defaultOptions: { queries: {
21
+ staleTime: 30 * 1e3,
22
+ retry: 1,
23
+ refetchOnWindowFocus: !1
24
+ } } }), R = 12, z = [
25
+ {
26
+ value: "ALL",
27
+ label: "All"
28
+ },
29
+ {
30
+ value: "ACTIVE",
31
+ label: "Active"
32
+ },
33
+ {
34
+ value: "MONITORING_PAUSED",
35
+ label: "Paused"
36
+ },
37
+ {
38
+ value: "ARCHIVED",
39
+ label: "Archived"
40
+ }
41
+ ], B = [
42
+ {
43
+ value: "ALL",
44
+ label: "All"
45
+ },
46
+ {
47
+ value: "ONLINE",
48
+ label: "Online"
49
+ },
50
+ {
51
+ value: "OFFLINE",
52
+ label: "Offline"
53
+ },
54
+ {
55
+ value: "DEGRADED",
56
+ label: "Degraded"
57
+ },
58
+ {
59
+ value: "MAINTENANCE",
60
+ label: "Maintenance"
61
+ },
62
+ {
63
+ value: "RETIRED",
64
+ label: "Retired"
65
+ }
66
+ ], V = [
67
+ {
68
+ value: "ALL",
69
+ label: "All"
70
+ },
71
+ {
72
+ value: "DRAFT",
73
+ label: "Draft"
74
+ },
75
+ {
76
+ value: "RECORDED",
77
+ label: "Recorded"
78
+ },
79
+ {
80
+ value: "VERIFIED",
81
+ label: "Verified"
82
+ },
83
+ {
84
+ value: "ADJUSTED",
85
+ label: "Adjusted"
86
+ }
87
+ ], H = [
88
+ {
89
+ value: "ALL",
90
+ label: "All"
91
+ },
92
+ {
93
+ value: "DRAFT",
94
+ label: "Draft"
95
+ },
96
+ {
97
+ value: "IN_REVIEW",
98
+ label: "In Review"
99
+ },
100
+ {
101
+ value: "PUBLISHED",
102
+ label: "Published"
103
+ },
104
+ {
105
+ value: "ARCHIVED",
106
+ label: "Archived"
107
+ }
108
+ ];
109
+ function U({ site: e }) {
110
+ let t = u();
111
+ return e.status === "ARCHIVED" ? /* @__PURE__ */ N("span", {
112
+ className: "text-xs text-text-secondary",
113
+ children: "Archived"
114
+ }) : /* @__PURE__ */ N(F, {
115
+ variant: "outline",
116
+ size: "sm",
117
+ onClick: () => t.mutate(e.id),
118
+ disabled: t.isPending,
119
+ children: "Archive"
120
+ });
121
+ }
122
+ function W() {
123
+ let [e, t] = C("ALL"), { data: n, isLoading: u, error: d, refetch: f } = g({
124
+ status: e === "ALL" ? void 0 : e,
125
+ pagination: { limit: 100 }
126
+ }), p = S(() => [
127
+ {
128
+ key: "name",
129
+ header: "Site",
130
+ render: (e) => /* @__PURE__ */ P("div", {
131
+ className: "min-w-0",
132
+ children: [/* @__PURE__ */ N("p", {
133
+ className: "font-medium text-text-primary truncate",
134
+ children: e.name
135
+ }), e.code && /* @__PURE__ */ N("p", {
136
+ className: "text-xs text-text-secondary",
137
+ children: e.code
138
+ })]
139
+ }),
140
+ sortValue: (e) => e.name.toLowerCase()
141
+ },
142
+ {
143
+ key: "type",
144
+ header: "Type",
145
+ render: (e) => i(e.type)
146
+ },
147
+ {
148
+ key: "region",
149
+ header: "Region",
150
+ render: (e) => e.region ?? "—",
151
+ hideOnMobile: !0
152
+ },
153
+ {
154
+ key: "status",
155
+ header: "Status",
156
+ render: (e) => /* @__PURE__ */ N(a, { status: e.status })
157
+ },
158
+ {
159
+ key: "created",
160
+ header: "Created",
161
+ render: (e) => r(e.createdAt),
162
+ sortValue: (e) => new Date(e.createdAt).getTime(),
163
+ hideOnMobile: !0
164
+ },
165
+ {
166
+ key: "actions",
167
+ header: "Actions",
168
+ align: "right",
169
+ render: (e) => /* @__PURE__ */ N(U, { site: e })
170
+ }
171
+ ], []);
172
+ if (u) return /* @__PURE__ */ N(s, { label: "Loading sites…" });
173
+ if (d) return /* @__PURE__ */ N(o, {
174
+ title: "Could not load sites",
175
+ message: d.message,
176
+ onRetry: f
177
+ });
178
+ let m = n?.items ?? [];
179
+ return /* @__PURE__ */ P(c, {
180
+ title: "Site registry",
181
+ description: "Pause monitoring or archive decommissioned sites.",
182
+ children: [/* @__PURE__ */ N("div", {
183
+ className: "mb-4",
184
+ children: /* @__PURE__ */ N(x, {
185
+ options: z,
186
+ value: e,
187
+ onChange: t
188
+ })
189
+ }), m.length === 0 ? /* @__PURE__ */ N(l, {
190
+ icon: /* @__PURE__ */ N(k, { size: 40 }),
191
+ title: "No sites found",
192
+ description: `There are no ${e === "ALL" ? "" : e.toLowerCase()} sites in this workspace.`
193
+ }) : /* @__PURE__ */ N(y, {
194
+ columns: p,
195
+ rows: m,
196
+ rowKey: (e) => e.id,
197
+ defaultSort: {
198
+ key: "created",
199
+ dir: "desc"
200
+ }
201
+ })]
202
+ });
203
+ }
204
+ var G = {
205
+ ONLINE: "MAINTENANCE",
206
+ OFFLINE: "MAINTENANCE",
207
+ DEGRADED: "MAINTENANCE",
208
+ MAINTENANCE: "ONLINE",
209
+ RETIRED: null
210
+ };
211
+ function K({ sensor: e }) {
212
+ let t = h(), n = G[e.status];
213
+ return /* @__PURE__ */ P("div", {
214
+ className: "flex flex-wrap items-center justify-end gap-2",
215
+ children: [n && /* @__PURE__ */ N(F, {
216
+ variant: "outline",
217
+ size: "sm",
218
+ onClick: () => t.mutate({
219
+ id: e.id,
220
+ status: n
221
+ }),
222
+ disabled: t.isPending,
223
+ children: n === "MAINTENANCE" ? "Send to maintenance" : "Bring online"
224
+ }), e.status !== "RETIRED" && /* @__PURE__ */ N(F, {
225
+ variant: "outline",
226
+ size: "sm",
227
+ onClick: () => t.mutate({
228
+ id: e.id,
229
+ status: "RETIRED"
230
+ }),
231
+ disabled: t.isPending,
232
+ children: "Retire"
233
+ })]
234
+ });
235
+ }
236
+ function q() {
237
+ let [e, t] = C("ALL"), { data: n, isLoading: u, error: d, refetch: f } = m({ status: e === "ALL" ? void 0 : e }), p = S(() => [
238
+ {
239
+ key: "name",
240
+ header: "Sensor",
241
+ render: (e) => /* @__PURE__ */ P("div", {
242
+ className: "min-w-0",
243
+ children: [/* @__PURE__ */ N("p", {
244
+ className: "font-medium text-text-primary truncate",
245
+ children: e.name
246
+ }), e.hardwareId && /* @__PURE__ */ N("p", {
247
+ className: "font-mono text-xs text-text-secondary",
248
+ children: e.hardwareId
249
+ })]
250
+ }),
251
+ sortValue: (e) => e.name.toLowerCase()
252
+ },
253
+ {
254
+ key: "kind",
255
+ header: "Kind",
256
+ render: (e) => i(e.kind)
257
+ },
258
+ {
259
+ key: "site",
260
+ header: "Site ID",
261
+ render: (e) => /* @__PURE__ */ N("span", {
262
+ className: "font-mono text-xs text-text-secondary",
263
+ children: e.siteId
264
+ }),
265
+ hideOnMobile: !0
266
+ },
267
+ {
268
+ key: "status",
269
+ header: "Status",
270
+ render: (e) => /* @__PURE__ */ N(a, { status: e.status })
271
+ },
272
+ {
273
+ key: "lastReading",
274
+ header: "Last Reading",
275
+ render: (e) => e.lastReadingAt ? r(e.lastReadingAt) : "—",
276
+ sortValue: (e) => e.lastReadingAt ? new Date(e.lastReadingAt).getTime() : 0,
277
+ hideOnMobile: !0
278
+ },
279
+ {
280
+ key: "actions",
281
+ header: "Actions",
282
+ align: "right",
283
+ render: (e) => /* @__PURE__ */ N(K, { sensor: e })
284
+ }
285
+ ], []);
286
+ if (u) return /* @__PURE__ */ N(s, { label: "Loading sensors…" });
287
+ if (d) return /* @__PURE__ */ N(o, {
288
+ title: "Could not load sensors",
289
+ message: d.message,
290
+ onRetry: f
291
+ });
292
+ let h = n?.items ?? [];
293
+ return /* @__PURE__ */ P(c, {
294
+ title: "Sensor fleet",
295
+ description: "Retire hardware or move sensors into maintenance.",
296
+ children: [/* @__PURE__ */ N("div", {
297
+ className: "mb-4",
298
+ children: /* @__PURE__ */ N(x, {
299
+ options: B,
300
+ value: e,
301
+ onChange: t
302
+ })
303
+ }), h.length === 0 ? /* @__PURE__ */ N(l, {
304
+ icon: /* @__PURE__ */ N(A, { size: 40 }),
305
+ title: "No sensors found",
306
+ description: `There are no ${e === "ALL" ? "" : e.toLowerCase()} sensors in this workspace.`
307
+ }) : /* @__PURE__ */ N(y, {
308
+ columns: p,
309
+ rows: h,
310
+ rowKey: (e) => e.id,
311
+ defaultSort: {
312
+ key: "lastReading",
313
+ dir: "desc"
314
+ }
315
+ })]
316
+ });
317
+ }
318
+ function J({ entry: e }) {
319
+ let t = _();
320
+ return e.status === "VERIFIED" ? /* @__PURE__ */ N("span", {
321
+ className: "text-xs text-text-secondary",
322
+ children: "Verified"
323
+ }) : /* @__PURE__ */ N(F, {
324
+ variant: "outline",
325
+ size: "sm",
326
+ onClick: () => t.mutate(e.id),
327
+ disabled: t.isPending,
328
+ children: "Verify"
329
+ });
330
+ }
331
+ function Y() {
332
+ let [e, t] = C("ALL"), [u, f] = C(0), [p, m] = C([]), h = u > 0 ? p[u - 1] : void 0, { data: g, isLoading: _, error: v, refetch: w } = d({
333
+ status: e === "ALL" ? void 0 : e,
334
+ pagination: {
335
+ limit: R,
336
+ cursor: h
337
+ }
338
+ }), T = S(() => [
339
+ {
340
+ key: "category",
341
+ header: "Category",
342
+ render: (e) => /* @__PURE__ */ P("div", {
343
+ className: "min-w-0",
344
+ children: [/* @__PURE__ */ N("p", {
345
+ className: "font-medium text-text-primary truncate",
346
+ children: e.category
347
+ }), e.factor && /* @__PURE__ */ N("p", {
348
+ className: "text-xs text-text-secondary",
349
+ children: e.factor.name
350
+ })]
351
+ })
352
+ },
353
+ {
354
+ key: "scope",
355
+ header: "Scope",
356
+ render: (e) => i(e.scope)
357
+ },
358
+ {
359
+ key: "co2e",
360
+ header: "CO₂e",
361
+ align: "right",
362
+ render: (e) => n(e.co2eKg),
363
+ sortValue: (e) => e.co2eKg
364
+ },
365
+ {
366
+ key: "period",
367
+ header: "Period",
368
+ render: (e) => r(e.periodStart),
369
+ sortValue: (e) => new Date(e.periodStart).getTime(),
370
+ hideOnMobile: !0
371
+ },
372
+ {
373
+ key: "status",
374
+ header: "Status",
375
+ render: (e) => /* @__PURE__ */ N(a, { status: e.status })
376
+ },
377
+ {
378
+ key: "actions",
379
+ header: "Actions",
380
+ align: "right",
381
+ render: (e) => /* @__PURE__ */ N(J, { entry: e })
382
+ }
383
+ ], []), E = (e) => {
384
+ e > u && g?.pageInfo.cursor ? m((e) => [...e, g.pageInfo.cursor]) : e < u && m((e) => e.slice(0, -1)), f(e);
385
+ };
386
+ if (_) return /* @__PURE__ */ N(s, { label: "Loading carbon entries…" });
387
+ if (v) return /* @__PURE__ */ N(o, {
388
+ title: "Could not load carbon entries",
389
+ message: v.message,
390
+ onRetry: w
391
+ });
392
+ let O = g?.items ?? [];
393
+ return /* @__PURE__ */ P(c, {
394
+ title: "Carbon ledger",
395
+ description: "Verify DRAFT/RECORDED entries across all sites and scopes.",
396
+ children: [/* @__PURE__ */ N("div", {
397
+ className: "mb-4",
398
+ children: /* @__PURE__ */ N(x, {
399
+ options: V,
400
+ value: e,
401
+ onChange: (e) => {
402
+ t(e), f(0), m([]);
403
+ }
404
+ })
405
+ }), O.length === 0 ? /* @__PURE__ */ N(l, {
406
+ icon: /* @__PURE__ */ N(D, { size: 40 }),
407
+ title: "No carbon entries found",
408
+ description: `There are no ${e === "ALL" ? "" : e.toLowerCase()} entries in this workspace.`
409
+ }) : /* @__PURE__ */ P(M, { children: [/* @__PURE__ */ N(y, {
410
+ columns: T,
411
+ rows: O,
412
+ rowKey: (e) => e.id,
413
+ defaultSort: {
414
+ key: "period",
415
+ dir: "desc"
416
+ }
417
+ }), /* @__PURE__ */ N(b, {
418
+ page: u,
419
+ pageSize: R,
420
+ itemCount: O.length,
421
+ hasMore: g?.pageInfo.hasMore ?? !1,
422
+ onPageChange: E
423
+ })] })]
424
+ });
425
+ }
426
+ function X({ report: e }) {
427
+ let t = f();
428
+ return e.status === "PUBLISHED" || e.status === "ARCHIVED" ? /* @__PURE__ */ N("span", {
429
+ className: "text-xs text-text-secondary",
430
+ children: i(e.status)
431
+ }) : /* @__PURE__ */ N(F, {
432
+ variant: "outline",
433
+ size: "sm",
434
+ onClick: () => t.mutate({
435
+ id: e.id,
436
+ fileId: e.file?.id ?? null
437
+ }),
438
+ disabled: t.isPending,
439
+ children: "Publish"
440
+ });
441
+ }
442
+ function Z() {
443
+ let [e, t] = C("ALL"), { data: n, isLoading: u, error: d, refetch: f } = p(e === "ALL" ? void 0 : e, { limit: 100 }), m = S(() => [
444
+ {
445
+ key: "title",
446
+ header: "Report",
447
+ render: (e) => /* @__PURE__ */ N("p", {
448
+ className: "font-medium text-text-primary truncate",
449
+ children: e.title
450
+ }),
451
+ sortValue: (e) => e.title.toLowerCase()
452
+ },
453
+ {
454
+ key: "framework",
455
+ header: "Framework",
456
+ render: (e) => i(e.framework)
457
+ },
458
+ {
459
+ key: "period",
460
+ header: "Period",
461
+ render: (e) => `${r(e.periodStart)} – ${r(e.periodEnd)}`,
462
+ hideOnMobile: !0
463
+ },
464
+ {
465
+ key: "status",
466
+ header: "Status",
467
+ render: (e) => /* @__PURE__ */ N(a, { status: e.status })
468
+ },
469
+ {
470
+ key: "published",
471
+ header: "Published",
472
+ render: (e) => e.publishedAt ? r(e.publishedAt) : "—",
473
+ sortValue: (e) => e.publishedAt ? new Date(e.publishedAt).getTime() : 0,
474
+ hideOnMobile: !0
475
+ },
476
+ {
477
+ key: "actions",
478
+ header: "Actions",
479
+ align: "right",
480
+ render: (e) => /* @__PURE__ */ N(X, { report: e })
481
+ }
482
+ ], []);
483
+ if (u) return /* @__PURE__ */ N(s, { label: "Loading reports…" });
484
+ if (d) return /* @__PURE__ */ N(o, {
485
+ title: "Could not load reports",
486
+ message: d.message,
487
+ onRetry: f
488
+ });
489
+ let h = n?.items ?? [];
490
+ return /* @__PURE__ */ P(c, {
491
+ title: "Sustainability reports",
492
+ description: "Publish reports once their line items are complete.",
493
+ children: [/* @__PURE__ */ N("div", {
494
+ className: "mb-4",
495
+ children: /* @__PURE__ */ N(x, {
496
+ options: H,
497
+ value: e,
498
+ onChange: t
499
+ })
500
+ }), h.length === 0 ? /* @__PURE__ */ N(l, {
501
+ icon: /* @__PURE__ */ N(O, { size: 40 }),
502
+ title: "No reports found",
503
+ description: `There are no ${e === "ALL" ? "" : e.toLowerCase()} reports in this workspace.`
504
+ }) : /* @__PURE__ */ N(y, {
505
+ columns: m,
506
+ rows: h,
507
+ rowKey: (e) => e.id,
508
+ defaultSort: {
509
+ key: "period",
510
+ dir: "desc"
511
+ }
512
+ })]
513
+ });
514
+ }
515
+ function Q() {
516
+ let [e, n] = C("sites"), r = S(() => [
517
+ {
518
+ value: "sites",
519
+ label: "Sites",
520
+ icon: /* @__PURE__ */ N(k, { size: 18 })
521
+ },
522
+ {
523
+ value: "sensors",
524
+ label: "Sensors",
525
+ icon: /* @__PURE__ */ N(A, { size: 18 })
526
+ },
527
+ {
528
+ value: "carbon",
529
+ label: "Carbon Ledger",
530
+ icon: /* @__PURE__ */ N(D, { size: 18 })
531
+ },
532
+ {
533
+ value: "reports",
534
+ label: "Reports",
535
+ icon: /* @__PURE__ */ N(O, { size: 18 })
536
+ }
537
+ ], []);
538
+ return /* @__PURE__ */ P(t, {
539
+ title: "EcoImpactHub Admin",
540
+ description: "Site, sensor, carbon-ledger and report governance.",
541
+ actions: /* @__PURE__ */ P("span", {
542
+ className: "inline-flex items-center gap-2 text-sm text-text-secondary",
543
+ children: [/* @__PURE__ */ N(j, { size: 18 }), "Workspace-scoped"]
544
+ }),
545
+ children: [/* @__PURE__ */ N(v, {
546
+ items: r,
547
+ value: e,
548
+ onChange: n
549
+ }), /* @__PURE__ */ P("div", {
550
+ className: "mt-6",
551
+ children: [
552
+ e === "sites" && /* @__PURE__ */ N(W, {}),
553
+ e === "sensors" && /* @__PURE__ */ N(q, {}),
554
+ e === "carbon" && /* @__PURE__ */ N(Y, {}),
555
+ e === "reports" && /* @__PURE__ */ N(Z, {})
556
+ ]
557
+ })]
558
+ });
559
+ }
560
+ var $ = (t) => /* @__PURE__ */ N(T, {
561
+ client: L,
562
+ children: /* @__PURE__ */ N(E, {
563
+ workspaceId: t.workspaceId ?? null,
564
+ gateway: "global",
565
+ defaultEnabled: !0,
566
+ children: /* @__PURE__ */ N(I, {
567
+ scopeId: t.workspaceId ?? null,
568
+ gateway: "workspace",
569
+ children: /* @__PURE__ */ N(e, {
570
+ ...t,
571
+ children: /* @__PURE__ */ N(Q, {})
572
+ })
573
+ })
574
+ })
575
+ });
576
+ //#endregion
577
+ export { $ as EcoImpactHubAdminRoot };
578
+
579
+ //# sourceMappingURL=EcoImpactHubAdminRoot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EcoImpactHubAdminRoot.js","names":[],"sources":["../../src/ecoimpacthub/EcoImpactHubAdminRoot.tsx"],"sourcesContent":["/**\n * EcoImpactHub Admin Root\n * @module ecoimpacthub\n *\n * Product-specific admin surface mounted inside `admin-app` under\n * `/admin/ecoimpacthub` (BOFF-3118). Per fleet-wide policy the ONLY valid\n * admin surface is the shared `admin.burdenoff.com` app — this is a\n * microfrontend mounted there, not a new subdomain. It covers three\n * governance operations product owners need outside the day-to-day\n * monitoring UI:\n *\n * 1. Site / sensor governance — pause monitoring, retire hardware, archive\n * decommissioned sites.\n * 2. Carbon-ledger oversight — inspect recorded carbon entries across all\n * sites/scopes and verify DRAFT/RECORDED entries.\n * 3. Report sign-off — publish sustainability reports once their line items\n * are complete.\n *\n * Reuses the real `wspace-ecoimpacthub-svc` GraphQL operations already\n * consumed by the workspace-facing pages (`ecoListSites`, `ecoArchiveSite`,\n * `ecoListSensors`, `ecoSetSensorStatus`, `ecoListCarbonEntries`,\n * `ecoVerifyCarbonEntry`, `ecoListReports`, `ecoPublishReport`) — no new\n * backend surface. Every mutation still carries its own `@rbac` directive at\n * the gateway; this panel does not re-implement authorization, it is a\n * governance-focused view over the same RBAC-enforced API.\n *\n * Remaining gap (documented, not built here): report-approval workflow\n * routing through wspace-workflow-svc (depends on the C2 event/workflow\n * wiring landing first) — today \"publish\" is a direct status transition,\n * not a multi-step approval chain.\n */\n\nimport type { FC } from 'react';\nimport { useMemo, useState } from 'react';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { FeatureFlagProvider } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { PermissionProvider } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { MapPin, Radio, Factory, FileText, ShieldCheck } from 'lucide-react';\nimport { EcoImpactHubProvider } from './context/EcoImpactHubContext';\nimport { PageLayout } from './components/PageLayout';\nimport { Tabs, type TabItem } from './components/Tabs';\nimport { DataTable, type Column } from './components/DataTable';\nimport { StatusBadge } from './components/StatusBadge';\nimport { LoadingView, ErrorView, Section } from './components/StateViews';\nimport { EmptyState } from './components/EmptyState';\nimport { Pagination } from './components/Pagination';\nimport { FilterTabs, type FilterOption } from './components/FilterTabs';\nimport {\n useEcoSites,\n useEcoArchiveSite,\n useEcoSensors,\n useEcoSetSensorStatus,\n useEcoCarbonEntries,\n useEcoVerifyCarbonEntry,\n useEcoReports,\n useEcoPublishReport,\n} from './hooks/useEcoImpactHubApi';\nimport { formatDate, formatCo2e, formatEnumLabel } from './utils';\nimport type {\n EcoImpactHubRootProps,\n EcoSite,\n EcoSiteStatus,\n EcoSensor,\n EcoSensorStatus,\n EcoCarbonEntry,\n EcoCarbonEntryStatus,\n EcoReport,\n EcoReportStatus,\n} from './types';\n\nexport interface EcoImpactHubAdminRootProps extends EcoImpactHubRootProps {\n /** Workspace token is supplied by admin-app for workspace-scoped MFEs. */\n workspaceToken?: string;\n}\n\ntype AdminTab = 'sites' | 'sensors' | 'carbon' | 'reports';\n\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: 30 * 1000,\n retry: 1,\n refetchOnWindowFocus: false,\n },\n },\n});\n\nconst PAGE_SIZE = 12;\n\nconst SITE_STATUS_OPTIONS: FilterOption<'ALL' | EcoSiteStatus>[] = [\n { value: 'ALL', label: 'All' },\n { value: 'ACTIVE', label: 'Active' },\n { value: 'MONITORING_PAUSED', label: 'Paused' },\n { value: 'ARCHIVED', label: 'Archived' },\n];\n\nconst SENSOR_STATUS_OPTIONS: FilterOption<'ALL' | EcoSensorStatus>[] = [\n { value: 'ALL', label: 'All' },\n { value: 'ONLINE', label: 'Online' },\n { value: 'OFFLINE', label: 'Offline' },\n { value: 'DEGRADED', label: 'Degraded' },\n { value: 'MAINTENANCE', label: 'Maintenance' },\n { value: 'RETIRED', label: 'Retired' },\n];\n\nconst CARBON_STATUS_OPTIONS: FilterOption<'ALL' | EcoCarbonEntryStatus>[] = [\n { value: 'ALL', label: 'All' },\n { value: 'DRAFT', label: 'Draft' },\n { value: 'RECORDED', label: 'Recorded' },\n { value: 'VERIFIED', label: 'Verified' },\n { value: 'ADJUSTED', label: 'Adjusted' },\n];\n\nconst REPORT_STATUS_OPTIONS: FilterOption<'ALL' | EcoReportStatus>[] = [\n { value: 'ALL', label: 'All' },\n { value: 'DRAFT', label: 'Draft' },\n { value: 'IN_REVIEW', label: 'In Review' },\n { value: 'PUBLISHED', label: 'Published' },\n { value: 'ARCHIVED', label: 'Archived' },\n];\n\n// ============================================================================\n// Sites governance\n// ============================================================================\n\nfunction SiteActions({ site }: { site: EcoSite }) {\n const archive = useEcoArchiveSite();\n if (site.status === 'ARCHIVED') {\n return <span className=\"text-xs text-text-secondary\">Archived</span>;\n }\n return (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => archive.mutate(site.id)}\n disabled={archive.isPending}\n >\n Archive\n </Button>\n );\n}\n\nfunction SitesPanel() {\n const [status, setStatus] = useState<'ALL' | EcoSiteStatus>('ALL');\n const { data, isLoading, error, refetch } = useEcoSites({\n status: status === 'ALL' ? undefined : status,\n pagination: { limit: 100 },\n });\n\n const columns = useMemo<Column<EcoSite>[]>(\n () => [\n {\n key: 'name',\n header: 'Site',\n render: (s) => (\n <div className=\"min-w-0\">\n <p className=\"font-medium text-text-primary truncate\">{s.name}</p>\n {s.code && <p className=\"text-xs text-text-secondary\">{s.code}</p>}\n </div>\n ),\n sortValue: (s) => s.name.toLowerCase(),\n },\n {\n key: 'type',\n header: 'Type',\n render: (s) => formatEnumLabel(s.type),\n },\n {\n key: 'region',\n header: 'Region',\n render: (s) => s.region ?? '—',\n hideOnMobile: true,\n },\n {\n key: 'status',\n header: 'Status',\n render: (s) => <StatusBadge status={s.status} />,\n },\n {\n key: 'created',\n header: 'Created',\n render: (s) => formatDate(s.createdAt),\n sortValue: (s) => new Date(s.createdAt).getTime(),\n hideOnMobile: true,\n },\n {\n key: 'actions',\n header: 'Actions',\n align: 'right',\n render: (s) => <SiteActions site={s} />,\n },\n ],\n []\n );\n\n if (isLoading) return <LoadingView label=\"Loading sites…\" />;\n if (error)\n return <ErrorView title=\"Could not load sites\" message={error.message} onRetry={refetch} />;\n\n const rows = data?.items ?? [];\n\n return (\n <Section title=\"Site registry\" description=\"Pause monitoring or archive decommissioned sites.\">\n <div className=\"mb-4\">\n <FilterTabs options={SITE_STATUS_OPTIONS} value={status} onChange={setStatus} />\n </div>\n {rows.length === 0 ? (\n <EmptyState\n icon={<MapPin size={40} />}\n title=\"No sites found\"\n description={`There are no ${status === 'ALL' ? '' : status.toLowerCase()} sites in this workspace.`}\n />\n ) : (\n <DataTable\n columns={columns}\n rows={rows}\n rowKey={(s) => s.id}\n defaultSort={{ key: 'created', dir: 'desc' }}\n />\n )}\n </Section>\n );\n}\n\n// ============================================================================\n// Sensor governance\n// ============================================================================\n\nconst SENSOR_STATUS_TRANSITIONS: Record<EcoSensorStatus, EcoSensorStatus | null> = {\n ONLINE: 'MAINTENANCE',\n OFFLINE: 'MAINTENANCE',\n DEGRADED: 'MAINTENANCE',\n MAINTENANCE: 'ONLINE',\n RETIRED: null,\n};\n\nfunction SensorActions({ sensor }: { sensor: EcoSensor }) {\n const setStatus = useEcoSetSensorStatus();\n const nextStatus = SENSOR_STATUS_TRANSITIONS[sensor.status];\n\n return (\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n {nextStatus && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setStatus.mutate({ id: sensor.id, status: nextStatus })}\n disabled={setStatus.isPending}\n >\n {nextStatus === 'MAINTENANCE' ? 'Send to maintenance' : 'Bring online'}\n </Button>\n )}\n {sensor.status !== 'RETIRED' && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setStatus.mutate({ id: sensor.id, status: 'RETIRED' })}\n disabled={setStatus.isPending}\n >\n Retire\n </Button>\n )}\n </div>\n );\n}\n\nfunction SensorsPanel() {\n const [status, setStatus] = useState<'ALL' | EcoSensorStatus>('ALL');\n const { data, isLoading, error, refetch } = useEcoSensors({\n status: status === 'ALL' ? undefined : status,\n });\n\n const columns = useMemo<Column<EcoSensor>[]>(\n () => [\n {\n key: 'name',\n header: 'Sensor',\n render: (s) => (\n <div className=\"min-w-0\">\n <p className=\"font-medium text-text-primary truncate\">{s.name}</p>\n {s.hardwareId && (\n <p className=\"font-mono text-xs text-text-secondary\">{s.hardwareId}</p>\n )}\n </div>\n ),\n sortValue: (s) => s.name.toLowerCase(),\n },\n {\n key: 'kind',\n header: 'Kind',\n render: (s) => formatEnumLabel(s.kind),\n },\n {\n key: 'site',\n header: 'Site ID',\n render: (s) => <span className=\"font-mono text-xs text-text-secondary\">{s.siteId}</span>,\n hideOnMobile: true,\n },\n {\n key: 'status',\n header: 'Status',\n render: (s) => <StatusBadge status={s.status} />,\n },\n {\n key: 'lastReading',\n header: 'Last Reading',\n render: (s) => (s.lastReadingAt ? formatDate(s.lastReadingAt) : '—'),\n sortValue: (s) => (s.lastReadingAt ? new Date(s.lastReadingAt).getTime() : 0),\n hideOnMobile: true,\n },\n {\n key: 'actions',\n header: 'Actions',\n align: 'right',\n render: (s) => <SensorActions sensor={s} />,\n },\n ],\n []\n );\n\n if (isLoading) return <LoadingView label=\"Loading sensors…\" />;\n if (error)\n return <ErrorView title=\"Could not load sensors\" message={error.message} onRetry={refetch} />;\n\n const rows = data?.items ?? [];\n\n return (\n <Section title=\"Sensor fleet\" description=\"Retire hardware or move sensors into maintenance.\">\n <div className=\"mb-4\">\n <FilterTabs options={SENSOR_STATUS_OPTIONS} value={status} onChange={setStatus} />\n </div>\n {rows.length === 0 ? (\n <EmptyState\n icon={<Radio size={40} />}\n title=\"No sensors found\"\n description={`There are no ${status === 'ALL' ? '' : status.toLowerCase()} sensors in this workspace.`}\n />\n ) : (\n <DataTable\n columns={columns}\n rows={rows}\n rowKey={(s) => s.id}\n defaultSort={{ key: 'lastReading', dir: 'desc' }}\n />\n )}\n </Section>\n );\n}\n\n// ============================================================================\n// Carbon-ledger oversight\n// ============================================================================\n\nfunction CarbonEntryActions({ entry }: { entry: EcoCarbonEntry }) {\n const verify = useEcoVerifyCarbonEntry();\n if (entry.status === 'VERIFIED') {\n return <span className=\"text-xs text-text-secondary\">Verified</span>;\n }\n return (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => verify.mutate(entry.id)}\n disabled={verify.isPending}\n >\n Verify\n </Button>\n );\n}\n\nfunction CarbonLedgerPanel() {\n const [status, setStatus] = useState<'ALL' | EcoCarbonEntryStatus>('ALL');\n const [page, setPage] = useState(0);\n const [cursors, setCursors] = useState<string[]>([]);\n\n const cursor = page > 0 ? cursors[page - 1] : undefined;\n const { data, isLoading, error, refetch } = useEcoCarbonEntries({\n status: status === 'ALL' ? undefined : status,\n pagination: { limit: PAGE_SIZE, cursor },\n });\n\n const columns = useMemo<Column<EcoCarbonEntry>[]>(\n () => [\n {\n key: 'category',\n header: 'Category',\n render: (c) => (\n <div className=\"min-w-0\">\n <p className=\"font-medium text-text-primary truncate\">{c.category}</p>\n {c.factor && <p className=\"text-xs text-text-secondary\">{c.factor.name}</p>}\n </div>\n ),\n },\n {\n key: 'scope',\n header: 'Scope',\n render: (c) => formatEnumLabel(c.scope),\n },\n {\n key: 'co2e',\n header: 'CO₂e',\n align: 'right',\n render: (c) => formatCo2e(c.co2eKg),\n sortValue: (c) => c.co2eKg,\n },\n {\n key: 'period',\n header: 'Period',\n render: (c) => formatDate(c.periodStart),\n sortValue: (c) => new Date(c.periodStart).getTime(),\n hideOnMobile: true,\n },\n {\n key: 'status',\n header: 'Status',\n render: (c) => <StatusBadge status={c.status} />,\n },\n {\n key: 'actions',\n header: 'Actions',\n align: 'right',\n render: (c) => <CarbonEntryActions entry={c} />,\n },\n ],\n []\n );\n\n const handlePageChange = (nextPage: number) => {\n if (nextPage > page && data?.pageInfo.cursor) {\n setCursors((prev) => [...prev, data.pageInfo.cursor as string]);\n } else if (nextPage < page) {\n setCursors((prev) => prev.slice(0, -1));\n }\n setPage(nextPage);\n };\n\n if (isLoading) return <LoadingView label=\"Loading carbon entries…\" />;\n if (error)\n return (\n <ErrorView title=\"Could not load carbon entries\" message={error.message} onRetry={refetch} />\n );\n\n const rows = data?.items ?? [];\n\n return (\n <Section\n title=\"Carbon ledger\"\n description=\"Verify DRAFT/RECORDED entries across all sites and scopes.\"\n >\n <div className=\"mb-4\">\n <FilterTabs\n options={CARBON_STATUS_OPTIONS}\n value={status}\n onChange={(v) => {\n setStatus(v);\n setPage(0);\n setCursors([]);\n }}\n />\n </div>\n {rows.length === 0 ? (\n <EmptyState\n icon={<Factory size={40} />}\n title=\"No carbon entries found\"\n description={`There are no ${status === 'ALL' ? '' : status.toLowerCase()} entries in this workspace.`}\n />\n ) : (\n <>\n <DataTable\n columns={columns}\n rows={rows}\n rowKey={(c) => c.id}\n defaultSort={{ key: 'period', dir: 'desc' }}\n />\n <Pagination\n page={page}\n pageSize={PAGE_SIZE}\n itemCount={rows.length}\n hasMore={data?.pageInfo.hasMore ?? false}\n onPageChange={handlePageChange}\n />\n </>\n )}\n </Section>\n );\n}\n\n// ============================================================================\n// Report sign-off\n// ============================================================================\n\nfunction ReportActions({ report }: { report: EcoReport }) {\n const publish = useEcoPublishReport();\n if (report.status === 'PUBLISHED' || report.status === 'ARCHIVED') {\n return <span className=\"text-xs text-text-secondary\">{formatEnumLabel(report.status)}</span>;\n }\n return (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => publish.mutate({ id: report.id, fileId: report.file?.id ?? null })}\n disabled={publish.isPending}\n >\n Publish\n </Button>\n );\n}\n\nfunction ReportsPanel() {\n const [status, setStatus] = useState<'ALL' | EcoReportStatus>('ALL');\n const { data, isLoading, error, refetch } = useEcoReports(status === 'ALL' ? undefined : status, {\n limit: 100,\n });\n\n const columns = useMemo<Column<EcoReport>[]>(\n () => [\n {\n key: 'title',\n header: 'Report',\n render: (r) => <p className=\"font-medium text-text-primary truncate\">{r.title}</p>,\n sortValue: (r) => r.title.toLowerCase(),\n },\n {\n key: 'framework',\n header: 'Framework',\n render: (r) => formatEnumLabel(r.framework),\n },\n {\n key: 'period',\n header: 'Period',\n render: (r) => `${formatDate(r.periodStart)} – ${formatDate(r.periodEnd)}`,\n hideOnMobile: true,\n },\n {\n key: 'status',\n header: 'Status',\n render: (r) => <StatusBadge status={r.status} />,\n },\n {\n key: 'published',\n header: 'Published',\n render: (r) => (r.publishedAt ? formatDate(r.publishedAt) : '—'),\n sortValue: (r) => (r.publishedAt ? new Date(r.publishedAt).getTime() : 0),\n hideOnMobile: true,\n },\n {\n key: 'actions',\n header: 'Actions',\n align: 'right',\n render: (r) => <ReportActions report={r} />,\n },\n ],\n []\n );\n\n if (isLoading) return <LoadingView label=\"Loading reports…\" />;\n if (error)\n return <ErrorView title=\"Could not load reports\" message={error.message} onRetry={refetch} />;\n\n const rows = data?.items ?? [];\n\n return (\n <Section\n title=\"Sustainability reports\"\n description=\"Publish reports once their line items are complete.\"\n >\n <div className=\"mb-4\">\n <FilterTabs options={REPORT_STATUS_OPTIONS} value={status} onChange={setStatus} />\n </div>\n {rows.length === 0 ? (\n <EmptyState\n icon={<FileText size={40} />}\n title=\"No reports found\"\n description={`There are no ${status === 'ALL' ? '' : status.toLowerCase()} reports in this workspace.`}\n />\n ) : (\n <DataTable\n columns={columns}\n rows={rows}\n rowKey={(r) => r.id}\n defaultSort={{ key: 'period', dir: 'desc' }}\n />\n )}\n </Section>\n );\n}\n\n// ============================================================================\n// Root\n// ============================================================================\n\nfunction EcoImpactHubAdminDashboard() {\n const [activeTab, setActiveTab] = useState<AdminTab>('sites');\n\n const tabs = useMemo<TabItem<AdminTab>[]>(\n () => [\n { value: 'sites', label: 'Sites', icon: <MapPin size={18} /> },\n { value: 'sensors', label: 'Sensors', icon: <Radio size={18} /> },\n { value: 'carbon', label: 'Carbon Ledger', icon: <Factory size={18} /> },\n { value: 'reports', label: 'Reports', icon: <FileText size={18} /> },\n ],\n []\n );\n\n return (\n <PageLayout\n title=\"EcoImpactHub Admin\"\n description=\"Site, sensor, carbon-ledger and report governance.\"\n actions={\n <span className=\"inline-flex items-center gap-2 text-sm text-text-secondary\">\n <ShieldCheck size={18} />\n Workspace-scoped\n </span>\n }\n >\n <Tabs items={tabs} value={activeTab} onChange={setActiveTab} />\n <div className=\"mt-6\">\n {activeTab === 'sites' && <SitesPanel />}\n {activeTab === 'sensors' && <SensorsPanel />}\n {activeTab === 'carbon' && <CarbonLedgerPanel />}\n {activeTab === 'reports' && <ReportsPanel />}\n </div>\n </PageLayout>\n );\n}\n\nexport const EcoImpactHubAdminRoot: FC<EcoImpactHubAdminRootProps> = (props) => {\n return (\n <QueryClientProvider client={queryClient}>\n <FeatureFlagProvider\n workspaceId={props.workspaceId ?? null}\n gateway=\"global\"\n defaultEnabled={true}\n >\n {/* Workspace-scoped RBAC so the admin panel's archive/verify/publish\n controls are gated client-side too. Gateway @rbac remains\n authoritative — this is a UX nicety, not a security control. */}\n <PermissionProvider scopeId={props.workspaceId ?? null} gateway=\"workspace\">\n <EcoImpactHubProvider {...props}>\n <EcoImpactHubAdminDashboard />\n </EcoImpactHubProvider>\n </PermissionProvider>\n </FeatureFlagProvider>\n </QueryClientProvider>\n );\n};\n\nexport { EcoImpactHubAdminRoot as AdminRoot };\n"],"mappings":"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"}
@@ -3,6 +3,7 @@
3
3
  * @module ecoimpacthub
4
4
  */
5
5
  export { EcoImpactHubRoot } from './EcoImpactHubRoot';
6
+ export { EcoImpactHubAdminRoot, EcoImpactHubAdminRoot as AdminRoot, type EcoImpactHubAdminRootProps, } from './EcoImpactHubAdminRoot';
6
7
  export type { EcoImpactHubRootProps, NavItem, FooterItem, TrendDirection } from './types';
7
8
  export { EcoImpactHubProvider, useEcoImpactHub } from './context';
8
9
  export { useSandboxAssistantTransport, type AssistantTransport } from './services';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ecoimpacthub/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD,YAAY,EAAE,qBAAqB,EAAE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG1F,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAGlE,OAAO,EAAE,4BAA4B,EAAE,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGnF,OAAO,EACL,EAAE,EACF,QAAQ,EACR,UAAU,EACV,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,cAAc,EACd,aAAa,EACb,UAAU,EACV,YAAY,EACZ,eAAe,GAChB,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ecoimpacthub/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EACL,qBAAqB,EACrB,qBAAqB,IAAI,SAAS,EAClC,KAAK,0BAA0B,GAChC,MAAM,yBAAyB,CAAC;AAGjC,YAAY,EAAE,qBAAqB,EAAE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG1F,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAGlE,OAAO,EAAE,4BAA4B,EAAE,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGnF,OAAO,EACL,EAAE,EACF,QAAQ,EACR,UAAU,EACV,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,cAAc,EACd,aAAa,EACb,UAAU,EACV,YAAY,EACZ,eAAe,GAChB,MAAM,SAAS,CAAC"}
@@ -4,5 +4,6 @@ import "./utils/cn.js";
4
4
  import "./utils/formatters.js";
5
5
  import "./context/index.js";
6
6
  import "./EcoImpactHubRoot.js";
7
+ import "./EcoImpactHubAdminRoot.js";
7
8
  import "./services/createSandboxAssistantTransport.js";
8
9
  import "./services/index.js";
@@ -8,8 +8,8 @@ import { Meter as te, SCOPE_HUE as ne, ScopeSplitBar as re } from "../carbonVisu
8
8
  import { useEcoCarbonEntries as ie, useEcoCarbonTotals as ae, useEcoCreateEmissionFactor as oe, useEcoCreateReductionTarget as se, useEcoEmissionFactors as ce, useEcoRecordCarbonEntry as le, useEcoReductionTargets as ue, useEcoSetReductionTargetStatus as de, useEcoSites as fe, useEcoVerifyCarbonEntry as pe } from "../../hooks/useEcoImpactHubApi.js";
9
9
  import { useCursorPager as me } from "../../hooks/useCursorPager.js";
10
10
  import "../../hooks/index.js";
11
- import { DataTable as u } from "../../components/DataTable.js";
12
11
  import { Tabs as he } from "../../components/Tabs.js";
12
+ import { DataTable as u } from "../../components/DataTable.js";
13
13
  import { Pagination as ge } from "../../components/Pagination.js";
14
14
  import { useMemo as _e, useState as d } from "react";
15
15
  import { Factory as f, Flame as ve, Leaf as ye, Plus as p, Target as be, Truck as xe, Zap as Se } from "lucide-react";
@@ -7,8 +7,8 @@ import "../../context/index.js";
7
7
  import { useEcoCreateHabitatProject as c, useEcoHabitatProjects as l, useEcoSites as u } from "../../hooks/useEcoImpactHubApi.js";
8
8
  import "../../hooks/index.js";
9
9
  import { DataTable as d } from "../../components/DataTable.js";
10
- import { LifecycleBadge as f } from "../badges.js";
11
- import { FilterTabs as p } from "../../components/FilterTabs.js";
10
+ import { FilterTabs as f } from "../../components/FilterTabs.js";
11
+ import { LifecycleBadge as p } from "../badges.js";
12
12
  import { useMemo as m, useState as h } from "react";
13
13
  import { Plus as g, Trees as _ } from "lucide-react";
14
14
  import { jsx as v, jsxs as y } from "react/jsx-runtime";
@@ -72,7 +72,7 @@ function L() {
72
72
  {
73
73
  key: "status",
74
74
  header: "Status",
75
- render: (e) => /* @__PURE__ */ v(f, { status: e.status })
75
+ render: (e) => /* @__PURE__ */ v(p, { status: e.status })
76
76
  },
77
77
  {
78
78
  key: "target",
@@ -142,7 +142,7 @@ function L() {
142
142
  children: [
143
143
  /* @__PURE__ */ v("div", {
144
144
  className: "mb-5 flex flex-wrap items-center gap-3",
145
- children: /* @__PURE__ */ v(p, {
145
+ children: /* @__PURE__ */ v(f, {
146
146
  options: N,
147
147
  value: R,
148
148
  onChange: z
@@ -6,8 +6,8 @@ import { EmptyState as te } from "../../components/EmptyState.js";
6
6
  import { useEcoCreateSensor as ne, useEcoCreateThreshold as re, useEcoMeasurements as ie, useEcoRecordMeasurement as ae, useEcoSensors as oe, useEcoSetSensorStatus as se, useEcoSetThresholdActive as ce, useEcoSites as le, useEcoThresholds as ue } from "../../hooks/useEcoImpactHubApi.js";
7
7
  import { useCursorPager as de } from "../../hooks/useCursorPager.js";
8
8
  import "../../hooks/index.js";
9
- import { DataTable as o } from "../../components/DataTable.js";
10
9
  import { Tabs as fe } from "../../components/Tabs.js";
10
+ import { DataTable as o } from "../../components/DataTable.js";
11
11
  import { Pagination as pe } from "../../components/Pagination.js";
12
12
  import { FilterTabs as me } from "../../components/FilterTabs.js";
13
13
  import { useMemo as he, useState as s } from "react";
@@ -10,8 +10,8 @@ import { useCursorPager as ne } from "../../hooks/useCursorPager.js";
10
10
  import "../../hooks/index.js";
11
11
  import { DataTable as l } from "../../components/DataTable.js";
12
12
  import { Pagination as re } from "../../components/Pagination.js";
13
- import { FrameworkBadge as u } from "../badges.js";
14
- import { FilterTabs as d } from "../../components/FilterTabs.js";
13
+ import { FilterTabs as u } from "../../components/FilterTabs.js";
14
+ import { FrameworkBadge as d } from "../badges.js";
15
15
  import { useMemo as f, useState as p } from "react";
16
16
  import { FileText as m, Plus as h } from "lucide-react";
17
17
  import { Fragment as g, jsx as _, jsxs as v } from "react/jsx-runtime";
@@ -72,7 +72,7 @@ function R() {
72
72
  key: "framework",
73
73
  header: "Framework",
74
74
  hideOnMobile: !0,
75
- render: (e) => /* @__PURE__ */ _(u, { framework: e.framework })
75
+ render: (e) => /* @__PURE__ */ _(d, { framework: e.framework })
76
76
  },
77
77
  {
78
78
  key: "status",
@@ -127,7 +127,7 @@ function R() {
127
127
  children: [
128
128
  /* @__PURE__ */ _("div", {
129
129
  className: "mb-5 flex flex-wrap items-center gap-3",
130
- children: /* @__PURE__ */ _(d, {
130
+ children: /* @__PURE__ */ _(u, {
131
131
  options: P,
132
132
  value: z,
133
133
  onChange: (e) => {
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ import { EcoImpactHubProvider as t, useEcoImpactHub as n } from "./ecoimpacthub/
3
3
  import { cn as r } from "./ecoimpacthub/utils/cn.js";
4
4
  import { formatCo2e as i, formatCoords as a, formatDate as o, formatDateTime as s, formatEnumLabel as c, formatNumber as l, formatPercent as u, formatQuantity as d, formatRelativeTime as f } from "./ecoimpacthub/utils/formatters.js";
5
5
  import { EcoImpactHubRoot as p } from "./ecoimpacthub/EcoImpactHubRoot.js";
6
- import { useSandboxAssistantTransport as m } from "./ecoimpacthub/services/createSandboxAssistantTransport.js";
6
+ import { EcoImpactHubAdminRoot as m } from "./ecoimpacthub/EcoImpactHubAdminRoot.js";
7
+ import { useSandboxAssistantTransport as h } from "./ecoimpacthub/services/createSandboxAssistantTransport.js";
7
8
  import "./ecoimpacthub/index.js";
8
- export { t as EcoImpactHubProvider, p as EcoImpactHubRoot, r as cn, i as formatCo2e, a as formatCoords, o as formatDate, s as formatDateTime, c as formatEnumLabel, l as formatNumber, u as formatPercent, d as formatQuantity, f as formatRelativeTime, e as joinPath, n as useEcoImpactHub, m as useSandboxAssistantTransport };
9
+ export { m as AdminRoot, m as EcoImpactHubAdminRoot, t as EcoImpactHubProvider, p as EcoImpactHubRoot, r as cn, i as formatCo2e, a as formatCoords, o as formatDate, s as formatDateTime, c as formatEnumLabel, l as formatNumber, u as formatPercent, d as formatQuantity, f as formatRelativeTime, e as joinPath, n as useEcoImpactHub, h as useSandboxAssistantTransport };
@@ -0,0 +1,9 @@
1
+ import { Meta, StoryObj } from '@storybook/react';
2
+ import { DashboardCustomizerDialog } from '../ecoimpacthub/components/DashboardCustomizerDialog';
3
+
4
+ declare const meta: Meta<typeof DashboardCustomizerDialog>;
5
+ export default meta;
6
+ type Story = StoryObj<typeof meta>;
7
+ export declare const AllWidgetsVisible: Story;
8
+ export declare const SomeHiddenWithNote: Story;
9
+ //# sourceMappingURL=DashboardCustomizerDialog.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DashboardCustomizerDialog.stories.d.ts","sourceRoot":"","sources":["../../src/stories/DashboardCustomizerDialog.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,sDAAsD,CAAC;AAwDjG,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,yBAAyB,CAKhD,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,iBAAiB,EAAE,KAI/B,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAShC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { Meta, StoryObj } from '@storybook/react';
2
+ import { DataTable } from '../ecoimpacthub/components/DataTable';
3
+
4
+ declare const meta: Meta<typeof DataTable>;
5
+ export default meta;
6
+ type Story = StoryObj<typeof meta>;
7
+ export declare const Default: Story;
8
+ export declare const Sortable: Story;
9
+ export declare const ClickableRows: Story;
10
+ export declare const Empty: Story;
11
+ //# sourceMappingURL=DataTable.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataTable.stories.d.ts","sourceRoot":"","sources":["../../src/stories/DataTable.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAe,MAAM,sCAAsC,CAAC;AAsD9E,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,SAAS,CAMhC,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAStB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAS3B,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,KAEnB,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { Meta, StoryObj } from '@storybook/react';
2
+ import { FeatureFlagGate } from '../ecoimpacthub/components/FeatureFlagGate';
3
+
4
+ /**
5
+ * FeatureFlagGate calls `useFeatureFlag(flag, true)` from
6
+ * `@burdenoff/fe-libs/shared/feature-flags`, whose `useFeatureFlags()` hook
7
+ * requires a `FeatureFlagProvider` ancestor (it throws otherwise — Storybook
8
+ * has no app shell to supply one). We wrap every story in a provider with
9
+ * `workspaceId={null}`, which skips the network fetch entirely and leaves
10
+ * every flag resolving to its default-allow value — the same behavior real
11
+ * users see when the flag service is unreachable, which is exactly the case
12
+ * this component exists to guarantee never locks anyone out.
13
+ */
14
+ declare const meta: Meta<typeof FeatureFlagGate>;
15
+ export default meta;
16
+ type Story = StoryObj<typeof meta>;
17
+ export declare const DefaultAllow: Story;
18
+ export declare const WithFallback: Story;
19
+ //# sourceMappingURL=FeatureFlagGate.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FeatureFlagGate.stories.d.ts","sourceRoot":"","sources":["../../src/stories/FeatureFlagGate.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAC;AAE7E;;;;;;;;;GASG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,eAAe,CAatC,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,YAAY,EAAE,KAS1B,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAc1B,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { Meta, StoryObj } from '@storybook/react';
2
+ import { FilterTabs } from '../ecoimpacthub/components/FilterTabs';
3
+
4
+ declare const meta: Meta<typeof FilterTabs>;
5
+ export default meta;
6
+ type Story = StoryObj<typeof meta>;
7
+ export declare const Default: Story;
8
+ export declare const WithoutCounts: Story;
9
+ //# sourceMappingURL=FilterTabs.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilterTabs.stories.d.ts","sourceRoot":"","sources":["../../src/stories/FilterTabs.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAqB,MAAM,uCAAuC,CAAC;AAUtF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,UAAU,CAMjC,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAKrB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAW3B,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { Meta, StoryObj } from '@storybook/react';
2
+ import { PageLayout } from '../ecoimpacthub/components/PageLayout';
3
+
4
+ declare const meta: Meta<typeof PageLayout>;
5
+ export default meta;
6
+ type Story = StoryObj<typeof meta>;
7
+ export declare const Default: Story;
8
+ export declare const AuroraHero: Story;
9
+ export declare const NoActions: Story;
10
+ //# sourceMappingURL=PageLayout.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PageLayout.stories.d.ts","sourceRoot":"","sources":["../../src/stories/PageLayout.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AAEnE,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,UAAU,CAMjC,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAWrB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAWxB,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAMvB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { Meta, StoryObj } from '@storybook/react';
2
+ import { Pagination } from '../ecoimpacthub/components/Pagination';
3
+
4
+ declare const meta: Meta<typeof Pagination>;
5
+ export default meta;
6
+ type Story = StoryObj<typeof meta>;
7
+ export declare const MiddlePage: Story;
8
+ export declare const FirstPage: Story;
9
+ export declare const LastPage: Story;
10
+ export declare const SinglePage: Story;
11
+ //# sourceMappingURL=Pagination.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Pagination.stories.d.ts","sourceRoot":"","sources":["../../src/stories/Pagination.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AAEnE,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,UAAU,CAMjC,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,UAAU,EAAE,KAKxB,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAKvB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAOtB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAIxB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { Meta, StoryObj } from '@storybook/react';
2
+ import { LoadingView, ErrorView, Section } from '../ecoimpacthub/components/StateViews';
3
+
4
+ declare const meta: Meta;
5
+ export default meta;
6
+ export declare const Loading: StoryObj<typeof LoadingView>;
7
+ export declare const Error: StoryObj<typeof ErrorView>;
8
+ export declare const ErrorWithoutRetry: StoryObj<typeof ErrorView>;
9
+ export declare const SectionWithAction: StoryObj<typeof Section>;
10
+ //# sourceMappingURL=StateViews.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StateViews.stories.d.ts","sourceRoot":"","sources":["../../src/stories/StateViews.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,uCAAuC,CAAC;AAExF,QAAA,MAAM,IAAI,EAAE,IAKX,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,eAAO,MAAM,OAAO,EAAE,QAAQ,CAAC,OAAO,WAAW,CAKhD,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,QAAQ,CAAC,OAAO,SAAS,CAO5C,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,OAAO,SAAS,CAKxD,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,OAAO,OAAO,CAetD,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { Meta, StoryObj } from '@storybook/react';
2
+ import { Tabs } from '../ecoimpacthub/components/Tabs';
3
+
4
+ declare const meta: Meta<typeof Tabs>;
5
+ export default meta;
6
+ type Story = StoryObj<typeof meta>;
7
+ export declare const Default: Story;
8
+ export declare const NoCounts: Story;
9
+ //# sourceMappingURL=Tabs.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Tabs.stories.d.ts","sourceRoot":"","sources":["../../src/stories/Tabs.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EAAE,IAAI,EAAgB,MAAM,iCAAiC,CAAC;AAoBrE,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,IAAI,CAM3B,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAKrB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAWtB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-ecoimpacthub",
3
- "version": "2026.720.5",
3
+ "version": "2026.720.6",
4
4
  "description": "Burdenoff EcoImpactHub Microfrontend",
5
5
  "type": "module",
6
6
  "files": [