@burdenoff/microfe-proserviceworld 2026.625.1 → 2026.626.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 (31) hide show
  1. package/dist/proserviceworld/pages/AdminReportsPage.js +102 -68
  2. package/dist/proserviceworld/pages/AdminReportsPage.js.map +1 -1
  3. package/dist/proserviceworld/pages/AdminUsersPage.js +37 -33
  4. package/dist/proserviceworld/pages/AdminUsersPage.js.map +1 -1
  5. package/dist/proserviceworld/pages/AnalyticsPage.js +66 -36
  6. package/dist/proserviceworld/pages/AnalyticsPage.js.map +1 -1
  7. package/dist/proserviceworld/pages/BookingsPage.js +52 -48
  8. package/dist/proserviceworld/pages/BookingsPage.js.map +1 -1
  9. package/dist/proserviceworld/pages/DashboardPage.js +275 -243
  10. package/dist/proserviceworld/pages/DashboardPage.js.map +1 -1
  11. package/dist/proserviceworld/pages/DocumentsPage.js +204 -200
  12. package/dist/proserviceworld/pages/DocumentsPage.js.map +1 -1
  13. package/dist/proserviceworld/pages/MessagesPage.js +200 -186
  14. package/dist/proserviceworld/pages/MessagesPage.js.map +1 -1
  15. package/dist/proserviceworld/pages/PaymentsPage.js +70 -39
  16. package/dist/proserviceworld/pages/PaymentsPage.js.map +1 -1
  17. package/dist/proserviceworld/pages/ProjectsPage.js +510 -477
  18. package/dist/proserviceworld/pages/ProjectsPage.js.map +1 -1
  19. package/dist/proserviceworld/pages/ProviderDetailPage.js +71 -41
  20. package/dist/proserviceworld/pages/ProviderDetailPage.js.map +1 -1
  21. package/dist/proserviceworld/pages/ProvidersPage.js +62 -58
  22. package/dist/proserviceworld/pages/ProvidersPage.js.map +1 -1
  23. package/dist/proserviceworld/pages/ReviewsPage.js +80 -63
  24. package/dist/proserviceworld/pages/ReviewsPage.js.map +1 -1
  25. package/dist/proserviceworld/pages/ServiceDetailsPage.js +118 -83
  26. package/dist/proserviceworld/pages/ServiceDetailsPage.js.map +1 -1
  27. package/dist/proserviceworld/pages/ServicesPage.js +134 -130
  28. package/dist/proserviceworld/pages/ServicesPage.js.map +1 -1
  29. package/dist/proserviceworld/pages/VerificationPage.js +23 -19
  30. package/dist/proserviceworld/pages/VerificationPage.js.map +1 -1
  31. package/package.json +2 -2
@@ -2,10 +2,10 @@ import { useProServiceWorldStore as e } from "../store/proserviceworldStore.js";
2
2
  import { useState as t } from "react";
3
3
  import { AlertTriangle as n, ArrowUpRight as r, BarChart3 as i, Calendar as a, DollarSign as o, Download as s, FileText as c, Minus as l, Shield as u, ShoppingCart as d, Star as f, TrendingDown as p, TrendingUp as m, Users as h } from "lucide-react";
4
4
  import { jsx as g, jsxs as _ } from "react/jsx-runtime";
5
- import { AuroraBackground as v, Badge as y, CTAOverflowMenu as b, Card as x, CardContent as S, CardHeader as C, CardTitle as w, GlassCard as T, GradientText as E } from "@burdenoff/fe-libs/ui";
5
+ import { AuroraBackground as v, Badge as y, CTAOverflowMenu as b, Card as x, CardContent as S, CardHeader as C, CardTitle as w, GlassCard as T, GradientText as E, NextSteps as D, PagePurpose as O } from "@burdenoff/fe-libs/ui";
6
6
  //#region src/proserviceworld/pages/AdminReportsPage.tsx
7
- function D() {
8
- let { adminReportMetrics: D, revenueData: O, servicePerformance: k, geographicData: A, adminUsers: j } = e(), [M, N] = t("overview"), [P, F] = t("30d"), I = [
7
+ function k() {
8
+ let { adminReportMetrics: k, revenueData: A, servicePerformance: j, geographicData: M, adminUsers: N } = e(), [P, F] = t("overview"), [I, L] = t("30d"), R = [
9
9
  {
10
10
  key: "overview",
11
11
  label: "Overview",
@@ -26,19 +26,19 @@ function D() {
26
26
  label: "Bookings",
27
27
  icon: d
28
28
  }
29
- ], L = (e) => e === "positive" ? /* @__PURE__ */ g(m, { className: "h-4 w-4 text-status-success-text" }) : e === "negative" ? /* @__PURE__ */ g(p, { className: "h-4 w-4 text-status-error-text" }) : /* @__PURE__ */ g(l, { className: "h-4 w-4 text-text-secondary" }), R = (e) => e === "positive" ? "text-status-success-text" : e === "negative" ? "text-status-error-text" : "text-text-secondary", z = [
29
+ ], z = (e) => e === "positive" ? /* @__PURE__ */ g(m, { className: "h-4 w-4 text-status-success-text" }) : e === "negative" ? /* @__PURE__ */ g(p, { className: "h-4 w-4 text-status-error-text" }) : /* @__PURE__ */ g(l, { className: "h-4 w-4 text-text-secondary" }), B = (e) => e === "positive" ? "text-status-success-text" : e === "negative" ? "text-status-error-text" : "text-text-secondary", V = [
30
30
  h,
31
31
  u,
32
32
  d,
33
33
  o,
34
34
  f,
35
35
  n
36
- ], B = Math.max(...O.map((e) => e.value)), V = Math.max(...k.map((e) => e.value)), H = j.reduce((e, t) => (e[t.role] = (e[t.role] ?? 0) + 1, e), {}), U = j.reduce((e, t) => (e[t.status] = (e[t.status] ?? 0) + 1, e), {}), W = {
36
+ ], H = Math.max(...A.map((e) => e.value)), U = Math.max(...j.map((e) => e.value)), W = N.reduce((e, t) => (e[t.role] = (e[t.role] ?? 0) + 1, e), {}), G = N.reduce((e, t) => (e[t.status] = (e[t.status] ?? 0) + 1, e), {}), K = {
37
37
  client: "bg-chart-1",
38
38
  provider: "bg-chart-2",
39
39
  admin: "bg-chart-3",
40
40
  team_member: "bg-chart-4"
41
- }, G = {
41
+ }, q = {
42
42
  active: "bg-status-success-text",
43
43
  suspended: "bg-status-warning-text",
44
44
  pending: "bg-chart-5",
@@ -71,14 +71,44 @@ function D() {
71
71
  })]
72
72
  })]
73
73
  }),
74
+ /* @__PURE__ */ g(O, {
75
+ icon: /* @__PURE__ */ g(i, { className: "h-4 w-4" }),
76
+ children: "The operational pulse of the platform. Track headline KPIs, dig into revenue, user, and booking trends across time ranges, and export reports for stakeholders — use it to spot what is growing, what needs attention, and where to act next."
77
+ }),
78
+ /* @__PURE__ */ g(D, {
79
+ storageKey: "proserviceworld-admin-reports",
80
+ steps: [
81
+ {
82
+ id: "revenue",
83
+ label: "Review revenue trends",
84
+ description: "Open the Revenue tab to compare months and spot growth or dips.",
85
+ icon: /* @__PURE__ */ g(o, { className: "h-4 w-4" }),
86
+ onClick: () => F("revenue")
87
+ },
88
+ {
89
+ id: "users",
90
+ label: "Check user health",
91
+ description: "See role and status distribution plus your top spenders.",
92
+ icon: /* @__PURE__ */ g(h, { className: "h-4 w-4" }),
93
+ onClick: () => F("users")
94
+ },
95
+ {
96
+ id: "export",
97
+ label: "Export a report",
98
+ description: "Generate a shareable report or CSV for stakeholders.",
99
+ icon: /* @__PURE__ */ g(s, { className: "h-4 w-4" }),
100
+ onClick: () => {}
101
+ }
102
+ ]
103
+ }),
74
104
  /* @__PURE__ */ _("div", {
75
105
  className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",
76
106
  children: [/* @__PURE__ */ g("div", {
77
107
  className: "flex gap-1 border-b border-border-seam",
78
- children: I.map(({ key: e, label: t, icon: n }) => /* @__PURE__ */ _("button", {
79
- onClick: () => N(e),
80
- "aria-pressed": M === e,
81
- className: `flex items-center gap-2 border-b-2 px-4 py-2 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus ${M === e ? "border-accent-blue text-accent-blue" : "border-transparent text-text-secondary hover:text-text-primary"}`,
108
+ children: R.map(({ key: e, label: t, icon: n }) => /* @__PURE__ */ _("button", {
109
+ onClick: () => F(e),
110
+ "aria-pressed": P === e,
111
+ className: `flex items-center gap-2 border-b-2 px-4 py-2 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus ${P === e ? "border-accent-blue text-accent-blue" : "border-transparent text-text-secondary hover:text-text-primary"}`,
82
112
  children: [/* @__PURE__ */ g(n, { className: "h-4 w-4" }), t]
83
113
  }, e))
84
114
  }), /* @__PURE__ */ _("div", {
@@ -91,9 +121,9 @@ function D() {
91
121
  "90d",
92
122
  "1y"
93
123
  ].map((e) => /* @__PURE__ */ g("button", {
94
- onClick: () => F(e),
95
- "aria-pressed": P === e,
96
- className: `px-3 py-1 text-xs font-medium tabular-nums focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus ${P === e ? "bg-accent-blue text-action-primary-text" : "text-text-secondary hover:bg-bg-sunken"}`,
124
+ onClick: () => L(e),
125
+ "aria-pressed": I === e,
126
+ className: `px-3 py-1 text-xs font-medium tabular-nums focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus ${I === e ? "bg-accent-blue text-action-primary-text" : "text-text-secondary hover:bg-bg-sunken"}`,
97
127
  children: e
98
128
  }, e))
99
129
  })]
@@ -101,39 +131,43 @@ function D() {
101
131
  }),
102
132
  /* @__PURE__ */ g("div", {
103
133
  className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3",
104
- children: D.map((e, t) => /* @__PURE__ */ g(T, {
105
- treatment: "metric",
106
- className: "border-border-seam",
107
- children: /* @__PURE__ */ _(S, {
108
- className: "pt-4",
109
- children: [
110
- /* @__PURE__ */ _("div", {
111
- className: "flex items-center justify-between",
112
- children: [/* @__PURE__ */ _("div", {
113
- className: "flex items-center gap-2",
114
- children: [/* @__PURE__ */ g(z[t % z.length] ?? i, { className: "h-4 w-4 text-text-secondary" }), /* @__PURE__ */ g("p", {
115
- className: "text-sm font-medium text-text-secondary",
116
- children: e.label
117
- })]
118
- }), L(e.changeType)]
119
- }),
120
- /* @__PURE__ */ g("p", {
121
- className: "mt-2 text-3xl font-bold tabular-nums",
122
- children: e.value
123
- }),
124
- /* @__PURE__ */ _("p", {
125
- className: `mt-1 flex items-center gap-1 text-xs ${R(e.changeType)}`,
126
- children: [
127
- /* @__PURE__ */ g(r, { className: "h-3 w-3" }),
128
- e.change,
129
- " vs last period"
130
- ]
131
- })
132
- ]
133
- })
134
- }, t))
134
+ children: k.map((e, t) => {
135
+ let n = V[t % V.length] ?? i;
136
+ return /* @__PURE__ */ g(T, {
137
+ treatment: t === 0 ? "glass" : "metric",
138
+ glow: t === 0,
139
+ className: "border-border-seam",
140
+ children: /* @__PURE__ */ _(S, {
141
+ className: "pt-4",
142
+ children: [
143
+ /* @__PURE__ */ _("div", {
144
+ className: "flex items-center justify-between",
145
+ children: [/* @__PURE__ */ _("div", {
146
+ className: "flex items-center gap-2",
147
+ children: [/* @__PURE__ */ g(n, { className: "h-4 w-4 text-text-secondary" }), /* @__PURE__ */ g("p", {
148
+ className: "text-sm font-medium text-text-secondary",
149
+ children: e.label
150
+ })]
151
+ }), z(e.changeType)]
152
+ }),
153
+ /* @__PURE__ */ g("p", {
154
+ className: "mt-2 text-3xl font-bold tabular-nums",
155
+ children: e.value
156
+ }),
157
+ /* @__PURE__ */ _("p", {
158
+ className: `mt-1 flex items-center gap-1 text-xs ${B(e.changeType)}`,
159
+ children: [
160
+ /* @__PURE__ */ g(r, { className: "h-3 w-3" }),
161
+ e.change,
162
+ " vs last period"
163
+ ]
164
+ })
165
+ ]
166
+ })
167
+ }, t);
168
+ })
135
169
  }),
136
- M === "overview" && /* @__PURE__ */ _("div", {
170
+ P === "overview" && /* @__PURE__ */ _("div", {
137
171
  className: "grid gap-6 lg:grid-cols-2",
138
172
  children: [
139
173
  /* @__PURE__ */ _(x, {
@@ -149,7 +183,7 @@ function D() {
149
183
  })]
150
184
  }) }), /* @__PURE__ */ g(S, {
151
185
  className: "space-y-3",
152
- children: O.map((e) => /* @__PURE__ */ _("div", {
186
+ children: A.map((e) => /* @__PURE__ */ _("div", {
153
187
  className: "flex items-center gap-3",
154
188
  children: [
155
189
  /* @__PURE__ */ g("span", {
@@ -160,7 +194,7 @@ function D() {
160
194
  className: "flex-1 h-5 bg-bg-sunken rounded overflow-hidden",
161
195
  children: /* @__PURE__ */ g("div", {
162
196
  className: "h-5 bg-accent-blue rounded",
163
- style: { width: `${e.value / B * 100}%` }
197
+ style: { width: `${e.value / H * 100}%` }
164
198
  })
165
199
  }),
166
200
  /* @__PURE__ */ _("span", {
@@ -188,7 +222,7 @@ function D() {
188
222
  })]
189
223
  }) }), /* @__PURE__ */ g(S, {
190
224
  className: "space-y-3",
191
- children: [...k].sort((e, t) => t.value - e.value).map((e) => /* @__PURE__ */ _("div", {
225
+ children: [...j].sort((e, t) => t.value - e.value).map((e) => /* @__PURE__ */ _("div", {
192
226
  className: "flex items-center gap-3",
193
227
  children: [
194
228
  /* @__PURE__ */ g("span", {
@@ -199,7 +233,7 @@ function D() {
199
233
  className: "flex-1 h-5 bg-bg-sunken rounded overflow-hidden",
200
234
  children: /* @__PURE__ */ g("div", {
201
235
  className: "h-5 bg-accent-purple rounded",
202
- style: { width: `${e.value / V * 100}%` }
236
+ style: { width: `${e.value / U * 100}%` }
203
237
  })
204
238
  }),
205
239
  /* @__PURE__ */ g("span", {
@@ -243,8 +277,8 @@ function D() {
243
277
  children: "Share"
244
278
  })
245
279
  ]
246
- }) }), /* @__PURE__ */ g("tbody", { children: A.map((e) => {
247
- let t = A.reduce((e, t) => e + t.revenue, 0), n = Math.round(e.revenue / t * 100), r = Math.round(e.revenue / e.clients);
280
+ }) }), /* @__PURE__ */ g("tbody", { children: M.map((e) => {
281
+ let t = M.reduce((e, t) => e + t.revenue, 0), n = Math.round(e.revenue / t * 100), r = Math.round(e.revenue / e.clients);
248
282
  return /* @__PURE__ */ _("tr", {
249
283
  className: "border-b border-border-seam hover:bg-bg-sunken",
250
284
  children: [
@@ -292,7 +326,7 @@ function D() {
292
326
  })
293
327
  ]
294
328
  }),
295
- M === "users" && /* @__PURE__ */ _("div", {
329
+ P === "users" && /* @__PURE__ */ _("div", {
296
330
  className: "grid gap-6 lg:grid-cols-2",
297
331
  children: [
298
332
  /* @__PURE__ */ _(x, {
@@ -302,8 +336,8 @@ function D() {
302
336
  children: "User Role Distribution"
303
337
  }) }), /* @__PURE__ */ g(S, {
304
338
  className: "space-y-3",
305
- children: Object.entries(H).map(([e, t]) => {
306
- let n = Math.round(t / j.length * 100);
339
+ children: Object.entries(W).map(([e, t]) => {
340
+ let n = Math.round(t / N.length * 100);
307
341
  return /* @__PURE__ */ _("div", {
308
342
  className: "flex items-center gap-3",
309
343
  children: [
@@ -314,7 +348,7 @@ function D() {
314
348
  /* @__PURE__ */ g("div", {
315
349
  className: "flex-1 h-5 bg-bg-sunken rounded overflow-hidden",
316
350
  children: /* @__PURE__ */ g("div", {
317
- className: `h-5 rounded ${W[e] ?? "bg-chart-6"}`,
351
+ className: `h-5 rounded ${K[e] ?? "bg-chart-6"}`,
318
352
  style: { width: `${n}%` }
319
353
  })
320
354
  }),
@@ -339,8 +373,8 @@ function D() {
339
373
  children: "User Status Distribution"
340
374
  }) }), /* @__PURE__ */ g(S, {
341
375
  className: "space-y-3",
342
- children: Object.entries(U).map(([e, t]) => {
343
- let n = Math.round(t / j.length * 100);
376
+ children: Object.entries(G).map(([e, t]) => {
377
+ let n = Math.round(t / N.length * 100);
344
378
  return /* @__PURE__ */ _("div", {
345
379
  className: "flex items-center gap-3",
346
380
  children: [
@@ -351,7 +385,7 @@ function D() {
351
385
  /* @__PURE__ */ g("div", {
352
386
  className: "flex-1 h-5 bg-bg-sunken rounded overflow-hidden",
353
387
  children: /* @__PURE__ */ g("div", {
354
- className: `h-5 rounded ${G[e] ?? "bg-chart-6"}`,
388
+ className: `h-5 rounded ${q[e] ?? "bg-chart-6"}`,
355
389
  style: { width: `${n}%` }
356
390
  })
357
391
  }),
@@ -376,7 +410,7 @@ function D() {
376
410
  children: "Top Users by Spending"
377
411
  }) }), /* @__PURE__ */ g(S, { children: /* @__PURE__ */ g("div", {
378
412
  className: "space-y-2",
379
- children: [...j].filter((e) => e.totalSpent > 0).sort((e, t) => t.totalSpent - e.totalSpent).slice(0, 5).map((e, t) => /* @__PURE__ */ _("div", {
413
+ children: [...N].filter((e) => e.totalSpent > 0).sort((e, t) => t.totalSpent - e.totalSpent).slice(0, 5).map((e, t) => /* @__PURE__ */ _("div", {
380
414
  className: "flex items-center justify-between rounded-lg border border-border-seam p-3",
381
415
  children: [/* @__PURE__ */ _("div", {
382
416
  className: "flex items-center gap-3",
@@ -405,7 +439,7 @@ function D() {
405
439
  })
406
440
  ]
407
441
  }),
408
- M === "revenue" && /* @__PURE__ */ g("div", {
442
+ P === "revenue" && /* @__PURE__ */ g("div", {
409
443
  className: "space-y-6",
410
444
  children: /* @__PURE__ */ _(x, {
411
445
  className: "border-border-seam",
@@ -414,7 +448,7 @@ function D() {
414
448
  children: "Monthly Revenue Comparison"
415
449
  }) }), /* @__PURE__ */ g(S, {
416
450
  className: "space-y-4",
417
- children: O.map((e) => {
451
+ children: A.map((e) => {
418
452
  let t = e.prev ? ((e.value - e.prev) / e.prev * 100).toFixed(1) : "0", n = e.prev ? e.value >= e.prev : !0;
419
453
  return /* @__PURE__ */ _("div", {
420
454
  className: "rounded-lg border border-border-seam p-4",
@@ -446,10 +480,10 @@ function D() {
446
480
  className: "mt-3 flex gap-1 h-4",
447
481
  children: [/* @__PURE__ */ g("div", {
448
482
  className: "h-4 rounded bg-accent-blue-subtle",
449
- style: { width: `${(e.prev ?? 0) / B * 100}%` }
483
+ style: { width: `${(e.prev ?? 0) / H * 100}%` }
450
484
  }), /* @__PURE__ */ g("div", {
451
485
  className: "h-4 rounded bg-accent-blue",
452
- style: { width: `${Math.max(0, (e.value - (e.prev ?? 0)) / B * 100)}%` }
486
+ style: { width: `${Math.max(0, (e.value - (e.prev ?? 0)) / H * 100)}%` }
453
487
  })]
454
488
  })]
455
489
  }, e.name);
@@ -457,7 +491,7 @@ function D() {
457
491
  })]
458
492
  })
459
493
  }),
460
- M === "bookings" && /* @__PURE__ */ _("div", {
494
+ P === "bookings" && /* @__PURE__ */ _("div", {
461
495
  className: "grid gap-6 lg:grid-cols-2",
462
496
  children: [/* @__PURE__ */ _(x, {
463
497
  className: "border-border-seam",
@@ -466,7 +500,7 @@ function D() {
466
500
  children: "Bookings by Service Category"
467
501
  }) }), /* @__PURE__ */ g(S, {
468
502
  className: "space-y-3",
469
- children: [...k].sort((e, t) => t.value - e.value).map((e, t) => /* @__PURE__ */ _("div", {
503
+ children: [...j].sort((e, t) => t.value - e.value).map((e, t) => /* @__PURE__ */ _("div", {
470
504
  className: "flex items-center gap-3",
471
505
  children: [/* @__PURE__ */ _("span", {
472
506
  className: "w-6 text-sm font-bold text-text-secondary tabular-nums",
@@ -486,7 +520,7 @@ function D() {
486
520
  className: "mt-1 h-2 overflow-hidden rounded-full bg-bg-sunken",
487
521
  children: /* @__PURE__ */ g("div", {
488
522
  className: "h-2 rounded-full bg-accent-blue",
489
- style: { width: `${e.value / V * 100}%` }
523
+ style: { width: `${e.value / U * 100}%` }
490
524
  })
491
525
  })]
492
526
  })]
@@ -502,7 +536,7 @@ function D() {
502
536
  children: [
503
537
  {
504
538
  label: "Total Bookings",
505
- value: k.reduce((e, t) => e + t.value, 0).toLocaleString(),
539
+ value: j.reduce((e, t) => e + t.value, 0).toLocaleString(),
506
540
  icon: d
507
541
  },
508
542
  {
@@ -540,6 +574,6 @@ function D() {
540
574
  });
541
575
  }
542
576
  //#endregion
543
- export { D as AdminReportsPage };
577
+ export { k as AdminReportsPage };
544
578
 
545
579
  //# sourceMappingURL=AdminReportsPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AdminReportsPage.js","names":[],"sources":["../../../src/proserviceworld/pages/AdminReportsPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Badge,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n AuroraBackground,\n GradientText,\n CTAOverflowMenu,\n} from '@burdenoff/fe-libs/ui';\nimport {\n TrendingUp,\n TrendingDown,\n Minus,\n Download,\n FileText,\n BarChart3,\n Calendar,\n Users,\n DollarSign,\n ShoppingCart,\n Star,\n AlertTriangle,\n ArrowUpRight,\n Shield,\n} from 'lucide-react';\nimport { useProServiceWorldStore } from '../store/proserviceworldStore';\n\ntype ReportTab = 'overview' | 'users' | 'revenue' | 'bookings';\ntype TimeRange = '7d' | '30d' | '90d' | '1y';\n\nexport function AdminReportsPage() {\n const { adminReportMetrics, revenueData, servicePerformance, geographicData, adminUsers } =\n useProServiceWorldStore();\n const [activeTab, setActiveTab] = useState<ReportTab>('overview');\n const [timeRange, setTimeRange] = useState<TimeRange>('30d');\n\n const tabs: { key: ReportTab; label: string; icon: typeof BarChart3 }[] = [\n { key: 'overview', label: 'Overview', icon: BarChart3 },\n { key: 'users', label: 'Users', icon: Users },\n { key: 'revenue', label: 'Revenue', icon: DollarSign },\n { key: 'bookings', label: 'Bookings', icon: ShoppingCart },\n ];\n\n const changeIcon = (type: string) => {\n if (type === 'positive')\n return <TrendingUp className=\"h-4 w-4 text-status-success-text\" />;\n if (type === 'negative')\n return <TrendingDown className=\"h-4 w-4 text-status-error-text\" />;\n return <Minus className=\"h-4 w-4 text-text-secondary\" />;\n };\n\n const changeColor = (type: string) =>\n type === 'positive'\n ? 'text-status-success-text'\n : type === 'negative'\n ? 'text-status-error-text'\n : 'text-text-secondary';\n\n const metricIcons = [Users, Shield, ShoppingCart, DollarSign, Star, AlertTriangle];\n\n const maxRevenue = Math.max(...revenueData.map((d) => d.value));\n const maxServiceBookings = Math.max(...servicePerformance.map((d) => d.value));\n\n // Role distribution\n const roleCounts = adminUsers.reduce<Record<string, number>>((acc, u) => {\n acc[u.role] = (acc[u.role] ?? 0) + 1;\n return acc;\n }, {});\n\n // Status distribution\n const statusCounts = adminUsers.reduce<Record<string, number>>((acc, u) => {\n acc[u.status] = (acc[u.status] ?? 0) + 1;\n return acc;\n }, {});\n\n const roleColors: Record<string, string> = {\n client: 'bg-chart-1',\n provider: 'bg-chart-2',\n admin: 'bg-chart-3',\n team_member: 'bg-chart-4',\n };\n\n const statusColors: Record<string, string> = {\n active: 'bg-status-success-text',\n suspended: 'bg-status-warning-text',\n pending: 'bg-chart-5',\n banned: 'bg-status-error-text',\n };\n\n return (\n <div className=\"space-y-6 p-6 bg-bg-canvas min-h-screen\">\n {/* Hero header — the ONE aurora backdrop for this page. */}\n <div className=\"relative overflow-hidden rounded-card -mx-2 px-2 pt-1\">\n <AuroraBackground intensity=\"subtle\" />\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold tracking-tight\">\n <GradientText>Admin Reports</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n Platform analytics, performance metrics, and operational reports.\n </p>\n </div>\n <CTAOverflowMenu\n primary={{\n label: 'Generate Report',\n onSelect: () => {},\n icon: <FileText className=\"h-4 w-4\" />,\n }}\n actions={[\n {\n label: 'Export CSV',\n onSelect: () => {},\n icon: <Download className=\"h-4 w-4\" />,\n },\n ]}\n />\n </div>\n </div>\n\n {/* Time Range + Tabs */}\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex gap-1 border-b border-border-seam\">\n {tabs.map(({ key, label, icon: Icon }) => (\n <button\n key={key}\n onClick={() => setActiveTab(key)}\n aria-pressed={activeTab === key}\n className={`flex items-center gap-2 border-b-2 px-4 py-2 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus ${\n activeTab === key\n ? 'border-accent-blue text-accent-blue'\n : 'border-transparent text-text-secondary hover:text-text-primary'\n }`}\n >\n <Icon className=\"h-4 w-4\" />\n {label}\n </button>\n ))}\n </div>\n <div className=\"flex items-center gap-2\">\n <Calendar className=\"h-4 w-4 text-text-secondary\" />\n <div className=\"flex rounded border border-border-seam\">\n {(['7d', '30d', '90d', '1y'] as TimeRange[]).map((range) => (\n <button\n key={range}\n onClick={() => setTimeRange(range)}\n aria-pressed={timeRange === range}\n className={`px-3 py-1 text-xs font-medium tabular-nums focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus ${\n timeRange === range\n ? 'bg-accent-blue text-action-primary-text'\n : 'text-text-secondary hover:bg-bg-sunken'\n }`}\n >\n {range}\n </button>\n ))}\n </div>\n </div>\n </div>\n\n {/* Metric Cards */}\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {adminReportMetrics.map((metric, i) => {\n const MetricIcon = metricIcons[i % metricIcons.length] ?? BarChart3;\n return (\n <GlassCard key={i} treatment=\"metric\" className=\"border-border-seam\">\n <CardContent className=\"pt-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <MetricIcon className=\"h-4 w-4 text-text-secondary\" />\n <p className=\"text-sm font-medium text-text-secondary\">{metric.label}</p>\n </div>\n {changeIcon(metric.changeType)}\n </div>\n <p className=\"mt-2 text-3xl font-bold tabular-nums\">{metric.value}</p>\n <p className={`mt-1 flex items-center gap-1 text-xs ${changeColor(metric.changeType)}`}>\n <ArrowUpRight className=\"h-3 w-3\" />\n {metric.change} vs last period\n </p>\n </CardContent>\n </GlassCard>\n );\n })}\n </div>\n\n {/* Overview Tab */}\n {activeTab === 'overview' && (\n <div className=\"grid gap-6 lg:grid-cols-2\">\n {/* Revenue trend */}\n <Card className=\"border-border-seam\">\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">Platform Revenue</CardTitle>\n <Badge variant=\"secondary\">Monthly</Badge>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {revenueData.map((point) => (\n <div key={point.name} className=\"flex items-center gap-3\">\n <span className=\"w-10 text-xs text-text-secondary\">{point.name}</span>\n <div className=\"flex-1 h-5 bg-bg-sunken rounded overflow-hidden\">\n <div\n className=\"h-5 bg-accent-blue rounded\"\n style={{ width: `${(point.value / maxRevenue) * 100}%` }}\n />\n </div>\n <span className=\"w-16 text-right text-xs font-medium tabular-nums\">\n ${(point.value / 1000).toFixed(1)}k\n </span>\n </div>\n ))}\n </CardContent>\n </Card>\n\n {/* Service breakdown */}\n <Card className=\"border-border-seam\">\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">Service Bookings</CardTitle>\n <Badge variant=\"secondary\">Total</Badge>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {[...servicePerformance]\n .sort((a, b) => b.value - a.value)\n .map((service) => (\n <div key={service.name} className=\"flex items-center gap-3\">\n <span className=\"w-32 truncate text-xs text-text-secondary\">\n {service.name}\n </span>\n <div className=\"flex-1 h-5 bg-bg-sunken rounded overflow-hidden\">\n <div\n className=\"h-5 bg-accent-purple rounded\"\n style={{ width: `${(service.value / maxServiceBookings) * 100}%` }}\n />\n </div>\n <span className=\"w-12 text-right text-xs font-medium tabular-nums\">\n {service.value}\n </span>\n </div>\n ))}\n </CardContent>\n </Card>\n\n {/* Geographic revenue */}\n <Card className=\"lg:col-span-2 border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base\">Revenue by Region</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"overflow-x-auto\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam text-left text-text-secondary\">\n <th className=\"p-3\">Region</th>\n <th className=\"p-3 text-right\">Clients</th>\n <th className=\"p-3 text-right\">Revenue</th>\n <th className=\"p-3 text-right\">Avg. per Client</th>\n <th className=\"p-3\">Share</th>\n </tr>\n </thead>\n <tbody>\n {geographicData.map((geo) => {\n const totalRevenue = geographicData.reduce((s, g) => s + g.revenue, 0);\n const pct = Math.round((geo.revenue / totalRevenue) * 100);\n const avgPerClient = Math.round(geo.revenue / geo.clients);\n return (\n <tr\n key={geo.country}\n className=\"border-b border-border-seam hover:bg-bg-sunken\"\n >\n <td className=\"p-3 font-medium\">{geo.country}</td>\n <td className=\"p-3 text-right tabular-nums\">{geo.clients}</td>\n <td className=\"p-3 text-right font-medium tabular-nums\">\n ${(geo.revenue / 1000).toFixed(0)}k\n </td>\n <td className=\"p-3 text-right text-text-secondary tabular-nums\">\n ${avgPerClient.toLocaleString()}\n </td>\n <td className=\"p-3\">\n <div className=\"flex items-center gap-2\">\n <div className=\"h-2 flex-1 overflow-hidden rounded-full bg-bg-sunken\">\n <div\n className=\"h-2 rounded-full bg-accent-blue\"\n style={{ width: `${pct}%` }}\n />\n </div>\n <span className=\"w-10 text-right text-xs tabular-nums\">{pct}%</span>\n </div>\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n </CardContent>\n </Card>\n </div>\n )}\n\n {/* Users Tab */}\n {activeTab === 'users' && (\n <div className=\"grid gap-6 lg:grid-cols-2\">\n <Card className=\"border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base\">User Role Distribution</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {Object.entries(roleCounts).map(([role, count]) => {\n const pct = Math.round((count / adminUsers.length) * 100);\n return (\n <div key={role} className=\"flex items-center gap-3\">\n <span className=\"w-24 text-sm font-medium capitalize\">\n {role.replace('_', ' ')}\n </span>\n <div className=\"flex-1 h-5 bg-bg-sunken rounded overflow-hidden\">\n <div\n className={`h-5 rounded ${roleColors[role] ?? 'bg-chart-6'}`}\n style={{ width: `${pct}%` }}\n />\n </div>\n <span className=\"w-16 text-right text-sm tabular-nums\">\n {count} ({pct}%)\n </span>\n </div>\n );\n })}\n </CardContent>\n </Card>\n\n <Card className=\"border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base\">User Status Distribution</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {Object.entries(statusCounts).map(([status, count]) => {\n const pct = Math.round((count / adminUsers.length) * 100);\n return (\n <div key={status} className=\"flex items-center gap-3\">\n <span className=\"w-24 text-sm font-medium capitalize\">{status}</span>\n <div className=\"flex-1 h-5 bg-bg-sunken rounded overflow-hidden\">\n <div\n className={`h-5 rounded ${statusColors[status] ?? 'bg-chart-6'}`}\n style={{ width: `${pct}%` }}\n />\n </div>\n <span className=\"w-16 text-right text-sm tabular-nums\">\n {count} ({pct}%)\n </span>\n </div>\n );\n })}\n </CardContent>\n </Card>\n\n {/* Top users by spend */}\n <Card className=\"lg:col-span-2 border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base\">Top Users by Spending</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-2\">\n {[...adminUsers]\n .filter((u) => u.totalSpent > 0)\n .sort((a, b) => b.totalSpent - a.totalSpent)\n .slice(0, 5)\n .map((user, idx) => (\n <div\n key={user.id}\n className=\"flex items-center justify-between rounded-lg border border-border-seam p-3\"\n >\n <div className=\"flex items-center gap-3\">\n <span className=\"flex h-8 w-8 items-center justify-center rounded-full bg-accent-soft text-sm font-bold text-text-primary tabular-nums\">\n {idx + 1}\n </span>\n <div>\n <p className=\"font-medium\">{user.name}</p>\n <p className=\"text-xs text-text-secondary\">{user.email}</p>\n </div>\n </div>\n <div className=\"text-right\">\n <p className=\"font-bold tabular-nums\">\n ${user.totalSpent.toLocaleString()}\n </p>\n <p className=\"text-xs text-text-secondary tabular-nums\">\n {user.bookingsCount} bookings\n </p>\n </div>\n </div>\n ))}\n </div>\n </CardContent>\n </Card>\n </div>\n )}\n\n {/* Revenue Tab */}\n {activeTab === 'revenue' && (\n <div className=\"space-y-6\">\n <Card className=\"border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base\">Monthly Revenue Comparison</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {revenueData.map((point) => {\n const growth = point.prev\n ? (((point.value - point.prev) / point.prev) * 100).toFixed(1)\n : '0';\n const isPositive = point.prev ? point.value >= point.prev : true;\n return (\n <div key={point.name} className=\"rounded-lg border border-border-seam p-4\">\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"font-medium\">{point.name} 2025</p>\n <div className=\"mt-1 flex items-center gap-4 text-sm text-text-secondary tabular-nums\">\n <span>Current: ${(point.value / 1000).toFixed(1)}k</span>\n <span>Previous: ${((point.prev ?? 0) / 1000).toFixed(1)}k</span>\n </div>\n </div>\n <Badge variant={isPositive ? 'default' : 'destructive'}>\n {isPositive ? '+' : ''}\n {growth}%\n </Badge>\n </div>\n <div className=\"mt-3 flex gap-1 h-4\">\n <div\n className=\"h-4 rounded bg-accent-blue-subtle\"\n style={{ width: `${((point.prev ?? 0) / maxRevenue) * 100}%` }}\n />\n <div\n className=\"h-4 rounded bg-accent-blue\"\n style={{\n width: `${Math.max(0, ((point.value - (point.prev ?? 0)) / maxRevenue) * 100)}%`,\n }}\n />\n </div>\n </div>\n );\n })}\n </CardContent>\n </Card>\n </div>\n )}\n\n {/* Bookings Tab */}\n {activeTab === 'bookings' && (\n <div className=\"grid gap-6 lg:grid-cols-2\">\n <Card className=\"border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base\">Bookings by Service Category</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {[...servicePerformance]\n .sort((a, b) => b.value - a.value)\n .map((service, idx) => (\n <div key={service.name} className=\"flex items-center gap-3\">\n <span className=\"w-6 text-sm font-bold text-text-secondary tabular-nums\">\n #{idx + 1}\n </span>\n <div className=\"flex-1\">\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"font-medium\">{service.name}</span>\n <span className=\"tabular-nums\">{service.value} bookings</span>\n </div>\n <div className=\"mt-1 h-2 overflow-hidden rounded-full bg-bg-sunken\">\n <div\n className=\"h-2 rounded-full bg-accent-blue\"\n style={{ width: `${(service.value / maxServiceBookings) * 100}%` }}\n />\n </div>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <Card className=\"border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base\">Quick Stats</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {[\n {\n label: 'Total Bookings',\n value: servicePerformance.reduce((s, p) => s + p.value, 0).toLocaleString(),\n icon: ShoppingCart,\n },\n { label: 'Avg. Booking Value', value: '$3,804', icon: DollarSign },\n { label: 'Completion Rate', value: '96.5%', icon: TrendingUp },\n { label: 'Client Satisfaction', value: '4.7/5.0', icon: Star },\n ].map(({ label, value, icon: Icon }) => (\n <div\n key={label}\n className=\"flex items-center justify-between rounded-lg border border-border-seam p-3\"\n >\n <div className=\"flex items-center gap-3\">\n <Icon className=\"h-5 w-5 text-text-secondary\" />\n <span className=\"text-sm font-medium\">{label}</span>\n </div>\n <span className=\"text-lg font-bold tabular-nums\">{value}</span>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AdminReportsPage.js","names":[],"sources":["../../../src/proserviceworld/pages/AdminReportsPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Badge,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n AuroraBackground,\n GradientText,\n CTAOverflowMenu,\n PagePurpose,\n NextSteps,\n} from '@burdenoff/fe-libs/ui';\nimport {\n TrendingUp,\n TrendingDown,\n Minus,\n Download,\n FileText,\n BarChart3,\n Calendar,\n Users,\n DollarSign,\n ShoppingCart,\n Star,\n AlertTriangle,\n ArrowUpRight,\n Shield,\n} from 'lucide-react';\nimport { useProServiceWorldStore } from '../store/proserviceworldStore';\n\ntype ReportTab = 'overview' | 'users' | 'revenue' | 'bookings';\ntype TimeRange = '7d' | '30d' | '90d' | '1y';\n\nexport function AdminReportsPage() {\n const { adminReportMetrics, revenueData, servicePerformance, geographicData, adminUsers } =\n useProServiceWorldStore();\n const [activeTab, setActiveTab] = useState<ReportTab>('overview');\n const [timeRange, setTimeRange] = useState<TimeRange>('30d');\n\n const tabs: { key: ReportTab; label: string; icon: typeof BarChart3 }[] = [\n { key: 'overview', label: 'Overview', icon: BarChart3 },\n { key: 'users', label: 'Users', icon: Users },\n { key: 'revenue', label: 'Revenue', icon: DollarSign },\n { key: 'bookings', label: 'Bookings', icon: ShoppingCart },\n ];\n\n const changeIcon = (type: string) => {\n if (type === 'positive')\n return <TrendingUp className=\"h-4 w-4 text-status-success-text\" />;\n if (type === 'negative')\n return <TrendingDown className=\"h-4 w-4 text-status-error-text\" />;\n return <Minus className=\"h-4 w-4 text-text-secondary\" />;\n };\n\n const changeColor = (type: string) =>\n type === 'positive'\n ? 'text-status-success-text'\n : type === 'negative'\n ? 'text-status-error-text'\n : 'text-text-secondary';\n\n const metricIcons = [Users, Shield, ShoppingCart, DollarSign, Star, AlertTriangle];\n\n const maxRevenue = Math.max(...revenueData.map((d) => d.value));\n const maxServiceBookings = Math.max(...servicePerformance.map((d) => d.value));\n\n // Role distribution\n const roleCounts = adminUsers.reduce<Record<string, number>>((acc, u) => {\n acc[u.role] = (acc[u.role] ?? 0) + 1;\n return acc;\n }, {});\n\n // Status distribution\n const statusCounts = adminUsers.reduce<Record<string, number>>((acc, u) => {\n acc[u.status] = (acc[u.status] ?? 0) + 1;\n return acc;\n }, {});\n\n const roleColors: Record<string, string> = {\n client: 'bg-chart-1',\n provider: 'bg-chart-2',\n admin: 'bg-chart-3',\n team_member: 'bg-chart-4',\n };\n\n const statusColors: Record<string, string> = {\n active: 'bg-status-success-text',\n suspended: 'bg-status-warning-text',\n pending: 'bg-chart-5',\n banned: 'bg-status-error-text',\n };\n\n return (\n <div className=\"space-y-6 p-6 bg-bg-canvas min-h-screen\">\n {/* Hero header — the ONE aurora backdrop for this page. */}\n <div className=\"relative overflow-hidden rounded-card -mx-2 px-2 pt-1\">\n <AuroraBackground intensity=\"subtle\" />\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold tracking-tight\">\n <GradientText>Admin Reports</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n Platform analytics, performance metrics, and operational reports.\n </p>\n </div>\n <CTAOverflowMenu\n primary={{\n label: 'Generate Report',\n onSelect: () => {},\n icon: <FileText className=\"h-4 w-4\" />,\n }}\n actions={[\n {\n label: 'Export CSV',\n onSelect: () => {},\n icon: <Download className=\"h-4 w-4\" />,\n },\n ]}\n />\n </div>\n </div>\n\n <PagePurpose icon={<BarChart3 className=\"h-4 w-4\" />}>\n The operational pulse of the platform. Track headline KPIs, dig into revenue, user, and\n booking trends across time ranges, and export reports for stakeholders — use it to spot\n what is growing, what needs attention, and where to act next.\n </PagePurpose>\n\n <NextSteps\n storageKey=\"proserviceworld-admin-reports\"\n steps={[\n {\n id: 'revenue',\n label: 'Review revenue trends',\n description: 'Open the Revenue tab to compare months and spot growth or dips.',\n icon: <DollarSign className=\"h-4 w-4\" />,\n onClick: () => setActiveTab('revenue'),\n },\n {\n id: 'users',\n label: 'Check user health',\n description: 'See role and status distribution plus your top spenders.',\n icon: <Users className=\"h-4 w-4\" />,\n onClick: () => setActiveTab('users'),\n },\n {\n id: 'export',\n label: 'Export a report',\n description: 'Generate a shareable report or CSV for stakeholders.',\n icon: <Download className=\"h-4 w-4\" />,\n onClick: () => {},\n },\n ]}\n />\n\n {/* Time Range + Tabs */}\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex gap-1 border-b border-border-seam\">\n {tabs.map(({ key, label, icon: Icon }) => (\n <button\n key={key}\n onClick={() => setActiveTab(key)}\n aria-pressed={activeTab === key}\n className={`flex items-center gap-2 border-b-2 px-4 py-2 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus ${\n activeTab === key\n ? 'border-accent-blue text-accent-blue'\n : 'border-transparent text-text-secondary hover:text-text-primary'\n }`}\n >\n <Icon className=\"h-4 w-4\" />\n {label}\n </button>\n ))}\n </div>\n <div className=\"flex items-center gap-2\">\n <Calendar className=\"h-4 w-4 text-text-secondary\" />\n <div className=\"flex rounded border border-border-seam\">\n {(['7d', '30d', '90d', '1y'] as TimeRange[]).map((range) => (\n <button\n key={range}\n onClick={() => setTimeRange(range)}\n aria-pressed={timeRange === range}\n className={`px-3 py-1 text-xs font-medium tabular-nums focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus ${\n timeRange === range\n ? 'bg-accent-blue text-action-primary-text'\n : 'text-text-secondary hover:bg-bg-sunken'\n }`}\n >\n {range}\n </button>\n ))}\n </div>\n </div>\n </div>\n\n {/* Metric Cards */}\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {adminReportMetrics.map((metric, i) => {\n const MetricIcon = metricIcons[i % metricIcons.length] ?? BarChart3;\n return (\n <GlassCard\n key={i}\n treatment={i === 0 ? 'glass' : 'metric'}\n glow={i === 0}\n className=\"border-border-seam\"\n >\n <CardContent className=\"pt-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <MetricIcon className=\"h-4 w-4 text-text-secondary\" />\n <p className=\"text-sm font-medium text-text-secondary\">{metric.label}</p>\n </div>\n {changeIcon(metric.changeType)}\n </div>\n <p className=\"mt-2 text-3xl font-bold tabular-nums\">{metric.value}</p>\n <p className={`mt-1 flex items-center gap-1 text-xs ${changeColor(metric.changeType)}`}>\n <ArrowUpRight className=\"h-3 w-3\" />\n {metric.change} vs last period\n </p>\n </CardContent>\n </GlassCard>\n );\n })}\n </div>\n\n {/* Overview Tab */}\n {activeTab === 'overview' && (\n <div className=\"grid gap-6 lg:grid-cols-2\">\n {/* Revenue trend */}\n <Card className=\"border-border-seam\">\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">Platform Revenue</CardTitle>\n <Badge variant=\"secondary\">Monthly</Badge>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {revenueData.map((point) => (\n <div key={point.name} className=\"flex items-center gap-3\">\n <span className=\"w-10 text-xs text-text-secondary\">{point.name}</span>\n <div className=\"flex-1 h-5 bg-bg-sunken rounded overflow-hidden\">\n <div\n className=\"h-5 bg-accent-blue rounded\"\n style={{ width: `${(point.value / maxRevenue) * 100}%` }}\n />\n </div>\n <span className=\"w-16 text-right text-xs font-medium tabular-nums\">\n ${(point.value / 1000).toFixed(1)}k\n </span>\n </div>\n ))}\n </CardContent>\n </Card>\n\n {/* Service breakdown */}\n <Card className=\"border-border-seam\">\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">Service Bookings</CardTitle>\n <Badge variant=\"secondary\">Total</Badge>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {[...servicePerformance]\n .sort((a, b) => b.value - a.value)\n .map((service) => (\n <div key={service.name} className=\"flex items-center gap-3\">\n <span className=\"w-32 truncate text-xs text-text-secondary\">\n {service.name}\n </span>\n <div className=\"flex-1 h-5 bg-bg-sunken rounded overflow-hidden\">\n <div\n className=\"h-5 bg-accent-purple rounded\"\n style={{ width: `${(service.value / maxServiceBookings) * 100}%` }}\n />\n </div>\n <span className=\"w-12 text-right text-xs font-medium tabular-nums\">\n {service.value}\n </span>\n </div>\n ))}\n </CardContent>\n </Card>\n\n {/* Geographic revenue */}\n <Card className=\"lg:col-span-2 border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base\">Revenue by Region</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"overflow-x-auto\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam text-left text-text-secondary\">\n <th className=\"p-3\">Region</th>\n <th className=\"p-3 text-right\">Clients</th>\n <th className=\"p-3 text-right\">Revenue</th>\n <th className=\"p-3 text-right\">Avg. per Client</th>\n <th className=\"p-3\">Share</th>\n </tr>\n </thead>\n <tbody>\n {geographicData.map((geo) => {\n const totalRevenue = geographicData.reduce((s, g) => s + g.revenue, 0);\n const pct = Math.round((geo.revenue / totalRevenue) * 100);\n const avgPerClient = Math.round(geo.revenue / geo.clients);\n return (\n <tr\n key={geo.country}\n className=\"border-b border-border-seam hover:bg-bg-sunken\"\n >\n <td className=\"p-3 font-medium\">{geo.country}</td>\n <td className=\"p-3 text-right tabular-nums\">{geo.clients}</td>\n <td className=\"p-3 text-right font-medium tabular-nums\">\n ${(geo.revenue / 1000).toFixed(0)}k\n </td>\n <td className=\"p-3 text-right text-text-secondary tabular-nums\">\n ${avgPerClient.toLocaleString()}\n </td>\n <td className=\"p-3\">\n <div className=\"flex items-center gap-2\">\n <div className=\"h-2 flex-1 overflow-hidden rounded-full bg-bg-sunken\">\n <div\n className=\"h-2 rounded-full bg-accent-blue\"\n style={{ width: `${pct}%` }}\n />\n </div>\n <span className=\"w-10 text-right text-xs tabular-nums\">{pct}%</span>\n </div>\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n </CardContent>\n </Card>\n </div>\n )}\n\n {/* Users Tab */}\n {activeTab === 'users' && (\n <div className=\"grid gap-6 lg:grid-cols-2\">\n <Card className=\"border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base\">User Role Distribution</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {Object.entries(roleCounts).map(([role, count]) => {\n const pct = Math.round((count / adminUsers.length) * 100);\n return (\n <div key={role} className=\"flex items-center gap-3\">\n <span className=\"w-24 text-sm font-medium capitalize\">\n {role.replace('_', ' ')}\n </span>\n <div className=\"flex-1 h-5 bg-bg-sunken rounded overflow-hidden\">\n <div\n className={`h-5 rounded ${roleColors[role] ?? 'bg-chart-6'}`}\n style={{ width: `${pct}%` }}\n />\n </div>\n <span className=\"w-16 text-right text-sm tabular-nums\">\n {count} ({pct}%)\n </span>\n </div>\n );\n })}\n </CardContent>\n </Card>\n\n <Card className=\"border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base\">User Status Distribution</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {Object.entries(statusCounts).map(([status, count]) => {\n const pct = Math.round((count / adminUsers.length) * 100);\n return (\n <div key={status} className=\"flex items-center gap-3\">\n <span className=\"w-24 text-sm font-medium capitalize\">{status}</span>\n <div className=\"flex-1 h-5 bg-bg-sunken rounded overflow-hidden\">\n <div\n className={`h-5 rounded ${statusColors[status] ?? 'bg-chart-6'}`}\n style={{ width: `${pct}%` }}\n />\n </div>\n <span className=\"w-16 text-right text-sm tabular-nums\">\n {count} ({pct}%)\n </span>\n </div>\n );\n })}\n </CardContent>\n </Card>\n\n {/* Top users by spend */}\n <Card className=\"lg:col-span-2 border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base\">Top Users by Spending</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-2\">\n {[...adminUsers]\n .filter((u) => u.totalSpent > 0)\n .sort((a, b) => b.totalSpent - a.totalSpent)\n .slice(0, 5)\n .map((user, idx) => (\n <div\n key={user.id}\n className=\"flex items-center justify-between rounded-lg border border-border-seam p-3\"\n >\n <div className=\"flex items-center gap-3\">\n <span className=\"flex h-8 w-8 items-center justify-center rounded-full bg-accent-soft text-sm font-bold text-text-primary tabular-nums\">\n {idx + 1}\n </span>\n <div>\n <p className=\"font-medium\">{user.name}</p>\n <p className=\"text-xs text-text-secondary\">{user.email}</p>\n </div>\n </div>\n <div className=\"text-right\">\n <p className=\"font-bold tabular-nums\">\n ${user.totalSpent.toLocaleString()}\n </p>\n <p className=\"text-xs text-text-secondary tabular-nums\">\n {user.bookingsCount} bookings\n </p>\n </div>\n </div>\n ))}\n </div>\n </CardContent>\n </Card>\n </div>\n )}\n\n {/* Revenue Tab */}\n {activeTab === 'revenue' && (\n <div className=\"space-y-6\">\n <Card className=\"border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base\">Monthly Revenue Comparison</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {revenueData.map((point) => {\n const growth = point.prev\n ? (((point.value - point.prev) / point.prev) * 100).toFixed(1)\n : '0';\n const isPositive = point.prev ? point.value >= point.prev : true;\n return (\n <div key={point.name} className=\"rounded-lg border border-border-seam p-4\">\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"font-medium\">{point.name} 2025</p>\n <div className=\"mt-1 flex items-center gap-4 text-sm text-text-secondary tabular-nums\">\n <span>Current: ${(point.value / 1000).toFixed(1)}k</span>\n <span>Previous: ${((point.prev ?? 0) / 1000).toFixed(1)}k</span>\n </div>\n </div>\n <Badge variant={isPositive ? 'default' : 'destructive'}>\n {isPositive ? '+' : ''}\n {growth}%\n </Badge>\n </div>\n <div className=\"mt-3 flex gap-1 h-4\">\n <div\n className=\"h-4 rounded bg-accent-blue-subtle\"\n style={{ width: `${((point.prev ?? 0) / maxRevenue) * 100}%` }}\n />\n <div\n className=\"h-4 rounded bg-accent-blue\"\n style={{\n width: `${Math.max(0, ((point.value - (point.prev ?? 0)) / maxRevenue) * 100)}%`,\n }}\n />\n </div>\n </div>\n );\n })}\n </CardContent>\n </Card>\n </div>\n )}\n\n {/* Bookings Tab */}\n {activeTab === 'bookings' && (\n <div className=\"grid gap-6 lg:grid-cols-2\">\n <Card className=\"border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base\">Bookings by Service Category</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {[...servicePerformance]\n .sort((a, b) => b.value - a.value)\n .map((service, idx) => (\n <div key={service.name} className=\"flex items-center gap-3\">\n <span className=\"w-6 text-sm font-bold text-text-secondary tabular-nums\">\n #{idx + 1}\n </span>\n <div className=\"flex-1\">\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"font-medium\">{service.name}</span>\n <span className=\"tabular-nums\">{service.value} bookings</span>\n </div>\n <div className=\"mt-1 h-2 overflow-hidden rounded-full bg-bg-sunken\">\n <div\n className=\"h-2 rounded-full bg-accent-blue\"\n style={{ width: `${(service.value / maxServiceBookings) * 100}%` }}\n />\n </div>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <Card className=\"border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base\">Quick Stats</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {[\n {\n label: 'Total Bookings',\n value: servicePerformance.reduce((s, p) => s + p.value, 0).toLocaleString(),\n icon: ShoppingCart,\n },\n { label: 'Avg. Booking Value', value: '$3,804', icon: DollarSign },\n { label: 'Completion Rate', value: '96.5%', icon: TrendingUp },\n { label: 'Client Satisfaction', value: '4.7/5.0', icon: Star },\n ].map(({ label, value, icon: Icon }) => (\n <div\n key={label}\n className=\"flex items-center justify-between rounded-lg border border-border-seam p-3\"\n >\n <div className=\"flex items-center gap-3\">\n <Icon className=\"h-5 w-5 text-text-secondary\" />\n <span className=\"text-sm font-medium\">{label}</span>\n </div>\n <span className=\"text-lg font-bold tabular-nums\">{value}</span>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;AAmCA,SAAgB,IAAmB;CACjC,IAAM,EAAE,uBAAoB,gBAAa,uBAAoB,mBAAgB,kBAC3E,GAAyB,EACrB,CAAC,GAAW,KAAgB,EAAoB,WAAW,EAC3D,CAAC,GAAW,KAAgB,EAAoB,MAAM,EAEtD,IAAoE;EACxE;GAAE,KAAK;GAAY,OAAO;GAAY,MAAM;GAAW;EACvD;GAAE,KAAK;GAAS,OAAO;GAAS,MAAM;GAAO;EAC7C;GAAE,KAAK;GAAW,OAAO;GAAW,MAAM;GAAY;EACtD;GAAE,KAAK;GAAY,OAAO;GAAY,MAAM;GAAc;EAC3D,EAEK,KAAc,MACd,MAAS,aACJ,kBAAC,GAAD,EAAY,WAAU,oCAAqC,CAAA,GAChE,MAAS,aACJ,kBAAC,GAAD,EAAc,WAAU,kCAAmC,CAAA,GAC7D,kBAAC,GAAD,EAAO,WAAU,+BAAgC,CAAA,EAGpD,KAAe,MACnB,MAAS,aACL,6BACA,MAAS,aACP,2BACA,uBAEF,IAAc;EAAC;EAAO;EAAQ;EAAc;EAAY;EAAM;EAAc,EAE5E,IAAa,KAAK,IAAI,GAAG,EAAY,KAAK,MAAM,EAAE,MAAM,CAAC,EACzD,IAAqB,KAAK,IAAI,GAAG,EAAmB,KAAK,MAAM,EAAE,MAAM,CAAC,EAGxE,IAAa,EAAW,QAAgC,GAAK,OACjE,EAAI,EAAE,SAAS,EAAI,EAAE,SAAS,KAAK,GAC5B,IACN,EAAE,CAAC,EAGA,IAAe,EAAW,QAAgC,GAAK,OACnE,EAAI,EAAE,WAAW,EAAI,EAAE,WAAW,KAAK,GAChC,IACN,EAAE,CAAC,EAEA,IAAqC;EACzC,QAAQ;EACR,UAAU;EACV,OAAO;EACP,aAAa;EACd,EAEK,IAAuC;EAC3C,QAAQ;EACR,WAAW;EACX,SAAS;EACT,QAAQ;EACT;AAED,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GAEE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD,EAAkB,WAAU,UAAW,CAAA,EACvC,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;MAAI,WAAU;gBACZ,kBAAC,GAAD,EAAA,UAAc,iBAA4B,CAAA;MACvC,CAAA,EACL,kBAAC,KAAD;MAAG,WAAU;gBAA8B;MAEvC,CAAA,CACA,EAAA,CAAA,EACN,kBAAC,GAAD;MACE,SAAS;OACP,OAAO;OACP,gBAAgB;OAChB,MAAM,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA;OACvC;MACD,SAAS,CACP;OACE,OAAO;OACP,gBAAgB;OAChB,MAAM,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA;OACvC,CACF;MACD,CAAA,CACE;OACF;;GAEN,kBAAC,GAAD;IAAa,MAAM,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA;cAAE;IAIxC,CAAA;GAEd,kBAAC,GAAD;IACE,YAAW;IACX,OAAO;KACL;MACE,IAAI;MACJ,OAAO;MACP,aAAa;MACb,MAAM,kBAAC,GAAD,EAAY,WAAU,WAAY,CAAA;MACxC,eAAe,EAAa,UAAU;MACvC;KACD;MACE,IAAI;MACJ,OAAO;MACP,aAAa;MACb,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;MACnC,eAAe,EAAa,QAAQ;MACrC;KACD;MACE,IAAI;MACJ,OAAO;MACP,aAAa;MACb,MAAM,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA;MACtC,eAAe;MAChB;KACF;IACD,CAAA;GAGF,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eACZ,EAAK,KAAK,EAAE,QAAK,UAAO,MAAM,QAC7B,kBAAC,UAAD;MAEE,eAAe,EAAa,EAAI;MAChC,gBAAc,MAAc;MAC5B,WAAW,sKACT,MAAc,IACV,wCACA;gBAPR,CAUE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAC3B,EACM;QAXF,EAWE,CACT;KACE,CAAA,EACN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD,EAAU,WAAU,+BAAgC,CAAA,EACpD,kBAAC,OAAD;MAAK,WAAU;gBACX;OAAC;OAAM;OAAO;OAAO;OAAK,CAAiB,KAAK,MAChD,kBAAC,UAAD;OAEE,eAAe,EAAa,EAAM;OAClC,gBAAc,MAAc;OAC5B,WAAW,8HACT,MAAc,IACV,4CACA;iBAGL;OACM,EAVF,EAUE,CACT;MACE,CAAA,CACF;OACF;;GAGN,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAmB,KAAK,GAAQ,MAAM;KACrC,IAAM,IAAa,EAAY,IAAI,EAAY,WAAW;AAC1D,YACE,kBAAC,GAAD;MAEE,WAAW,MAAM,IAAI,UAAU;MAC/B,MAAM,MAAM;MACZ,WAAU;gBAEV,kBAAC,GAAD;OAAa,WAAU;iBAAvB;QACE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,GAAD,EAAY,WAAU,+BAAgC,CAAA,EACtD,kBAAC,KAAD;WAAG,WAAU;qBAA2C,EAAO;WAAU,CAAA,CACrE;aACL,EAAW,EAAO,WAAW,CAC1B;;QACN,kBAAC,KAAD;SAAG,WAAU;mBAAwC,EAAO;SAAU,CAAA;QACtE,kBAAC,KAAD;SAAG,WAAW,wCAAwC,EAAY,EAAO,WAAW;mBAApF;UACE,kBAAC,GAAD,EAAc,WAAU,WAAY,CAAA;UACnC,EAAO;UAAO;UACb;;QACQ;;MACJ,EAnBL,EAmBK;MAEd;IACE,CAAA;GAGL,MAAc,cACb,kBAAC,OAAD;IAAK,WAAU;cAAf;KAEE,kBAAC,GAAD;MAAM,WAAU;gBAAhB,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD;QAAW,WAAU;kBAAY;QAA4B,CAAA,EAC7D,kBAAC,GAAD;QAAO,SAAQ;kBAAY;QAAe,CAAA,CACtC;UACK,CAAA,EACb,kBAAC,GAAD;OAAa,WAAU;iBACpB,EAAY,KAAK,MAChB,kBAAC,OAAD;QAAsB,WAAU;kBAAhC;SACE,kBAAC,QAAD;UAAM,WAAU;oBAAoC,EAAM;UAAY,CAAA;SACtE,kBAAC,OAAD;UAAK,WAAU;oBACb,kBAAC,OAAD;WACE,WAAU;WACV,OAAO,EAAE,OAAO,GAAI,EAAM,QAAQ,IAAc,IAAI,IAAI;WACxD,CAAA;UACE,CAAA;SACN,kBAAC,QAAD;UAAM,WAAU;oBAAhB;WAAmE;YAC9D,EAAM,QAAQ,KAAM,QAAQ,EAAE;WAAC;WAC7B;;SACH;UAXI,EAAM,KAWV,CACN;OACU,CAAA,CACT;;KAGP,kBAAC,GAAD;MAAM,WAAU;gBAAhB,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD;QAAW,WAAU;kBAAY;QAA4B,CAAA,EAC7D,kBAAC,GAAD;QAAO,SAAQ;kBAAY;QAAa,CAAA,CACpC;UACK,CAAA,EACb,kBAAC,GAAD;OAAa,WAAU;iBACpB,CAAC,GAAG,EAAmB,CACrB,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,CACjC,KAAK,MACJ,kBAAC,OAAD;QAAwB,WAAU;kBAAlC;SACE,kBAAC,QAAD;UAAM,WAAU;oBACb,EAAQ;UACJ,CAAA;SACP,kBAAC,OAAD;UAAK,WAAU;oBACb,kBAAC,OAAD;WACE,WAAU;WACV,OAAO,EAAE,OAAO,GAAI,EAAQ,QAAQ,IAAsB,IAAI,IAAI;WAClE,CAAA;UACE,CAAA;SACN,kBAAC,QAAD;UAAM,WAAU;oBACb,EAAQ;UACJ,CAAA;SACH;UAbI,EAAQ,KAaZ,CACN;OACQ,CAAA,CACT;;KAGP,kBAAC,GAAD;MAAM,WAAU;gBAAhB,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;OAAW,WAAU;iBAAY;OAA6B,CAAA,EACnD,CAAA,EACb,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,SAAD;QAAO,WAAU;kBAAjB,CACE,kBAAC,SAAD,EAAA,UACE,kBAAC,MAAD;SAAI,WAAU;mBAAd;UACE,kBAAC,MAAD;WAAI,WAAU;qBAAM;WAAW,CAAA;UAC/B,kBAAC,MAAD;WAAI,WAAU;qBAAiB;WAAY,CAAA;UAC3C,kBAAC,MAAD;WAAI,WAAU;qBAAiB;WAAY,CAAA;UAC3C,kBAAC,MAAD;WAAI,WAAU;qBAAiB;WAAoB,CAAA;UACnD,kBAAC,MAAD;WAAI,WAAU;qBAAM;WAAU,CAAA;UAC3B;YACC,CAAA,EACR,kBAAC,SAAD,EAAA,UACG,EAAe,KAAK,MAAQ;SAC3B,IAAM,IAAe,EAAe,QAAQ,GAAG,MAAM,IAAI,EAAE,SAAS,EAAE,EAChE,IAAM,KAAK,MAAO,EAAI,UAAU,IAAgB,IAAI,EACpD,IAAe,KAAK,MAAM,EAAI,UAAU,EAAI,QAAQ;AAC1D,gBACE,kBAAC,MAAD;UAEE,WAAU;oBAFZ;WAIE,kBAAC,MAAD;YAAI,WAAU;sBAAmB,EAAI;YAAa,CAAA;WAClD,kBAAC,MAAD;YAAI,WAAU;sBAA+B,EAAI;YAAa,CAAA;WAC9D,kBAAC,MAAD;YAAI,WAAU;sBAAd;aAAwD;cACnD,EAAI,UAAU,KAAM,QAAQ,EAAE;aAAC;aAC/B;;WACL,kBAAC,MAAD;YAAI,WAAU;sBAAd,CAAgE,KAC5D,EAAa,gBAAgB,CAC5B;;WACL,kBAAC,MAAD;YAAI,WAAU;sBACZ,kBAAC,OAAD;aAAK,WAAU;uBAAf,CACE,kBAAC,OAAD;cAAK,WAAU;wBACb,kBAAC,OAAD;eACE,WAAU;eACV,OAAO,EAAE,OAAO,GAAG,EAAI,IAAI;eAC3B,CAAA;cACE,CAAA,EACN,kBAAC,QAAD;cAAM,WAAU;wBAAhB,CAAwD,GAAI,IAAQ;gBAChE;;YACH,CAAA;WACF;YAtBE,EAAI,QAsBN;UAEP,EACI,CAAA,CACF;;OACJ,CAAA,EACM,CAAA,CACT;;KACH;;GAIP,MAAc,WACb,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD;MAAM,WAAU;gBAAhB,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;OAAW,WAAU;iBAAY;OAAkC,CAAA,EACxD,CAAA,EACb,kBAAC,GAAD;OAAa,WAAU;iBACpB,OAAO,QAAQ,EAAW,CAAC,KAAK,CAAC,GAAM,OAAW;QACjD,IAAM,IAAM,KAAK,MAAO,IAAQ,EAAW,SAAU,IAAI;AACzD,eACE,kBAAC,OAAD;SAAgB,WAAU;mBAA1B;UACE,kBAAC,QAAD;WAAM,WAAU;qBACb,EAAK,QAAQ,KAAK,IAAI;WAClB,CAAA;UACP,kBAAC,OAAD;WAAK,WAAU;qBACb,kBAAC,OAAD;YACE,WAAW,eAAe,EAAW,MAAS;YAC9C,OAAO,EAAE,OAAO,GAAG,EAAI,IAAI;YAC3B,CAAA;WACE,CAAA;UACN,kBAAC,QAAD;WAAM,WAAU;qBAAhB;YACG;YAAM;YAAG;YAAI;YACT;;UACH;WAbI,EAaJ;SAER;OACU,CAAA,CACT;;KAEP,kBAAC,GAAD;MAAM,WAAU;gBAAhB,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;OAAW,WAAU;iBAAY;OAAoC,CAAA,EAC1D,CAAA,EACb,kBAAC,GAAD;OAAa,WAAU;iBACpB,OAAO,QAAQ,EAAa,CAAC,KAAK,CAAC,GAAQ,OAAW;QACrD,IAAM,IAAM,KAAK,MAAO,IAAQ,EAAW,SAAU,IAAI;AACzD,eACE,kBAAC,OAAD;SAAkB,WAAU;mBAA5B;UACE,kBAAC,QAAD;WAAM,WAAU;qBAAuC;WAAc,CAAA;UACrE,kBAAC,OAAD;WAAK,WAAU;qBACb,kBAAC,OAAD;YACE,WAAW,eAAe,EAAa,MAAW;YAClD,OAAO,EAAE,OAAO,GAAG,EAAI,IAAI;YAC3B,CAAA;WACE,CAAA;UACN,kBAAC,QAAD;WAAM,WAAU;qBAAhB;YACG;YAAM;YAAG;YAAI;YACT;;UACH;WAXI,EAWJ;SAER;OACU,CAAA,CACT;;KAGP,kBAAC,GAAD;MAAM,WAAU;gBAAhB,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;OAAW,WAAU;iBAAY;OAAiC,CAAA,EACvD,CAAA,EACb,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;OAAK,WAAU;iBACZ,CAAC,GAAG,EAAW,CACb,QAAQ,MAAM,EAAE,aAAa,EAAE,CAC/B,MAAM,GAAG,MAAM,EAAE,aAAa,EAAE,WAAW,CAC3C,MAAM,GAAG,EAAE,CACX,KAAK,GAAM,MACV,kBAAC,OAAD;QAEE,WAAU;kBAFZ,CAIE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,QAAD;UAAM,WAAU;oBACb,IAAM;UACF,CAAA,EACP,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;UAAG,WAAU;oBAAe,EAAK;UAAS,CAAA,EAC1C,kBAAC,KAAD;UAAG,WAAU;oBAA+B,EAAK;UAAU,CAAA,CACvD,EAAA,CAAA,CACF;YACN,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,KAAD;UAAG,WAAU;oBAAb,CAAsC,KAClC,EAAK,WAAW,gBAAgB,CAChC;aACJ,kBAAC,KAAD;UAAG,WAAU;oBAAb,CACG,EAAK,eAAc,YAClB;YACA;WACF;UApBC,EAAK,GAoBN,CACN;OACA,CAAA,EACM,CAAA,CACT;;KACH;;GAIP,MAAc,aACb,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD;KAAM,WAAU;eAAhB,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;MAAW,WAAU;gBAAY;MAAsC,CAAA,EAC5D,CAAA,EACb,kBAAC,GAAD;MAAa,WAAU;gBACpB,EAAY,KAAK,MAAU;OAC1B,IAAM,IAAS,EAAM,SACd,EAAM,QAAQ,EAAM,QAAQ,EAAM,OAAQ,KAAK,QAAQ,EAAE,GAC5D,KACE,IAAa,EAAM,OAAO,EAAM,SAAS,EAAM,OAAO;AAC5D,cACE,kBAAC,OAAD;QAAsB,WAAU;kBAAhC,CACE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;UAAG,WAAU;oBAAb,CAA4B,EAAM,MAAK,QAAS;aAChD,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,QAAD,EAAA,UAAA;WAAM;YAAY,EAAM,QAAQ,KAAM,QAAQ,EAAE;WAAC;WAAQ,EAAA,CAAA,EACzD,kBAAC,QAAD,EAAA,UAAA;WAAM;aAAc,EAAM,QAAQ,KAAK,KAAM,QAAQ,EAAE;WAAC;WAAQ,EAAA,CAAA,CAC5D;YACF,EAAA,CAAA,EACN,kBAAC,GAAD;UAAO,SAAS,IAAa,YAAY;oBAAzC;WACG,IAAa,MAAM;WACnB;WAAO;WACF;YACJ;YACN,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,OAAD;UACE,WAAU;UACV,OAAO,EAAE,OAAO,IAAK,EAAM,QAAQ,KAAK,IAAc,IAAI,IAAI;UAC9D,CAAA,EACF,kBAAC,OAAD;UACE,WAAU;UACV,OAAO,EACL,OAAO,GAAG,KAAK,IAAI,IAAK,EAAM,SAAS,EAAM,QAAQ,MAAM,IAAc,IAAI,CAAC,IAC/E;UACD,CAAA,CACE;WACF;UA1BI,EAAM,KA0BV;QAER;MACU,CAAA,CACT;;IACH,CAAA;GAIP,MAAc,cACb,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KAAM,WAAU;eAAhB,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;MAAW,WAAU;gBAAY;MAAwC,CAAA,EAC9D,CAAA,EACb,kBAAC,GAAD;MAAa,WAAU;gBACpB,CAAC,GAAG,EAAmB,CACrB,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,CACjC,KAAK,GAAS,MACb,kBAAC,OAAD;OAAwB,WAAU;iBAAlC,CACE,kBAAC,QAAD;QAAM,WAAU;kBAAhB,CAAyE,KACrE,IAAM,EACH;WACP,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,QAAD;UAAM,WAAU;oBAAe,EAAQ;UAAY,CAAA,EACnD,kBAAC,QAAD;UAAM,WAAU;oBAAhB,CAAgC,EAAQ,OAAM,YAAgB;YAC1D;YACN,kBAAC,OAAD;SAAK,WAAU;mBACb,kBAAC,OAAD;UACE,WAAU;UACV,OAAO,EAAE,OAAO,GAAI,EAAQ,QAAQ,IAAsB,IAAI,IAAI;UAClE,CAAA;SACE,CAAA,CACF;UACF;SAhBI,EAAQ,KAgBZ,CACN;MACQ,CAAA,CACT;QAEP,kBAAC,GAAD;KAAM,WAAU;eAAhB,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;MAAW,WAAU;gBAAY;MAAuB,CAAA,EAC7C,CAAA,EACb,kBAAC,GAAD;MAAa,WAAU;gBACpB;OACC;QACE,OAAO;QACP,OAAO,EAAmB,QAAQ,GAAG,MAAM,IAAI,EAAE,OAAO,EAAE,CAAC,gBAAgB;QAC3E,MAAM;QACP;OACD;QAAE,OAAO;QAAsB,OAAO;QAAU,MAAM;QAAY;OAClE;QAAE,OAAO;QAAmB,OAAO;QAAS,MAAM;QAAY;OAC9D;QAAE,OAAO;QAAuB,OAAO;QAAW,MAAM;QAAM;OAC/D,CAAC,KAAK,EAAE,UAAO,UAAO,MAAM,QAC3B,kBAAC,OAAD;OAEE,WAAU;iBAFZ,CAIE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD,EAAM,WAAU,+BAAgC,CAAA,EAChD,kBAAC,QAAD;SAAM,WAAU;mBAAuB;SAAa,CAAA,CAChD;WACN,kBAAC,QAAD;QAAM,WAAU;kBAAkC;QAAa,CAAA,CAC3D;SARC,EAQD,CACN;MACU,CAAA,CACT;OACH;;GAEJ"}