@burdenoff/microfe-movethewheels 2026.625.1 → 2026.626.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/dist/{AIAssistantPage-CNyoKtID.js → AIAssistantPage-AvsMbunM.js} +35 -29
  2. package/dist/{AnalyticsPage-Ck615ox7.js → AnalyticsPage-CCLfHgQZ.js} +36 -25
  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-DTmyuC11.js → DashboardPage-D2HRqwg9.js} +93 -89
  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-DCfOmBa2.js → FleetPage-DddXt8r8.js} +109 -71
  12. package/dist/ImportExportPage-BW6qO3kc.js +248 -0
  13. package/dist/{InventoryPage-BW0QXWuf.js → InventoryPage-rMGuaJN-.js} +74 -70
  14. package/dist/LiveTrackingPage-DQ1q4Id3.js +375 -0
  15. package/dist/MarketplacePage-DKrXAv62.js +219 -0
  16. package/dist/OrderDetailsPage-CFASgsYX.js +431 -0
  17. package/dist/OrdersListPage-BHeT8S5o.js +309 -0
  18. package/dist/ProductDetailsPage-CFGcbaHo.js +195 -0
  19. package/dist/ProductsPage--xEpbQ8A.js +171 -0
  20. package/dist/{ReportsPage-Df3hciPy.js → ReportsPage-Bb7_90rK.js} +53 -45
  21. package/dist/RouteDetailsPage-CVtDVb1N.js +282 -0
  22. package/dist/RoutesPage-s57PtgcQ.js +163 -0
  23. package/dist/SettingsPage-BYNCBOpN.js +298 -0
  24. package/dist/{TrackingPage-CU0Vk4mx.js → TrackingPage-CcRc_dva.js} +77 -72
  25. package/dist/VehicleDetailsPage-3YDMPsPs.js +220 -0
  26. package/dist/VehiclesPage-UlxPWP9K.js +167 -0
  27. package/dist/WarehouseDetailsPage-Db7KeN-d.js +238 -0
  28. package/dist/WarehousesPage-CuTO-OPp.js +164 -0
  29. package/dist/index.js +2 -2
  30. package/package.json +2 -2
  31. package/src/movethewheels/components/DataTable.tsx +37 -2
  32. package/src/movethewheels/components/MetricCard.tsx +3 -1
  33. package/src/movethewheels/pages/AIAssistantPage.tsx +11 -3
  34. package/src/movethewheels/pages/AnalyticsPage.tsx +31 -25
  35. package/src/movethewheels/pages/CreateOrderPage.tsx +56 -17
  36. package/src/movethewheels/pages/CustomerDetailsPage.tsx +63 -38
  37. package/src/movethewheels/pages/CustomersPage.tsx +40 -2
  38. package/src/movethewheels/pages/DashboardPage.tsx +8 -1
  39. package/src/movethewheels/pages/DriverDetailsPage.tsx +57 -26
  40. package/src/movethewheels/pages/DriversPage.tsx +37 -1
  41. package/src/movethewheels/pages/FinancePage.tsx +45 -41
  42. package/src/movethewheels/pages/FleetPage.tsx +68 -25
  43. package/src/movethewheels/pages/ImportExportPage.tsx +46 -29
  44. package/src/movethewheels/pages/InventoryPage.tsx +20 -23
  45. package/src/movethewheels/pages/LiveTrackingPage.tsx +58 -20
  46. package/src/movethewheels/pages/MarketplacePage.tsx +37 -3
  47. package/src/movethewheels/pages/OrderDetailsPage.tsx +74 -46
  48. package/src/movethewheels/pages/OrdersListPage.tsx +62 -1
  49. package/src/movethewheels/pages/ProductDetailsPage.tsx +36 -11
  50. package/src/movethewheels/pages/ProductsPage.tsx +33 -1
  51. package/src/movethewheels/pages/ReportsPage.tsx +23 -19
  52. package/src/movethewheels/pages/RouteDetailsPage.tsx +71 -31
  53. package/src/movethewheels/pages/RoutesPage.tsx +41 -5
  54. package/src/movethewheels/pages/SettingsPage.tsx +68 -26
  55. package/src/movethewheels/pages/TrackingPage.tsx +50 -47
  56. package/src/movethewheels/pages/VehicleDetailsPage.tsx +49 -24
  57. package/src/movethewheels/pages/VehiclesPage.tsx +33 -1
  58. package/src/movethewheels/pages/WarehouseDetailsPage.tsx +55 -30
  59. package/src/movethewheels/pages/WarehousesPage.tsx +42 -4
  60. package/dist/CreateOrderPage-C9Vb57Yn.js +0 -471
  61. package/dist/CustomerDetailsPage-BVkHRZvi.js +0 -239
  62. package/dist/CustomersPage-DhQg-6h_.js +0 -118
  63. package/dist/DataTable-CfWvFw5B.js +0 -239
  64. package/dist/DriverDetailsPage-DaaCQ-2O.js +0 -297
  65. package/dist/DriversPage-D0RMBB_t.js +0 -129
  66. package/dist/FinancePage-BUXqW1IM.js +0 -154
  67. package/dist/ImportExportPage-BM1BoRcE.js +0 -232
  68. package/dist/LiveTrackingPage-DqcGXdkw.js +0 -332
  69. package/dist/MarketplacePage-DFqsxNYU.js +0 -192
  70. package/dist/OrderDetailsPage-Dx1m3cVA.js +0 -398
  71. package/dist/OrdersListPage-DHYBGrWf.js +0 -256
  72. package/dist/ProductDetailsPage-DOXO90kb.js +0 -168
  73. package/dist/ProductsPage-RLMTwWN0.js +0 -133
  74. package/dist/RouteDetailsPage-xzFDeR-X.js +0 -240
  75. package/dist/RoutesPage-DDFy1QVi.js +0 -118
  76. package/dist/SettingsPage-JH_-UPbf.js +0 -247
  77. package/dist/VehicleDetailsPage-P4xDttKw.js +0 -194
  78. package/dist/VehiclesPage-tJZ64QKV.js +0 -129
  79. package/dist/WarehouseDetailsPage-Bt_w2Yf7.js +0 -215
  80. package/dist/WarehousesPage-HsPpEFeG.js +0 -126
@@ -5,16 +5,8 @@
5
5
  import { Package, Warehouse, AlertTriangle, ChevronRight, Plus } from 'lucide-react';
6
6
  import { PageLayout, PageSection } from '../components/PageLayout';
7
7
  import { MetricCard, MetricGrid } from '../components/MetricCard';
8
- import {
9
- Card,
10
- CardContent,
11
- CardHeader,
12
- CardTitle,
13
- Button,
14
- Badge,
15
- Progress,
16
- } from '../components/ui';
17
- import { CTAOverflowMenu } from '@burdenoff/fe-libs/ui';
8
+ import { Card, CardContent, Button, Badge, Progress } from '../components/ui';
9
+ import { CTAOverflowMenu, EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';
18
10
  import { useInventory, useInventoryStats } from '../hooks/useInventory';
19
11
  import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
20
12
  import { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';
@@ -59,6 +51,13 @@ export default function InventoryPage() {
59
51
  />
60
52
  }
61
53
  >
54
+ <PagePurpose icon={<Package size={18} />}>
55
+ {t(
56
+ 'movethewheels.inventory.purpose',
57
+ 'A real-time view of what you have and where. Track stock value and quantities across warehouses, catch low-stock items before they run out, and drill into products or warehouses to manage what you can promise on an order.'
58
+ )}
59
+ </PagePurpose>
60
+
62
61
  <MetricGrid columns={4}>
63
62
  <MetricCard
64
63
  label={t('movethewheels.inventory.metrics.totalProducts', 'Total Products')}
@@ -85,22 +84,20 @@ export default function InventoryPage() {
85
84
  </MetricGrid>
86
85
 
87
86
  {lowStockItems.length > 0 && (
88
- <Card className="border-yellow-200">
89
- <CardHeader>
90
- <CardTitle className="flex items-center gap-2 text-yellow-600">
91
- <AlertTriangle size={18} />
92
- {t('movethewheels.inventory.lowStock.title', 'Low Stock Alert')} (
93
- {lowStockItems.length} {t('movethewheels.inventory.lowStock.items', 'items')})
94
- </CardTitle>
95
- </CardHeader>
96
- <CardContent>
87
+ <EmphasisPanel className="space-y-4">
88
+ <h2 className="flex items-center gap-2 text-base font-semibold text-status-warning-text">
89
+ <AlertTriangle size={18} />
90
+ {t('movethewheels.inventory.lowStock.title', 'Low Stock Alert')} ({lowStockItems.length}{' '}
91
+ {t('movethewheels.inventory.lowStock.items', 'items')})
92
+ </h2>
93
+ <div>
97
94
  <div className="space-y-3">
98
95
  {lowStockItems.slice(0, 5).map((item) => {
99
96
  const product = products.find((p) => p.id === item.productId);
100
97
  return (
101
98
  <div
102
99
  key={item.id}
103
- className="flex items-center justify-between p-3 bg-yellow-50 dark:bg-yellow-900/20 rounded-lg"
100
+ className="flex items-center justify-between p-3 bg-status-warning-bg/10 rounded-lg"
104
101
  >
105
102
  <div>
106
103
  <p className="font-medium">
@@ -112,7 +109,7 @@ export default function InventoryPage() {
112
109
  </p>
113
110
  </div>
114
111
  <div className="text-right">
115
- <p className="font-medium text-yellow-600">
112
+ <p className="font-medium text-status-warning-text">
116
113
  {item.availableQuantity}{' '}
117
114
  {t('movethewheels.inventory.lowStock.left', 'left')}
118
115
  </p>
@@ -125,8 +122,8 @@ export default function InventoryPage() {
125
122
  );
126
123
  })}
127
124
  </div>
128
- </CardContent>
129
- </Card>
125
+ </div>
126
+ </EmphasisPanel>
130
127
  )}
131
128
 
132
129
  <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
@@ -6,7 +6,7 @@
6
6
 
7
7
  import { useState } from 'react';
8
8
  import { MapPin, Truck, Package, RefreshCw, List, Map } from 'lucide-react';
9
- import { PageLayout } from '../components/PageLayout';
9
+ import { PageLayout, EmptyState } from '../components/PageLayout';
10
10
  import { StatusBadge } from '../components/StatusBadge';
11
11
  import { MetricCard, MetricGrid } from '../components/MetricCard';
12
12
  import {
@@ -21,6 +21,7 @@ import {
21
21
  TabsTrigger,
22
22
  ScrollArea,
23
23
  } from '../components/ui';
24
+ import { EmphasisPanel, NextSteps, PagePurpose } from '@burdenoff/fe-libs/ui';
24
25
  import { useLiveTracking, useTrackingAlerts } from '../hooks/useTracking';
25
26
  import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
26
27
  import { formatDate } from '../utils/formatters';
@@ -67,6 +68,40 @@ export default function LiveTrackingPage() {
67
68
  </div>
68
69
  }
69
70
  >
71
+ <PagePurpose icon={<MapPin size={18} />}>
72
+ A real-time operations board for every delivery currently on the road. Watch where drivers
73
+ are, which orders are out for delivery, and react to alerts — switch to the map for a
74
+ bird&apos;s-eye view or the list to drill into a single shipment.
75
+ </PagePurpose>
76
+
77
+ <NextSteps
78
+ storageKey="movethewheels-live-tracking"
79
+ steps={[
80
+ {
81
+ id: 'select',
82
+ label: 'Open a delivery',
83
+ description: 'Switch to the list and pick a shipment to see full details.',
84
+ icon: <List size={16} />,
85
+ onClick: () => setViewMode('list'),
86
+ },
87
+ {
88
+ id: 'alerts',
89
+ label: 'Clear outstanding alerts',
90
+ description: 'Review delays and exceptions that need attention.',
91
+ icon: <Truck size={16} />,
92
+ done: unacknowledgedAlerts.length === 0,
93
+ onClick: () => setViewMode('list'),
94
+ },
95
+ {
96
+ id: 'new-order',
97
+ label: 'Create another order',
98
+ description: 'Add a new delivery to the pipeline.',
99
+ icon: <Package size={16} />,
100
+ onClick: () => goTo('orders/new'),
101
+ },
102
+ ]}
103
+ />
104
+
70
105
  {/* Quick Stats */}
71
106
  <MetricGrid columns={4}>
72
107
  <MetricCard
@@ -171,9 +206,11 @@ export default function LiveTrackingPage() {
171
206
  );
172
207
  })}
173
208
  {activeDeliveries.length === 0 && (
174
- <div className="p-8 text-center text-text-secondary">
175
- No active deliveries
176
- </div>
209
+ <EmptyState
210
+ illustration="empty-sessions"
211
+ title="No active deliveries"
212
+ description="When orders are dispatched they'll appear here in real time."
213
+ />
177
214
  )}
178
215
  </div>
179
216
  </ScrollArea>
@@ -184,18 +221,16 @@ export default function LiveTrackingPage() {
184
221
 
185
222
  {/* Sidebar */}
186
223
  <div className="space-y-6">
187
- {/* Selected Delivery Details */}
224
+ {/* Selected Delivery Details — the page's single emphasis zone when a delivery is open */}
188
225
  {selected ? (
189
- <Card>
190
- <CardHeader>
191
- <div className="flex items-center justify-between">
192
- <CardTitle>Delivery Details</CardTitle>
193
- <Button variant="ghost" size="sm" onClick={() => setSelectedDelivery(null)}>
194
- Clear
195
- </Button>
196
- </div>
197
- </CardHeader>
198
- <CardContent className="space-y-4">
226
+ <EmphasisPanel className="space-y-4">
227
+ <div className="flex items-center justify-between">
228
+ <h2 className="text-base font-semibold text-text-primary">Delivery Details</h2>
229
+ <Button variant="ghost" size="sm" onClick={() => setSelectedDelivery(null)}>
230
+ Clear
231
+ </Button>
232
+ </div>
233
+ <div className="space-y-4">
199
234
  <div>
200
235
  <p className="text-sm text-text-secondary">Order</p>
201
236
  <p className="font-medium">{selected.order?.orderNumber ?? '-'}</p>
@@ -250,13 +285,16 @@ export default function LiveTrackingPage() {
250
285
  Track Details
251
286
  </Button>
252
287
  </div>
253
- </CardContent>
254
- </Card>
288
+ </div>
289
+ </EmphasisPanel>
255
290
  ) : (
256
291
  <Card>
257
- <CardContent className="p-8 text-center text-text-secondary">
258
- <MapPin size={32} className="mx-auto mb-2 opacity-50" />
259
- <p>Select a delivery to see details</p>
292
+ <CardContent className="p-6">
293
+ <EmptyState
294
+ illustration="empty-generic"
295
+ title="No delivery selected"
296
+ description="Pick a delivery from the list to see its driver, vehicle, ETA and live location."
297
+ />
260
298
  </CardContent>
261
299
  </Card>
262
300
  )}
@@ -6,6 +6,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
6
6
  import { Store, Star, MapPin, Clock, Filter, Search } from 'lucide-react';
7
7
  import { PageLayout } from '../components/PageLayout';
8
8
  import { Card, CardContent, CardHeader, CardTitle, Button, Badge, Input } from '../components/ui';
9
+ import { EmphasisPanel, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';
9
10
  import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
10
11
  import { formatCurrency } from '../utils/formatters';
11
12
  import { executeGraphQL } from '../utils/graphqlClient';
@@ -146,6 +147,12 @@ export default function MarketplacePage() {
146
147
  </Button>
147
148
  }
148
149
  >
150
+ <PagePurpose icon={<Store size={18} />}>
151
+ Don&apos;t own every leg of the journey? Find vetted third-party logistics providers and
152
+ service offerings here — compare ratings, verification status and pricing, then engage a
153
+ partner to cover routes, warehousing or specialised handling you can&apos;t do in-house.
154
+ </PagePurpose>
155
+
149
156
  <Card>
150
157
  <CardContent className="p-4">
151
158
  <div className="relative">
@@ -166,6 +173,21 @@ export default function MarketplacePage() {
166
173
  <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
167
174
  <div className="lg:col-span-2 space-y-4">
168
175
  <h3 className="font-semibold">Service Providers ({filteredProviders.length})</h3>
176
+ {filteredProviders.length === 0 && (
177
+ <Card>
178
+ <CardContent className="p-0">
179
+ <IllustratedEmptyState
180
+ illustration={search.trim() ? 'empty-search' : 'empty-people'}
181
+ title={search.trim() ? 'No providers match your search' : 'No providers yet'}
182
+ description={
183
+ search.trim()
184
+ ? 'Try a different search term to find logistics partners.'
185
+ : 'Verified logistics service providers will appear here as they join the marketplace.'
186
+ }
187
+ />
188
+ </CardContent>
189
+ </Card>
190
+ )}
169
191
  {filteredProviders.map((provider) => (
170
192
  <Card key={provider.id} className="hover:shadow-md transition-shadow cursor-pointer">
171
193
  <CardContent className="p-6">
@@ -204,8 +226,20 @@ export default function MarketplacePage() {
204
226
  ))}
205
227
  </div>
206
228
 
207
- <div className="space-y-4">
208
- <h3 className="font-semibold">Popular Services</h3>
229
+ {/* Popular Services — the page's single emphasis zone */}
230
+ <EmphasisPanel className="space-y-4">
231
+ <h3 className="text-base font-semibold text-text-primary">Popular Services</h3>
232
+ {filteredOfferings.length === 0 && (
233
+ <IllustratedEmptyState
234
+ illustration={search.trim() ? 'empty-search' : 'empty-generic'}
235
+ title={search.trim() ? 'No matching services' : 'No services listed yet'}
236
+ description={
237
+ search.trim()
238
+ ? 'Adjust your search to discover service offerings.'
239
+ : 'Service offerings from providers will be listed here.'
240
+ }
241
+ />
242
+ )}
209
243
  {filteredOfferings.map((service) => (
210
244
  <Card key={service.id}>
211
245
  <CardHeader>
@@ -228,7 +262,7 @@ export default function MarketplacePage() {
228
262
  </CardContent>
229
263
  </Card>
230
264
  ))}
231
- </div>
265
+ </EmphasisPanel>
232
266
  </div>
233
267
  </PageLayout>
234
268
  );
@@ -42,6 +42,7 @@ import {
42
42
  TableHeader,
43
43
  TableRow,
44
44
  } from '../components/ui';
45
+ import { EmphasisPanel, NextSteps, PagePurpose } from '@burdenoff/fe-libs/ui';
45
46
  import { useOrder } from '../hooks/useOrders';
46
47
  import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
47
48
  import { formatCurrency, formatDate, formatAddress } from '../utils/formatters';
@@ -108,6 +109,39 @@ export default function OrderDetailsPage() {
108
109
  </div>
109
110
  }
110
111
  >
112
+ <PagePurpose icon={<Package size={18} />}>
113
+ Everything about this one delivery in a single place — who it&apos;s for, where it&apos;s
114
+ going, what&apos;s inside, the running cost and the full status history. Use this page to
115
+ review the order, hand it to a driver, print the docket, or jump into live tracking.
116
+ </PagePurpose>
117
+
118
+ <NextSteps
119
+ storageKey="movethewheels-order-details"
120
+ steps={[
121
+ {
122
+ id: 'track',
123
+ label: 'Track this order live',
124
+ description: 'See where the shipment is right now on the map.',
125
+ icon: <MapPin size={16} />,
126
+ onClick: () => goTo(`tracking?order=${order.id}`),
127
+ },
128
+ {
129
+ id: 'edit',
130
+ label: 'Edit order details',
131
+ description: 'Update items, addresses or instructions before dispatch.',
132
+ icon: <Edit size={16} />,
133
+ onClick: () => goTo(`orders/${orderId}/edit`),
134
+ },
135
+ {
136
+ id: 'print',
137
+ label: 'Print the delivery docket',
138
+ description: 'Generate a printable copy for the driver or warehouse.',
139
+ icon: <Printer size={16} />,
140
+ onClick: () => window.print(),
141
+ },
142
+ ]}
143
+ />
144
+
111
145
  <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
112
146
  {/* Main Content */}
113
147
  <div className="lg:col-span-2 space-y-6">
@@ -124,9 +158,7 @@ export default function OrderDetailsPage() {
124
158
  <div>
125
159
  <h4 className="font-medium mb-2">{order.customerInfo.name}</h4>
126
160
  {order.customerInfo.company && (
127
- <p className="text-sm text-text-secondary mb-2">
128
- {order.customerInfo.company}
129
- </p>
161
+ <p className="text-sm text-text-secondary mb-2">{order.customerInfo.company}</p>
130
162
  )}
131
163
  <div className="space-y-1 text-sm">
132
164
  <p className="flex items-center gap-2">
@@ -285,52 +317,48 @@ export default function OrderDetailsPage() {
285
317
 
286
318
  {/* Sidebar */}
287
319
  <div className="space-y-6">
288
- {/* Order Summary */}
289
- <Card>
290
- <CardHeader>
291
- <CardTitle className="flex items-center gap-2">
292
- <DollarSign size={18} />
293
- Order Summary
294
- </CardTitle>
295
- </CardHeader>
296
- <CardContent>
297
- <div className="space-y-3">
298
- <div className="flex justify-between text-sm">
299
- <span className="text-text-secondary">Subtotal</span>
300
- <span>{formatCurrency(order.pricing.subtotal)}</span>
301
- </div>
302
- <div className="flex justify-between text-sm">
303
- <span className="text-text-secondary">Delivery</span>
304
- <span>{formatCurrency(order.pricing.fees.delivery)}</span>
305
- </div>
306
- <div className="flex justify-between text-sm">
307
- <span className="text-text-secondary">Handling</span>
308
- <span>{formatCurrency(order.pricing.fees.handling)}</span>
309
- </div>
310
- {order.pricing.fees.insurance && (
311
- <div className="flex justify-between text-sm">
312
- <span className="text-text-secondary">Insurance</span>
313
- <span>{formatCurrency(order.pricing.fees.insurance)}</span>
314
- </div>
315
- )}
320
+ {/* Order Summary — the page's single emphasis zone */}
321
+ <EmphasisPanel>
322
+ <h2 className="flex items-center gap-2 text-base font-semibold text-text-primary mb-4">
323
+ <DollarSign size={18} />
324
+ Order Summary
325
+ </h2>
326
+ <div className="space-y-3">
327
+ <div className="flex justify-between text-sm">
328
+ <span className="text-text-secondary">Subtotal</span>
329
+ <span>{formatCurrency(order.pricing.subtotal)}</span>
330
+ </div>
331
+ <div className="flex justify-between text-sm">
332
+ <span className="text-text-secondary">Delivery</span>
333
+ <span>{formatCurrency(order.pricing.fees.delivery)}</span>
334
+ </div>
335
+ <div className="flex justify-between text-sm">
336
+ <span className="text-text-secondary">Handling</span>
337
+ <span>{formatCurrency(order.pricing.fees.handling)}</span>
338
+ </div>
339
+ {order.pricing.fees.insurance && (
316
340
  <div className="flex justify-between text-sm">
317
- <span className="text-text-secondary">Taxes</span>
318
- <span>{formatCurrency(order.pricing.taxes)}</span>
319
- </div>
320
- <Separator />
321
- <div className="flex justify-between font-medium">
322
- <span>Total</span>
323
- <span className="text-lg">{formatCurrency(order.pricing.total)}</span>
324
- </div>
325
- <div className="pt-2">
326
- <p className="text-sm text-text-secondary">Payment Method</p>
327
- <p className="text-sm capitalize">
328
- {order.pricing.paymentMethod.replace('_', ' ')}
329
- </p>
341
+ <span className="text-text-secondary">Insurance</span>
342
+ <span>{formatCurrency(order.pricing.fees.insurance)}</span>
330
343
  </div>
344
+ )}
345
+ <div className="flex justify-between text-sm">
346
+ <span className="text-text-secondary">Taxes</span>
347
+ <span>{formatCurrency(order.pricing.taxes)}</span>
331
348
  </div>
332
- </CardContent>
333
- </Card>
349
+ <Separator />
350
+ <div className="flex justify-between font-medium">
351
+ <span>Total</span>
352
+ <span className="text-lg">{formatCurrency(order.pricing.total)}</span>
353
+ </div>
354
+ <div className="pt-2">
355
+ <p className="text-sm text-text-secondary">Payment Method</p>
356
+ <p className="text-sm capitalize">
357
+ {order.pricing.paymentMethod.replace('_', ' ')}
358
+ </p>
359
+ </div>
360
+ </div>
361
+ </EmphasisPanel>
334
362
 
335
363
  {/* Assignment Info */}
336
364
  <Card>
@@ -9,7 +9,7 @@ import { Package, Plus, Filter, Download, RefreshCw } from 'lucide-react';
9
9
  import { PageLayout } from '../components/PageLayout';
10
10
  import { DataTable, type Column } from '../components/DataTable';
11
11
  import { StatusBadge, PriorityBadge, TypeBadge } from '../components/StatusBadge';
12
- import { CTAOverflowMenu } from '@burdenoff/fe-libs/ui';
12
+ import { CTAOverflowMenu, EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';
13
13
  import {
14
14
  Button,
15
15
  Card,
@@ -174,6 +174,55 @@ export default function OrdersListPage() {
174
174
  />
175
175
  }
176
176
  >
177
+ <PagePurpose icon={<Package size={18} />}>
178
+ {t(
179
+ 'movethewheels.orders.purpose',
180
+ 'Every delivery job lives here — B2B and B2C orders, their status, priority and value. Use this list to find an order, filter by status or type, and open one to assign a driver, track it, or update fulfilment.'
181
+ )}
182
+ </PagePurpose>
183
+
184
+ {/* Pipeline at a glance — the page's single emphasis zone */}
185
+ <EmphasisPanel>
186
+ <p className="text-sm font-medium text-text-secondary">
187
+ {t('movethewheels.orders.glance.title', 'Pipeline at a glance')}
188
+ </p>
189
+ <div className="mt-3 grid grid-cols-2 sm:grid-cols-4 gap-4">
190
+ <div>
191
+ <p className="text-2xl font-bold text-text-primary tabular-nums">{totalOrders}</p>
192
+ <p className="text-xs text-text-secondary">
193
+ {t('movethewheels.orders.glance.total', 'Total orders')}
194
+ </p>
195
+ </div>
196
+ <div>
197
+ <p className="text-2xl font-bold text-text-primary tabular-nums">
198
+ {orders.filter((o) => o.status === 'pending').length}
199
+ </p>
200
+ <p className="text-xs text-text-secondary">
201
+ {t('movethewheels.orders.glance.pending', 'Pending')}
202
+ </p>
203
+ </div>
204
+ <div>
205
+ <p className="text-2xl font-bold text-text-primary tabular-nums">
206
+ {
207
+ orders.filter((o) => o.status === 'in_transit' || o.status === 'out_for_delivery')
208
+ .length
209
+ }
210
+ </p>
211
+ <p className="text-xs text-text-secondary">
212
+ {t('movethewheels.orders.glance.inTransit', 'In transit')}
213
+ </p>
214
+ </div>
215
+ <div>
216
+ <p className="text-2xl font-bold text-text-primary tabular-nums">
217
+ {orders.filter((o) => o.status === 'delivered').length}
218
+ </p>
219
+ <p className="text-xs text-text-secondary">
220
+ {t('movethewheels.orders.glance.delivered', 'Delivered')}
221
+ </p>
222
+ </div>
223
+ </div>
224
+ </EmphasisPanel>
225
+
177
226
  {/* Filters */}
178
227
  <Card>
179
228
  <CardContent className="p-4">
@@ -241,6 +290,18 @@ export default function OrdersListPage() {
241
290
  onRowClick={(row) => goTo(`orders/${row.id}`)}
242
291
  getRowId={(row) => row.id}
243
292
  emptyMessage={t('movethewheels.orders.empty', 'No orders found')}
293
+ emptyIllustration="empty-data"
294
+ emptyTitle={t('movethewheels.orders.emptyTitle', 'No orders yet')}
295
+ emptyDescription={t(
296
+ 'movethewheels.orders.emptyDescription',
297
+ 'Create your first order to start moving shipments through the pipeline.'
298
+ )}
299
+ emptyAction={
300
+ <Button onClick={() => goTo('orders/new')}>
301
+ <Plus size={16} className="mr-1.5" />
302
+ {t('movethewheels.orders.actions.newOrder', 'New Order')}
303
+ </Button>
304
+ }
244
305
  />
245
306
  </PageLayout>
246
307
  );
@@ -6,6 +6,7 @@ import { useParams } from 'react-router-dom';
6
6
  import { Package, ArrowLeft, Edit, Box, DollarSign, Tag } from 'lucide-react';
7
7
  import { PageLayout, LoadingState, ErrorState } from '../components/PageLayout';
8
8
  import { Card, CardContent, CardHeader, CardTitle, Button, Badge } from '../components/ui';
9
+ import { EmphasisPanel, NextSteps, PagePurpose } from '@burdenoff/fe-libs/ui';
9
10
  import { useProduct } from '../hooks/useInventory';
10
11
  import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
11
12
  import { formatCurrency } from '../utils/formatters';
@@ -17,6 +18,7 @@ export default function ProductDetailsPage() {
17
18
  const { product, isLoading, error, refetch } = useProduct(productId);
18
19
 
19
20
  const goBack = () => navigate?.(joinPath(basePath, 'inventory/products'));
21
+ const goTo = (path: string) => navigate?.(joinPath(basePath, path));
20
22
 
21
23
  if (isLoading) return <LoadingState message="Loading product details..." />;
22
24
  if (error || !product) return <ErrorState title="Product not found" onRetry={refetch} />;
@@ -46,6 +48,32 @@ export default function ProductDetailsPage() {
46
48
  </div>
47
49
  }
48
50
  >
51
+ <PagePurpose icon={<Package size={18} />}>
52
+ The catalog record for this item — its dimensions, weight, value and handling flags. These
53
+ drive how it&apos;s packed, priced and routed, so keep them accurate before adding the
54
+ product to an order or stocking it in a warehouse.
55
+ </PagePurpose>
56
+
57
+ <NextSteps
58
+ storageKey="movethewheels-product-details"
59
+ steps={[
60
+ {
61
+ id: 'order',
62
+ label: 'Add this product to an order',
63
+ description: 'Include it on a new delivery.',
64
+ icon: <Package size={16} />,
65
+ onClick: () => goTo('orders/new'),
66
+ },
67
+ {
68
+ id: 'edit',
69
+ label: 'Edit product details',
70
+ description: 'Update dimensions, value or handling flags.',
71
+ icon: <Tag size={16} />,
72
+ onClick: () => {},
73
+ },
74
+ ]}
75
+ />
76
+
49
77
  <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
50
78
  <div className="lg:col-span-2 space-y-6">
51
79
  <Card>
@@ -119,17 +147,14 @@ export default function ProductDetailsPage() {
119
147
  </div>
120
148
 
121
149
  <div className="space-y-6">
122
- <Card>
123
- <CardHeader>
124
- <CardTitle className="flex items-center gap-2">
125
- <DollarSign size={18} /> Pricing
126
- </CardTitle>
127
- </CardHeader>
128
- <CardContent>
129
- <p className="text-3xl font-bold">{formatCurrency(product.value)}</p>
130
- <p className="text-sm text-text-secondary">Unit price</p>
131
- </CardContent>
132
- </Card>
150
+ {/* Pricing — the page's single emphasis zone */}
151
+ <EmphasisPanel>
152
+ <h2 className="flex items-center gap-2 text-base font-semibold text-text-primary mb-3">
153
+ <DollarSign size={18} /> Pricing
154
+ </h2>
155
+ <p className="text-3xl font-bold">{formatCurrency(product.value)}</p>
156
+ <p className="text-sm text-text-secondary">Unit price</p>
157
+ </EmphasisPanel>
133
158
 
134
159
  <Card>
135
160
  <CardHeader>
@@ -6,7 +6,7 @@ import { Package, Plus, RefreshCw, Download } from 'lucide-react';
6
6
  import { PageLayout } from '../components/PageLayout';
7
7
  import { DataTable, type Column } from '../components/DataTable';
8
8
  import { Badge } from '../components/ui';
9
- import { CTAOverflowMenu } from '@burdenoff/fe-libs/ui';
9
+ import { CTAOverflowMenu, EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';
10
10
  import { useProducts } from '../hooks/useInventory';
11
11
  import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
12
12
  import { formatCurrency } from '../utils/formatters';
@@ -106,6 +106,35 @@ export default function ProductsPage() {
106
106
  />
107
107
  }
108
108
  >
109
+ <PagePurpose icon={<Package size={18} />}>
110
+ The catalog of items you ship. Each product&apos;s dimensions, weight, value and handling
111
+ flags (fragile, hazardous, temperature-controlled) drive how it&apos;s packed, priced and
112
+ routed — keep them accurate so shipments are quoted and handled correctly.
113
+ </PagePurpose>
114
+
115
+ {/* Catalog at a glance — the page's single emphasis zone */}
116
+ <EmphasisPanel>
117
+ <p className="text-sm font-medium text-text-secondary">Catalog at a glance</p>
118
+ <div className="mt-3 grid grid-cols-3 gap-4">
119
+ <div>
120
+ <p className="text-2xl font-bold text-text-primary tabular-nums">{totalProducts}</p>
121
+ <p className="text-xs text-text-secondary">Total products</p>
122
+ </div>
123
+ <div>
124
+ <p className="text-2xl font-bold text-text-primary tabular-nums">
125
+ {products.filter((p) => p.fragile || p.hazardous).length}
126
+ </p>
127
+ <p className="text-xs text-text-secondary">Special handling</p>
128
+ </div>
129
+ <div>
130
+ <p className="text-2xl font-bold text-text-primary tabular-nums">
131
+ {products.filter((p) => p.temperatureControlled).length}
132
+ </p>
133
+ <p className="text-xs text-text-secondary">Temp-controlled</p>
134
+ </div>
135
+ </div>
136
+ </EmphasisPanel>
137
+
109
138
  <DataTable
110
139
  columns={columns}
111
140
  data={products}
@@ -115,6 +144,9 @@ export default function ProductsPage() {
115
144
  searchFields={['name', 'sku', 'category'] as (keyof Product)[]}
116
145
  onRowClick={(row) => goTo(`inventory/products/${row.id}`)}
117
146
  getRowId={(row) => row.id}
147
+ emptyIllustration="empty-files"
148
+ emptyTitle="No products yet"
149
+ emptyDescription="Add products to your catalog so they can be added to orders and stocked in warehouses."
118
150
  />
119
151
  </PageLayout>
120
152
  );