@burdenoff/microfe-movethewheels 2026.626.2 → 2026.703.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 (135) hide show
  1. package/dist/{AIAssistantPage-AvsMbunM.js → AIAssistantPage-C3cPsWt-.js} +100 -73
  2. package/dist/AnalyticsPage-Dz6g2MvK.js +215 -0
  3. package/dist/{CreateOrderPage-CjlnEtk3.js → CreateOrderPage-C5iwnjp4.js} +36 -67
  4. package/dist/CustomerDetailsPage-B6nwFyLO.js +406 -0
  5. package/dist/{CustomersPage-CGGfD4ki.js → CustomersPage-2Y05LVyh.js} +26 -28
  6. package/dist/{DashboardPage-D2HRqwg9.js → DashboardPage-BVjQi0EB.js} +85 -83
  7. package/dist/{DataTable-CD9ZhpLB.js → DataTable-DmciIKKM.js} +3 -3
  8. package/dist/DriverDetailsPage-CN3WQ0B9.js +507 -0
  9. package/dist/{DriversPage-DKiynISH.js → DriversPage-B0Zpx8OQ.js} +25 -27
  10. package/dist/{FinancePage-Vg8WPs38.js → FinancePage-DEDykSOP.js} +9 -9
  11. package/dist/FleetPage-DqkFi3s3.js +365 -0
  12. package/dist/FormError-BlOjnXOq.js +15 -0
  13. package/dist/ImportExportPage-DKJRCezl.js +290 -0
  14. package/dist/InventoryPage-DwfgCUQq.js +253 -0
  15. package/dist/{LiveTrackingPage-DQ1q4Id3.js → LiveTrackingPage-DCX-K-LR.js} +60 -56
  16. package/dist/MarketplacePage-CIQ97_zp.js +247 -0
  17. package/dist/{MetricCard-B7yMyvMX.js → MetricCard-BY0QrMD4.js} +1 -1
  18. package/dist/{OrderDetailsPage-CFASgsYX.js → OrderDetailsPage-DYiZ-9UK.js} +83 -85
  19. package/dist/{OrdersListPage-BHeT8S5o.js → OrdersListPage-BjDlCKJd.js} +31 -33
  20. package/dist/{PageLayout-D3N8MCTm.js → PageLayout-D4LDHJJq.js} +483 -422
  21. package/dist/ProductDetailsPage-C9uOiYLp.js +350 -0
  22. package/dist/{ProductsPage--xEpbQ8A.js → ProductsPage-C1G9h7Xd.js} +22 -24
  23. package/dist/ReportsPage-Zp53q3_8.js +284 -0
  24. package/dist/RouteDetailsPage-DUStXSf9.js +531 -0
  25. package/dist/RoutesPage-DMfoicM1.js +144 -0
  26. package/dist/SettingsPage-Bn-v0mbQ.js +421 -0
  27. package/dist/StatusBadge-BZurYHMy.js +152 -0
  28. package/dist/{TrackingPage-CcRc_dva.js → TrackingPage-W-jtdM3Y.js} +59 -61
  29. package/dist/VehicleDetailsPage-Bceo5oz3.js +410 -0
  30. package/dist/{VehiclesPage-UlxPWP9K.js → VehiclesPage-VBtOep91.js} +20 -22
  31. package/dist/WarehouseDetailsPage-L_6sWigM.js +493 -0
  32. package/dist/{WarehousesPage-CuTO-OPp.js → WarehousesPage-DCbXXXWE.js} +16 -18
  33. package/dist/{arrow-left-CBpZKkpq.js → arrow-left-n48Y-Wis.js} +1 -1
  34. package/dist/{box-CAaiElsb.js → box-D9Pal4HM.js} +1 -1
  35. package/dist/{chart-column-D1Ym15-S.js → chart-column-BFIJysDR.js} +1 -1
  36. package/dist/{chevron-right-BIFGi0UA.js → chevron-right-EMIIyyJ1.js} +1 -1
  37. package/dist/{circle-alert-DjmNo5_L.js → circle-alert-iY24lSlp.js} +1 -1
  38. package/dist/{circle-check-big-CjuPVo3_.js → circle-check-big-w0TrLKMF.js} +1 -1
  39. package/dist/{clock-BjkdnddD.js → clock-DJZtdl8u.js} +1 -1
  40. package/dist/{dollar-sign-IB4O0wuQ.js → dollar-sign-CgKQRz_e.js} +1 -1
  41. package/dist/{download-Dpa9vqoG.js → download-DRXxoiQR.js} +1 -1
  42. package/dist/{file-text-C8Uioy11.js → file-text-DWWY6_f5.js} +1 -1
  43. package/dist/{filter-Da5OZaHI.js → filter-DloLC2eE.js} +1 -1
  44. package/dist/index.js +186 -162
  45. package/dist/{map-_Per4sT9.js → map-CkJaULb2.js} +1 -1
  46. package/dist/{map-pin-BSaf5IDL.js → map-pin-BGiCvyCs.js} +1 -1
  47. package/dist/{navigation-DaTbrhw2.js → navigation-D36prnAn.js} +1 -1
  48. package/dist/{package-BE7U0wQE.js → package-BChUzpJS.js} +1 -1
  49. package/dist/{phone-DV4StZiA.js → phone-Ac9s3mo_.js} +1 -1
  50. package/dist/{plus-Dl1rLeJR.js → plus-Z76q-FZm.js} +1 -1
  51. package/dist/{refresh-cw-CWfERAit.js → refresh-cw-DKt6f5T6.js} +1 -1
  52. package/dist/{save-XH8vydOn.js → save-CojywNhG.js} +1 -1
  53. package/dist/{search-OxoIiL_C.js → search-CDGefqb3.js} +1 -1
  54. package/dist/{square-pen-hLIbFQFV.js → square-pen-CopE9GmB.js} +1 -1
  55. package/dist/{star-YsVV3MNQ.js → star-nHlLjDKR.js} +1 -1
  56. package/dist/{store-RCBl7HB-.js → store-BR9Voi5E.js} +1 -1
  57. package/dist/trash-2-BKhar6Hs.js +32 -0
  58. package/dist/{trending-up-C-85AwGT.js → trending-up-Dohgd4t_.js} +1 -1
  59. package/dist/{triangle-alert-BOhfGgmh.js → triangle-alert-i-XQL9Rd.js} +1 -1
  60. package/dist/{truck-CtDjNFbi.js → truck-C0v_hbLR.js} +1 -1
  61. package/dist/{useAnalytics-ph7eTIK6.js → useAnalytics-DS8n0xgg.js} +40 -40
  62. package/dist/useAssistant-D4v3oxD3.js +84 -0
  63. package/dist/{useCustomers-bS3a4ytk.js → useCustomers-BmTNGxiI.js} +24 -24
  64. package/dist/{useFleet-BdETplNE.js → useFleet-DKqXZ16m.js} +133 -109
  65. package/dist/useImportExport-DHr-SWSw.js +55 -0
  66. package/dist/{useInventory-Dwn18FPz.js → useInventory-DkyiVY_A.js} +95 -75
  67. package/dist/{useOrders-D_3_hGMp.js → useOrders-Cfk1GLiq.js} +42 -42
  68. package/dist/useReports-CTqZr-AB.js +78 -0
  69. package/dist/{useRoutes-v4aBaS-E.js → useRoutes-BQWO607N.js} +31 -31
  70. package/dist/useSettings-CkDH_-gM.js +81 -0
  71. package/dist/{useTracking-De2KIUNu.js → useTracking-B-va1kO3.js} +22 -22
  72. package/dist/{user-Dz5TJZFs.js → user-jyFU3lXk.js} +1 -1
  73. package/dist/{users-g2N0eL-Z.js → users-DZ-ilS6B.js} +1 -1
  74. package/dist/{warehouse-D3WWDeTX.js → warehouse-6m5kXMLu.js} +1 -1
  75. package/dist/{wrench-CmxY1n4I.js → wrench-CANXWxF-.js} +1 -1
  76. package/package.json +1 -1
  77. package/src/movethewheels/MoveTheWheelsRoutes.tsx +31 -3
  78. package/src/movethewheels/components/FormError.tsx +25 -0
  79. package/src/movethewheels/components/StatusBadge.tsx +18 -37
  80. package/src/movethewheels/constants/index.ts +67 -26
  81. package/src/movethewheels/hooks/index.ts +12 -0
  82. package/src/movethewheels/hooks/useAnalytics.ts +20 -6
  83. package/src/movethewheels/hooks/useAssistant.ts +74 -0
  84. package/src/movethewheels/hooks/useFleet.ts +170 -59
  85. package/src/movethewheels/hooks/useImportExport.ts +101 -0
  86. package/src/movethewheels/hooks/useInventory.ts +107 -0
  87. package/src/movethewheels/hooks/useReports.ts +158 -0
  88. package/src/movethewheels/hooks/useSettings.ts +120 -0
  89. package/src/movethewheels/pages/AIAssistantPage.tsx +53 -15
  90. package/src/movethewheels/pages/AnalyticsPage.tsx +67 -64
  91. package/src/movethewheels/pages/CustomerDetailsPage.tsx +154 -21
  92. package/src/movethewheels/pages/CustomersPage.tsx +1 -1
  93. package/src/movethewheels/pages/DashboardPage.tsx +42 -22
  94. package/src/movethewheels/pages/DriverDetailsPage.tsx +160 -3
  95. package/src/movethewheels/pages/DriversPage.tsx +6 -2
  96. package/src/movethewheels/pages/FleetPage.tsx +96 -38
  97. package/src/movethewheels/pages/ImportExportPage.tsx +174 -68
  98. package/src/movethewheels/pages/InventoryPage.tsx +66 -28
  99. package/src/movethewheels/pages/LiveTrackingPage.tsx +12 -3
  100. package/src/movethewheels/pages/MarketplacePage.tsx +87 -45
  101. package/src/movethewheels/pages/OrderDetailsPage.tsx +2 -2
  102. package/src/movethewheels/pages/ProductDetailsPage.tsx +146 -3
  103. package/src/movethewheels/pages/ProductsPage.tsx +5 -1
  104. package/src/movethewheels/pages/ReportsPage.tsx +194 -90
  105. package/src/movethewheels/pages/RouteDetailsPage.tsx +290 -36
  106. package/src/movethewheels/pages/RoutesPage.tsx +4 -9
  107. package/src/movethewheels/pages/SettingsPage.tsx +234 -56
  108. package/src/movethewheels/pages/TrackingPage.tsx +6 -6
  109. package/src/movethewheels/pages/VehicleDetailsPage.tsx +158 -2
  110. package/src/movethewheels/pages/VehiclesPage.tsx +5 -1
  111. package/src/movethewheels/pages/WarehouseDetailsPage.tsx +224 -2
  112. package/src/movethewheels/pages/WarehousesPage.tsx +5 -1
  113. package/src/movethewheels/providers/MoveTheWheelsProvider.tsx +7 -6
  114. package/src/movethewheels/store/movethewheelsStore.ts +1 -1
  115. package/dist/AnalyticsPage-CCLfHgQZ.js +0 -212
  116. package/dist/CustomerDetailsPage-I6cdDHUi.js +0 -265
  117. package/dist/DriverDetailsPage-rg_pGNuP.js +0 -330
  118. package/dist/FleetPage-DddXt8r8.js +0 -332
  119. package/dist/ImportExportPage-BW6qO3kc.js +0 -248
  120. package/dist/InventoryPage-rMGuaJN-.js +0 -222
  121. package/dist/MarketplacePage-DKrXAv62.js +0 -219
  122. package/dist/ProductDetailsPage-CFGcbaHo.js +0 -195
  123. package/dist/ReportsPage-Bb7_90rK.js +0 -235
  124. package/dist/RouteDetailsPage-CVtDVb1N.js +0 -282
  125. package/dist/RoutesPage-s57PtgcQ.js +0 -163
  126. package/dist/SettingsPage-BYNCBOpN.js +0 -298
  127. package/dist/StatusBadge-CijYQXtb.js +0 -209
  128. package/dist/VehicleDetailsPage-3YDMPsPs.js +0 -220
  129. package/dist/WarehouseDetailsPage-Db7KeN-d.js +0 -238
  130. package/dist/graphqlClient-CdJyR_ed.js +0 -55
  131. package/dist/navigation-BgnOfsVd.js +0 -6
  132. package/dist/route-Dp9JiN_E.js +0 -51
  133. package/dist/settings-3Rw5NwFF.js +0 -28
  134. package/src/movethewheels/constants/mockData.ts +0 -1342
  135. /package/dist/{formatters-_vJlC-47.js → formatters-CF2S2l1m.js} +0 -0
@@ -2,16 +2,298 @@
2
2
  * Route Details Page
3
3
  */
4
4
 
5
+ import { useState } from 'react';
5
6
  import { useParams } from 'react-router-dom';
6
- import { Navigation, ArrowLeft, Edit, MapPin, Clock, Zap, CheckCircle } from 'lucide-react';
7
- import { PageLayout, LoadingState, ErrorState, EmptyState } from '../components/PageLayout';
7
+ import {
8
+ Navigation,
9
+ ArrowLeft,
10
+ Edit,
11
+ MapPin,
12
+ Clock,
13
+ Zap,
14
+ CheckCircle,
15
+ Plus,
16
+ Trash2,
17
+ Save,
18
+ } from 'lucide-react';
19
+ import { PageLayout, LoadingState, ErrorState } from '../components/PageLayout';
8
20
  import { StatusBadge } from '../components/StatusBadge';
9
- import { Card, CardContent, CardHeader, CardTitle, Button, Badge } from '../components/ui';
21
+ import {
22
+ Card,
23
+ CardContent,
24
+ CardHeader,
25
+ CardTitle,
26
+ Button,
27
+ Badge,
28
+ Input,
29
+ Label,
30
+ Select,
31
+ SelectContent,
32
+ SelectItem,
33
+ SelectTrigger,
34
+ SelectValue,
35
+ } from '../components/ui';
10
36
  import { EmphasisPanel, NextSteps, PagePurpose } from '@burdenoff/fe-libs/ui';
11
37
  import { useRoute, useRoutes } from '../hooks/useRoutes';
38
+ import { useFleet } from '../hooks/useFleet';
12
39
  import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
13
40
  import { formatDate, formatAddress } from '../utils/formatters';
14
41
  import { joinPath } from '../utils/navigation';
42
+ import { ROUTE_STATUS_COLORS } from '../constants';
43
+ import { FormError } from '../components/FormError';
44
+ import type { Route as RouteType, RouteStop } from '../types';
45
+
46
+ const ROUTE_STATUS_OPTIONS: { value: RouteType['status']; label: string }[] = [
47
+ { value: 'planned', label: 'Planned' },
48
+ { value: 'in_progress', label: 'In Progress' },
49
+ { value: 'completed', label: 'Completed' },
50
+ { value: 'cancelled', label: 'Cancelled' },
51
+ ];
52
+
53
+ function NewRouteForm() {
54
+ const { basePath, navigate } = useMoveTheWheels();
55
+ const { createRoute } = useRoutes();
56
+ const { vehicles, drivers } = useFleet();
57
+ const [form, setForm] = useState<{
58
+ name: string;
59
+ status: RouteType['status'];
60
+ vehicleId: string;
61
+ driverId: string;
62
+ stops: { address: string; type: 'pickup' | 'delivery' }[];
63
+ }>({
64
+ name: '',
65
+ status: 'planned',
66
+ vehicleId: '',
67
+ driverId: '',
68
+ stops: [{ address: '', type: 'delivery' }],
69
+ });
70
+ const [submitting, setSubmitting] = useState(false);
71
+ const [error, setError] = useState<string | null>(null);
72
+
73
+ const goBack = () => navigate?.(joinPath(basePath, 'routes'));
74
+
75
+ const addStop = () =>
76
+ setForm((prev) => ({
77
+ ...prev,
78
+ stops: [...prev.stops, { address: '', type: 'delivery' }],
79
+ }));
80
+
81
+ const removeStop = (index: number) =>
82
+ setForm((prev) => ({
83
+ ...prev,
84
+ stops: prev.stops.filter((_, i) => i !== index),
85
+ }));
86
+
87
+ const updateStop = (index: number, field: 'address' | 'type', value: string) =>
88
+ setForm((prev) => ({
89
+ ...prev,
90
+ stops: prev.stops.map((stop, i) => (i === index ? { ...stop, [field]: value } : stop)),
91
+ }));
92
+
93
+ const handleSubmit = async (e: React.FormEvent) => {
94
+ e.preventDefault();
95
+ if (!form.name.trim()) {
96
+ setError('Route name is required.');
97
+ return;
98
+ }
99
+ const filledStops = form.stops.filter((stop) => stop.address.trim());
100
+ if (filledStops.length === 0) {
101
+ setError('Add at least one stop with an address.');
102
+ return;
103
+ }
104
+ setSubmitting(true);
105
+ setError(null);
106
+ try {
107
+ const stops: RouteStop[] = filledStops.map((stop, index) => ({
108
+ id: `stop-${index + 1}`,
109
+ orderId: '',
110
+ sequence: index + 1,
111
+ address: {
112
+ street: stop.address.trim(),
113
+ city: '',
114
+ state: '',
115
+ postalCode: '',
116
+ country: '',
117
+ },
118
+ type: stop.type,
119
+ scheduledTime: new Date(),
120
+ duration: 0,
121
+ status: 'pending',
122
+ }));
123
+ const created = await createRoute({
124
+ name: form.name.trim(),
125
+ status: form.status,
126
+ vehicleId: form.vehicleId || undefined,
127
+ driverId: form.driverId || undefined,
128
+ stops,
129
+ });
130
+ navigate?.(joinPath(basePath, `routes/${created.id}`));
131
+ } catch (err) {
132
+ console.error('Failed to create route:', err);
133
+ setError(err instanceof Error ? err.message : 'Failed to create route. Please try again.');
134
+ setSubmitting(false);
135
+ }
136
+ };
137
+
138
+ return (
139
+ <PageLayout
140
+ title="Create Route"
141
+ subtitle="Plan a new delivery route"
142
+ icon={<Navigation size={24} />}
143
+ headerActions={
144
+ <div className="flex gap-2">
145
+ <Button variant="outline" onClick={goBack} disabled={submitting}>
146
+ <ArrowLeft size={16} /> Cancel
147
+ </Button>
148
+ <Button onClick={handleSubmit} disabled={submitting}>
149
+ <Save size={16} /> {submitting ? 'Saving...' : 'Create Route'}
150
+ </Button>
151
+ </div>
152
+ }
153
+ >
154
+ <PagePurpose icon={<Navigation size={18} />}>
155
+ Plan a new delivery route — name it, list the stops to visit, and optionally assign a vehicle
156
+ and driver. Once created you can optimize it to sequence the stops into the shortest run.
157
+ </PagePurpose>
158
+
159
+ <form onSubmit={handleSubmit} className="max-w-3xl space-y-6">
160
+ <FormError message={error} />
161
+
162
+ <EmphasisPanel>
163
+ <h2 className="text-base font-semibold text-text-primary mb-4">Route Details</h2>
164
+ <div className="space-y-4">
165
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
166
+ <div className="space-y-2">
167
+ <Label htmlFor="name">
168
+ Route Name <span className="text-status-error-text">*</span>
169
+ </Label>
170
+ <Input
171
+ id="name"
172
+ value={form.name}
173
+ onChange={(e) => setForm((prev) => ({ ...prev, name: e.target.value }))}
174
+ placeholder="Downtown morning run"
175
+ required
176
+ />
177
+ </div>
178
+ <div className="space-y-2">
179
+ <Label htmlFor="status">Status</Label>
180
+ <Select
181
+ value={form.status}
182
+ onValueChange={(value) =>
183
+ setForm((prev) => ({ ...prev, status: value as RouteType['status'] }))
184
+ }
185
+ >
186
+ <SelectTrigger id="status">
187
+ <SelectValue />
188
+ </SelectTrigger>
189
+ <SelectContent>
190
+ {ROUTE_STATUS_OPTIONS.map((option) => (
191
+ <SelectItem key={option.value} value={option.value}>
192
+ {option.label}
193
+ </SelectItem>
194
+ ))}
195
+ </SelectContent>
196
+ </Select>
197
+ </div>
198
+ </div>
199
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
200
+ <div className="space-y-2">
201
+ <Label htmlFor="vehicle">Vehicle (optional)</Label>
202
+ <Select
203
+ value={form.vehicleId}
204
+ onValueChange={(value) => setForm((prev) => ({ ...prev, vehicleId: value }))}
205
+ >
206
+ <SelectTrigger id="vehicle">
207
+ <SelectValue placeholder="Assign later" />
208
+ </SelectTrigger>
209
+ <SelectContent>
210
+ {vehicles.map((vehicle) => (
211
+ <SelectItem key={vehicle.id} value={vehicle.id}>
212
+ {vehicle.vehicleNumber} ({vehicle.type})
213
+ </SelectItem>
214
+ ))}
215
+ </SelectContent>
216
+ </Select>
217
+ </div>
218
+ <div className="space-y-2">
219
+ <Label htmlFor="driver">Driver (optional)</Label>
220
+ <Select
221
+ value={form.driverId}
222
+ onValueChange={(value) => setForm((prev) => ({ ...prev, driverId: value }))}
223
+ >
224
+ <SelectTrigger id="driver">
225
+ <SelectValue placeholder="Assign later" />
226
+ </SelectTrigger>
227
+ <SelectContent>
228
+ {drivers.map((driver) => (
229
+ <SelectItem key={driver.id} value={driver.id}>
230
+ {driver.fullName} ({driver.employeeId})
231
+ </SelectItem>
232
+ ))}
233
+ </SelectContent>
234
+ </Select>
235
+ </div>
236
+ </div>
237
+ </div>
238
+ </EmphasisPanel>
239
+
240
+ <Card>
241
+ <CardHeader className="flex flex-row items-center justify-between">
242
+ <CardTitle>
243
+ Stops <span className="text-status-error-text">*</span>
244
+ </CardTitle>
245
+ <Button type="button" variant="outline" size="sm" onClick={addStop}>
246
+ <Plus size={16} /> Add Stop
247
+ </Button>
248
+ </CardHeader>
249
+ <CardContent className="space-y-4">
250
+ {form.stops.map((stop, index) => (
251
+ <div key={index} className="grid grid-cols-1 md:grid-cols-12 gap-3 items-end">
252
+ <div className="md:col-span-7 space-y-2">
253
+ <Label htmlFor={`stop-address-${index}`}>Stop {index + 1} address</Label>
254
+ <Input
255
+ id={`stop-address-${index}`}
256
+ value={stop.address}
257
+ onChange={(e) => updateStop(index, 'address', e.target.value)}
258
+ placeholder="123 Main St, San Francisco, CA"
259
+ />
260
+ </div>
261
+ <div className="md:col-span-4 space-y-2">
262
+ <Label htmlFor={`stop-type-${index}`}>Type</Label>
263
+ <Select
264
+ value={stop.type}
265
+ onValueChange={(value) => updateStop(index, 'type', value)}
266
+ >
267
+ <SelectTrigger id={`stop-type-${index}`}>
268
+ <SelectValue />
269
+ </SelectTrigger>
270
+ <SelectContent>
271
+ <SelectItem value="pickup">Pickup</SelectItem>
272
+ <SelectItem value="delivery">Delivery</SelectItem>
273
+ </SelectContent>
274
+ </Select>
275
+ </div>
276
+ <div className="md:col-span-1 flex justify-end">
277
+ <Button
278
+ type="button"
279
+ variant="ghost"
280
+ size="icon"
281
+ className="text-status-error-text"
282
+ onClick={() => removeStop(index)}
283
+ disabled={form.stops.length === 1}
284
+ aria-label={`Remove stop ${index + 1}`}
285
+ >
286
+ <Trash2 size={16} />
287
+ </Button>
288
+ </div>
289
+ </div>
290
+ ))}
291
+ </CardContent>
292
+ </Card>
293
+ </form>
294
+ </PageLayout>
295
+ );
296
+ }
15
297
 
16
298
  export default function RouteDetailsPage() {
17
299
  const { routeId } = useParams<{ routeId: string }>();
@@ -24,28 +306,7 @@ export default function RouteDetailsPage() {
24
306
 
25
307
  // Handle new route form
26
308
  if (!routeId) {
27
- return (
28
- <PageLayout
29
- title="Create Route"
30
- subtitle="Plan a new delivery route"
31
- icon={<Navigation size={24} />}
32
- headerActions={
33
- <Button variant="outline" onClick={goBack}>
34
- <ArrowLeft size={16} /> Back
35
- </Button>
36
- }
37
- >
38
- <PagePurpose icon={<Navigation size={18} />}>
39
- Plan a new delivery route — pick the stops to visit, and the optimizer will sequence them
40
- into the shortest driving plan so one driver can cover them in a single run.
41
- </PagePurpose>
42
- <EmptyState
43
- illustration="onboarding"
44
- title="Build your route"
45
- description="The route planner lets you add stops, set the running order, and optimize for distance and time."
46
- />
47
- </PageLayout>
48
- );
309
+ return <NewRouteForm />;
49
310
  }
50
311
 
51
312
  if (isLoading) return <LoadingState message="Loading route details..." />;
@@ -60,13 +321,6 @@ export default function RouteDetailsPage() {
60
321
  }
61
322
  };
62
323
 
63
- const statusColors = {
64
- planned: { bg: 'bg-blue-100', text: 'text-blue-700' },
65
- in_progress: { bg: 'bg-yellow-100', text: 'text-yellow-700' },
66
- completed: { bg: 'bg-green-100', text: 'text-green-700' },
67
- cancelled: { bg: 'bg-red-100', text: 'text-red-700' },
68
- };
69
-
70
324
  return (
71
325
  <PageLayout
72
326
  title={route.name}
@@ -89,7 +343,7 @@ export default function RouteDetailsPage() {
89
343
  }
90
344
  headerContent={
91
345
  <div className="flex gap-2">
92
- <StatusBadge status={route.status} customColors={statusColors[route.status]} />
346
+ <StatusBadge status={route.status} customColors={ROUTE_STATUS_COLORS[route.status]} />
93
347
  <Badge variant={route.optimized ? 'default' : 'secondary'}>
94
348
  {route.optimized ? 'Optimized' : 'Not Optimized'}
95
349
  </Badge>
@@ -159,7 +413,7 @@ export default function RouteDetailsPage() {
159
413
  <div key={stop.id} className="flex gap-4">
160
414
  <div className="relative">
161
415
  <div
162
- className={`w-8 h-8 rounded-full flex items-center justify-center ${stop.status === 'completed' ? 'bg-green-500 text-white' : 'bg-bg-sunken'}`}
416
+ className={`w-8 h-8 rounded-full flex items-center justify-center ${stop.status === 'completed' ? 'bg-status-success-text text-text-inverse' : 'bg-bg-sunken'}`}
163
417
  >
164
418
  {stop.status === 'completed' ? <CheckCircle size={16} /> : stop.sequence}
165
419
  </div>
@@ -188,7 +442,7 @@ export default function RouteDetailsPage() {
188
442
  Scheduled: {formatDate(stop.scheduledTime, 'time')}
189
443
  </p>
190
444
  {stop.actualTime && (
191
- <p className="text-sm text-green-600">
445
+ <p className="text-sm text-status-success-text">
192
446
  Actual: {formatDate(stop.actualTime, 'time')}
193
447
  </p>
194
448
  )}
@@ -267,7 +521,7 @@ export default function RouteDetailsPage() {
267
521
  {route.trafficConditions.map((tc, i) => (
268
522
  <div
269
523
  key={i}
270
- className={`p-2 rounded mb-2 ${tc.condition === 'severe' ? 'bg-red-50' : tc.condition === 'heavy' ? 'bg-orange-50' : 'bg-yellow-50'}`}
524
+ className={`p-2 rounded mb-2 ${tc.condition === 'severe' ? 'bg-status-error-bg-subtle' : tc.condition === 'heavy' ? 'bg-status-warning-bg-subtle' : 'bg-status-warning-bg-subtle'}`}
271
525
  >
272
526
  <p className="text-sm font-medium capitalize">{tc.condition} traffic</p>
273
527
  <p className="text-xs text-text-secondary">
@@ -12,6 +12,7 @@ import { useRoutes } from '../hooks/useRoutes';
12
12
  import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
13
13
  import { formatDate } from '../utils/formatters';
14
14
  import { joinPath } from '../utils/navigation';
15
+ import { ROUTE_STATUS_COLORS } from '../constants';
15
16
  import type { Route } from '../types';
16
17
 
17
18
  export default function RoutesPage() {
@@ -33,15 +34,9 @@ export default function RoutesPage() {
33
34
  header: 'Status',
34
35
  accessorKey: 'status',
35
36
  sortable: true,
36
- cell: (row) => {
37
- const colors = {
38
- planned: { bg: 'bg-blue-100', text: 'text-blue-700' },
39
- in_progress: { bg: 'bg-yellow-100', text: 'text-yellow-700' },
40
- completed: { bg: 'bg-green-100', text: 'text-green-700' },
41
- cancelled: { bg: 'bg-red-100', text: 'text-red-700' },
42
- };
43
- return <StatusBadge status={row.status} customColors={colors[row.status]} />;
44
- },
37
+ cell: (row) => (
38
+ <StatusBadge status={row.status} customColors={ROUTE_STATUS_COLORS[row.status]} />
39
+ ),
45
40
  },
46
41
  {
47
42
  id: 'stops',