@burdenoff/microfe-movethewheels 2026.624.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 (119) hide show
  1. package/dist/{AIAssistantPage-BrHX2lQn.js → AIAssistantPage-AvsMbunM.js} +39 -33
  2. package/dist/{AnalyticsPage-DI6Wcaw5.js → AnalyticsPage-CCLfHgQZ.js} +44 -33
  3. package/dist/CreateOrderPage-CjlnEtk3.js +510 -0
  4. package/dist/CustomerDetailsPage-I6cdDHUi.js +265 -0
  5. package/dist/CustomersPage-CGGfD4ki.js +163 -0
  6. package/dist/{DashboardPage-3ZOnwg1a.js → DashboardPage-D2HRqwg9.js} +122 -111
  7. package/dist/DataTable-CD9ZhpLB.js +249 -0
  8. package/dist/DriverDetailsPage-rg_pGNuP.js +330 -0
  9. package/dist/DriversPage-DKiynISH.js +167 -0
  10. package/dist/FinancePage-Vg8WPs38.js +158 -0
  11. package/dist/{FleetPage-CPS7r4J3.js → FleetPage-DddXt8r8.js} +124 -85
  12. package/dist/ImportExportPage-BW6qO3kc.js +248 -0
  13. package/dist/InventoryPage-rMGuaJN-.js +222 -0
  14. package/dist/LiveTrackingPage-DQ1q4Id3.js +375 -0
  15. package/dist/MarketplacePage-DKrXAv62.js +219 -0
  16. package/dist/MetricCard-B7yMyvMX.js +146 -0
  17. package/dist/OrderDetailsPage-CFASgsYX.js +431 -0
  18. package/dist/OrdersListPage-BHeT8S5o.js +309 -0
  19. package/dist/{PageLayout-xDTiBTDS.js → PageLayout-D3N8MCTm.js} +213 -195
  20. package/dist/ProductDetailsPage-CFGcbaHo.js +195 -0
  21. package/dist/ProductsPage--xEpbQ8A.js +171 -0
  22. package/dist/{ReportsPage-B8OyWGzl.js → ReportsPage-Bb7_90rK.js} +57 -49
  23. package/dist/RouteDetailsPage-CVtDVb1N.js +282 -0
  24. package/dist/RoutesPage-s57PtgcQ.js +163 -0
  25. package/dist/SettingsPage-BYNCBOpN.js +298 -0
  26. package/dist/{StatusBadge-C--7NhoW.js → StatusBadge-CijYQXtb.js} +5 -2
  27. package/dist/{TrackingPage-BldUm_g7.js → TrackingPage-CcRc_dva.js} +88 -83
  28. package/dist/VehicleDetailsPage-3YDMPsPs.js +220 -0
  29. package/dist/VehiclesPage-UlxPWP9K.js +167 -0
  30. package/dist/WarehouseDetailsPage-Db7KeN-d.js +238 -0
  31. package/dist/WarehousesPage-CuTO-OPp.js +164 -0
  32. package/dist/{arrow-left-Bk5GsGNk.js → arrow-left-CBpZKkpq.js} +1 -1
  33. package/dist/{box-BAMv2-7M.js → box-CAaiElsb.js} +1 -1
  34. package/dist/{chart-column-CAfkf4o6.js → chart-column-D1Ym15-S.js} +1 -1
  35. package/dist/{chevron-right-Czrt_Qew.js → chevron-right-BIFGi0UA.js} +1 -1
  36. package/dist/{circle-alert-CEuV9Pij.js → circle-alert-DjmNo5_L.js} +1 -1
  37. package/dist/{circle-check-big-Cx8aO6B-.js → circle-check-big-CjuPVo3_.js} +1 -1
  38. package/dist/{clock-Be95bq7_.js → clock-BjkdnddD.js} +1 -1
  39. package/dist/{dollar-sign-kJqItPli.js → dollar-sign-IB4O0wuQ.js} +1 -1
  40. package/dist/{download-caab0D3V.js → download-Dpa9vqoG.js} +1 -1
  41. package/dist/{file-text-b1qhrJn1.js → file-text-C8Uioy11.js} +1 -1
  42. package/dist/{filter-BWmLTZB-.js → filter-Da5OZaHI.js} +1 -1
  43. package/dist/index.js +16 -16
  44. package/dist/{map-CS2aFgyO.js → map-_Per4sT9.js} +1 -1
  45. package/dist/{map-pin-96FeqL7H.js → map-pin-BSaf5IDL.js} +1 -1
  46. package/dist/{navigation-i6UXEjTC.js → navigation-DaTbrhw2.js} +1 -1
  47. package/dist/{package-KhSi3xaT.js → package-BE7U0wQE.js} +1 -1
  48. package/dist/{phone-B-h3tbsr.js → phone-DV4StZiA.js} +1 -1
  49. package/dist/{plus-D2BYAzMn.js → plus-Dl1rLeJR.js} +1 -1
  50. package/dist/{refresh-cw-D5Sy01s-.js → refresh-cw-CWfERAit.js} +1 -1
  51. package/dist/{route-CBDXuwH9.js → route-Dp9JiN_E.js} +1 -1
  52. package/dist/{save-CMc7h-Vi.js → save-XH8vydOn.js} +1 -1
  53. package/dist/{search-DVrUQbOg.js → search-OxoIiL_C.js} +1 -1
  54. package/dist/{settings-BwzIRYv3.js → settings-3Rw5NwFF.js} +1 -1
  55. package/dist/{square-pen-DmW36Bau.js → square-pen-hLIbFQFV.js} +1 -1
  56. package/dist/{star-Cv2MzxZL.js → star-YsVV3MNQ.js} +1 -1
  57. package/dist/{store-CLH957vl.js → store-RCBl7HB-.js} +1 -1
  58. package/dist/{trending-up-l8M0BO_w.js → trending-up-C-85AwGT.js} +1 -1
  59. package/dist/{triangle-alert-BI45s6bH.js → triangle-alert-BOhfGgmh.js} +1 -1
  60. package/dist/{truck-DX3lNQkz.js → truck-CtDjNFbi.js} +1 -1
  61. package/dist/{user-D8EY1uvt.js → user-Dz5TJZFs.js} +1 -1
  62. package/dist/{users-CfG0J8wP.js → users-g2N0eL-Z.js} +1 -1
  63. package/dist/{warehouse-Dt_bAr82.js → warehouse-D3WWDeTX.js} +1 -1
  64. package/dist/{wrench-C50eI_Iy.js → wrench-CmxY1n4I.js} +1 -1
  65. package/package.json +2 -2
  66. package/src/movethewheels/components/DataTable.tsx +41 -6
  67. package/src/movethewheels/components/MetricCard.tsx +51 -20
  68. package/src/movethewheels/components/PageLayout.tsx +60 -5
  69. package/src/movethewheels/components/StatusBadge.tsx +2 -1
  70. package/src/movethewheels/pages/AIAssistantPage.tsx +11 -3
  71. package/src/movethewheels/pages/AnalyticsPage.tsx +31 -25
  72. package/src/movethewheels/pages/CreateOrderPage.tsx +56 -17
  73. package/src/movethewheels/pages/CustomerDetailsPage.tsx +63 -38
  74. package/src/movethewheels/pages/CustomersPage.tsx +51 -12
  75. package/src/movethewheels/pages/DashboardPage.tsx +62 -48
  76. package/src/movethewheels/pages/DriverDetailsPage.tsx +57 -26
  77. package/src/movethewheels/pages/DriversPage.tsx +45 -12
  78. package/src/movethewheels/pages/FinancePage.tsx +45 -41
  79. package/src/movethewheels/pages/FleetPage.tsx +82 -34
  80. package/src/movethewheels/pages/ImportExportPage.tsx +46 -29
  81. package/src/movethewheels/pages/InventoryPage.tsx +37 -33
  82. package/src/movethewheels/pages/LiveTrackingPage.tsx +58 -20
  83. package/src/movethewheels/pages/MarketplacePage.tsx +37 -3
  84. package/src/movethewheels/pages/OrderDetailsPage.tsx +74 -46
  85. package/src/movethewheels/pages/OrdersListPage.tsx +81 -14
  86. package/src/movethewheels/pages/ProductDetailsPage.tsx +36 -11
  87. package/src/movethewheels/pages/ProductsPage.tsx +41 -12
  88. package/src/movethewheels/pages/ReportsPage.tsx +23 -19
  89. package/src/movethewheels/pages/RouteDetailsPage.tsx +71 -31
  90. package/src/movethewheels/pages/RoutesPage.tsx +48 -9
  91. package/src/movethewheels/pages/SettingsPage.tsx +68 -26
  92. package/src/movethewheels/pages/TrackingPage.tsx +52 -49
  93. package/src/movethewheels/pages/VehicleDetailsPage.tsx +49 -24
  94. package/src/movethewheels/pages/VehiclesPage.tsx +41 -15
  95. package/src/movethewheels/pages/WarehouseDetailsPage.tsx +55 -30
  96. package/src/movethewheels/pages/WarehousesPage.tsx +46 -9
  97. package/dist/CreateOrderPage-DfkSi6JF.js +0 -471
  98. package/dist/CustomerDetailsPage-DzAIu_tH.js +0 -239
  99. package/dist/CustomersPage-d21ixOYa.js +0 -119
  100. package/dist/DataTable-CZGz3SJu.js +0 -239
  101. package/dist/DriverDetailsPage-YuZSlPSV.js +0 -297
  102. package/dist/DriversPage-BOhqEBTv.js +0 -127
  103. package/dist/FinancePage-CnjUNXOb.js +0 -154
  104. package/dist/ImportExportPage-zNjs7xsV.js +0 -232
  105. package/dist/InventoryPage-C9g5d3SW.js +0 -223
  106. package/dist/LiveTrackingPage-DoBvtdBG.js +0 -332
  107. package/dist/MarketplacePage-BEj5hcBF.js +0 -192
  108. package/dist/MetricCard-DeHVeVwl.js +0 -135
  109. package/dist/OrderDetailsPage-D-9lDZYU.js +0 -398
  110. package/dist/OrdersListPage-CJzHbgY3.js +0 -257
  111. package/dist/ProductDetailsPage-3rKtzXpy.js +0 -168
  112. package/dist/ProductsPage-B0P_wjBJ.js +0 -131
  113. package/dist/RouteDetailsPage-DGjKTUMj.js +0 -240
  114. package/dist/RoutesPage-CpopY8xN.js +0 -116
  115. package/dist/SettingsPage-BvXSa3gi.js +0 -247
  116. package/dist/VehicleDetailsPage-Dqv--MVW.js +0 -194
  117. package/dist/VehiclesPage-CCBHRDHu.js +0 -127
  118. package/dist/WarehouseDetailsPage-ZObC_c7W.js +0 -215
  119. package/dist/WarehousesPage-CpgZEVW9.js +0 -121
@@ -15,6 +15,7 @@ import {
15
15
  Badge,
16
16
  Progress,
17
17
  } from '../components/ui';
18
+ import { EmphasisPanel, NextSteps, PagePurpose } from '@burdenoff/fe-libs/ui';
18
19
  import { useDriver } from '../hooks/useFleet';
19
20
  import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
20
21
  import { formatCurrency, formatDate } from '../utils/formatters';
@@ -26,6 +27,7 @@ export default function DriverDetailsPage() {
26
27
  const { driver, isLoading, error, refetch } = useDriver(driverId);
27
28
 
28
29
  const goBack = () => navigate?.(joinPath(basePath, 'fleet/drivers'));
30
+ const goTo = (path: string) => navigate?.(joinPath(basePath, path));
29
31
 
30
32
  if (isLoading) return <LoadingState message="Loading driver details..." />;
31
33
  if (error || !driver) return <ErrorState title="Driver not found" onRetry={refetch} />;
@@ -56,35 +58,64 @@ export default function DriverDetailsPage() {
56
58
  </div>
57
59
  }
58
60
  >
61
+ <PagePurpose icon={<Users size={18} />}>
62
+ A driver&apos;s full profile — performance ratings, working hours, documents, earnings and
63
+ live location. Use it to confirm someone is road-ready and compliant before assigning them
64
+ an order or route.
65
+ </PagePurpose>
66
+
67
+ <NextSteps
68
+ storageKey="movethewheels-driver-details"
69
+ steps={[
70
+ {
71
+ id: 'assign',
72
+ label: 'Assign to an order',
73
+ description: 'Hand a pending delivery to this driver.',
74
+ icon: <MapPin size={16} />,
75
+ onClick: () => goTo('orders'),
76
+ },
77
+ {
78
+ id: 'routes',
79
+ label: 'Plan their route',
80
+ description: 'Batch nearby drop-offs into an optimized itinerary.',
81
+ icon: <Clock size={16} />,
82
+ onClick: () => goTo('routes'),
83
+ },
84
+ {
85
+ id: 'edit',
86
+ label: 'Update driver record',
87
+ description: 'Refresh documents, shift or compliance details.',
88
+ icon: <Edit size={16} />,
89
+ onClick: () => {},
90
+ },
91
+ ]}
92
+ />
93
+
59
94
  <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
60
95
  <div className="lg:col-span-2 space-y-6">
61
- {/* Ratings */}
62
- <Card>
63
- <CardHeader>
64
- <CardTitle className="flex items-center gap-2">
65
- <Star size={18} /> Ratings
66
- </CardTitle>
67
- </CardHeader>
68
- <CardContent>
69
- <div className="grid grid-cols-2 md:grid-cols-3 gap-4">
70
- {[
71
- { label: 'Punctuality', value: driver.ratings.punctuality },
72
- { label: 'Communication', value: driver.ratings.communication },
73
- { label: 'Handling', value: driver.ratings.carefulHandling },
74
- { label: 'Professionalism', value: driver.ratings.professionalism },
75
- { label: 'On-Time Delivery', value: driver.ratings.onTimeDelivery },
76
- ].map((rating) => (
77
- <div key={rating.label}>
78
- <p className="text-sm text-text-secondary">{rating.label}</p>
79
- <div className="flex items-center gap-2 mt-1">
80
- <Progress value={rating.value * 20} className="flex-1 h-2" />
81
- <span className="text-sm font-medium">{rating.value.toFixed(1)}</span>
82
- </div>
96
+ {/* Ratings — the page's single emphasis zone */}
97
+ <EmphasisPanel>
98
+ <h2 className="flex items-center gap-2 text-base font-semibold text-text-primary mb-4">
99
+ <Star size={18} /> Ratings
100
+ </h2>
101
+ <div className="grid grid-cols-2 md:grid-cols-3 gap-4">
102
+ {[
103
+ { label: 'Punctuality', value: driver.ratings.punctuality },
104
+ { label: 'Communication', value: driver.ratings.communication },
105
+ { label: 'Handling', value: driver.ratings.carefulHandling },
106
+ { label: 'Professionalism', value: driver.ratings.professionalism },
107
+ { label: 'On-Time Delivery', value: driver.ratings.onTimeDelivery },
108
+ ].map((rating) => (
109
+ <div key={rating.label}>
110
+ <p className="text-sm text-text-secondary">{rating.label}</p>
111
+ <div className="flex items-center gap-2 mt-1">
112
+ <Progress value={rating.value * 20} className="flex-1 h-2" />
113
+ <span className="text-sm font-medium">{rating.value.toFixed(1)}</span>
83
114
  </div>
84
- ))}
85
- </div>
86
- </CardContent>
87
- </Card>
115
+ </div>
116
+ ))}
117
+ </div>
118
+ </EmphasisPanel>
88
119
 
89
120
  {/* Working Hours */}
90
121
  <Card>
@@ -6,7 +6,8 @@ import { Users, Plus, RefreshCw, Download, Star } from 'lucide-react';
6
6
  import { PageLayout } from '../components/PageLayout';
7
7
  import { DataTable, type Column } from '../components/DataTable';
8
8
  import { StatusBadge } from '../components/StatusBadge';
9
- import { Button, Avatar, AvatarFallback } from '../components/ui';
9
+ import { Avatar, AvatarFallback } from '../components/ui';
10
+ import { CTAOverflowMenu, EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';
10
11
  import { useDrivers } from '../hooks/useFleet';
11
12
  import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
12
13
  import { formatDate } from '../utils/formatters';
@@ -90,19 +91,48 @@ export default function DriversPage() {
90
91
  subtitle={`${totalDrivers} drivers`}
91
92
  icon={<Users size={24} />}
92
93
  headerActions={
93
- <div className="flex gap-2">
94
- <Button variant="outline" onClick={refetch}>
95
- <RefreshCw size={16} /> Refresh
96
- </Button>
97
- <Button variant="outline">
98
- <Download size={16} /> Export
99
- </Button>
100
- <Button>
101
- <Plus size={16} /> Add Driver
102
- </Button>
103
- </div>
94
+ <CTAOverflowMenu
95
+ primary={{ label: 'Add Driver', icon: <Plus size={16} />, onSelect: () => {} }}
96
+ actions={[
97
+ { label: 'Refresh', icon: <RefreshCw size={16} />, onSelect: () => refetch() },
98
+ { label: 'Export', icon: <Download size={16} />, onSelect: () => {} },
99
+ ]}
100
+ />
104
101
  }
105
102
  >
103
+ <PagePurpose icon={<Users size={18} />}>
104
+ Your delivery workforce. Track each driver&apos;s availability, performance rating,
105
+ completed deliveries and license status here — open a driver to review their history before
106
+ assigning them to an order or route.
107
+ </PagePurpose>
108
+
109
+ {/* Workforce at a glance — the page's single emphasis zone */}
110
+ <EmphasisPanel>
111
+ <p className="text-sm font-medium text-text-secondary">Workforce at a glance</p>
112
+ <div className="mt-3 grid grid-cols-3 gap-4">
113
+ <div>
114
+ <p className="text-2xl font-bold text-text-primary tabular-nums">{totalDrivers}</p>
115
+ <p className="text-xs text-text-secondary">Total drivers</p>
116
+ </div>
117
+ <div>
118
+ <p className="text-2xl font-bold text-text-primary tabular-nums">
119
+ {drivers.filter((d) => d.status === 'available' || d.status === 'busy').length}
120
+ </p>
121
+ <p className="text-xs text-text-secondary">On duty / available</p>
122
+ </div>
123
+ <div>
124
+ <p className="text-2xl font-bold text-text-primary tabular-nums">
125
+ {drivers.length > 0
126
+ ? (drivers.reduce((sum, d) => sum + d.ratings.overall, 0) / drivers.length).toFixed(
127
+ 1
128
+ )
129
+ : '—'}
130
+ </p>
131
+ <p className="text-xs text-text-secondary">Avg rating</p>
132
+ </div>
133
+ </div>
134
+ </EmphasisPanel>
135
+
106
136
  <DataTable
107
137
  columns={columns}
108
138
  data={drivers}
@@ -112,6 +142,9 @@ export default function DriversPage() {
112
142
  searchFields={['fullName', 'employeeId'] as (keyof Driver)[]}
113
143
  onRowClick={(row) => goTo(`fleet/drivers/${row.id}`)}
114
144
  getRowId={(row) => row.id}
145
+ emptyIllustration="empty-people"
146
+ emptyTitle="No drivers yet"
147
+ emptyDescription="Add drivers to start assigning deliveries and routes."
115
148
  />
116
149
  </PageLayout>
117
150
  );
@@ -6,6 +6,7 @@ import { DollarSign, TrendingUp, CreditCard, FileText, Download } from 'lucide-r
6
6
  import { PageLayout } from '../components/PageLayout';
7
7
  import { MetricCard, MetricGrid } from '../components/MetricCard';
8
8
  import { Card, CardContent, CardHeader, CardTitle, Button } from '../components/ui';
9
+ import { EmphasisPanel, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';
9
10
  import { useAnalytics } from '../hooks/useAnalytics';
10
11
  import { useOrderStats } from '../hooks/useOrders';
11
12
  import { formatCurrency } from '../utils/formatters';
@@ -33,8 +34,16 @@ export default function FinancePage() {
33
34
  </div>
34
35
  }
35
36
  >
37
+ <PagePurpose icon={<DollarSign size={18} />}>
38
+ Follow the money behind your deliveries. See revenue earned, what&apos;s been collected
39
+ versus still owed, and average order value — use it to chase pending payments, forecast cash
40
+ flow, and confirm which shipments have actually been paid for.
41
+ </PagePurpose>
42
+
36
43
  <MetricGrid columns={4}>
37
44
  <MetricCard
45
+ treatment="glass"
46
+ glow
38
47
  label="Total Revenue"
39
48
  value={formatCurrency(analytics.overview.totalRevenue)}
40
49
  icon={<DollarSign size={20} />}
@@ -81,47 +90,42 @@ export default function FinancePage() {
81
90
  </CardContent>
82
91
  </Card>
83
92
 
84
- <Card>
85
- <CardHeader>
86
- <CardTitle>Payment Status</CardTitle>
87
- </CardHeader>
88
- <CardContent>
89
- <div className="space-y-4">
90
- <div className="flex items-center justify-between p-4 bg-green-50 dark:bg-green-900/20 rounded-lg">
91
- <div className="flex items-center gap-3">
92
- <div className="w-10 h-10 rounded-full bg-green-100 dark:bg-green-800 flex items-center justify-center">
93
- <TrendingUp size={20} className="text-green-600" />
94
- </div>
95
- <div>
96
- <p className="font-medium">Paid</p>
97
- <p className="text-sm text-text-secondary">
98
- {stats.byStatus.delivered} orders
99
- </p>
100
- </div>
93
+ {/* Payment Status — the page's single emphasis zone */}
94
+ <EmphasisPanel className="space-y-4">
95
+ <h2 className="text-base font-semibold text-text-primary">Payment Status</h2>
96
+ <div className="space-y-4">
97
+ <div className="flex items-center justify-between p-4 bg-status-success-bg/10 rounded-lg">
98
+ <div className="flex items-center gap-3">
99
+ <div className="w-10 h-10 rounded-full bg-status-success-bg/20 flex items-center justify-center">
100
+ <TrendingUp size={20} className="text-status-success-text" />
101
+ </div>
102
+ <div>
103
+ <p className="font-medium">Paid</p>
104
+ <p className="text-sm text-text-secondary">{stats.byStatus.delivered} orders</p>
101
105
  </div>
102
- <span className="text-xl font-bold text-green-600">
103
- {formatCurrency(completedPayments)}
104
- </span>
105
106
  </div>
106
- <div className="flex items-center justify-between p-4 bg-yellow-50 dark:bg-yellow-900/20 rounded-lg">
107
- <div className="flex items-center gap-3">
108
- <div className="w-10 h-10 rounded-full bg-yellow-100 dark:bg-yellow-800 flex items-center justify-center">
109
- <CreditCard size={20} className="text-yellow-600" />
110
- </div>
111
- <div>
112
- <p className="font-medium">Pending</p>
113
- <p className="text-sm text-text-secondary">
114
- {stats.byStatus.pending + stats.byStatus.in_transit} orders
115
- </p>
116
- </div>
107
+ <span className="text-xl font-bold text-status-success-text">
108
+ {formatCurrency(completedPayments)}
109
+ </span>
110
+ </div>
111
+ <div className="flex items-center justify-between p-4 bg-status-warning-bg/10 rounded-lg">
112
+ <div className="flex items-center gap-3">
113
+ <div className="w-10 h-10 rounded-full bg-status-warning-bg/20 flex items-center justify-center">
114
+ <CreditCard size={20} className="text-status-warning-text" />
115
+ </div>
116
+ <div>
117
+ <p className="font-medium">Pending</p>
118
+ <p className="text-sm text-text-secondary">
119
+ {stats.byStatus.pending + stats.byStatus.in_transit} orders
120
+ </p>
117
121
  </div>
118
- <span className="text-xl font-bold text-yellow-600">
119
- {formatCurrency(pendingPayments)}
120
- </span>
121
122
  </div>
123
+ <span className="text-xl font-bold text-status-warning-text">
124
+ {formatCurrency(pendingPayments)}
125
+ </span>
122
126
  </div>
123
- </CardContent>
124
- </Card>
127
+ </div>
128
+ </EmphasisPanel>
125
129
  </div>
126
130
 
127
131
  <Card>
@@ -129,11 +133,11 @@ export default function FinancePage() {
129
133
  <CardTitle>Recent Transactions</CardTitle>
130
134
  </CardHeader>
131
135
  <CardContent>
132
- <div className="text-center py-8 text-text-secondary">
133
- <FileText size={48} className="mx-auto mb-4 opacity-50" />
134
- <p>Transaction history would be displayed here</p>
135
- <p className="text-sm">Integration with payment gateway required</p>
136
- </div>
136
+ <IllustratedEmptyState
137
+ illustration="empty-data"
138
+ title="No transactions yet"
139
+ description="Once payments are processed, your transaction history will appear here. Connect a payment gateway to start recording transactions."
140
+ />
137
141
  </CardContent>
138
142
  </Card>
139
143
  </PageLayout>
@@ -18,6 +18,7 @@ import {
18
18
  Avatar,
19
19
  AvatarFallback,
20
20
  } from '../components/ui';
21
+ import { CTAOverflowMenu, EmphasisPanel, PagePurpose, NextSteps } from '@burdenoff/fe-libs/ui';
21
22
  import { useFleetStats, useVehicles, useDrivers } from '../hooks/useFleet';
22
23
  import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
23
24
  import { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';
@@ -46,18 +47,65 @@ export default function FleetPage() {
46
47
  subtitle={t('movethewheels.fleet.subtitle', 'Manage your vehicles and drivers')}
47
48
  icon={<Truck size={24} />}
48
49
  headerActions={
49
- <div className="flex gap-2">
50
- <Button variant="outline" onClick={() => goTo('fleet/vehicles')}>
51
- <Truck size={16} />
52
- {t('movethewheels.fleet.actions.allVehicles', 'All Vehicles')}
53
- </Button>
54
- <Button variant="outline" onClick={() => goTo('fleet/drivers')}>
55
- <Users size={16} />
56
- {t('movethewheels.fleet.actions.allDrivers', 'All Drivers')}
57
- </Button>
58
- </div>
50
+ <CTAOverflowMenu
51
+ primary={{
52
+ label: t('movethewheels.fleet.actions.allVehicles', 'All Vehicles'),
53
+ icon: <Truck size={16} />,
54
+ onSelect: () => goTo('fleet/vehicles'),
55
+ }}
56
+ actions={[
57
+ {
58
+ label: t('movethewheels.fleet.actions.allDrivers', 'All Drivers'),
59
+ icon: <Users size={16} />,
60
+ onSelect: () => goTo('fleet/drivers'),
61
+ },
62
+ ]}
63
+ />
59
64
  }
60
65
  >
66
+ <PagePurpose icon={<Truck size={18} />}>
67
+ {t(
68
+ 'movethewheels.fleet.purpose',
69
+ 'Your command center for vehicles and drivers. See utilization at a glance, keep an eye on availability and ratings, and act on maintenance alerts so you always have road-ready capacity to fulfil orders.'
70
+ )}
71
+ </PagePurpose>
72
+
73
+ <NextSteps
74
+ storageKey="movethewheels-fleet"
75
+ steps={[
76
+ {
77
+ id: 'vehicles',
78
+ label: t('movethewheels.fleet.nextSteps.vehicles', 'Review your vehicles'),
79
+ description: t(
80
+ 'movethewheels.fleet.nextSteps.vehiclesDesc',
81
+ 'Check capacity, fuel and maintenance status across the fleet.'
82
+ ),
83
+ icon: <Truck size={16} />,
84
+ onClick: () => goTo('fleet/vehicles'),
85
+ },
86
+ {
87
+ id: 'drivers',
88
+ label: t('movethewheels.fleet.nextSteps.drivers', 'Review your drivers'),
89
+ description: t(
90
+ 'movethewheels.fleet.nextSteps.driversDesc',
91
+ 'See availability, ratings and delivery history before assigning work.'
92
+ ),
93
+ icon: <Users size={16} />,
94
+ onClick: () => goTo('fleet/drivers'),
95
+ },
96
+ {
97
+ id: 'assign',
98
+ label: t('movethewheels.fleet.nextSteps.assign', 'Assign capacity to orders'),
99
+ description: t(
100
+ 'movethewheels.fleet.nextSteps.assignDesc',
101
+ 'Open an order to assign an available vehicle and driver.'
102
+ ),
103
+ icon: <ChevronRight size={16} />,
104
+ onClick: () => goTo('orders'),
105
+ },
106
+ ]}
107
+ />
108
+
61
109
  {/* Key Metrics */}
62
110
  <MetricGrid columns={4}>
63
111
  <MetricCard
@@ -75,6 +123,8 @@ export default function FleetPage() {
75
123
  onClick={() => goTo('fleet/drivers')}
76
124
  />
77
125
  <MetricCard
126
+ treatment="glass"
127
+ glow
78
128
  label={t('movethewheels.fleet.metrics.utilization', 'Fleet Utilization')}
79
129
  value={`${stats.utilization.toFixed(0)}%`}
80
130
  icon={<Truck size={20} />}
@@ -197,29 +247,27 @@ export default function FleetPage() {
197
247
  </PageSection>
198
248
  </div>
199
249
 
200
- {/* Status Summary */}
250
+ {/* Status Summary — Vehicle Status is the page's single emphasis zone */}
201
251
  <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
202
252
  {/* Vehicle Status */}
203
- <Card>
204
- <CardHeader>
205
- <CardTitle>{t('movethewheels.fleet.status.vehicleTitle', 'Vehicle Status')}</CardTitle>
206
- </CardHeader>
207
- <CardContent>
208
- <div className="space-y-4">
209
- {Object.entries(stats.vehiclesByStatus).map(([status, count]) => (
210
- <div key={status} className="flex items-center justify-between">
211
- <div className="flex items-center gap-3">
212
- <StatusBadge status={status} type="vehicle" />
213
- </div>
214
- <div className="flex items-center gap-3">
215
- <span className="font-medium">{count}</span>
216
- <Progress value={(count / stats.totalVehicles) * 100} className="w-24 h-2" />
217
- </div>
253
+ <EmphasisPanel className="space-y-4">
254
+ <h2 className="text-base font-semibold text-text-primary">
255
+ {t('movethewheels.fleet.status.vehicleTitle', 'Vehicle Status')}
256
+ </h2>
257
+ <div className="space-y-4">
258
+ {Object.entries(stats.vehiclesByStatus).map(([status, count]) => (
259
+ <div key={status} className="flex items-center justify-between">
260
+ <div className="flex items-center gap-3">
261
+ <StatusBadge status={status} type="vehicle" />
218
262
  </div>
219
- ))}
220
- </div>
221
- </CardContent>
222
- </Card>
263
+ <div className="flex items-center gap-3">
264
+ <span className="font-medium">{count}</span>
265
+ <Progress value={(count / stats.totalVehicles) * 100} className="w-24 h-2" />
266
+ </div>
267
+ </div>
268
+ ))}
269
+ </div>
270
+ </EmphasisPanel>
223
271
 
224
272
  {/* Driver Status */}
225
273
  <Card>
@@ -246,9 +294,9 @@ export default function FleetPage() {
246
294
 
247
295
  {/* Maintenance Alerts */}
248
296
  {stats.vehiclesByStatus.maintenance > 0 && (
249
- <Card className="border-yellow-200 dark:border-yellow-800">
297
+ <Card className="border-status-warning-border">
250
298
  <CardHeader>
251
- <CardTitle className="flex items-center gap-2 text-yellow-600">
299
+ <CardTitle className="flex items-center gap-2 text-status-warning-text">
252
300
  <Wrench size={18} />
253
301
  {t('movethewheels.fleet.maintenance.title', 'Maintenance Required')}
254
302
  </CardTitle>
@@ -260,10 +308,10 @@ export default function FleetPage() {
260
308
  .map((vehicle) => (
261
309
  <div
262
310
  key={vehicle.id}
263
- className="flex items-center justify-between p-3 bg-yellow-50 dark:bg-yellow-900/20 rounded-lg"
311
+ className="flex items-center justify-between p-3 bg-status-warning-bg/10 rounded-lg"
264
312
  >
265
313
  <div className="flex items-center gap-3">
266
- <Truck size={20} className="text-yellow-600" />
314
+ <Truck size={20} className="text-status-warning-text" />
267
315
  <div>
268
316
  <p className="font-medium">{vehicle.vehicleNumber}</p>
269
317
  <p className="text-sm text-text-secondary">
@@ -5,6 +5,7 @@
5
5
  import { Upload, Download, FileText, FileSpreadsheet, Check } from 'lucide-react';
6
6
  import { PageLayout } from '../components/PageLayout';
7
7
  import { Card, CardContent, CardHeader, CardTitle, Button, Badge } from '../components/ui';
8
+ import { EmphasisPanel, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';
8
9
 
9
10
  export default function ImportExportPage() {
10
11
  const importOptions = [
@@ -69,14 +70,19 @@ export default function ImportExportPage() {
69
70
  subtitle="Import and export your data"
70
71
  icon={<FileText size={24} />}
71
72
  >
73
+ <PagePurpose icon={<FileText size={18} />}>
74
+ Move data in and out in bulk. Import orders, customers, products or inventory from CSV/Excel
75
+ to onboard or migrate without re-keying, and export any dataset for accounting, BI tools or
76
+ backups — no manual copy-paste required.
77
+ </PagePurpose>
78
+
72
79
  <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
73
- <Card>
74
- <CardHeader>
75
- <CardTitle className="flex items-center gap-2">
76
- <Upload size={18} /> Import Data
77
- </CardTitle>
78
- </CardHeader>
79
- <CardContent className="space-y-4">
80
+ {/* Import Data — the page's single emphasis zone */}
81
+ <EmphasisPanel className="space-y-4">
82
+ <h2 className="flex items-center gap-2 text-base font-semibold text-text-primary">
83
+ <Upload size={18} /> Import Data
84
+ </h2>
85
+ <div className="space-y-4">
80
86
  {importOptions.map((opt) => (
81
87
  <div
82
88
  key={opt.name}
@@ -99,8 +105,8 @@ export default function ImportExportPage() {
99
105
  </div>
100
106
  </div>
101
107
  ))}
102
- </CardContent>
103
- </Card>
108
+ </div>
109
+ </EmphasisPanel>
104
110
 
105
111
  <Card>
106
112
  <CardHeader>
@@ -136,28 +142,39 @@ export default function ImportExportPage() {
136
142
  <CardTitle>Recent Activity</CardTitle>
137
143
  </CardHeader>
138
144
  <CardContent>
139
- <div className="space-y-3">
140
- {recentActivity.map((activity, i) => (
141
- <div key={i} className="flex items-center justify-between p-3 bg-bg-sunken/50 rounded-lg">
142
- <div className="flex items-center gap-3">
143
- {activity.type === 'import' ? (
144
- <Upload size={16} className="text-primary" />
145
- ) : (
146
- <Download size={16} className="text-primary" />
147
- )}
148
- <div>
149
- <p className="font-medium">{activity.name}</p>
150
- <p className="text-sm text-text-secondary">
151
- {activity.type === 'import' ? 'Imported' : 'Exported'} on {activity.date}
152
- </p>
145
+ {recentActivity.length === 0 ? (
146
+ <IllustratedEmptyState
147
+ illustration="empty-data"
148
+ title="No import or export activity yet"
149
+ description="Your recent imports and exports will show up here once you run one."
150
+ />
151
+ ) : (
152
+ <div className="space-y-3">
153
+ {recentActivity.map((activity, i) => (
154
+ <div
155
+ key={i}
156
+ className="flex items-center justify-between p-3 bg-bg-sunken/50 rounded-lg"
157
+ >
158
+ <div className="flex items-center gap-3">
159
+ {activity.type === 'import' ? (
160
+ <Upload size={16} className="text-primary" />
161
+ ) : (
162
+ <Download size={16} className="text-primary" />
163
+ )}
164
+ <div>
165
+ <p className="font-medium">{activity.name}</p>
166
+ <p className="text-sm text-text-secondary">
167
+ {activity.type === 'import' ? 'Imported' : 'Exported'} on {activity.date}
168
+ </p>
169
+ </div>
153
170
  </div>
171
+ <Badge variant="default" className="gap-1">
172
+ <Check size={12} /> {activity.status}
173
+ </Badge>
154
174
  </div>
155
- <Badge variant="default" className="gap-1">
156
- <Check size={12} /> {activity.status}
157
- </Badge>
158
- </div>
159
- ))}
160
- </div>
175
+ ))}
176
+ </div>
177
+ )}
161
178
  </CardContent>
162
179
  </Card>
163
180
  </PageLayout>