@burdenoff/microfe-assethandler 2026.714.2 → 2026.719.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/dist/assethandler/AssetHandlerRoutes.d.ts.map +1 -1
  2. package/dist/assethandler/AssetHandlerRoutes.js +9 -17
  3. package/dist/assethandler/AssetHandlerRoutes.js.map +1 -1
  4. package/dist/assethandler/ops/NewWorkOrderDialog.d.ts.map +1 -1
  5. package/dist/assethandler/ops/NewWorkOrderDialog.js +110 -74
  6. package/dist/assethandler/ops/NewWorkOrderDialog.js.map +1 -1
  7. package/dist/assethandler/pages/AssetsAssetCreatePage.d.ts.map +1 -1
  8. package/dist/assethandler/pages/AssetsAssetCreatePage.js +189 -126
  9. package/dist/assethandler/pages/AssetsAssetCreatePage.js.map +1 -1
  10. package/dist/assethandler/pages/AssetsAssetDetailPage.d.ts.map +1 -1
  11. package/dist/assethandler/pages/AssetsAssetDetailPage.js +312 -251
  12. package/dist/assethandler/pages/AssetsAssetDetailPage.js.map +1 -1
  13. package/dist/assethandler/pages/OperationsWorkOrderDetailPage.d.ts.map +1 -1
  14. package/dist/assethandler/pages/OperationsWorkOrderDetailPage.js +286 -222
  15. package/dist/assethandler/pages/OperationsWorkOrderDetailPage.js.map +1 -1
  16. package/dist/stories/ListEmptyState.stories.d.ts +10 -0
  17. package/dist/stories/ListEmptyState.stories.d.ts.map +1 -0
  18. package/dist/stories/SectionHeader.stories.d.ts +10 -0
  19. package/dist/stories/SectionHeader.stories.d.ts.map +1 -0
  20. package/dist/stories/StatTile.stories.d.ts +10 -0
  21. package/dist/stories/StatTile.stories.d.ts.map +1 -0
  22. package/dist/utils/pageContext.d.ts.map +1 -1
  23. package/dist/utils/pageContext.js +26 -18
  24. package/dist/utils/pageContext.js.map +1 -1
  25. package/package.json +16 -3
  26. package/dist/assethandler/pages/EsgDashboardPage.js +0 -423
  27. package/dist/assethandler/pages/EsgDashboardPage.js.map +0 -1
  28. package/dist/assethandler/pages/KnowledgeBasePage.js +0 -521
  29. package/dist/assethandler/pages/KnowledgeBasePage.js.map +0 -1
@@ -1,423 +0,0 @@
1
- import { cn as e } from "../utils/cn.js";
2
- import { notify as t } from "../utils/toast.js";
3
- import { formatNumber as n, seriesColor as r } from "../components/charts/chartTheme.js";
4
- import { BarsChart as i } from "../components/charts/BarsChart.js";
5
- import { DonutChart as a } from "../components/charts/DonutChart.js";
6
- import { Pagination as o, usePagination as s } from "../components/Pagination.js";
7
- import { StatTile as c } from "../components/StatTile.js";
8
- import { ChartCard as l } from "../components/ChartCard.js";
9
- import { SectionHeader as u } from "../components/SectionHeader.js";
10
- import "../components/index.js";
11
- import { useMemo as d, useState as f } from "react";
12
- import { Leaf as p, Minus as m, Plus as h, TrendingDown as g, TrendingUp as _ } from "lucide-react";
13
- import { gql as v } from "@apollo/client";
14
- import { useMutation as y, useQuery as b } from "@apollo/client/react";
15
- import { Fragment as x, jsx as S, jsxs as C } from "react/jsx-runtime";
16
- import { Button as w, GlassCard as T, IllustratedEmptyState as E, Input as D, Label as O, PagePurpose as k, ResponsiveDialog as A, ResponsiveDialogContent as j, ResponsiveDialogDescription as M, ResponsiveDialogFooter as N, ResponsiveDialogHeader as P, ResponsiveDialogTitle as F, Select as I, SelectContent as L, SelectItem as R, SelectTrigger as z, SelectValue as B } from "@burdenoff/fe-libs/ui";
17
- //#region src/assethandler/pages/EsgDashboardPage.tsx
18
- var V = v`
19
- query AssetHandlerEsgMetrics {
20
- esgMetrics {
21
- id
22
- metricKey
23
- metricName
24
- category
25
- unit
26
- value
27
- target
28
- trend
29
- periodStart
30
- periodEnd
31
- }
32
- }
33
- `, H = v`
34
- mutation AssetHandlerUpsertEsgMetric($input: UpsertEsgMetricInput!) {
35
- upsertEsgMetric(input: $input) {
36
- id
37
- metricName
38
- }
39
- }
40
- `, U = [
41
- "environment",
42
- "social",
43
- "governance"
44
- ], W = [
45
- "improving",
46
- "stable",
47
- "declining"
48
- ], G = {
49
- improving: {
50
- label: "Improving",
51
- icon: _,
52
- tone: "positive",
53
- dir: "up"
54
- },
55
- declining: {
56
- label: "Declining",
57
- icon: g,
58
- tone: "negative",
59
- dir: "down"
60
- },
61
- stable: {
62
- label: "Stable",
63
- icon: m,
64
- tone: "neutral",
65
- dir: "neutral"
66
- }
67
- }, K = {
68
- positive: "bg-status-success-bg-subtle text-status-success-text",
69
- negative: "bg-status-error-bg-subtle text-status-error-text",
70
- neutral: "bg-bg-sunken text-text-secondary"
71
- }, q = (e) => e.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
72
- function J() {
73
- let e = /* @__PURE__ */ new Date();
74
- return new Date(e.getFullYear(), e.getMonth(), 1).toISOString().slice(0, 10);
75
- }
76
- function Y() {
77
- return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
78
- }
79
- function X({ trend: t }) {
80
- let n = G[t ?? "stable"] ?? G.stable, r = n.icon;
81
- return /* @__PURE__ */ C("span", {
82
- className: e("inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium", K[n.tone]),
83
- children: [/* @__PURE__ */ S(r, { className: "h-3 w-3" }), n.label]
84
- });
85
- }
86
- function Z({ open: e, onOpenChange: n, onSaved: r }) {
87
- let [i, a] = f(""), [o, s] = f("environment"), [c, l] = f(""), [u, d] = f(""), [p, m] = f(""), [h, g] = f("stable"), [_, v] = f(J()), [b, x] = f(Y()), [T, { loading: E }] = y(H, {
88
- onCompleted: (e) => {
89
- t.success("Metric saved", `${e.upsertEsgMetric.metricName} was recorded.`), a(""), l(""), d(""), m(""), n(!1), r();
90
- },
91
- onError: (e) => t.error("Could not save metric", e.message)
92
- });
93
- return /* @__PURE__ */ S(A, {
94
- open: e,
95
- onOpenChange: n,
96
- children: /* @__PURE__ */ C(j, {
97
- className: "max-h-[85vh] overflow-y-auto sm:max-w-2xl",
98
- children: [/* @__PURE__ */ C(P, { children: [/* @__PURE__ */ S(F, { children: "Save Metric" }), /* @__PURE__ */ S(M, { children: "Record an ESG metric to track progress toward your sustainability targets." })] }), /* @__PURE__ */ C("form", {
99
- className: "space-y-3",
100
- onSubmit: (e) => {
101
- e.preventDefault();
102
- let n = Number(u);
103
- if (!i.trim() || !c.trim()) {
104
- t.warning("Missing details", "Metric name and unit are required.");
105
- return;
106
- }
107
- if (!Number.isFinite(n) || u.trim() === "") {
108
- t.warning("Invalid value", "Enter a numeric metric value.");
109
- return;
110
- }
111
- if (!_ || !b) {
112
- t.warning("Missing period", "Period start and end are required.");
113
- return;
114
- }
115
- let r = p.trim() === "" ? null : Number(p);
116
- T({ variables: { input: {
117
- metricKey: q(i),
118
- metricName: i.trim(),
119
- category: o,
120
- unit: c.trim(),
121
- value: n,
122
- target: r != null && Number.isFinite(r) ? r : null,
123
- trend: h,
124
- periodStart: new Date(_).toISOString(),
125
- periodEnd: new Date(b).toISOString()
126
- } } });
127
- },
128
- children: [
129
- /* @__PURE__ */ C("div", {
130
- className: "grid gap-3 md:grid-cols-3",
131
- children: [
132
- /* @__PURE__ */ C("div", {
133
- className: "space-y-2",
134
- children: [/* @__PURE__ */ S(O, { children: "Metric Name *" }), /* @__PURE__ */ S(D, {
135
- placeholder: "e.g., Scope 2 carbon emissions",
136
- value: i,
137
- onChange: (e) => a(e.target.value)
138
- })]
139
- }),
140
- /* @__PURE__ */ C("div", {
141
- className: "space-y-2",
142
- children: [/* @__PURE__ */ S(O, { children: "Category" }), /* @__PURE__ */ C(I, {
143
- value: o,
144
- onValueChange: (e) => s(e),
145
- children: [/* @__PURE__ */ S(z, { children: /* @__PURE__ */ S(B, {}) }), /* @__PURE__ */ S(L, { children: U.map((e) => /* @__PURE__ */ S(R, {
146
- value: e,
147
- className: "capitalize",
148
- children: e
149
- }, e)) })]
150
- })]
151
- }),
152
- /* @__PURE__ */ C("div", {
153
- className: "space-y-2",
154
- children: [/* @__PURE__ */ S(O, { children: "Unit *" }), /* @__PURE__ */ S(D, {
155
- placeholder: "e.g., tCO2e",
156
- value: c,
157
- onChange: (e) => l(e.target.value)
158
- })]
159
- })
160
- ]
161
- }),
162
- /* @__PURE__ */ C("div", {
163
- className: "grid gap-3 md:grid-cols-3",
164
- children: [
165
- /* @__PURE__ */ C("div", {
166
- className: "space-y-2",
167
- children: [/* @__PURE__ */ S(O, { children: "Value *" }), /* @__PURE__ */ S(D, {
168
- type: "number",
169
- step: "any",
170
- value: u,
171
- onChange: (e) => d(e.target.value)
172
- })]
173
- }),
174
- /* @__PURE__ */ C("div", {
175
- className: "space-y-2",
176
- children: [/* @__PURE__ */ S(O, { children: "Target" }), /* @__PURE__ */ S(D, {
177
- type: "number",
178
- step: "any",
179
- value: p,
180
- onChange: (e) => m(e.target.value)
181
- })]
182
- }),
183
- /* @__PURE__ */ C("div", {
184
- className: "space-y-2",
185
- children: [/* @__PURE__ */ S(O, { children: "Trend" }), /* @__PURE__ */ C(I, {
186
- value: h,
187
- onValueChange: (e) => g(e),
188
- children: [/* @__PURE__ */ S(z, { children: /* @__PURE__ */ S(B, {}) }), /* @__PURE__ */ S(L, { children: W.map((e) => /* @__PURE__ */ S(R, {
189
- value: e,
190
- className: "capitalize",
191
- children: e
192
- }, e)) })]
193
- })]
194
- })
195
- ]
196
- }),
197
- /* @__PURE__ */ C("div", {
198
- className: "grid gap-3 md:grid-cols-2",
199
- children: [/* @__PURE__ */ C("div", {
200
- className: "space-y-2",
201
- children: [/* @__PURE__ */ S(O, { children: "Period Start *" }), /* @__PURE__ */ S(D, {
202
- type: "date",
203
- value: _,
204
- onChange: (e) => v(e.target.value)
205
- })]
206
- }), /* @__PURE__ */ C("div", {
207
- className: "space-y-2",
208
- children: [/* @__PURE__ */ S(O, { children: "Period End *" }), /* @__PURE__ */ S(D, {
209
- type: "date",
210
- value: b,
211
- onChange: (e) => x(e.target.value)
212
- })]
213
- })]
214
- }),
215
- /* @__PURE__ */ C(N, { children: [/* @__PURE__ */ S(w, {
216
- type: "button",
217
- variant: "outline",
218
- onClick: () => n(!1),
219
- disabled: E,
220
- children: "Cancel"
221
- }), /* @__PURE__ */ S(w, {
222
- type: "submit",
223
- disabled: E,
224
- children: E ? "Saving…" : "Save Metric"
225
- })] })
226
- ]
227
- })]
228
- })
229
- });
230
- }
231
- function Q() {
232
- let [t, m] = f(!1), [g, _] = f("ALL"), { data: v, loading: y, refetch: D } = b(V, { fetchPolicy: "cache-and-network" }), O = d(() => v?.esgMetrics ?? [], [v?.esgMetrics]), A = d(() => O.slice(0, 4), [O]), j = d(() => g === "ALL" ? O : O.filter((e) => e.category === g), [O, g]), M = d(() => {
233
- let e = O.reduce((e, t) => (e[t.category] = (e[t.category] ?? 0) + 1, e), {});
234
- return Object.entries(e).map(([e, t], n) => ({
235
- name: e.charAt(0).toUpperCase() + e.slice(1),
236
- value: t,
237
- color: r(n)
238
- }));
239
- }, [O]), N = d(() => O.filter((e) => e.target != null).slice(0, 8).map((e) => ({
240
- name: e.metricName,
241
- value: e.value,
242
- target: e.target
243
- })), [O]), P = d(() => {
244
- let e = { ALL: O.length };
245
- for (let t of O) e[t.category] = (e[t.category] ?? 0) + 1;
246
- return e;
247
- }, [O]), F = s(j, {
248
- pageSize: 8,
249
- resetKey: g
250
- });
251
- return /* @__PURE__ */ C("div", {
252
- className: "space-y-5 p-4 sm:p-6",
253
- children: [
254
- /* @__PURE__ */ S(u, {
255
- hero: !0,
256
- icon: p,
257
- title: "ESG Dashboard",
258
- description: "Measure the environmental and governance impact of your estate against targets.",
259
- actions: /* @__PURE__ */ C(w, {
260
- className: "w-full sm:w-auto",
261
- onClick: () => m(!0),
262
- children: [/* @__PURE__ */ S(h, { className: "mr-2 h-4 w-4" }), "Save Metric"]
263
- })
264
- }),
265
- /* @__PURE__ */ S(k, { children: "Track energy use, carbon emissions and responsible disposal against targets — and produce the evidence ESG reporting and audits require." }),
266
- /* @__PURE__ */ S(Z, {
267
- open: t,
268
- onOpenChange: m,
269
- onSaved: () => void D()
270
- }),
271
- y && O.length === 0 ? /* @__PURE__ */ S("div", {
272
- className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-4",
273
- children: Array.from({ length: 4 }).map((e, t) => /* @__PURE__ */ S("div", { className: "h-28 rounded-xl bg-bg-sunken motion-safe:animate-vc-shimmer" }, t))
274
- }) : null,
275
- !y && O.length === 0 ? /* @__PURE__ */ S(E, {
276
- illustration: "empty-data",
277
- title: "No ESG metrics recorded yet",
278
- description: "Save a metric to start tracking sustainability progress against your targets."
279
- }) : null,
280
- A.length > 0 ? /* @__PURE__ */ S("div", {
281
- className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-4",
282
- children: A.map((e) => {
283
- let t = G[e.trend ?? "stable"] ?? G.stable;
284
- return /* @__PURE__ */ S(c, {
285
- label: `${e.metricName} (${e.unit})`,
286
- value: e.value,
287
- format: n,
288
- delta: t.label,
289
- deltaDirection: t.dir,
290
- deltaTone: t.tone,
291
- icon: p
292
- }, e.id);
293
- })
294
- }) : null,
295
- O.length > 0 ? /* @__PURE__ */ C("div", {
296
- className: "grid gap-4 lg:grid-cols-2",
297
- children: [/* @__PURE__ */ S(l, {
298
- title: "Value vs. target",
299
- subtitle: "Metrics measured against their targets",
300
- children: N.length > 0 ? /* @__PURE__ */ S(i, {
301
- data: N,
302
- xKey: "name",
303
- series: [{
304
- key: "value",
305
- label: "Value"
306
- }, {
307
- key: "target",
308
- label: "Target"
309
- }],
310
- orientation: "horizontal",
311
- height: 240,
312
- categoryWidth: 150,
313
- ariaLabel: "Metric value versus target"
314
- }) : /* @__PURE__ */ S("div", {
315
- className: "flex h-[240px] items-center justify-center text-sm text-text-secondary",
316
- children: "Set a target on a metric to compare value against target."
317
- })
318
- }), /* @__PURE__ */ S(l, {
319
- title: "By category",
320
- subtitle: "Metrics across E / S / G",
321
- children: /* @__PURE__ */ S(a, {
322
- data: M,
323
- height: 240,
324
- centerLabel: "Metrics",
325
- centerValue: O.length,
326
- ariaLabel: "Metrics by category"
327
- })
328
- })]
329
- }) : null,
330
- O.length > 0 ? /* @__PURE__ */ C(x, { children: [
331
- /* @__PURE__ */ S("div", {
332
- className: "flex flex-wrap items-center gap-2",
333
- children: ["ALL", ...U].map((t) => /* @__PURE__ */ C("button", {
334
- type: "button",
335
- onClick: () => _(t),
336
- className: e("rounded-full px-3.5 py-1.5 text-sm font-medium capitalize transition-colors", g === t ? "bg-action-primary-bg text-action-primary-text" : "bg-bg-sunken text-text-secondary hover:text-text-primary"),
337
- children: [t === "ALL" ? "All" : t, /* @__PURE__ */ S("span", {
338
- className: "ml-1.5 text-xs opacity-70 tabular-nums",
339
- children: P[t] ?? 0
340
- })]
341
- }, t))
342
- }),
343
- /* @__PURE__ */ S("div", {
344
- className: "grid gap-4 sm:grid-cols-2",
345
- children: F.pageItems.map((e) => {
346
- let t = e.target && e.target > 0 ? Math.min(100, Math.round(e.value / e.target * 100)) : null;
347
- return /* @__PURE__ */ S(T, {
348
- treatment: "glass",
349
- className: "border-border-seam",
350
- children: /* @__PURE__ */ C("div", {
351
- className: "space-y-3 p-4",
352
- children: [
353
- /* @__PURE__ */ C("div", {
354
- className: "flex items-start justify-between gap-2",
355
- children: [/* @__PURE__ */ C("div", {
356
- className: "min-w-0",
357
- children: [/* @__PURE__ */ S("p", {
358
- className: "text-xs uppercase tracking-wide text-text-secondary",
359
- children: e.category
360
- }), /* @__PURE__ */ S("h2", {
361
- className: "mt-0.5 text-base font-semibold text-text-primary",
362
- children: e.metricName
363
- })]
364
- }), /* @__PURE__ */ S(X, { trend: e.trend })]
365
- }),
366
- /* @__PURE__ */ C("div", {
367
- className: "flex items-baseline gap-2",
368
- children: [
369
- /* @__PURE__ */ S("span", {
370
- className: "text-2xl font-bold tabular-nums text-text-primary",
371
- children: n(e.value)
372
- }),
373
- /* @__PURE__ */ S("span", {
374
- className: "text-sm text-text-secondary",
375
- children: e.unit
376
- }),
377
- e.target == null ? null : /* @__PURE__ */ C("span", {
378
- className: "text-xs text-text-muted",
379
- children: ["target ", n(e.target)]
380
- })
381
- ]
382
- }),
383
- t == null ? null : /* @__PURE__ */ C("div", {
384
- className: "space-y-1",
385
- children: [/* @__PURE__ */ C("div", {
386
- className: "flex items-center justify-between text-xs text-text-secondary",
387
- children: [/* @__PURE__ */ S("span", { children: "Progress to target" }), /* @__PURE__ */ C("span", {
388
- className: "font-medium tabular-nums",
389
- children: [t, "%"]
390
- })]
391
- }), /* @__PURE__ */ S("div", {
392
- className: "h-2 overflow-hidden rounded-full bg-bg-sunken",
393
- children: /* @__PURE__ */ S("div", {
394
- className: "h-full rounded-full bg-action-primary-bg",
395
- style: { width: `${t}%` }
396
- })
397
- })]
398
- })
399
- ]
400
- })
401
- }, e.id);
402
- })
403
- }),
404
- /* @__PURE__ */ S(o, {
405
- page: F.page,
406
- pageCount: F.pageCount,
407
- rangeStart: F.rangeStart,
408
- rangeEnd: F.rangeEnd,
409
- totalItems: F.totalItems,
410
- canPrev: F.canPrev,
411
- canNext: F.canNext,
412
- onPrev: F.prevPage,
413
- onNext: F.nextPage,
414
- itemLabel: "metrics"
415
- })
416
- ] }) : null
417
- ]
418
- });
419
- }
420
- //#endregion
421
- export { Q as EsgDashboardPage };
422
-
423
- //# sourceMappingURL=EsgDashboardPage.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"EsgDashboardPage.js","names":[],"sources":["../../../src/assethandler/pages/EsgDashboardPage.tsx"],"sourcesContent":["import { Leaf, Plus, TrendingUp, TrendingDown, Minus } from 'lucide-react';\nimport type React from 'react';\nimport {\n Button,\n IllustratedEmptyState,\n GlassCard,\n PagePurpose,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { useMemo, useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport {\n Pagination,\n usePagination,\n SectionHeader,\n StatTile,\n ChartCard,\n DonutChart,\n BarsChart,\n seriesColor,\n formatNumber,\n type DonutSlice,\n} from '../components';\nimport { cn } from '../utils/cn';\nimport { notify } from '../utils/toast';\n\nconst ESG_METRICS_QUERY = gql`\n query AssetHandlerEsgMetrics {\n esgMetrics {\n id\n metricKey\n metricName\n category\n unit\n value\n target\n trend\n periodStart\n periodEnd\n }\n }\n`;\n\nconst UPSERT_ESG_METRIC_MUTATION = gql`\n mutation AssetHandlerUpsertEsgMetric($input: UpsertEsgMetricInput!) {\n upsertEsgMetric(input: $input) {\n id\n metricName\n }\n }\n`;\n\ninterface EsgMetric {\n id: string;\n metricKey: string;\n metricName: string;\n category: string;\n unit: string;\n value: number;\n target: number | null;\n trend: string | null;\n periodStart: string;\n periodEnd: string;\n}\n\ninterface UpsertEsgMetricResult {\n upsertEsgMetric: { id: string; metricName: string };\n}\n\nconst ESG_CATEGORIES = ['environment', 'social', 'governance'] as const;\nconst ESG_TRENDS = ['improving', 'stable', 'declining'] as const;\n\nconst TREND_META: Record<\n string,\n {\n label: string;\n icon: typeof TrendingUp;\n tone: 'positive' | 'negative' | 'neutral';\n dir: 'up' | 'down' | 'neutral';\n }\n> = {\n improving: { label: 'Improving', icon: TrendingUp, tone: 'positive', dir: 'up' },\n declining: { label: 'Declining', icon: TrendingDown, tone: 'negative', dir: 'down' },\n stable: { label: 'Stable', icon: Minus, tone: 'neutral', dir: 'neutral' },\n};\n\nconst TREND_PILL: Record<'positive' | 'negative' | 'neutral', string> = {\n positive: 'bg-status-success-bg-subtle text-status-success-text',\n negative: 'bg-status-error-bg-subtle text-status-error-text',\n neutral: 'bg-bg-sunken text-text-secondary',\n};\n\nconst slugify = (value: string): string =>\n value\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n\nfunction firstOfMonthISO(): string {\n const now = new Date();\n return new Date(now.getFullYear(), now.getMonth(), 1).toISOString().slice(0, 10);\n}\n\nfunction todayISO(): string {\n return new Date().toISOString().slice(0, 10);\n}\n\nfunction TrendBadge({ trend }: { trend: string | null }) {\n const meta = TREND_META[trend ?? 'stable'] ?? TREND_META.stable;\n const Icon = meta.icon;\n return (\n <span\n className={cn(\n 'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium',\n TREND_PILL[meta.tone]\n )}\n >\n <Icon className=\"h-3 w-3\" />\n {meta.label}\n </span>\n );\n}\n\nfunction RecordMetricDialog({\n open,\n onOpenChange,\n onSaved,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onSaved: () => void;\n}) {\n const [metricName, setMetricName] = useState('');\n const [category, setCategory] = useState<(typeof ESG_CATEGORIES)[number]>('environment');\n const [unit, setUnit] = useState('');\n const [value, setValue] = useState('');\n const [target, setTarget] = useState('');\n const [trend, setTrend] = useState<(typeof ESG_TRENDS)[number]>('stable');\n const [periodStart, setPeriodStart] = useState(firstOfMonthISO());\n const [periodEnd, setPeriodEnd] = useState(todayISO());\n\n const [upsertEsgMetric, { loading: saving }] = useMutation<UpsertEsgMetricResult>(\n UPSERT_ESG_METRIC_MUTATION,\n {\n onCompleted: (result) => {\n notify.success('Metric saved', `${result.upsertEsgMetric.metricName} was recorded.`);\n setMetricName('');\n setUnit('');\n setValue('');\n setTarget('');\n onOpenChange(false);\n onSaved();\n },\n onError: (error) => notify.error('Could not save metric', error.message),\n }\n );\n\n const handleSubmit = (event: React.FormEvent) => {\n event.preventDefault();\n const parsedValue = Number(value);\n if (!metricName.trim() || !unit.trim()) {\n notify.warning('Missing details', 'Metric name and unit are required.');\n return;\n }\n if (!Number.isFinite(parsedValue) || value.trim() === '') {\n notify.warning('Invalid value', 'Enter a numeric metric value.');\n return;\n }\n if (!periodStart || !periodEnd) {\n notify.warning('Missing period', 'Period start and end are required.');\n return;\n }\n const parsedTarget = target.trim() === '' ? null : Number(target);\n void upsertEsgMetric({\n variables: {\n input: {\n metricKey: slugify(metricName),\n metricName: metricName.trim(),\n category,\n unit: unit.trim(),\n value: parsedValue,\n target: parsedTarget != null && Number.isFinite(parsedTarget) ? parsedTarget : null,\n trend,\n periodStart: new Date(periodStart).toISOString(),\n periodEnd: new Date(periodEnd).toISOString(),\n },\n },\n });\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"max-h-[85vh] overflow-y-auto sm:max-w-2xl\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Save Metric</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Record an ESG metric to track progress toward your sustainability targets.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <form className=\"space-y-3\" onSubmit={handleSubmit}>\n <div className=\"grid gap-3 md:grid-cols-3\">\n <div className=\"space-y-2\">\n <Label>Metric Name *</Label>\n <Input\n placeholder=\"e.g., Scope 2 carbon emissions\"\n value={metricName}\n onChange={(e) => setMetricName(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Category</Label>\n <Select value={category} onValueChange={(v) => setCategory(v as typeof category)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {ESG_CATEGORIES.map((c) => (\n <SelectItem key={c} value={c} className=\"capitalize\">\n {c}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label>Unit *</Label>\n <Input\n placeholder=\"e.g., tCO2e\"\n value={unit}\n onChange={(e) => setUnit(e.target.value)}\n />\n </div>\n </div>\n <div className=\"grid gap-3 md:grid-cols-3\">\n <div className=\"space-y-2\">\n <Label>Value *</Label>\n <Input\n type=\"number\"\n step=\"any\"\n value={value}\n onChange={(e) => setValue(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Target</Label>\n <Input\n type=\"number\"\n step=\"any\"\n value={target}\n onChange={(e) => setTarget(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Trend</Label>\n <Select value={trend} onValueChange={(v) => setTrend(v as typeof trend)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {ESG_TRENDS.map((t) => (\n <SelectItem key={t} value={t} className=\"capitalize\">\n {t}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n <div className=\"grid gap-3 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Period Start *</Label>\n <Input\n type=\"date\"\n value={periodStart}\n onChange={(e) => setPeriodStart(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Period End *</Label>\n <Input type=\"date\" value={periodEnd} onChange={(e) => setPeriodEnd(e.target.value)} />\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={saving}\n >\n Cancel\n </Button>\n <Button type=\"submit\" disabled={saving}>\n {saving ? 'Saving…' : 'Save Metric'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\nexport function EsgDashboardPage() {\n const [dialogOpen, setDialogOpen] = useState(false);\n const [category, setCategory] = useState<string>('ALL');\n\n const { data, loading, refetch } = useQuery<{ esgMetrics: EsgMetric[] }>(ESG_METRICS_QUERY, {\n fetchPolicy: 'cache-and-network',\n });\n\n const metrics = useMemo(() => data?.esgMetrics ?? [], [data?.esgMetrics]);\n\n const headline = useMemo(() => metrics.slice(0, 4), [metrics]);\n\n const filtered = useMemo(\n () => (category === 'ALL' ? metrics : metrics.filter((m) => m.category === category)),\n [metrics, category]\n );\n\n const categoryMix = useMemo<DonutSlice[]>(() => {\n const counts = metrics.reduce<Record<string, number>>((acc, m) => {\n acc[m.category] = (acc[m.category] ?? 0) + 1;\n return acc;\n }, {});\n return Object.entries(counts).map(([cat, value], i) => ({\n name: cat.charAt(0).toUpperCase() + cat.slice(1),\n value,\n color: seriesColor(i),\n }));\n }, [metrics]);\n\n const valueVsTarget = useMemo(\n () =>\n metrics\n .filter((m) => m.target != null)\n .slice(0, 8)\n .map((m) => ({ name: m.metricName, value: m.value, target: m.target as number })),\n [metrics]\n );\n\n const categoryCounts = useMemo(() => {\n const counts: Record<string, number> = { ALL: metrics.length };\n for (const m of metrics) counts[m.category] = (counts[m.category] ?? 0) + 1;\n return counts;\n }, [metrics]);\n\n const pagination = usePagination(filtered, { pageSize: 8, resetKey: category });\n\n return (\n <div className=\"space-y-5 p-4 sm:p-6\">\n <SectionHeader\n hero\n icon={Leaf}\n title=\"ESG Dashboard\"\n description=\"Measure the environmental and governance impact of your estate against targets.\"\n actions={\n <Button className=\"w-full sm:w-auto\" onClick={() => setDialogOpen(true)}>\n <Plus className=\"mr-2 h-4 w-4\" />\n Save Metric\n </Button>\n }\n />\n <PagePurpose>\n Track energy use, carbon emissions and responsible disposal against targets — and produce\n the evidence ESG reporting and audits require.\n </PagePurpose>\n\n <RecordMetricDialog\n open={dialogOpen}\n onOpenChange={setDialogOpen}\n onSaved={() => void refetch()}\n />\n\n {loading && metrics.length === 0 ? (\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n {Array.from({ length: 4 }).map((_, i) => (\n <div key={i} className=\"h-28 rounded-xl bg-bg-sunken motion-safe:animate-vc-shimmer\" />\n ))}\n </div>\n ) : null}\n\n {!loading && metrics.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No ESG metrics recorded yet\"\n description=\"Save a metric to start tracking sustainability progress against your targets.\"\n />\n ) : null}\n\n {headline.length > 0 ? (\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n {headline.map((m) => {\n const meta = TREND_META[m.trend ?? 'stable'] ?? TREND_META.stable;\n return (\n <StatTile\n key={m.id}\n label={`${m.metricName} (${m.unit})`}\n value={m.value}\n format={formatNumber}\n delta={meta.label}\n deltaDirection={meta.dir}\n deltaTone={meta.tone}\n icon={Leaf}\n />\n );\n })}\n </div>\n ) : null}\n\n {metrics.length > 0 ? (\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <ChartCard title=\"Value vs. target\" subtitle=\"Metrics measured against their targets\">\n {valueVsTarget.length > 0 ? (\n <BarsChart\n data={valueVsTarget}\n xKey=\"name\"\n series={[\n { key: 'value', label: 'Value' },\n { key: 'target', label: 'Target' },\n ]}\n orientation=\"horizontal\"\n height={240}\n categoryWidth={150}\n ariaLabel=\"Metric value versus target\"\n />\n ) : (\n <div className=\"flex h-[240px] items-center justify-center text-sm text-text-secondary\">\n Set a target on a metric to compare value against target.\n </div>\n )}\n </ChartCard>\n <ChartCard title=\"By category\" subtitle=\"Metrics across E / S / G\">\n <DonutChart\n data={categoryMix}\n height={240}\n centerLabel=\"Metrics\"\n centerValue={metrics.length}\n ariaLabel=\"Metrics by category\"\n />\n </ChartCard>\n </div>\n ) : null}\n\n {metrics.length > 0 ? (\n <>\n <div className=\"flex flex-wrap items-center gap-2\">\n {(['ALL', ...ESG_CATEGORIES] as const).map((c) => (\n <button\n key={c}\n type=\"button\"\n onClick={() => setCategory(c)}\n className={cn(\n 'rounded-full px-3.5 py-1.5 text-sm font-medium capitalize transition-colors',\n category === c\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-sunken text-text-secondary hover:text-text-primary'\n )}\n >\n {c === 'ALL' ? 'All' : c}\n <span className=\"ml-1.5 text-xs opacity-70 tabular-nums\">\n {categoryCounts[c] ?? 0}\n </span>\n </button>\n ))}\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n {pagination.pageItems.map((metric) => {\n const pct =\n metric.target && metric.target > 0\n ? Math.min(100, Math.round((metric.value / metric.target) * 100))\n : null;\n return (\n <GlassCard key={metric.id} treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"space-y-3 p-4\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">\n {metric.category}\n </p>\n <h2 className=\"mt-0.5 text-base font-semibold text-text-primary\">\n {metric.metricName}\n </h2>\n </div>\n <TrendBadge trend={metric.trend} />\n </div>\n <div className=\"flex items-baseline gap-2\">\n <span className=\"text-2xl font-bold tabular-nums text-text-primary\">\n {formatNumber(metric.value)}\n </span>\n <span className=\"text-sm text-text-secondary\">{metric.unit}</span>\n {metric.target != null ? (\n <span className=\"text-xs text-text-muted\">\n target {formatNumber(metric.target)}\n </span>\n ) : null}\n </div>\n {pct != null ? (\n <div className=\"space-y-1\">\n <div className=\"flex items-center justify-between text-xs text-text-secondary\">\n <span>Progress to target</span>\n <span className=\"font-medium tabular-nums\">{pct}%</span>\n </div>\n <div className=\"h-2 overflow-hidden rounded-full bg-bg-sunken\">\n <div\n className=\"h-full rounded-full bg-action-primary-bg\"\n style={{ width: `${pct}%` }}\n />\n </div>\n </div>\n ) : null}\n </div>\n </GlassCard>\n );\n })}\n </div>\n\n <Pagination\n page={pagination.page}\n pageCount={pagination.pageCount}\n rangeStart={pagination.rangeStart}\n rangeEnd={pagination.rangeEnd}\n totalItems={pagination.totalItems}\n canPrev={pagination.canPrev}\n canNext={pagination.canNext}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"metrics\"\n />\n </>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}