@burdenoff/microfe-atheletebridge 2026.624.1 → 2026.625.2

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 (99) hide show
  1. package/dist/atheletebridge/components/EmptyState.js +18 -11
  2. package/dist/atheletebridge/components/EmptyState.js.map +1 -1
  3. package/dist/atheletebridge/components/InvestmentCard.js +7 -7
  4. package/dist/atheletebridge/components/InvestmentCard.js.map +1 -1
  5. package/dist/atheletebridge/components/MetricsCard.js +20 -14
  6. package/dist/atheletebridge/components/MetricsCard.js.map +1 -1
  7. package/dist/atheletebridge/components/PageLayout.js +30 -19
  8. package/dist/atheletebridge/components/PageLayout.js.map +1 -1
  9. package/dist/atheletebridge/pages/HomePage.js +210 -195
  10. package/dist/atheletebridge/pages/HomePage.js.map +1 -1
  11. package/dist/atheletebridge/pages/admin/AdminAnalyticsPage.js +90 -82
  12. package/dist/atheletebridge/pages/admin/AdminAnalyticsPage.js.map +1 -1
  13. package/dist/atheletebridge/pages/admin/AdminDashboard.js +76 -44
  14. package/dist/atheletebridge/pages/admin/AdminDashboard.js.map +1 -1
  15. package/dist/atheletebridge/pages/admin/AdminFinancialPage.js +63 -55
  16. package/dist/atheletebridge/pages/admin/AdminFinancialPage.js.map +1 -1
  17. package/dist/atheletebridge/pages/admin/AdminOrdersPage.js +244 -237
  18. package/dist/atheletebridge/pages/admin/AdminOrdersPage.js.map +1 -1
  19. package/dist/atheletebridge/pages/admin/AdminProfilePage.js +59 -57
  20. package/dist/atheletebridge/pages/admin/AdminProfilePage.js.map +1 -1
  21. package/dist/atheletebridge/pages/admin/AdminSettingsPage.js +110 -106
  22. package/dist/atheletebridge/pages/admin/AdminSettingsPage.js.map +1 -1
  23. package/dist/atheletebridge/pages/admin/CartManagementPage.js +166 -159
  24. package/dist/atheletebridge/pages/admin/CartManagementPage.js.map +1 -1
  25. package/dist/atheletebridge/pages/admin/UserManagementPage.js +310 -303
  26. package/dist/atheletebridge/pages/admin/UserManagementPage.js.map +1 -1
  27. package/dist/atheletebridge/pages/cart-owner/AnalyticsDashboard.js +86 -81
  28. package/dist/atheletebridge/pages/cart-owner/AnalyticsDashboard.js.map +1 -1
  29. package/dist/atheletebridge/pages/cart-owner/BusinessSettingsPage.js +170 -166
  30. package/dist/atheletebridge/pages/cart-owner/BusinessSettingsPage.js.map +1 -1
  31. package/dist/atheletebridge/pages/cart-owner/CartOwnerDashboard.js +141 -109
  32. package/dist/atheletebridge/pages/cart-owner/CartOwnerDashboard.js.map +1 -1
  33. package/dist/atheletebridge/pages/cart-owner/CartOwnerProfilePage.js +139 -134
  34. package/dist/atheletebridge/pages/cart-owner/CartOwnerProfilePage.js.map +1 -1
  35. package/dist/atheletebridge/pages/cart-owner/CartServiceConfigPage.js +109 -107
  36. package/dist/atheletebridge/pages/cart-owner/CartServiceConfigPage.js.map +1 -1
  37. package/dist/atheletebridge/pages/cart-owner/InventoryManagementPage.js +318 -318
  38. package/dist/atheletebridge/pages/cart-owner/InventoryManagementPage.js.map +1 -1
  39. package/dist/atheletebridge/pages/cart-owner/OrderManagementPage.js +262 -262
  40. package/dist/atheletebridge/pages/cart-owner/OrderManagementPage.js.map +1 -1
  41. package/dist/atheletebridge/pages/cart-owner/StaffManagementPage.js +170 -162
  42. package/dist/atheletebridge/pages/cart-owner/StaffManagementPage.js.map +1 -1
  43. package/dist/atheletebridge/pages/common/HelpSupportPage.js +292 -298
  44. package/dist/atheletebridge/pages/common/HelpSupportPage.js.map +1 -1
  45. package/dist/atheletebridge/pages/common/NotificationCenterPage.js +100 -91
  46. package/dist/atheletebridge/pages/common/NotificationCenterPage.js.map +1 -1
  47. package/dist/atheletebridge/pages/common/SettingsPage.js +742 -734
  48. package/dist/atheletebridge/pages/common/SettingsPage.js.map +1 -1
  49. package/dist/atheletebridge/pages/customer/BookingDetailsPage.js +365 -356
  50. package/dist/atheletebridge/pages/customer/BookingDetailsPage.js.map +1 -1
  51. package/dist/atheletebridge/pages/customer/CartDetailPage.js +277 -241
  52. package/dist/atheletebridge/pages/customer/CartDetailPage.js.map +1 -1
  53. package/dist/atheletebridge/pages/customer/CartDiscoveryPage.js +261 -250
  54. package/dist/atheletebridge/pages/customer/CartDiscoveryPage.js.map +1 -1
  55. package/dist/atheletebridge/pages/customer/CheckoutPage.js +93 -89
  56. package/dist/atheletebridge/pages/customer/CheckoutPage.js.map +1 -1
  57. package/dist/atheletebridge/pages/customer/CustomerDashboard.js +430 -387
  58. package/dist/atheletebridge/pages/customer/CustomerDashboard.js.map +1 -1
  59. package/dist/atheletebridge/pages/customer/CustomerProfilePage.js +526 -490
  60. package/dist/atheletebridge/pages/customer/CustomerProfilePage.js.map +1 -1
  61. package/dist/atheletebridge/pages/customer/DirectServiceBookingPage.js +524 -512
  62. package/dist/atheletebridge/pages/customer/DirectServiceBookingPage.js.map +1 -1
  63. package/dist/atheletebridge/pages/customer/FavoritesPage.js +84 -75
  64. package/dist/atheletebridge/pages/customer/FavoritesPage.js.map +1 -1
  65. package/dist/atheletebridge/pages/customer/OrderHistoryPage.js +117 -108
  66. package/dist/atheletebridge/pages/customer/OrderHistoryPage.js.map +1 -1
  67. package/dist/atheletebridge/pages/customer/OrderTrackingPage.js +66 -61
  68. package/dist/atheletebridge/pages/customer/OrderTrackingPage.js.map +1 -1
  69. package/dist/atheletebridge/pages/customer/PaymentMethodsPage.js +81 -75
  70. package/dist/atheletebridge/pages/customer/PaymentMethodsPage.js.map +1 -1
  71. package/dist/atheletebridge/pages/customer/ReviewsPage.js +81 -72
  72. package/dist/atheletebridge/pages/customer/ReviewsPage.js.map +1 -1
  73. package/dist/atheletebridge/pages/customer/SavedAddressesPage.js +63 -55
  74. package/dist/atheletebridge/pages/customer/SavedAddressesPage.js.map +1 -1
  75. package/dist/atheletebridge/pages/investor/InvestmentDetailsPage.js +93 -61
  76. package/dist/atheletebridge/pages/investor/InvestmentDetailsPage.js.map +1 -1
  77. package/dist/atheletebridge/pages/investor/InvestmentOpportunitiesPage.js +90 -84
  78. package/dist/atheletebridge/pages/investor/InvestmentOpportunitiesPage.js.map +1 -1
  79. package/dist/atheletebridge/pages/investor/InvestorAnalyticsPage.js +60 -55
  80. package/dist/atheletebridge/pages/investor/InvestorAnalyticsPage.js.map +1 -1
  81. package/dist/atheletebridge/pages/investor/InvestorDashboard.js +345 -311
  82. package/dist/atheletebridge/pages/investor/InvestorDashboard.js.map +1 -1
  83. package/dist/atheletebridge/pages/investor/InvestorInvestmentsPage.js +38 -32
  84. package/dist/atheletebridge/pages/investor/InvestorInvestmentsPage.js.map +1 -1
  85. package/dist/atheletebridge/pages/investor/InvestorPortfolioPage.js +75 -67
  86. package/dist/atheletebridge/pages/investor/InvestorPortfolioPage.js.map +1 -1
  87. package/dist/atheletebridge/pages/investor/InvestorProfilePage.js +385 -381
  88. package/dist/atheletebridge/pages/investor/InvestorProfilePage.js.map +1 -1
  89. package/dist/atheletebridge/pages/worker/TaskDetailsPage.js +353 -319
  90. package/dist/atheletebridge/pages/worker/TaskDetailsPage.js.map +1 -1
  91. package/dist/atheletebridge/pages/worker/WorkerDashboard.js +353 -318
  92. package/dist/atheletebridge/pages/worker/WorkerDashboard.js.map +1 -1
  93. package/dist/atheletebridge/pages/worker/WorkerOrdersPage.js +134 -128
  94. package/dist/atheletebridge/pages/worker/WorkerOrdersPage.js.map +1 -1
  95. package/dist/atheletebridge/pages/worker/WorkerProfilePage.js +81 -77
  96. package/dist/atheletebridge/pages/worker/WorkerProfilePage.js.map +1 -1
  97. package/dist/atheletebridge/pages/worker/WorkerSchedulePage.js +352 -342
  98. package/dist/atheletebridge/pages/worker/WorkerSchedulePage.js.map +1 -1
  99. package/package.json +3 -3
@@ -6,8 +6,9 @@ import { formatRelativeTime as i } from "../../utils/formatters.js";
6
6
  import { useCallback as a, useMemo as o, useState as s } from "react";
7
7
  import { AlertCircle as c, AlertTriangle as l, ArrowUpDown as u, Bell as d, Check as f, CheckCheck as p, Clock as m, CreditCard as h, Inbox as g, MailOpen as _, Megaphone as v, RefreshCw as y, Search as b, ShoppingBag as x, Star as S, Trash2 as C, TrendingUp as w, Truck as T, UserCheck as E, Users as D, X as O } from "lucide-react";
8
8
  import { Fragment as k, jsx as A, jsxs as j } from "react/jsx-runtime";
9
+ import { EmphasisPanel as M, PagePurpose as N } from "@burdenoff/fe-libs/ui";
9
10
  //#region src/atheletebridge/pages/common/NotificationCenterPage.tsx
10
- var M = [
11
+ var P = [
11
12
  {
12
13
  id: "n-001",
13
14
  type: "order_update",
@@ -169,7 +170,7 @@ var M = [
169
170
  amount: 280
170
171
  }
171
172
  }
172
- ], N = {
173
+ ], F = {
173
174
  order_update: {
174
175
  icon: x,
175
176
  color: "text-blue-600 dark:text-blue-400",
@@ -230,22 +231,22 @@ var M = [
230
231
  bg: "bg-teal-500/10",
231
232
  label: "Account"
232
233
  }
233
- }, P = {
234
+ }, I = {
234
235
  urgent: "bg-red-500/20 text-red-600 dark:text-red-400",
235
236
  high: "bg-orange-500/20 text-orange-600 dark:text-orange-400",
236
237
  medium: "bg-blue-500/20 text-blue-600 dark:text-blue-400",
237
238
  low: "bg-bg-sunken text-text-secondary"
238
- }, F = {
239
+ }, L = {
239
240
  urgent: "border-l-red-500",
240
241
  high: "border-l-orange-500",
241
242
  medium: "border-l-blue-500",
242
243
  low: "border-l-border"
243
- }, I = {
244
+ }, R = {
244
245
  urgent: 4,
245
246
  high: 3,
246
247
  medium: 2,
247
248
  low: 1
248
- }, L = [
249
+ }, z = [
249
250
  {
250
251
  id: "all",
251
252
  label: "All",
@@ -272,18 +273,18 @@ var M = [
272
273
  icon: d
273
274
  }
274
275
  ];
275
- function R(e) {
276
+ function B(e) {
276
277
  let t = new Date(e), n = /* @__PURE__ */ new Date(), r = new Date(n.getFullYear(), n.getMonth(), n.getDate()), i = /* @__PURE__ */ new Date(r.getTime() - 1440 * 60 * 1e3);
277
278
  return t >= r ? "Today" : t >= i ? "Yesterday" : "Earlier";
278
279
  }
279
- function z(e) {
280
+ function V(e) {
280
281
  let t = [], n = /* @__PURE__ */ new Map(), r = [
281
282
  "Today",
282
283
  "Yesterday",
283
284
  "Earlier"
284
285
  ];
285
286
  for (let t of e) {
286
- let e = R(t.createdAt);
287
+ let e = B(t.createdAt);
287
288
  n.has(e) || n.set(e, []), n.get(e).push(t);
288
289
  }
289
290
  for (let e of r) {
@@ -295,11 +296,11 @@ function z(e) {
295
296
  }
296
297
  return t;
297
298
  }
298
- function B() {
299
- let { navigateTo: c } = e(), [l, h] = s(M), [g, v] = s("all"), [x, S] = s(""), [w, T] = s("recent"), [E, D] = s(!1), B = o(() => l.filter((e) => !e.isRead).length, [l]), V = o(() => l.filter((e) => e.priority === "urgent").length, [l]), H = o(() => l.filter((e) => R(e.createdAt) === "Today").length, [l]), U = o(() => {
299
+ function H() {
300
+ let { navigateTo: c } = e(), [l, h] = s(P), [g, v] = s("all"), [x, S] = s(""), [w, T] = s("recent"), [E, D] = s(!1), H = o(() => l.filter((e) => !e.isRead).length, [l]), U = o(() => l.filter((e) => e.priority === "urgent").length, [l]), W = o(() => l.filter((e) => B(e.createdAt) === "Today").length, [l]), G = o(() => {
300
301
  let e = /* @__PURE__ */ new Date(Date.now() - 10080 * 60 * 1e3);
301
302
  return l.filter((t) => new Date(t.createdAt) >= e).length;
302
- }, [l]), W = o(() => {
303
+ }, [l]), K = o(() => {
303
304
  let e = {
304
305
  all: 0,
305
306
  orders: 0,
@@ -309,7 +310,7 @@ function B() {
309
310
  };
310
311
  for (let t of l) e.all++, t.isRead || e.unread++, (t.type === "order_update" || t.type === "delivery") && e.orders++, t.type === "promotion" && e.promotions++, (t.type === "system" || t.type === "alert" || t.type === "account") && e.system++;
311
312
  return e;
312
- }, [l]), G = o(() => {
313
+ }, [l]), q = o(() => {
313
314
  let e = [...l];
314
315
  switch (g) {
315
316
  case "orders":
@@ -334,7 +335,7 @@ function B() {
334
335
  e.sort((e, t) => new Date(t.createdAt).getTime() - new Date(e.createdAt).getTime());
335
336
  break;
336
337
  case "priority":
337
- e.sort((e, t) => I[t.priority] - I[e.priority]);
338
+ e.sort((e, t) => R[t.priority] - R[e.priority]);
338
339
  break;
339
340
  case "unread":
340
341
  e.sort((e, t) => e.isRead === t.isRead ? 0 : e.isRead ? 1 : -1);
@@ -346,102 +347,109 @@ function B() {
346
347
  g,
347
348
  x,
348
349
  w
349
- ]), K = o(() => z(G), [G]), q = a((e) => {
350
+ ]), J = o(() => V(q), [q]), Y = a((e) => {
350
351
  h((t) => t.map((t) => t.id === e ? {
351
352
  ...t,
352
353
  isRead: !0
353
354
  } : t));
354
- }, []), J = a(() => {
355
+ }, []), X = a(() => {
355
356
  h((e) => e.map((e) => ({
356
357
  ...e,
357
358
  isRead: !0
358
359
  })));
359
- }, []), Y = a((e) => {
360
+ }, []), Z = a((e) => {
360
361
  h((t) => t.filter((t) => t.id !== e));
361
- }, []), X = a((e) => {
362
- e.isRead || q(e.id), e.actionUrl && c(e.actionUrl);
363
- }, [q, c]), Z = a(() => {
362
+ }, []), Q = a((e) => {
363
+ e.isRead || Y(e.id), e.actionUrl && c(e.actionUrl);
364
+ }, [Y, c]), $ = a(() => {
364
365
  window.confirm("Are you sure you want to clear all notifications?") && h([]);
365
366
  }, []);
366
367
  return /* @__PURE__ */ j(n, {
367
368
  title: "Notifications",
368
- description: B > 0 ? `${B} unread notification${B === 1 ? "" : "s"}` : "All caught up!",
369
+ description: H > 0 ? `${H} unread notification${H === 1 ? "" : "s"}` : "All caught up!",
369
370
  actions: /* @__PURE__ */ j("div", {
370
371
  className: "flex items-center gap-2",
371
372
  children: [l.length > 0 && /* @__PURE__ */ j("button", {
372
373
  type: "button",
373
- onClick: Z,
374
+ onClick: $,
374
375
  className: "flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-secondary hover:text-text-primary hover:bg-accent transition-colors",
375
376
  children: [/* @__PURE__ */ A(C, { className: "h-4 w-4" }), /* @__PURE__ */ A("span", {
376
377
  className: "hidden sm:inline",
377
378
  children: "Clear All"
378
379
  })]
379
- }), B > 0 && /* @__PURE__ */ j("button", {
380
+ }), H > 0 && /* @__PURE__ */ j("button", {
380
381
  type: "button",
381
- onClick: J,
382
+ onClick: X,
382
383
  className: "flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors",
383
384
  children: [/* @__PURE__ */ A(p, { className: "h-4 w-4" }), "Mark All Read"]
384
385
  })]
385
386
  }),
386
387
  children: [
387
- /* @__PURE__ */ j("div", {
388
- className: "grid grid-cols-2 gap-3 sm:grid-cols-5 mb-6",
389
- children: [
390
- /* @__PURE__ */ j("div", {
391
- className: "rounded-lg border border-border-subtle bg-bg-surface p-3 text-center",
392
- children: [/* @__PURE__ */ A("p", {
393
- className: "text-2xl font-bold text-text-primary",
394
- children: l.length
395
- }), /* @__PURE__ */ A("p", {
396
- className: "text-xs text-text-secondary",
397
- children: "Total"
398
- })]
399
- }),
400
- /* @__PURE__ */ j("div", {
401
- className: "rounded-lg border border-blue-500/30 bg-blue-500/5 p-3 text-center",
402
- children: [/* @__PURE__ */ A("p", {
403
- className: "text-2xl font-bold text-blue-600 dark:text-blue-400",
404
- children: B
405
- }), /* @__PURE__ */ A("p", {
406
- className: "text-xs text-text-secondary",
407
- children: "Unread"
408
- })]
409
- }),
410
- /* @__PURE__ */ j("div", {
411
- className: "rounded-lg border border-red-500/30 bg-red-500/5 p-3 text-center",
412
- children: [/* @__PURE__ */ A("p", {
413
- className: "text-2xl font-bold text-red-600 dark:text-red-400",
414
- children: V
415
- }), /* @__PURE__ */ A("p", {
416
- className: "text-xs text-text-secondary",
417
- children: "Urgent"
418
- })]
419
- }),
420
- /* @__PURE__ */ j("div", {
421
- className: "rounded-lg border border-green-500/30 bg-green-500/5 p-3 text-center",
422
- children: [/* @__PURE__ */ A("p", {
423
- className: "text-2xl font-bold text-green-600 dark:text-green-400",
424
- children: H
425
- }), /* @__PURE__ */ A("p", {
426
- className: "text-xs text-text-secondary",
427
- children: "Today"
428
- })]
429
- }),
430
- /* @__PURE__ */ j("div", {
431
- className: "rounded-lg border border-yellow-500/30 bg-yellow-500/5 p-3 text-center",
432
- children: [/* @__PURE__ */ A("p", {
433
- className: "text-2xl font-bold text-yellow-600 dark:text-yellow-400",
434
- children: U
435
- }), /* @__PURE__ */ A("p", {
436
- className: "text-xs text-text-secondary",
437
- children: "This Week"
438
- })]
439
- })
440
- ]
388
+ /* @__PURE__ */ A(N, {
389
+ className: "mb-6",
390
+ children: "Stay on top of what's happening. Order updates, alerts and announcements all land here. Filter and search to find what matters, mark things read, and clear the noise so important notifications never slip past you."
391
+ }),
392
+ /* @__PURE__ */ A(M, {
393
+ className: "mb-6",
394
+ children: /* @__PURE__ */ j("div", {
395
+ className: "grid grid-cols-2 gap-3 sm:grid-cols-5",
396
+ children: [
397
+ /* @__PURE__ */ j("div", {
398
+ className: "rounded-lg border border-border-subtle bg-bg-surface p-3 text-center",
399
+ children: [/* @__PURE__ */ A("p", {
400
+ className: "text-2xl font-bold text-text-primary",
401
+ children: l.length
402
+ }), /* @__PURE__ */ A("p", {
403
+ className: "text-xs text-text-secondary",
404
+ children: "Total"
405
+ })]
406
+ }),
407
+ /* @__PURE__ */ j("div", {
408
+ className: "rounded-lg border border-blue-500/30 bg-blue-500/5 p-3 text-center",
409
+ children: [/* @__PURE__ */ A("p", {
410
+ className: "text-2xl font-bold text-blue-600 dark:text-blue-400",
411
+ children: H
412
+ }), /* @__PURE__ */ A("p", {
413
+ className: "text-xs text-text-secondary",
414
+ children: "Unread"
415
+ })]
416
+ }),
417
+ /* @__PURE__ */ j("div", {
418
+ className: "rounded-lg border border-red-500/30 bg-red-500/5 p-3 text-center",
419
+ children: [/* @__PURE__ */ A("p", {
420
+ className: "text-2xl font-bold text-red-600 dark:text-red-400",
421
+ children: U
422
+ }), /* @__PURE__ */ A("p", {
423
+ className: "text-xs text-text-secondary",
424
+ children: "Urgent"
425
+ })]
426
+ }),
427
+ /* @__PURE__ */ j("div", {
428
+ className: "rounded-lg border border-green-500/30 bg-green-500/5 p-3 text-center",
429
+ children: [/* @__PURE__ */ A("p", {
430
+ className: "text-2xl font-bold text-green-600 dark:text-green-400",
431
+ children: W
432
+ }), /* @__PURE__ */ A("p", {
433
+ className: "text-xs text-text-secondary",
434
+ children: "Today"
435
+ })]
436
+ }),
437
+ /* @__PURE__ */ j("div", {
438
+ className: "rounded-lg border border-yellow-500/30 bg-yellow-500/5 p-3 text-center",
439
+ children: [/* @__PURE__ */ A("p", {
440
+ className: "text-2xl font-bold text-yellow-600 dark:text-yellow-400",
441
+ children: G
442
+ }), /* @__PURE__ */ A("p", {
443
+ className: "text-xs text-text-secondary",
444
+ children: "This Week"
445
+ })]
446
+ })
447
+ ]
448
+ })
441
449
  }),
442
450
  /* @__PURE__ */ A("div", {
443
451
  className: "flex items-center gap-2 mb-4 overflow-x-auto pb-1",
444
- children: L.map((e) => {
452
+ children: z.map((e) => {
445
453
  let n = e.icon;
446
454
  return /* @__PURE__ */ j("button", {
447
455
  type: "button",
@@ -452,7 +460,7 @@ function B() {
452
460
  e.label,
453
461
  /* @__PURE__ */ A("span", {
454
462
  className: t("inline-flex h-5 min-w-[20px] items-center justify-center rounded-full px-1 text-xs", g === e.id ? "bg-action-primary-bg text-action-primary-text" : "bg-bg-sunken text-text-secondary"),
455
- children: W[e.id]
463
+ children: K[e.id]
456
464
  })
457
465
  ]
458
466
  }, e.id);
@@ -517,7 +525,8 @@ function B() {
517
525
  })] })]
518
526
  })]
519
527
  }),
520
- G.length === 0 ? /* @__PURE__ */ A(r, {
528
+ q.length === 0 ? /* @__PURE__ */ A(r, {
529
+ illustration: "empty-notifications",
521
530
  icon: /* @__PURE__ */ A(d, { className: "h-12 w-12" }),
522
531
  title: "No notifications",
523
532
  description: x ? "No notifications match your search. Try different keywords." : g === "unread" ? "You're all caught up! No unread notifications." : "No notifications in this category yet.",
@@ -534,7 +543,7 @@ function B() {
534
543
  })
535
544
  }) : /* @__PURE__ */ A("div", {
536
545
  className: "space-y-6",
537
- children: K.map((e) => /* @__PURE__ */ j("div", { children: [/* @__PURE__ */ j("div", {
546
+ children: J.map((e) => /* @__PURE__ */ j("div", { children: [/* @__PURE__ */ j("div", {
538
547
  className: "flex items-center gap-3 mb-2",
539
548
  children: [
540
549
  /* @__PURE__ */ A("h3", {
@@ -554,9 +563,9 @@ function B() {
554
563
  }), /* @__PURE__ */ A("div", {
555
564
  className: "rounded-lg border border-border-subtle bg-bg-surface divide-y divide-border overflow-hidden",
556
565
  children: e.items.map((e) => {
557
- let n = N[e.type] ?? N.system, r = n.icon;
566
+ let n = F[e.type] ?? F.system, r = n.icon;
558
567
  return /* @__PURE__ */ j("div", {
559
- className: t("flex items-start gap-3 px-4 py-4 border-l-4 transition-colors", F[e.priority], !e.isRead && "bg-accent/30"),
568
+ className: t("flex items-start gap-3 px-4 py-4 border-l-4 transition-colors", L[e.priority], !e.isRead && "bg-accent/30"),
560
569
  children: [
561
570
  /* @__PURE__ */ A("div", {
562
571
  className: t("flex h-10 w-10 shrink-0 items-center justify-center rounded-full", n.bg),
@@ -574,7 +583,7 @@ function B() {
574
583
  }),
575
584
  !e.isRead && /* @__PURE__ */ A("span", { className: "h-2 w-2 rounded-full bg-action-primary-bg shrink-0" }),
576
585
  /* @__PURE__ */ A("span", {
577
- className: t("inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium", P[e.priority]),
586
+ className: t("inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium", I[e.priority]),
578
587
  children: e.priority
579
588
  })
580
589
  ]
@@ -605,20 +614,20 @@ function B() {
605
614
  children: [
606
615
  e.actionUrl && /* @__PURE__ */ A("button", {
607
616
  type: "button",
608
- onClick: () => X(e),
617
+ onClick: () => Q(e),
609
618
  className: "rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors",
610
619
  children: e.actionText ?? "View"
611
620
  }),
612
621
  !e.isRead && /* @__PURE__ */ j("button", {
613
622
  type: "button",
614
- onClick: () => q(e.id),
623
+ onClick: () => Y(e.id),
615
624
  title: "Mark as read",
616
625
  className: "flex items-center gap-1 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-accent transition-colors",
617
626
  children: [/* @__PURE__ */ A(f, { className: "h-3 w-3" }), "Mark Read"]
618
627
  }),
619
628
  /* @__PURE__ */ j("button", {
620
629
  type: "button",
621
- onClick: () => Y(e.id),
630
+ onClick: () => Z(e.id),
622
631
  title: "Delete notification",
623
632
  className: "flex items-center gap-1 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-status-error-text hover:bg-status-error-bg/10 transition-colors",
624
633
  children: [/* @__PURE__ */ A(C, { className: "h-3 w-3" }), "Delete"]
@@ -636,13 +645,13 @@ function B() {
636
645
  })
637
646
  })] }, e.label))
638
647
  }),
639
- G.length > 0 && /* @__PURE__ */ j("div", {
648
+ q.length > 0 && /* @__PURE__ */ j("div", {
640
649
  className: "mt-6 flex items-center justify-between rounded-lg border border-border-subtle bg-bg-surface px-4 py-3",
641
650
  children: [/* @__PURE__ */ j("p", {
642
651
  className: "text-sm text-text-secondary",
643
652
  children: [
644
653
  "Showing ",
645
- G.length,
654
+ q.length,
646
655
  " of ",
647
656
  l.length,
648
657
  " notifications"
@@ -660,6 +669,6 @@ function B() {
660
669
  });
661
670
  }
662
671
  //#endregion
663
- export { B as NotificationCenterPage };
672
+ export { H as NotificationCenterPage };
664
673
 
665
674
  //# sourceMappingURL=NotificationCenterPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"NotificationCenterPage.js","names":[],"sources":["../../../../src/atheletebridge/pages/common/NotificationCenterPage.tsx"],"sourcesContent":["/**\n * Notification Center Page\n * @module atheletebridge/pages/common\n *\n * Full-featured notification center with tab filters (All, Orders,\n * Promotions, System, Unread), date grouping (Today, Yesterday, Earlier),\n * mark-as-read / mark-all-as-read, delete notification, search,\n * type/priority badges, action buttons, stats overview, and empty states.\n */\n\nimport { useState, useMemo, useCallback } from 'react';\nimport {\n Bell,\n ShoppingBag,\n TrendingUp,\n Star,\n AlertCircle,\n CheckCircle2,\n CreditCard,\n Users,\n AlertTriangle,\n Megaphone,\n Check,\n CheckCheck,\n Trash2,\n Search,\n X,\n MailOpen,\n Clock,\n Truck,\n UserCheck,\n Inbox,\n RefreshCw,\n SlidersHorizontal,\n ArrowUpDown,\n} from 'lucide-react';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { useAthleteBridge } from '../../context/AthleteBridgeContext';\nimport { cn } from '../../utils/cn';\nimport { formatRelativeTime } from '../../utils/formatters';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype NotificationType =\n | 'order_update'\n | 'payment'\n | 'promotion'\n | 'system'\n | 'review'\n | 'staff'\n | 'investment'\n | 'alert'\n | 'delivery'\n | 'account';\n\ntype NotificationPriority = 'low' | 'medium' | 'high' | 'urgent';\n\ntype TabId = 'all' | 'orders' | 'promotions' | 'system' | 'unread';\n\ntype SortOption = 'recent' | 'priority' | 'unread';\n\ninterface Notification {\n id: string;\n type: NotificationType;\n title: string;\n message: string;\n priority: NotificationPriority;\n isRead: boolean;\n createdAt: string;\n actionUrl?: string;\n actionText?: string;\n metadata?: {\n orderId?: string;\n cartId?: string;\n amount?: number;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Mock notifications (14 items, rich variety)\n// ---------------------------------------------------------------------------\n\nconst initialNotifications: Notification[] = [\n {\n id: 'n-001',\n type: 'order_update',\n title: 'Order Delivered Successfully!',\n message:\n 'Your order #ORD-001 from Dosa Express has been delivered. Rate your experience to help others!',\n priority: 'medium',\n isRead: false,\n createdAt: new Date(Date.now() - 8 * 60 * 1000).toISOString(),\n actionUrl: '/customer/order/ORD-001',\n actionText: 'Rate Order',\n metadata: { orderId: 'ORD-001', cartId: 'FOOD-001' },\n },\n {\n id: 'n-002',\n type: 'payment',\n title: 'Payment Confirmed',\n message:\n 'Your payment of \\u20B9495 for order #ORD-002 at Quick Cuts Salon has been processed successfully.',\n priority: 'medium',\n isRead: false,\n createdAt: new Date(Date.now() - 35 * 60 * 1000).toISOString(),\n metadata: { orderId: 'ORD-002', amount: 495 },\n },\n {\n id: 'n-003',\n type: 'promotion',\n title: '20% Off Beauty Services This Weekend!',\n message:\n \"Glow Beauty Services is offering 20% off on all treatments this weekend only. Don't miss out!\",\n priority: 'low',\n isRead: false,\n createdAt: new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/customer/cart/SERV-002',\n actionText: 'Book Now',\n metadata: { cartId: 'SERV-002' },\n },\n {\n id: 'n-004',\n type: 'review',\n title: 'New Review Response',\n message:\n 'Dosa Express replied to your review: \"Thank you so much for your kind words! We hope to serve you again soon.\"',\n priority: 'low',\n isRead: false,\n createdAt: new Date(Date.now() - 4 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/customer/reviews',\n actionText: 'View Reply',\n },\n {\n id: 'n-005',\n type: 'system',\n title: 'App Update Available',\n message:\n 'Version 2.4.0 of AthleteBridge is available with improved performance, new category filters, and bug fixes.',\n priority: 'medium',\n isRead: false,\n createdAt: new Date(Date.now() - 7 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/settings',\n actionText: 'Update Now',\n },\n {\n id: 'n-006',\n type: 'order_update',\n title: 'Appointment Confirmed',\n message:\n 'Your appointment at Quick Cuts Salon has been confirmed for tomorrow at 3:00 PM. The stylist Suresh will be serving you.',\n priority: 'medium',\n isRead: true,\n createdAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/customer/order/ORD-002',\n actionText: 'View Details',\n metadata: { orderId: 'ORD-002' },\n },\n {\n id: 'n-007',\n type: 'investment',\n title: 'Monthly Returns Credited',\n message:\n 'You received \\u20B91,250 in monthly returns from your Quick Cuts Salon investment. Total portfolio value: \\u20B92,12,500.',\n priority: 'medium',\n isRead: true,\n createdAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/investor/portfolio',\n actionText: 'View Portfolio',\n metadata: { amount: 1250 },\n },\n {\n id: 'n-008',\n type: 'delivery',\n title: 'Delivery Worker Assigned',\n message:\n 'Ravi Kumar (rated 4.8) has been assigned to deliver your order from Biryani Pot. Estimated arrival: 25 minutes.',\n priority: 'high',\n isRead: true,\n createdAt: new Date(Date.now() - 1.5 * 24 * 60 * 60 * 1000).toISOString(),\n metadata: { orderId: 'ORD-003' },\n },\n {\n id: 'n-009',\n type: 'alert',\n title: 'Unusual Login Attempt Detected',\n message:\n 'We detected a login attempt from a new device in Mumbai. If this was not you, please change your password immediately.',\n priority: 'urgent',\n isRead: true,\n createdAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/settings',\n actionText: 'Review Activity',\n },\n {\n id: 'n-010',\n type: 'promotion',\n title: 'Flash Sale: Mobile Accessories',\n message:\n 'Gadget Zone Brigade is running a flash sale! Up to 30% off on bluetooth headphones, cases, and chargers.',\n priority: 'low',\n isRead: true,\n createdAt: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/customer/cart/RETAIL-003',\n actionText: 'Shop Now',\n metadata: { cartId: 'RETAIL-003' },\n },\n {\n id: 'n-011',\n type: 'system',\n title: 'Scheduled Platform Maintenance',\n message:\n 'Platform maintenance is scheduled for Sunday 2:00 AM - 4:00 AM IST. Some services may be briefly unavailable during this window.',\n priority: 'high',\n isRead: true,\n createdAt: new Date(Date.now() - 4 * 24 * 60 * 60 * 1000).toISOString(),\n },\n {\n id: 'n-012',\n type: 'account',\n title: 'KYC Verification Complete',\n message:\n 'Your KYC verification has been completed successfully. You now have full access to all platform features including investments.',\n priority: 'medium',\n isRead: true,\n createdAt: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString(),\n },\n {\n id: 'n-013',\n type: 'staff',\n title: 'Staff Schedule Updated',\n message:\n 'Priya Sharma has updated her availability for this week. She will be unavailable on Wednesday and Thursday.',\n priority: 'medium',\n isRead: true,\n createdAt: new Date(Date.now() - 6 * 24 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/owner/staff',\n actionText: 'View Schedule',\n },\n {\n id: 'n-014',\n type: 'payment',\n title: 'Refund Processed',\n message:\n 'Your refund of \\u20B9280 for order #ORD-005 has been processed. The amount will reflect in your account within 3-5 business days.',\n priority: 'medium',\n isRead: true,\n createdAt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(),\n metadata: { orderId: 'ORD-005', amount: 280 },\n },\n];\n\n// ---------------------------------------------------------------------------\n// Type icon/color configuration\n// ---------------------------------------------------------------------------\n\nconst typeConfig: Record<string, { icon: typeof Bell; color: string; bg: string; label: string }> =\n {\n order_update: {\n icon: ShoppingBag,\n color: 'text-blue-600 dark:text-blue-400',\n bg: 'bg-blue-500/10',\n label: 'Order',\n },\n payment: {\n icon: CreditCard,\n color: 'text-green-600 dark:text-green-400',\n bg: 'bg-green-500/10',\n label: 'Payment',\n },\n promotion: {\n icon: Megaphone,\n color: 'text-orange-600 dark:text-orange-400',\n bg: 'bg-orange-500/10',\n label: 'Promo',\n },\n system: {\n icon: AlertCircle,\n color: 'text-purple-600 dark:text-purple-400',\n bg: 'bg-purple-500/10',\n label: 'System',\n },\n review: {\n icon: Star,\n color: 'text-yellow-600 dark:text-yellow-400',\n bg: 'bg-yellow-500/10',\n label: 'Review',\n },\n staff: {\n icon: Users,\n color: 'text-indigo-600 dark:text-indigo-400',\n bg: 'bg-indigo-500/10',\n label: 'Staff',\n },\n investment: {\n icon: TrendingUp,\n color: 'text-emerald-600 dark:text-emerald-400',\n bg: 'bg-emerald-500/10',\n label: 'Investment',\n },\n alert: {\n icon: AlertTriangle,\n color: 'text-red-600 dark:text-red-400',\n bg: 'bg-red-500/10',\n label: 'Alert',\n },\n delivery: {\n icon: Truck,\n color: 'text-cyan-600 dark:text-cyan-400',\n bg: 'bg-cyan-500/10',\n label: 'Delivery',\n },\n account: {\n icon: UserCheck,\n color: 'text-teal-600 dark:text-teal-400',\n bg: 'bg-teal-500/10',\n label: 'Account',\n },\n };\n\n// ---------------------------------------------------------------------------\n// Priority styling\n// ---------------------------------------------------------------------------\n\nconst priorityStyles: Record<NotificationPriority, string> = {\n urgent: 'bg-red-500/20 text-red-600 dark:text-red-400',\n high: 'bg-orange-500/20 text-orange-600 dark:text-orange-400',\n medium: 'bg-blue-500/20 text-blue-600 dark:text-blue-400',\n low: 'bg-bg-sunken text-text-secondary',\n};\n\nconst priorityBorderColors: Record<NotificationPriority, string> = {\n urgent: 'border-l-red-500',\n high: 'border-l-orange-500',\n medium: 'border-l-blue-500',\n low: 'border-l-border',\n};\n\nconst priorityOrder: Record<NotificationPriority, number> = {\n urgent: 4,\n high: 3,\n medium: 2,\n low: 1,\n};\n\n// ---------------------------------------------------------------------------\n// Tab definitions\n// ---------------------------------------------------------------------------\n\nconst tabs: { id: TabId; label: string; icon: typeof Bell }[] = [\n { id: 'all', label: 'All', icon: Inbox },\n { id: 'orders', label: 'Orders', icon: ShoppingBag },\n { id: 'promotions', label: 'Promotions', icon: Megaphone },\n { id: 'system', label: 'System', icon: AlertCircle },\n { id: 'unread', label: 'Unread', icon: Bell },\n];\n\n// ---------------------------------------------------------------------------\n// Date grouping helpers\n// ---------------------------------------------------------------------------\n\nfunction getDateGroup(dateStr: string): string {\n const date = new Date(dateStr);\n const now = new Date();\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000);\n\n if (date >= today) return 'Today';\n if (date >= yesterday) return 'Yesterday';\n return 'Earlier';\n}\n\nfunction groupByDate(items: Notification[]): { label: string; items: Notification[] }[] {\n const groups: { label: string; items: Notification[] }[] = [];\n const map = new Map<string, Notification[]>();\n const order = ['Today', 'Yesterday', 'Earlier'];\n\n for (const n of items) {\n const group = getDateGroup(n.createdAt);\n if (!map.has(group)) map.set(group, []);\n map.get(group)!.push(n);\n }\n\n for (const label of order) {\n const items = map.get(label);\n if (items && items.length > 0) {\n groups.push({ label, items });\n }\n }\n\n return groups;\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function NotificationCenterPage() {\n const { navigateTo } = useAthleteBridge();\n const [notifications, setNotifications] = useState<Notification[]>(initialNotifications);\n const [activeTab, setActiveTab] = useState<TabId>('all');\n const [searchQuery, setSearchQuery] = useState('');\n const [sortBy, setSortBy] = useState<SortOption>('recent');\n const [showSortMenu, setShowSortMenu] = useState(false);\n\n // ---------------------------------------------------------------------------\n // Derived counts\n // ---------------------------------------------------------------------------\n\n const unreadCount = useMemo(() => notifications.filter((n) => !n.isRead).length, [notifications]);\n\n const urgentCount = useMemo(\n () => notifications.filter((n) => n.priority === 'urgent').length,\n [notifications]\n );\n\n const todayCount = useMemo(\n () => notifications.filter((n) => getDateGroup(n.createdAt) === 'Today').length,\n [notifications]\n );\n\n const thisWeekCount = useMemo(() => {\n const weekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);\n return notifications.filter((n) => new Date(n.createdAt) >= weekAgo).length;\n }, [notifications]);\n\n const tabCounts = useMemo(() => {\n const counts: Record<TabId, number> = {\n all: 0,\n orders: 0,\n promotions: 0,\n system: 0,\n unread: 0,\n };\n for (const n of notifications) {\n counts.all++;\n if (!n.isRead) counts.unread++;\n if (n.type === 'order_update' || n.type === 'delivery') counts.orders++;\n if (n.type === 'promotion') counts.promotions++;\n if (n.type === 'system' || n.type === 'alert' || n.type === 'account') counts.system++;\n }\n return counts;\n }, [notifications]);\n\n // ---------------------------------------------------------------------------\n // Filtered & sorted list\n // ---------------------------------------------------------------------------\n\n const filteredNotifications = useMemo(() => {\n let list = [...notifications];\n\n // Tab filter\n switch (activeTab) {\n case 'orders':\n list = list.filter((n) => n.type === 'order_update' || n.type === 'delivery');\n break;\n case 'promotions':\n list = list.filter((n) => n.type === 'promotion');\n break;\n case 'system':\n list = list.filter(\n (n) => n.type === 'system' || n.type === 'alert' || n.type === 'account'\n );\n break;\n case 'unread':\n list = list.filter((n) => !n.isRead);\n break;\n }\n\n // Search filter\n if (searchQuery) {\n const q = searchQuery.toLowerCase();\n list = list.filter(\n (n) => n.title.toLowerCase().includes(q) || n.message.toLowerCase().includes(q)\n );\n }\n\n // Sort\n switch (sortBy) {\n case 'recent':\n list.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());\n break;\n case 'priority':\n list.sort((a, b) => priorityOrder[b.priority] - priorityOrder[a.priority]);\n break;\n case 'unread':\n list.sort((a, b) => (a.isRead === b.isRead ? 0 : a.isRead ? 1 : -1));\n break;\n }\n\n return list;\n }, [notifications, activeTab, searchQuery, sortBy]);\n\n // Grouped by date\n const grouped = useMemo(() => groupByDate(filteredNotifications), [filteredNotifications]);\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n const markAsRead = useCallback((id: string) => {\n setNotifications((prev) => prev.map((n) => (n.id === id ? { ...n, isRead: true } : n)));\n }, []);\n\n const markAllAsRead = useCallback(() => {\n setNotifications((prev) => prev.map((n) => ({ ...n, isRead: true })));\n }, []);\n\n const deleteNotification = useCallback((id: string) => {\n setNotifications((prev) => prev.filter((n) => n.id !== id));\n }, []);\n\n const handleAction = useCallback(\n (notif: Notification) => {\n if (!notif.isRead) markAsRead(notif.id);\n if (notif.actionUrl) navigateTo(notif.actionUrl);\n },\n [markAsRead, navigateTo]\n );\n\n const clearAll = useCallback(() => {\n if (window.confirm('Are you sure you want to clear all notifications?')) {\n setNotifications([]);\n }\n }, []);\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n\n return (\n <PageLayout\n title=\"Notifications\"\n description={\n unreadCount > 0\n ? `${unreadCount} unread notification${unreadCount !== 1 ? 's' : ''}`\n : 'All caught up!'\n }\n actions={\n <div className=\"flex items-center gap-2\">\n {notifications.length > 0 && (\n <button\n type=\"button\"\n onClick={clearAll}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-secondary hover:text-text-primary hover:bg-accent transition-colors\"\n >\n <Trash2 className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">Clear All</span>\n </button>\n )}\n {unreadCount > 0 && (\n <button\n type=\"button\"\n onClick={markAllAsRead}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <CheckCheck className=\"h-4 w-4\" />\n Mark All Read\n </button>\n )}\n </div>\n }\n >\n {/* ---- Stats Overview ---- */}\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-5 mb-6\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-3 text-center\">\n <p className=\"text-2xl font-bold text-text-primary\">{notifications.length}</p>\n <p className=\"text-xs text-text-secondary\">Total</p>\n </div>\n <div className=\"rounded-lg border border-blue-500/30 bg-blue-500/5 p-3 text-center\">\n <p className=\"text-2xl font-bold text-blue-600 dark:text-blue-400\">{unreadCount}</p>\n <p className=\"text-xs text-text-secondary\">Unread</p>\n </div>\n <div className=\"rounded-lg border border-red-500/30 bg-red-500/5 p-3 text-center\">\n <p className=\"text-2xl font-bold text-red-600 dark:text-red-400\">{urgentCount}</p>\n <p className=\"text-xs text-text-secondary\">Urgent</p>\n </div>\n <div className=\"rounded-lg border border-green-500/30 bg-green-500/5 p-3 text-center\">\n <p className=\"text-2xl font-bold text-green-600 dark:text-green-400\">{todayCount}</p>\n <p className=\"text-xs text-text-secondary\">Today</p>\n </div>\n <div className=\"rounded-lg border border-yellow-500/30 bg-yellow-500/5 p-3 text-center\">\n <p className=\"text-2xl font-bold text-yellow-600 dark:text-yellow-400\">{thisWeekCount}</p>\n <p className=\"text-xs text-text-secondary\">This Week</p>\n </div>\n </div>\n\n {/* ---- Tabs ---- */}\n <div className=\"flex items-center gap-2 mb-4 overflow-x-auto pb-1\">\n {tabs.map((tab) => {\n const TabIcon = tab.icon;\n return (\n <button\n key={tab.id}\n type=\"button\"\n onClick={() => setActiveTab(tab.id)}\n className={cn(\n 'flex items-center gap-1.5 whitespace-nowrap rounded-full border px-3 py-1.5 text-sm font-medium transition-colors',\n activeTab === tab.id\n ? 'border-primary bg-action-primary-bg/10 text-text-primary'\n : 'border-border-subtle text-text-secondary hover:text-text-primary hover:border-accent-foreground/20'\n )}\n >\n <TabIcon className=\"h-3.5 w-3.5\" />\n {tab.label}\n <span\n className={cn(\n 'inline-flex h-5 min-w-[20px] items-center justify-center rounded-full px-1 text-xs',\n activeTab === tab.id\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-sunken text-text-secondary'\n )}\n >\n {tabCounts[tab.id]}\n </span>\n </button>\n );\n })}\n </div>\n\n {/* ---- Search & Sort ---- */}\n <div className=\"flex items-center gap-3 mb-6\">\n <div className=\"relative flex-1\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <input\n type=\"text\"\n placeholder=\"Search notifications...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2.5 pl-10 pr-9 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n {searchQuery && (\n <button\n type=\"button\"\n onClick={() => setSearchQuery('')}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-text-secondary hover:text-text-primary\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n\n {/* Sort dropdown */}\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setShowSortMenu(!showSortMenu)}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-2.5 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <ArrowUpDown className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">Sort</span>\n </button>\n {showSortMenu && (\n <>\n {/* Backdrop */}\n <div className=\"fixed inset-0 z-10\" onClick={() => setShowSortMenu(false)} />\n <div className=\"absolute right-0 top-full mt-1 z-20 w-44 rounded-lg border border-border-subtle bg-bg-surface shadow-lg py-1\">\n {(\n [\n { value: 'recent', label: 'Most Recent' },\n { value: 'priority', label: 'By Priority' },\n { value: 'unread', label: 'Unread First' },\n ] as const\n ).map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n onClick={() => {\n setSortBy(opt.value);\n setShowSortMenu(false);\n }}\n className={cn(\n 'w-full text-left px-3 py-2 text-sm transition-colors',\n sortBy === opt.value\n ? 'bg-action-primary-bg/10 text-text-primary font-medium'\n : 'text-text-secondary hover:bg-accent hover:text-text-primary'\n )}\n >\n {opt.label}\n </button>\n ))}\n </div>\n </>\n )}\n </div>\n </div>\n\n {/* ---- Notification List ---- */}\n {filteredNotifications.length === 0 ? (\n <EmptyState\n icon={<Bell className=\"h-12 w-12\" />}\n title=\"No notifications\"\n description={\n searchQuery\n ? 'No notifications match your search. Try different keywords.'\n : activeTab === 'unread'\n ? \"You're all caught up! No unread notifications.\"\n : 'No notifications in this category yet.'\n }\n action={\n searchQuery ? (\n <button\n type=\"button\"\n onClick={() => setSearchQuery('')}\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n Clear Search\n </button>\n ) : activeTab !== 'all' ? (\n <button\n type=\"button\"\n onClick={() => setActiveTab('all')}\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n View All Notifications\n </button>\n ) : undefined\n }\n />\n ) : (\n <div className=\"space-y-6\">\n {grouped.map((group) => (\n <div key={group.label}>\n {/* Date group header */}\n <div className=\"flex items-center gap-3 mb-2\">\n <h3 className=\"text-xs font-semibold uppercase tracking-wider text-text-secondary\">\n {group.label}\n </h3>\n <div className=\"flex-1 border-t border-border-subtle\" />\n <span className=\"text-xs text-text-secondary\">\n {group.items.length} notification{group.items.length !== 1 ? 's' : ''}\n </span>\n </div>\n\n {/* Notification cards */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface divide-y divide-border overflow-hidden\">\n {group.items.map((notif) => {\n const config = typeConfig[notif.type] ?? typeConfig.system;\n const NotifIcon = config.icon;\n\n return (\n <div\n key={notif.id}\n className={cn(\n 'flex items-start gap-3 px-4 py-4 border-l-4 transition-colors',\n priorityBorderColors[notif.priority],\n !notif.isRead && 'bg-accent/30'\n )}\n >\n {/* Type icon */}\n <div\n className={cn(\n 'flex h-10 w-10 shrink-0 items-center justify-center rounded-full',\n config.bg\n )}\n >\n <NotifIcon className={cn('h-5 w-5', config.color)} />\n </div>\n\n {/* Content */}\n <div className=\"flex-1 min-w-0\">\n {/* Title row */}\n <div className=\"flex items-center gap-2 flex-wrap\">\n <h4\n className={cn(\n 'text-sm text-text-primary',\n !notif.isRead ? 'font-semibold' : 'font-medium'\n )}\n >\n {notif.title}\n </h4>\n {!notif.isRead && (\n <span className=\"h-2 w-2 rounded-full bg-action-primary-bg shrink-0\" />\n )}\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium',\n priorityStyles[notif.priority]\n )}\n >\n {notif.priority}\n </span>\n </div>\n\n {/* Message */}\n <p className=\"mt-1 text-sm text-text-secondary leading-relaxed\">\n {notif.message}\n </p>\n\n {/* Metadata row */}\n <div className=\"mt-2 flex items-center gap-3 flex-wrap\">\n <span className=\"flex items-center gap-1 text-xs text-text-secondary\">\n <Clock className=\"h-3 w-3\" />\n {formatRelativeTime(notif.createdAt)}\n </span>\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium',\n config.bg,\n config.color\n )}\n >\n {config.label}\n </span>\n {notif.metadata?.orderId && (\n <span className=\"text-xs text-text-secondary\">\n #{notif.metadata.orderId}\n </span>\n )}\n </div>\n\n {/* Action buttons row */}\n <div className=\"mt-3 flex items-center gap-2 flex-wrap\">\n {notif.actionUrl && (\n <button\n type=\"button\"\n onClick={() => handleAction(notif)}\n className=\"rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors\"\n >\n {notif.actionText ?? 'View'}\n </button>\n )}\n {!notif.isRead && (\n <button\n type=\"button\"\n onClick={() => markAsRead(notif.id)}\n title=\"Mark as read\"\n className=\"flex items-center gap-1 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <Check className=\"h-3 w-3\" />\n Mark Read\n </button>\n )}\n <button\n type=\"button\"\n onClick={() => deleteNotification(notif.id)}\n title=\"Delete notification\"\n className=\"flex items-center gap-1 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-status-error-text hover:bg-status-error-bg/10 transition-colors\"\n >\n <Trash2 className=\"h-3 w-3\" />\n Delete\n </button>\n </div>\n </div>\n\n {/* Read/unread indicator */}\n <div className=\"shrink-0 pt-1\">\n {notif.isRead ? (\n <MailOpen className=\"h-4 w-4 text-text-secondary/40\" />\n ) : (\n <Bell className=\"h-4 w-4 text-primary\" />\n )}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* ---- Footer summary ---- */}\n {filteredNotifications.length > 0 && (\n <div className=\"mt-6 flex items-center justify-between rounded-lg border border-border-subtle bg-bg-surface px-4 py-3\">\n <p className=\"text-sm text-text-secondary\">\n Showing {filteredNotifications.length} of {notifications.length} notifications\n </p>\n {activeTab !== 'all' && (\n <button\n type=\"button\"\n onClick={() => {\n setActiveTab('all');\n setSearchQuery('');\n }}\n className=\"flex items-center gap-1.5 text-sm font-medium text-primary hover:underline\"\n >\n <RefreshCw className=\"h-3.5 w-3.5\" />\n Show All\n </button>\n )}\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"NotificationCenterPage.js","names":[],"sources":["../../../../src/atheletebridge/pages/common/NotificationCenterPage.tsx"],"sourcesContent":["/**\n * Notification Center Page\n * @module atheletebridge/pages/common\n *\n * Full-featured notification center with tab filters (All, Orders,\n * Promotions, System, Unread), date grouping (Today, Yesterday, Earlier),\n * mark-as-read / mark-all-as-read, delete notification, search,\n * type/priority badges, action buttons, stats overview, and empty states.\n */\n\nimport { useState, useMemo, useCallback } from 'react';\nimport {\n Bell,\n ShoppingBag,\n TrendingUp,\n Star,\n AlertCircle,\n CheckCircle2,\n CreditCard,\n Users,\n AlertTriangle,\n Megaphone,\n Check,\n CheckCheck,\n Trash2,\n Search,\n X,\n MailOpen,\n Clock,\n Truck,\n UserCheck,\n Inbox,\n RefreshCw,\n SlidersHorizontal,\n ArrowUpDown,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { useAthleteBridge } from '../../context/AthleteBridgeContext';\nimport { cn } from '../../utils/cn';\nimport { formatRelativeTime } from '../../utils/formatters';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype NotificationType =\n | 'order_update'\n | 'payment'\n | 'promotion'\n | 'system'\n | 'review'\n | 'staff'\n | 'investment'\n | 'alert'\n | 'delivery'\n | 'account';\n\ntype NotificationPriority = 'low' | 'medium' | 'high' | 'urgent';\n\ntype TabId = 'all' | 'orders' | 'promotions' | 'system' | 'unread';\n\ntype SortOption = 'recent' | 'priority' | 'unread';\n\ninterface Notification {\n id: string;\n type: NotificationType;\n title: string;\n message: string;\n priority: NotificationPriority;\n isRead: boolean;\n createdAt: string;\n actionUrl?: string;\n actionText?: string;\n metadata?: {\n orderId?: string;\n cartId?: string;\n amount?: number;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Mock notifications (14 items, rich variety)\n// ---------------------------------------------------------------------------\n\nconst initialNotifications: Notification[] = [\n {\n id: 'n-001',\n type: 'order_update',\n title: 'Order Delivered Successfully!',\n message:\n 'Your order #ORD-001 from Dosa Express has been delivered. Rate your experience to help others!',\n priority: 'medium',\n isRead: false,\n createdAt: new Date(Date.now() - 8 * 60 * 1000).toISOString(),\n actionUrl: '/customer/order/ORD-001',\n actionText: 'Rate Order',\n metadata: { orderId: 'ORD-001', cartId: 'FOOD-001' },\n },\n {\n id: 'n-002',\n type: 'payment',\n title: 'Payment Confirmed',\n message:\n 'Your payment of \\u20B9495 for order #ORD-002 at Quick Cuts Salon has been processed successfully.',\n priority: 'medium',\n isRead: false,\n createdAt: new Date(Date.now() - 35 * 60 * 1000).toISOString(),\n metadata: { orderId: 'ORD-002', amount: 495 },\n },\n {\n id: 'n-003',\n type: 'promotion',\n title: '20% Off Beauty Services This Weekend!',\n message:\n \"Glow Beauty Services is offering 20% off on all treatments this weekend only. Don't miss out!\",\n priority: 'low',\n isRead: false,\n createdAt: new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/customer/cart/SERV-002',\n actionText: 'Book Now',\n metadata: { cartId: 'SERV-002' },\n },\n {\n id: 'n-004',\n type: 'review',\n title: 'New Review Response',\n message:\n 'Dosa Express replied to your review: \"Thank you so much for your kind words! We hope to serve you again soon.\"',\n priority: 'low',\n isRead: false,\n createdAt: new Date(Date.now() - 4 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/customer/reviews',\n actionText: 'View Reply',\n },\n {\n id: 'n-005',\n type: 'system',\n title: 'App Update Available',\n message:\n 'Version 2.4.0 of AthleteBridge is available with improved performance, new category filters, and bug fixes.',\n priority: 'medium',\n isRead: false,\n createdAt: new Date(Date.now() - 7 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/settings',\n actionText: 'Update Now',\n },\n {\n id: 'n-006',\n type: 'order_update',\n title: 'Appointment Confirmed',\n message:\n 'Your appointment at Quick Cuts Salon has been confirmed for tomorrow at 3:00 PM. The stylist Suresh will be serving you.',\n priority: 'medium',\n isRead: true,\n createdAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/customer/order/ORD-002',\n actionText: 'View Details',\n metadata: { orderId: 'ORD-002' },\n },\n {\n id: 'n-007',\n type: 'investment',\n title: 'Monthly Returns Credited',\n message:\n 'You received \\u20B91,250 in monthly returns from your Quick Cuts Salon investment. Total portfolio value: \\u20B92,12,500.',\n priority: 'medium',\n isRead: true,\n createdAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/investor/portfolio',\n actionText: 'View Portfolio',\n metadata: { amount: 1250 },\n },\n {\n id: 'n-008',\n type: 'delivery',\n title: 'Delivery Worker Assigned',\n message:\n 'Ravi Kumar (rated 4.8) has been assigned to deliver your order from Biryani Pot. Estimated arrival: 25 minutes.',\n priority: 'high',\n isRead: true,\n createdAt: new Date(Date.now() - 1.5 * 24 * 60 * 60 * 1000).toISOString(),\n metadata: { orderId: 'ORD-003' },\n },\n {\n id: 'n-009',\n type: 'alert',\n title: 'Unusual Login Attempt Detected',\n message:\n 'We detected a login attempt from a new device in Mumbai. If this was not you, please change your password immediately.',\n priority: 'urgent',\n isRead: true,\n createdAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/settings',\n actionText: 'Review Activity',\n },\n {\n id: 'n-010',\n type: 'promotion',\n title: 'Flash Sale: Mobile Accessories',\n message:\n 'Gadget Zone Brigade is running a flash sale! Up to 30% off on bluetooth headphones, cases, and chargers.',\n priority: 'low',\n isRead: true,\n createdAt: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/customer/cart/RETAIL-003',\n actionText: 'Shop Now',\n metadata: { cartId: 'RETAIL-003' },\n },\n {\n id: 'n-011',\n type: 'system',\n title: 'Scheduled Platform Maintenance',\n message:\n 'Platform maintenance is scheduled for Sunday 2:00 AM - 4:00 AM IST. Some services may be briefly unavailable during this window.',\n priority: 'high',\n isRead: true,\n createdAt: new Date(Date.now() - 4 * 24 * 60 * 60 * 1000).toISOString(),\n },\n {\n id: 'n-012',\n type: 'account',\n title: 'KYC Verification Complete',\n message:\n 'Your KYC verification has been completed successfully. You now have full access to all platform features including investments.',\n priority: 'medium',\n isRead: true,\n createdAt: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString(),\n },\n {\n id: 'n-013',\n type: 'staff',\n title: 'Staff Schedule Updated',\n message:\n 'Priya Sharma has updated her availability for this week. She will be unavailable on Wednesday and Thursday.',\n priority: 'medium',\n isRead: true,\n createdAt: new Date(Date.now() - 6 * 24 * 60 * 60 * 1000).toISOString(),\n actionUrl: '/owner/staff',\n actionText: 'View Schedule',\n },\n {\n id: 'n-014',\n type: 'payment',\n title: 'Refund Processed',\n message:\n 'Your refund of \\u20B9280 for order #ORD-005 has been processed. The amount will reflect in your account within 3-5 business days.',\n priority: 'medium',\n isRead: true,\n createdAt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(),\n metadata: { orderId: 'ORD-005', amount: 280 },\n },\n];\n\n// ---------------------------------------------------------------------------\n// Type icon/color configuration\n// ---------------------------------------------------------------------------\n\nconst typeConfig: Record<string, { icon: typeof Bell; color: string; bg: string; label: string }> =\n {\n order_update: {\n icon: ShoppingBag,\n color: 'text-blue-600 dark:text-blue-400',\n bg: 'bg-blue-500/10',\n label: 'Order',\n },\n payment: {\n icon: CreditCard,\n color: 'text-green-600 dark:text-green-400',\n bg: 'bg-green-500/10',\n label: 'Payment',\n },\n promotion: {\n icon: Megaphone,\n color: 'text-orange-600 dark:text-orange-400',\n bg: 'bg-orange-500/10',\n label: 'Promo',\n },\n system: {\n icon: AlertCircle,\n color: 'text-purple-600 dark:text-purple-400',\n bg: 'bg-purple-500/10',\n label: 'System',\n },\n review: {\n icon: Star,\n color: 'text-yellow-600 dark:text-yellow-400',\n bg: 'bg-yellow-500/10',\n label: 'Review',\n },\n staff: {\n icon: Users,\n color: 'text-indigo-600 dark:text-indigo-400',\n bg: 'bg-indigo-500/10',\n label: 'Staff',\n },\n investment: {\n icon: TrendingUp,\n color: 'text-emerald-600 dark:text-emerald-400',\n bg: 'bg-emerald-500/10',\n label: 'Investment',\n },\n alert: {\n icon: AlertTriangle,\n color: 'text-red-600 dark:text-red-400',\n bg: 'bg-red-500/10',\n label: 'Alert',\n },\n delivery: {\n icon: Truck,\n color: 'text-cyan-600 dark:text-cyan-400',\n bg: 'bg-cyan-500/10',\n label: 'Delivery',\n },\n account: {\n icon: UserCheck,\n color: 'text-teal-600 dark:text-teal-400',\n bg: 'bg-teal-500/10',\n label: 'Account',\n },\n };\n\n// ---------------------------------------------------------------------------\n// Priority styling\n// ---------------------------------------------------------------------------\n\nconst priorityStyles: Record<NotificationPriority, string> = {\n urgent: 'bg-red-500/20 text-red-600 dark:text-red-400',\n high: 'bg-orange-500/20 text-orange-600 dark:text-orange-400',\n medium: 'bg-blue-500/20 text-blue-600 dark:text-blue-400',\n low: 'bg-bg-sunken text-text-secondary',\n};\n\nconst priorityBorderColors: Record<NotificationPriority, string> = {\n urgent: 'border-l-red-500',\n high: 'border-l-orange-500',\n medium: 'border-l-blue-500',\n low: 'border-l-border',\n};\n\nconst priorityOrder: Record<NotificationPriority, number> = {\n urgent: 4,\n high: 3,\n medium: 2,\n low: 1,\n};\n\n// ---------------------------------------------------------------------------\n// Tab definitions\n// ---------------------------------------------------------------------------\n\nconst tabs: { id: TabId; label: string; icon: typeof Bell }[] = [\n { id: 'all', label: 'All', icon: Inbox },\n { id: 'orders', label: 'Orders', icon: ShoppingBag },\n { id: 'promotions', label: 'Promotions', icon: Megaphone },\n { id: 'system', label: 'System', icon: AlertCircle },\n { id: 'unread', label: 'Unread', icon: Bell },\n];\n\n// ---------------------------------------------------------------------------\n// Date grouping helpers\n// ---------------------------------------------------------------------------\n\nfunction getDateGroup(dateStr: string): string {\n const date = new Date(dateStr);\n const now = new Date();\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000);\n\n if (date >= today) return 'Today';\n if (date >= yesterday) return 'Yesterday';\n return 'Earlier';\n}\n\nfunction groupByDate(items: Notification[]): { label: string; items: Notification[] }[] {\n const groups: { label: string; items: Notification[] }[] = [];\n const map = new Map<string, Notification[]>();\n const order = ['Today', 'Yesterday', 'Earlier'];\n\n for (const n of items) {\n const group = getDateGroup(n.createdAt);\n if (!map.has(group)) map.set(group, []);\n map.get(group)!.push(n);\n }\n\n for (const label of order) {\n const items = map.get(label);\n if (items && items.length > 0) {\n groups.push({ label, items });\n }\n }\n\n return groups;\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function NotificationCenterPage() {\n const { navigateTo } = useAthleteBridge();\n const [notifications, setNotifications] = useState<Notification[]>(initialNotifications);\n const [activeTab, setActiveTab] = useState<TabId>('all');\n const [searchQuery, setSearchQuery] = useState('');\n const [sortBy, setSortBy] = useState<SortOption>('recent');\n const [showSortMenu, setShowSortMenu] = useState(false);\n\n // ---------------------------------------------------------------------------\n // Derived counts\n // ---------------------------------------------------------------------------\n\n const unreadCount = useMemo(() => notifications.filter((n) => !n.isRead).length, [notifications]);\n\n const urgentCount = useMemo(\n () => notifications.filter((n) => n.priority === 'urgent').length,\n [notifications]\n );\n\n const todayCount = useMemo(\n () => notifications.filter((n) => getDateGroup(n.createdAt) === 'Today').length,\n [notifications]\n );\n\n const thisWeekCount = useMemo(() => {\n const weekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);\n return notifications.filter((n) => new Date(n.createdAt) >= weekAgo).length;\n }, [notifications]);\n\n const tabCounts = useMemo(() => {\n const counts: Record<TabId, number> = {\n all: 0,\n orders: 0,\n promotions: 0,\n system: 0,\n unread: 0,\n };\n for (const n of notifications) {\n counts.all++;\n if (!n.isRead) counts.unread++;\n if (n.type === 'order_update' || n.type === 'delivery') counts.orders++;\n if (n.type === 'promotion') counts.promotions++;\n if (n.type === 'system' || n.type === 'alert' || n.type === 'account') counts.system++;\n }\n return counts;\n }, [notifications]);\n\n // ---------------------------------------------------------------------------\n // Filtered & sorted list\n // ---------------------------------------------------------------------------\n\n const filteredNotifications = useMemo(() => {\n let list = [...notifications];\n\n // Tab filter\n switch (activeTab) {\n case 'orders':\n list = list.filter((n) => n.type === 'order_update' || n.type === 'delivery');\n break;\n case 'promotions':\n list = list.filter((n) => n.type === 'promotion');\n break;\n case 'system':\n list = list.filter(\n (n) => n.type === 'system' || n.type === 'alert' || n.type === 'account'\n );\n break;\n case 'unread':\n list = list.filter((n) => !n.isRead);\n break;\n }\n\n // Search filter\n if (searchQuery) {\n const q = searchQuery.toLowerCase();\n list = list.filter(\n (n) => n.title.toLowerCase().includes(q) || n.message.toLowerCase().includes(q)\n );\n }\n\n // Sort\n switch (sortBy) {\n case 'recent':\n list.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());\n break;\n case 'priority':\n list.sort((a, b) => priorityOrder[b.priority] - priorityOrder[a.priority]);\n break;\n case 'unread':\n list.sort((a, b) => (a.isRead === b.isRead ? 0 : a.isRead ? 1 : -1));\n break;\n }\n\n return list;\n }, [notifications, activeTab, searchQuery, sortBy]);\n\n // Grouped by date\n const grouped = useMemo(() => groupByDate(filteredNotifications), [filteredNotifications]);\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n const markAsRead = useCallback((id: string) => {\n setNotifications((prev) => prev.map((n) => (n.id === id ? { ...n, isRead: true } : n)));\n }, []);\n\n const markAllAsRead = useCallback(() => {\n setNotifications((prev) => prev.map((n) => ({ ...n, isRead: true })));\n }, []);\n\n const deleteNotification = useCallback((id: string) => {\n setNotifications((prev) => prev.filter((n) => n.id !== id));\n }, []);\n\n const handleAction = useCallback(\n (notif: Notification) => {\n if (!notif.isRead) markAsRead(notif.id);\n if (notif.actionUrl) navigateTo(notif.actionUrl);\n },\n [markAsRead, navigateTo]\n );\n\n const clearAll = useCallback(() => {\n if (window.confirm('Are you sure you want to clear all notifications?')) {\n setNotifications([]);\n }\n }, []);\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n\n return (\n <PageLayout\n title=\"Notifications\"\n description={\n unreadCount > 0\n ? `${unreadCount} unread notification${unreadCount !== 1 ? 's' : ''}`\n : 'All caught up!'\n }\n actions={\n <div className=\"flex items-center gap-2\">\n {notifications.length > 0 && (\n <button\n type=\"button\"\n onClick={clearAll}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-secondary hover:text-text-primary hover:bg-accent transition-colors\"\n >\n <Trash2 className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">Clear All</span>\n </button>\n )}\n {unreadCount > 0 && (\n <button\n type=\"button\"\n onClick={markAllAsRead}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <CheckCheck className=\"h-4 w-4\" />\n Mark All Read\n </button>\n )}\n </div>\n }\n >\n <PagePurpose className=\"mb-6\">\n Stay on top of what&apos;s happening. Order updates, alerts and announcements all land here.\n Filter and search to find what matters, mark things read, and clear the noise so important\n notifications never slip past you.\n </PagePurpose>\n\n {/* ---- Stats Overview ---- */}\n <EmphasisPanel className=\"mb-6\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-5\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-3 text-center\">\n <p className=\"text-2xl font-bold text-text-primary\">{notifications.length}</p>\n <p className=\"text-xs text-text-secondary\">Total</p>\n </div>\n <div className=\"rounded-lg border border-blue-500/30 bg-blue-500/5 p-3 text-center\">\n <p className=\"text-2xl font-bold text-blue-600 dark:text-blue-400\">{unreadCount}</p>\n <p className=\"text-xs text-text-secondary\">Unread</p>\n </div>\n <div className=\"rounded-lg border border-red-500/30 bg-red-500/5 p-3 text-center\">\n <p className=\"text-2xl font-bold text-red-600 dark:text-red-400\">{urgentCount}</p>\n <p className=\"text-xs text-text-secondary\">Urgent</p>\n </div>\n <div className=\"rounded-lg border border-green-500/30 bg-green-500/5 p-3 text-center\">\n <p className=\"text-2xl font-bold text-green-600 dark:text-green-400\">{todayCount}</p>\n <p className=\"text-xs text-text-secondary\">Today</p>\n </div>\n <div className=\"rounded-lg border border-yellow-500/30 bg-yellow-500/5 p-3 text-center\">\n <p className=\"text-2xl font-bold text-yellow-600 dark:text-yellow-400\">{thisWeekCount}</p>\n <p className=\"text-xs text-text-secondary\">This Week</p>\n </div>\n </div>\n </EmphasisPanel>\n\n {/* ---- Tabs ---- */}\n <div className=\"flex items-center gap-2 mb-4 overflow-x-auto pb-1\">\n {tabs.map((tab) => {\n const TabIcon = tab.icon;\n return (\n <button\n key={tab.id}\n type=\"button\"\n onClick={() => setActiveTab(tab.id)}\n className={cn(\n 'flex items-center gap-1.5 whitespace-nowrap rounded-full border px-3 py-1.5 text-sm font-medium transition-colors',\n activeTab === tab.id\n ? 'border-primary bg-action-primary-bg/10 text-text-primary'\n : 'border-border-subtle text-text-secondary hover:text-text-primary hover:border-accent-foreground/20'\n )}\n >\n <TabIcon className=\"h-3.5 w-3.5\" />\n {tab.label}\n <span\n className={cn(\n 'inline-flex h-5 min-w-[20px] items-center justify-center rounded-full px-1 text-xs',\n activeTab === tab.id\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-sunken text-text-secondary'\n )}\n >\n {tabCounts[tab.id]}\n </span>\n </button>\n );\n })}\n </div>\n\n {/* ---- Search & Sort ---- */}\n <div className=\"flex items-center gap-3 mb-6\">\n <div className=\"relative flex-1\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <input\n type=\"text\"\n placeholder=\"Search notifications...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2.5 pl-10 pr-9 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n {searchQuery && (\n <button\n type=\"button\"\n onClick={() => setSearchQuery('')}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-text-secondary hover:text-text-primary\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n\n {/* Sort dropdown */}\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setShowSortMenu(!showSortMenu)}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-2.5 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <ArrowUpDown className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">Sort</span>\n </button>\n {showSortMenu && (\n <>\n {/* Backdrop */}\n <div className=\"fixed inset-0 z-10\" onClick={() => setShowSortMenu(false)} />\n <div className=\"absolute right-0 top-full mt-1 z-20 w-44 rounded-lg border border-border-subtle bg-bg-surface shadow-lg py-1\">\n {(\n [\n { value: 'recent', label: 'Most Recent' },\n { value: 'priority', label: 'By Priority' },\n { value: 'unread', label: 'Unread First' },\n ] as const\n ).map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n onClick={() => {\n setSortBy(opt.value);\n setShowSortMenu(false);\n }}\n className={cn(\n 'w-full text-left px-3 py-2 text-sm transition-colors',\n sortBy === opt.value\n ? 'bg-action-primary-bg/10 text-text-primary font-medium'\n : 'text-text-secondary hover:bg-accent hover:text-text-primary'\n )}\n >\n {opt.label}\n </button>\n ))}\n </div>\n </>\n )}\n </div>\n </div>\n\n {/* ---- Notification List ---- */}\n {filteredNotifications.length === 0 ? (\n <EmptyState\n illustration=\"empty-notifications\"\n icon={<Bell className=\"h-12 w-12\" />}\n title=\"No notifications\"\n description={\n searchQuery\n ? 'No notifications match your search. Try different keywords.'\n : activeTab === 'unread'\n ? \"You're all caught up! No unread notifications.\"\n : 'No notifications in this category yet.'\n }\n action={\n searchQuery ? (\n <button\n type=\"button\"\n onClick={() => setSearchQuery('')}\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n Clear Search\n </button>\n ) : activeTab !== 'all' ? (\n <button\n type=\"button\"\n onClick={() => setActiveTab('all')}\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n View All Notifications\n </button>\n ) : undefined\n }\n />\n ) : (\n <div className=\"space-y-6\">\n {grouped.map((group) => (\n <div key={group.label}>\n {/* Date group header */}\n <div className=\"flex items-center gap-3 mb-2\">\n <h3 className=\"text-xs font-semibold uppercase tracking-wider text-text-secondary\">\n {group.label}\n </h3>\n <div className=\"flex-1 border-t border-border-subtle\" />\n <span className=\"text-xs text-text-secondary\">\n {group.items.length} notification{group.items.length !== 1 ? 's' : ''}\n </span>\n </div>\n\n {/* Notification cards */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface divide-y divide-border overflow-hidden\">\n {group.items.map((notif) => {\n const config = typeConfig[notif.type] ?? typeConfig.system;\n const NotifIcon = config.icon;\n\n return (\n <div\n key={notif.id}\n className={cn(\n 'flex items-start gap-3 px-4 py-4 border-l-4 transition-colors',\n priorityBorderColors[notif.priority],\n !notif.isRead && 'bg-accent/30'\n )}\n >\n {/* Type icon */}\n <div\n className={cn(\n 'flex h-10 w-10 shrink-0 items-center justify-center rounded-full',\n config.bg\n )}\n >\n <NotifIcon className={cn('h-5 w-5', config.color)} />\n </div>\n\n {/* Content */}\n <div className=\"flex-1 min-w-0\">\n {/* Title row */}\n <div className=\"flex items-center gap-2 flex-wrap\">\n <h4\n className={cn(\n 'text-sm text-text-primary',\n !notif.isRead ? 'font-semibold' : 'font-medium'\n )}\n >\n {notif.title}\n </h4>\n {!notif.isRead && (\n <span className=\"h-2 w-2 rounded-full bg-action-primary-bg shrink-0\" />\n )}\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium',\n priorityStyles[notif.priority]\n )}\n >\n {notif.priority}\n </span>\n </div>\n\n {/* Message */}\n <p className=\"mt-1 text-sm text-text-secondary leading-relaxed\">\n {notif.message}\n </p>\n\n {/* Metadata row */}\n <div className=\"mt-2 flex items-center gap-3 flex-wrap\">\n <span className=\"flex items-center gap-1 text-xs text-text-secondary\">\n <Clock className=\"h-3 w-3\" />\n {formatRelativeTime(notif.createdAt)}\n </span>\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium',\n config.bg,\n config.color\n )}\n >\n {config.label}\n </span>\n {notif.metadata?.orderId && (\n <span className=\"text-xs text-text-secondary\">\n #{notif.metadata.orderId}\n </span>\n )}\n </div>\n\n {/* Action buttons row */}\n <div className=\"mt-3 flex items-center gap-2 flex-wrap\">\n {notif.actionUrl && (\n <button\n type=\"button\"\n onClick={() => handleAction(notif)}\n className=\"rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors\"\n >\n {notif.actionText ?? 'View'}\n </button>\n )}\n {!notif.isRead && (\n <button\n type=\"button\"\n onClick={() => markAsRead(notif.id)}\n title=\"Mark as read\"\n className=\"flex items-center gap-1 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <Check className=\"h-3 w-3\" />\n Mark Read\n </button>\n )}\n <button\n type=\"button\"\n onClick={() => deleteNotification(notif.id)}\n title=\"Delete notification\"\n className=\"flex items-center gap-1 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-status-error-text hover:bg-status-error-bg/10 transition-colors\"\n >\n <Trash2 className=\"h-3 w-3\" />\n Delete\n </button>\n </div>\n </div>\n\n {/* Read/unread indicator */}\n <div className=\"shrink-0 pt-1\">\n {notif.isRead ? (\n <MailOpen className=\"h-4 w-4 text-text-secondary/40\" />\n ) : (\n <Bell className=\"h-4 w-4 text-primary\" />\n )}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* ---- Footer summary ---- */}\n {filteredNotifications.length > 0 && (\n <div className=\"mt-6 flex items-center justify-between rounded-lg border border-border-subtle bg-bg-surface px-4 py-3\">\n <p className=\"text-sm text-text-secondary\">\n Showing {filteredNotifications.length} of {notifications.length} notifications\n </p>\n {activeTab !== 'all' && (\n <button\n type=\"button\"\n onClick={() => {\n setActiveTab('all');\n setSearchQuery('');\n }}\n className=\"flex items-center gap-1.5 text-sm font-medium text-primary hover:underline\"\n >\n <RefreshCw className=\"h-3.5 w-3.5\" />\n Show All\n </button>\n )}\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}