@burdenoff/microfe-movethewheels 2026.925.1 → 2026.925.3

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 (47) hide show
  1. package/dist/components/StatusBadge.js +31 -31
  2. package/dist/constants/index.js +19 -5
  3. package/dist/hooks/useCustomers.js +0 -3
  4. package/dist/hooks/useFleet.js +197 -175
  5. package/dist/hooks/useInventory.js +144 -145
  6. package/dist/hooks/useRoutes.js +5 -14
  7. package/dist/movethewheels/components/StatusBadge.d.ts +3 -1
  8. package/dist/movethewheels/constants/index.d.ts +2 -0
  9. package/dist/movethewheels/hooks/useFleet.d.ts +53 -1
  10. package/dist/movethewheels/hooks/useInventory.d.ts +10 -0
  11. package/dist/movethewheels/types/index.d.ts +29 -108
  12. package/dist/node_modules/lucide-react/dist/esm/icons/sticky-note.js +11 -0
  13. package/dist/node_modules/lucide-react/dist/esm/icons/user-x.js +30 -0
  14. package/dist/pages/CustomerDetailsPage.js +666 -344
  15. package/dist/pages/CustomersPage.js +71 -80
  16. package/dist/pages/DriverDetailsPage.js +702 -421
  17. package/dist/pages/DriversPage.js +106 -117
  18. package/dist/pages/FleetPage.js +5 -13
  19. package/dist/pages/InventoryPage.js +4 -4
  20. package/dist/pages/OrderDetailsPage.js +279 -274
  21. package/dist/pages/RouteDetailsPage.js +300 -263
  22. package/dist/pages/RoutesPage.js +130 -67
  23. package/dist/pages/VehicleDetailsPage.js +562 -287
  24. package/dist/pages/VehiclesPage.js +119 -70
  25. package/dist/pages/WarehouseDetailsPage.js +410 -370
  26. package/dist/pages/WarehousesPage.js +131 -82
  27. package/package.json +1 -1
  28. package/src/movethewheels/components/StatusBadge.tsx +16 -2
  29. package/src/movethewheels/constants/index.ts +21 -0
  30. package/src/movethewheels/hooks/useCustomers.ts +0 -3
  31. package/src/movethewheels/hooks/useFleet.ts +236 -62
  32. package/src/movethewheels/hooks/useInventory.ts +76 -32
  33. package/src/movethewheels/hooks/useRoutes.ts +17 -12
  34. package/src/movethewheels/pages/CustomerDetailsPage.tsx +376 -109
  35. package/src/movethewheels/pages/CustomersPage.tsx +6 -15
  36. package/src/movethewheels/pages/DriverDetailsPage.tsx +516 -156
  37. package/src/movethewheels/pages/DriversPage.tsx +28 -11
  38. package/src/movethewheels/pages/FleetPage.tsx +9 -11
  39. package/src/movethewheels/pages/InventoryPage.tsx +14 -5
  40. package/src/movethewheels/pages/OrderDetailsPage.tsx +12 -7
  41. package/src/movethewheels/pages/RouteDetailsPage.tsx +89 -41
  42. package/src/movethewheels/pages/RoutesPage.tsx +66 -2
  43. package/src/movethewheels/pages/VehicleDetailsPage.tsx +282 -20
  44. package/src/movethewheels/pages/VehiclesPage.tsx +68 -3
  45. package/src/movethewheels/pages/WarehouseDetailsPage.tsx +213 -135
  46. package/src/movethewheels/pages/WarehousesPage.tsx +77 -16
  47. package/src/movethewheels/types/index.ts +30 -108
@@ -4,7 +4,18 @@
4
4
 
5
5
  import { useEffect, useState } from 'react';
6
6
  import { useParams, useLocation } from 'react-router';
7
- import { Truck, ArrowLeft, MapPin, Fuel, UserRound, Edit, Save, Mail, Phone } from 'lucide-react';
7
+ import {
8
+ Truck,
9
+ ArrowLeft,
10
+ MapPin,
11
+ Fuel,
12
+ UserRound,
13
+ Edit,
14
+ Save,
15
+ Mail,
16
+ Phone,
17
+ Trash2,
18
+ } from 'lucide-react';
8
19
  import { PageLayout, LoadingState, ErrorState } from '../components/PageLayout';
9
20
  import { StatusBadge, VehicleTypeBadge } from '../components/StatusBadge';
10
21
  import {
@@ -24,8 +35,20 @@ import {
24
35
  Avatar,
25
36
  AvatarFallback,
26
37
  } from '../components/ui';
27
- import { EmphasisPanel, NextSteps, PagePurpose } from '@burdenoff/fe-libs/ui';
28
- import { useVehicle, useVehicleDrivers, useFleet } from '../hooks/useFleet';
38
+ import {
39
+ EmphasisPanel,
40
+ NextSteps,
41
+ PagePurpose,
42
+ ResponsiveDialog,
43
+ ResponsiveDialogContent,
44
+ ResponsiveDialogHeader,
45
+ ResponsiveDialogFooter,
46
+ ResponsiveDialogTitle,
47
+ ResponsiveDialogDescription,
48
+ } from '@burdenoff/fe-libs/ui';
49
+ import { useVehicle, useVehicleDrivers, useFleet, toApiVehicleStatus } from '../hooks/useFleet';
50
+ import type { VehicleStatus } from '../types';
51
+ import { VEHICLE_STATUS_LABELS } from '../constants';
29
52
  import { useRecordVehicleService } from '../hooks/useFleetIntelligence';
30
53
  import { VehicleServiceCard } from '../components/VehicleServiceCard';
31
54
  import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
@@ -47,9 +70,19 @@ const VEHICLE_TYPE_OPTIONS = [
47
70
  { value: 'DRONE', label: 'Drone' },
48
71
  ];
49
72
 
73
+ const VEHICLE_STATUS_OPTIONS: Array<{ value: VehicleStatus; label: string }> = (
74
+ Object.entries(VEHICLE_STATUS_LABELS) as Array<[VehicleStatus, string]>
75
+ ).map(([value, label]) => ({ value, label }));
76
+
77
+ const OWNERSHIP_TYPE_OPTIONS = [
78
+ { value: 'owned', label: 'Owned' },
79
+ { value: 'leased', label: 'Leased' },
80
+ { value: 'rented', label: 'Rented' },
81
+ ];
82
+
50
83
  function NewVehicleForm({ editId }: { editId?: string }) {
51
84
  const { basePath, navigate } = useMoveTheWheels();
52
- const { createVehicle, updateVehicle } = useFleet();
85
+ const { createVehicle, updateVehicle, deleteVehicle } = useFleet();
53
86
  const { vehicle } = useVehicle(editId);
54
87
  const isEditing = !!editId;
55
88
  const [form, setForm] = useState({
@@ -58,9 +91,20 @@ function NewVehicleForm({ editId }: { editId?: string }) {
58
91
  make: '',
59
92
  model: '',
60
93
  licensePlate: '',
94
+ ownershipType: '',
95
+ year: '',
96
+ status: 'available' as VehicleStatus,
97
+ fuelType: '',
98
+ fuelEfficiencyLPer100Km: '',
99
+ capacityWeight: '',
100
+ capacityVolume: '',
101
+ capacityPallets: '',
61
102
  });
62
103
  const [submitting, setSubmitting] = useState(false);
63
104
  const [error, setError] = useState<string | null>(null);
105
+ const [deleteOpen, setDeleteOpen] = useState(false);
106
+ const [deleting, setDeleting] = useState(false);
107
+ const [deleteError, setDeleteError] = useState<string | null>(null);
64
108
 
65
109
  useEffect(() => {
66
110
  if (editId && vehicle) {
@@ -70,6 +114,17 @@ function NewVehicleForm({ editId }: { editId?: string }) {
70
114
  make: vehicle.make ?? '',
71
115
  model: vehicle.model ?? '',
72
116
  licensePlate: vehicle.licensePlate ?? '',
117
+ ownershipType: vehicle.ownershipType ?? '',
118
+ year: vehicle.year ? String(vehicle.year) : '',
119
+ status: vehicle.status,
120
+ fuelType: vehicle.fuelType ?? '',
121
+ fuelEfficiencyLPer100Km:
122
+ vehicle.fuelEfficiencyLPer100Km !== undefined
123
+ ? String(vehicle.fuelEfficiencyLPer100Km)
124
+ : '',
125
+ capacityWeight: vehicle.capacity.weight ? String(vehicle.capacity.weight) : '',
126
+ capacityVolume: vehicle.capacity.volume ? String(vehicle.capacity.volume) : '',
127
+ capacityPallets: vehicle.capacity.pallets ? String(vehicle.capacity.pallets) : '',
73
128
  });
74
129
  }
75
130
  }, [editId, vehicle]);
@@ -85,23 +140,33 @@ function NewVehicleForm({ editId }: { editId?: string }) {
85
140
  setSubmitting(true);
86
141
  setError(null);
87
142
  try {
143
+ const payload = {
144
+ vehicleNumber: form.vehicleNumber.trim(),
145
+ type: form.type,
146
+ make: form.make.trim() || undefined,
147
+ model: form.model.trim() || undefined,
148
+ licensePlate: form.licensePlate.trim() || undefined,
149
+ ownershipType: form.ownershipType || undefined,
150
+ year: form.year ? Number(form.year) : undefined,
151
+ status: toApiVehicleStatus(form.status),
152
+ fuelType: form.fuelType || undefined,
153
+ fuelEfficiencyLPer100Km: form.fuelEfficiencyLPer100Km
154
+ ? Number(form.fuelEfficiencyLPer100Km)
155
+ : undefined,
156
+ capacity:
157
+ form.capacityWeight || form.capacityVolume || form.capacityPallets
158
+ ? {
159
+ weight: form.capacityWeight ? Number(form.capacityWeight) : undefined,
160
+ volume: form.capacityVolume ? Number(form.capacityVolume) : undefined,
161
+ pallets: form.capacityPallets ? Number(form.capacityPallets) : undefined,
162
+ }
163
+ : undefined,
164
+ };
88
165
  if (editId) {
89
- const updated = await updateVehicle(editId, {
90
- vehicleNumber: form.vehicleNumber.trim(),
91
- type: form.type,
92
- make: form.make.trim() || undefined,
93
- model: form.model.trim() || undefined,
94
- licensePlate: form.licensePlate.trim() || undefined,
95
- });
166
+ const updated = await updateVehicle(editId, payload);
96
167
  navigate?.(joinPath(basePath, `fleet/vehicles/${updated.id}`));
97
168
  } else {
98
- const created = await createVehicle({
99
- vehicleNumber: form.vehicleNumber.trim(),
100
- type: form.type,
101
- make: form.make.trim() || undefined,
102
- model: form.model.trim() || undefined,
103
- licensePlate: form.licensePlate.trim() || undefined,
104
- });
169
+ const created = await createVehicle(payload);
105
170
  navigate?.(joinPath(basePath, `fleet/vehicles/${created.id}`));
106
171
  }
107
172
  } catch (err) {
@@ -111,6 +176,21 @@ function NewVehicleForm({ editId }: { editId?: string }) {
111
176
  }
112
177
  };
113
178
 
179
+ const handleDelete = async () => {
180
+ if (!editId) return;
181
+ setDeleting(true);
182
+ setDeleteError(null);
183
+ try {
184
+ await deleteVehicle(editId);
185
+ setDeleteOpen(false);
186
+ navigate?.(joinPath(basePath, 'fleet/vehicles'));
187
+ } catch (err) {
188
+ setDeleteError(err instanceof Error ? err.message : 'Failed to delete vehicle.');
189
+ } finally {
190
+ setDeleting(false);
191
+ }
192
+ };
193
+
114
194
  return (
115
195
  <PageLayout
116
196
  title={isEditing ? 'Edit Vehicle' : 'Add Vehicle'}
@@ -207,9 +287,175 @@ function NewVehicleForm({ editId }: { editId?: string }) {
207
287
  />
208
288
  </div>
209
289
  </div>
290
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
291
+ <div className="space-y-2">
292
+ <Label htmlFor="ownershipType">Ownership</Label>
293
+ <Select
294
+ value={form.ownershipType || undefined}
295
+ onValueChange={(value) => setForm((prev) => ({ ...prev, ownershipType: value }))}
296
+ >
297
+ <SelectTrigger id="ownershipType">
298
+ <SelectValue placeholder="Select ownership" />
299
+ </SelectTrigger>
300
+ <SelectContent>
301
+ {OWNERSHIP_TYPE_OPTIONS.map((option) => (
302
+ <SelectItem key={option.value} value={option.value}>
303
+ {option.label}
304
+ </SelectItem>
305
+ ))}
306
+ </SelectContent>
307
+ </Select>
308
+ </div>
309
+ <div className="space-y-2">
310
+ <Label htmlFor="year">Year</Label>
311
+ <Input
312
+ id="year"
313
+ type="number"
314
+ min={1980}
315
+ max={new Date().getFullYear() + 1}
316
+ value={form.year}
317
+ onChange={(e) => setForm((prev) => ({ ...prev, year: e.target.value }))}
318
+ placeholder={String(new Date().getFullYear())}
319
+ />
320
+ </div>
321
+ <div className="space-y-2">
322
+ <Label htmlFor="vehicleStatus">Status</Label>
323
+ <Select
324
+ value={form.status}
325
+ onValueChange={(value) =>
326
+ setForm((prev) => ({ ...prev, status: value as VehicleStatus }))
327
+ }
328
+ >
329
+ <SelectTrigger id="vehicleStatus">
330
+ <SelectValue />
331
+ </SelectTrigger>
332
+ <SelectContent>
333
+ {VEHICLE_STATUS_OPTIONS.map((option) => (
334
+ <SelectItem key={option.value} value={option.value}>
335
+ {option.label}
336
+ </SelectItem>
337
+ ))}
338
+ </SelectContent>
339
+ </Select>
340
+ </div>
341
+ </div>
342
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
343
+ <div className="space-y-2">
344
+ <Label htmlFor="fuelType">Fuel Type</Label>
345
+ <Input
346
+ id="fuelType"
347
+ value={form.fuelType}
348
+ onChange={(e) => setForm((prev) => ({ ...prev, fuelType: e.target.value }))}
349
+ placeholder="Diesel"
350
+ />
351
+ </div>
352
+ <div className="space-y-2">
353
+ <Label htmlFor="fuelEfficiency">Fuel Efficiency (L/100km)</Label>
354
+ <Input
355
+ id="fuelEfficiency"
356
+ type="number"
357
+ min={0}
358
+ step={0.1}
359
+ value={form.fuelEfficiencyLPer100Km}
360
+ onChange={(e) =>
361
+ setForm((prev) => ({ ...prev, fuelEfficiencyLPer100Km: e.target.value }))
362
+ }
363
+ placeholder="12.5"
364
+ />
365
+ </div>
366
+ </div>
367
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
368
+ <div className="space-y-2">
369
+ <Label htmlFor="capacityWeight">Capacity — Weight (kg)</Label>
370
+ <Input
371
+ id="capacityWeight"
372
+ type="number"
373
+ min={0}
374
+ value={form.capacityWeight}
375
+ onChange={(e) => setForm((prev) => ({ ...prev, capacityWeight: e.target.value }))}
376
+ placeholder="5000"
377
+ />
378
+ </div>
379
+ <div className="space-y-2">
380
+ <Label htmlFor="capacityVolume">Capacity — Volume (m³)</Label>
381
+ <Input
382
+ id="capacityVolume"
383
+ type="number"
384
+ min={0}
385
+ step={0.1}
386
+ value={form.capacityVolume}
387
+ onChange={(e) => setForm((prev) => ({ ...prev, capacityVolume: e.target.value }))}
388
+ placeholder="18"
389
+ />
390
+ </div>
391
+ <div className="space-y-2">
392
+ <Label htmlFor="capacityPallets">Capacity — Pallets</Label>
393
+ <Input
394
+ id="capacityPallets"
395
+ type="number"
396
+ min={0}
397
+ value={form.capacityPallets}
398
+ onChange={(e) =>
399
+ setForm((prev) => ({ ...prev, capacityPallets: e.target.value }))
400
+ }
401
+ placeholder="12"
402
+ />
403
+ </div>
404
+ </div>
210
405
  </div>
211
406
  </EmphasisPanel>
407
+
408
+ {isEditing && (
409
+ <Card className="border-status-error-border">
410
+ <CardHeader>
411
+ <CardTitle className="flex items-center gap-2 text-status-error-text">
412
+ <Trash2 size={18} /> Delete Vehicle
413
+ </CardTitle>
414
+ </CardHeader>
415
+ <CardContent>
416
+ <p className="mb-3 text-sm text-text-secondary">
417
+ Removes this vehicle from the active fleet. It can no longer be assigned to drivers,
418
+ orders, or routes. This cannot be undone from here.
419
+ </p>
420
+ <Button
421
+ type="button"
422
+ variant="outline"
423
+ className="border-status-error-border text-status-error-text hover:bg-status-error-bg-subtle"
424
+ onClick={() => setDeleteOpen(true)}
425
+ >
426
+ <Trash2 size={16} /> Delete this vehicle
427
+ </Button>
428
+ </CardContent>
429
+ </Card>
430
+ )}
212
431
  </form>
432
+
433
+ <ResponsiveDialog open={deleteOpen} onOpenChange={setDeleteOpen}>
434
+ <ResponsiveDialogContent>
435
+ <ResponsiveDialogHeader>
436
+ <ResponsiveDialogTitle>Delete this vehicle?</ResponsiveDialogTitle>
437
+ <ResponsiveDialogDescription>
438
+ This removes {form.vehicleNumber || 'this vehicle'} from the active fleet. It cannot
439
+ be undone from here.
440
+ </ResponsiveDialogDescription>
441
+ </ResponsiveDialogHeader>
442
+ <div className="px-1">
443
+ <FormError message={deleteError} />
444
+ </div>
445
+ <ResponsiveDialogFooter>
446
+ <Button variant="outline" onClick={() => setDeleteOpen(false)} disabled={deleting}>
447
+ Cancel
448
+ </Button>
449
+ <Button
450
+ className="bg-status-error-text text-text-inverse hover:opacity-90"
451
+ onClick={handleDelete}
452
+ disabled={deleting}
453
+ >
454
+ {deleting ? 'Deleting...' : 'Delete vehicle'}
455
+ </Button>
456
+ </ResponsiveDialogFooter>
457
+ </ResponsiveDialogContent>
458
+ </ResponsiveDialog>
213
459
  </PageLayout>
214
460
  );
215
461
  }
@@ -245,7 +491,7 @@ export default function VehicleDetailsPage() {
245
491
  return (
246
492
  <PageLayout
247
493
  title={vehicle.vehicleNumber}
248
- subtitle={`${vehicle.make} ${vehicle.model} (${vehicle.year})`}
494
+ subtitle={`${vehicle.make} ${vehicle.model}${vehicle.year ? ` (${vehicle.year})` : ''}`}
249
495
  icon={<Truck size={24} />}
250
496
  headerActions={
251
497
  <div className="flex gap-2">
@@ -322,7 +568,7 @@ export default function VehicleDetailsPage() {
322
568
  </div>
323
569
  <div>
324
570
  <p className="text-sm text-text-secondary">Year</p>
325
- <p className="font-medium">{vehicle.year}</p>
571
+ <p className="font-medium">{vehicle.year ?? '—'}</p>
326
572
  </div>
327
573
  <div>
328
574
  <p className="text-sm text-text-secondary">License Plate</p>
@@ -394,6 +640,22 @@ export default function VehicleDetailsPage() {
394
640
  </p>
395
641
  </div>
396
642
  )}
643
+ {(vehicle.fuelType || vehicle.fuelEfficiencyLPer100Km !== undefined) && (
644
+ <div className="grid grid-cols-2 gap-4">
645
+ {vehicle.fuelType && (
646
+ <div>
647
+ <p className="text-sm text-text-secondary">Fuel Type</p>
648
+ <p className="font-medium">{vehicle.fuelType}</p>
649
+ </div>
650
+ )}
651
+ {vehicle.fuelEfficiencyLPer100Km !== undefined && (
652
+ <div>
653
+ <p className="text-sm text-text-secondary">Efficiency</p>
654
+ <p className="font-medium">{vehicle.fuelEfficiencyLPer100Km} L/100km</p>
655
+ </div>
656
+ )}
657
+ </div>
658
+ )}
397
659
  </CardContent>
398
660
  </Card>
399
661
 
@@ -11,24 +11,44 @@ import {
11
11
  CircleCheck,
12
12
  Route as RouteIcon,
13
13
  Wrench,
14
+ Filter,
14
15
  } from 'lucide-react';
15
16
  import { PageLayout } from '../components/PageLayout';
16
17
  import { MetricCard, MetricGrid } from '../components/MetricCard';
17
18
  import { DataTable, type Column } from '../components/DataTable';
18
19
  import { StatusBadge, VehicleTypeBadge } from '../components/StatusBadge';
19
- import { Progress } from '../components/ui';
20
+ import {
21
+ Progress,
22
+ Card,
23
+ CardContent,
24
+ Select,
25
+ SelectContent,
26
+ SelectItem,
27
+ SelectTrigger,
28
+ SelectValue,
29
+ Button,
30
+ } from '../components/ui';
20
31
  import { CTAOverflowMenu, PagePurpose } from '@burdenoff/fe-libs/ui';
21
32
  import { useVehicles, useFleetStats } from '../hooks/useFleet';
22
33
  import { useDebouncedValue } from '../hooks/useDebouncedValue';
23
34
  import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
24
35
  import { joinPath } from '../utils/navigation';
25
- import type { Vehicle } from '../types';
36
+ import { VEHICLE_STATUS_LABELS } from '../constants';
37
+ import type { Vehicle, VehicleStatus } from '../types';
38
+
39
+ const STATUS_OPTIONS: Array<{ value: VehicleStatus | 'all'; label: string }> = [
40
+ { value: 'all', label: 'All statuses' },
41
+ ...(Object.entries(VEHICLE_STATUS_LABELS) as Array<[VehicleStatus, string]>).map(
42
+ ([value, label]) => ({ value, label })
43
+ ),
44
+ ];
26
45
 
27
46
  export default function VehiclesPage() {
28
47
  const { basePath, navigate } = useMoveTheWheels();
29
48
  const [page, setPage] = useState(0);
30
49
  const [pageSize, setPageSize] = useState(25);
31
50
  const [search, setSearch] = useState('');
51
+ const [statusFilter, setStatusFilter] = useState<VehicleStatus | 'all'>('all');
32
52
  const debouncedSearch = useDebouncedValue(search);
33
53
  const {
34
54
  vehicles,
@@ -41,7 +61,9 @@ export default function VehiclesPage() {
41
61
  limit: pageSize,
42
62
  offset: page * pageSize,
43
63
  search: debouncedSearch || undefined,
64
+ status: statusFilter === 'all' ? undefined : statusFilter,
44
65
  });
66
+ const filtersActive = statusFilter !== 'all' || search.length > 0;
45
67
  // Fleet totals + tiles from the live aggregate, not the current page.
46
68
  const { stats } = useFleetStats();
47
69
  const totalVehicles = stats.totalVehicles;
@@ -74,7 +96,7 @@ export default function VehiclesPage() {
74
96
  <p className="font-medium">
75
97
  {row.make} {row.model}
76
98
  </p>
77
- <p className="text-sm text-text-secondary">{row.year}</p>
99
+ <p className="text-sm text-text-secondary">{row.year ?? '—'}</p>
78
100
  </div>
79
101
  ),
80
102
  },
@@ -178,6 +200,49 @@ export default function VehiclesPage() {
178
200
  </MetricGrid>
179
201
  </div>
180
202
 
203
+ {/* Filters */}
204
+ <Card>
205
+ <CardContent className="p-4">
206
+ <div className="flex flex-wrap items-center gap-4">
207
+ <div className="flex items-center gap-2">
208
+ <Filter size={16} className="text-text-secondary" />
209
+ <span className="text-sm font-medium">Filters:</span>
210
+ </div>
211
+ <Select
212
+ value={statusFilter}
213
+ onValueChange={(value) => {
214
+ setStatusFilter(value as VehicleStatus | 'all');
215
+ setPage(0);
216
+ }}
217
+ >
218
+ <SelectTrigger className="w-[180px]">
219
+ <SelectValue placeholder="Status" />
220
+ </SelectTrigger>
221
+ <SelectContent>
222
+ {STATUS_OPTIONS.map((option) => (
223
+ <SelectItem key={option.value} value={option.value}>
224
+ {option.label}
225
+ </SelectItem>
226
+ ))}
227
+ </SelectContent>
228
+ </Select>
229
+ {filtersActive && (
230
+ <Button
231
+ variant="ghost"
232
+ size="sm"
233
+ onClick={() => {
234
+ setStatusFilter('all');
235
+ setSearch('');
236
+ setPage(0);
237
+ }}
238
+ >
239
+ Clear filters
240
+ </Button>
241
+ )}
242
+ </div>
243
+ </CardContent>
244
+ </Card>
245
+
181
246
  <DataTable
182
247
  columns={columns}
183
248
  data={vehicles}