@burdenoff/microfe-movethewheels 2026.921.1 → 2026.923.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.
- package/dist/generated/wspace-types.d.ts +1676 -3
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/useFleet.js +4 -2
- package/dist/hooks/useOrders.js +89 -84
- package/dist/hooks/useRoutes.js +1 -1
- package/dist/index.js +6 -6
- package/dist/movethewheels/hooks/useOrders.d.ts +15 -0
- package/dist/movethewheels/hooks/useRoutes.d.ts +16 -0
- package/dist/movethewheels/types/index.d.ts +5 -0
- package/dist/pages/CreateOrderPage.js +266 -210
- package/dist/pages/OrderDetailsPage.js +305 -237
- package/dist/pages/RouteDetailsPage.js +247 -238
- package/package.json +1 -1
- package/src/generated/wspace-types.ts +1948 -3
- package/src/movethewheels/hooks/useFleet.ts +9 -2
- package/src/movethewheels/hooks/useOrders.ts +35 -0
- package/src/movethewheels/hooks/useRoutes.ts +1 -1
- package/src/movethewheels/pages/CreateOrderPage.tsx +84 -1
- package/src/movethewheels/pages/OrderDetailsPage.tsx +79 -10
- package/src/movethewheels/pages/RouteDetailsPage.tsx +14 -4
- package/src/movethewheels/types/index.ts +5 -0
|
@@ -533,7 +533,13 @@ export function useFleet(options: UseFleetOptions = {}): UseFleetResult {
|
|
|
533
533
|
// refetched) every render when the caller passes an inline filters object.
|
|
534
534
|
const filters = useMemo(
|
|
535
535
|
() => rawFilters,
|
|
536
|
-
[
|
|
536
|
+
[
|
|
537
|
+
rawFilters?.driverId,
|
|
538
|
+
rawFilters?.search,
|
|
539
|
+
rawFilters?.status,
|
|
540
|
+
rawFilters?.vehicleId,
|
|
541
|
+
rawFilters?.vehicleType,
|
|
542
|
+
]
|
|
537
543
|
);
|
|
538
544
|
const graphQLOptions = useGraphqlOptions();
|
|
539
545
|
const [vehicles, setVehicles] = useState<Vehicle[]>([]);
|
|
@@ -551,13 +557,14 @@ export function useFleet(options: UseFleetOptions = {}): UseFleetResult {
|
|
|
551
557
|
search: filters?.search,
|
|
552
558
|
type: filters?.vehicleType?.toUpperCase(),
|
|
553
559
|
status: filters?.status ? toApiVehicleStatus(filters.status) : undefined,
|
|
560
|
+
driverId: filters?.driverId,
|
|
554
561
|
},
|
|
555
562
|
pagination: { limit, offset: 0 },
|
|
556
563
|
}),
|
|
557
564
|
executeGraphQL<{ drivers: ApiDriver[] }>(graphQLOptions, LIST_DRIVERS_QUERY, {
|
|
558
565
|
filter: {
|
|
559
566
|
search: filters?.search,
|
|
560
|
-
vehicleId: filters?.
|
|
567
|
+
vehicleId: filters?.vehicleId,
|
|
561
568
|
},
|
|
562
569
|
pagination: { limit, offset: 0 },
|
|
563
570
|
}),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
2
|
import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
|
|
3
3
|
import type { Order, OrderFilter, OrderStatus } from '../types';
|
|
4
|
+
import { mapRoute } from './useRoutes';
|
|
4
5
|
import { executeGraphQL } from '../utils/graphqlClient';
|
|
5
6
|
|
|
6
7
|
interface UseOrdersOptions {
|
|
@@ -53,6 +54,21 @@ export interface ApiOrder {
|
|
|
53
54
|
scheduledDelivery?: string | null;
|
|
54
55
|
vehicleId?: string | null;
|
|
55
56
|
driverId?: string | null;
|
|
57
|
+
routeId?: string | null;
|
|
58
|
+
route?: {
|
|
59
|
+
id: string;
|
|
60
|
+
name: string;
|
|
61
|
+
status: string;
|
|
62
|
+
vehicleId?: string | null;
|
|
63
|
+
driverId?: string | null;
|
|
64
|
+
waypoints?: unknown;
|
|
65
|
+
estimatedDistance?: number | null;
|
|
66
|
+
estimatedDuration?: number | null;
|
|
67
|
+
fuelCost?: number | null;
|
|
68
|
+
actualDistance?: number | null;
|
|
69
|
+
actualDuration?: number | null;
|
|
70
|
+
createdAt: string;
|
|
71
|
+
} | null;
|
|
56
72
|
createdAt: string;
|
|
57
73
|
updatedAt: string;
|
|
58
74
|
customer?: {
|
|
@@ -85,6 +101,21 @@ const DELIVERY_JOB_FIELDS = `
|
|
|
85
101
|
scheduledDelivery
|
|
86
102
|
vehicleId
|
|
87
103
|
driverId
|
|
104
|
+
routeId
|
|
105
|
+
route {
|
|
106
|
+
id
|
|
107
|
+
name
|
|
108
|
+
status
|
|
109
|
+
vehicleId
|
|
110
|
+
driverId
|
|
111
|
+
waypoints
|
|
112
|
+
estimatedDistance
|
|
113
|
+
estimatedDuration
|
|
114
|
+
fuelCost
|
|
115
|
+
actualDistance
|
|
116
|
+
actualDuration
|
|
117
|
+
createdAt
|
|
118
|
+
}
|
|
88
119
|
createdAt
|
|
89
120
|
updatedAt
|
|
90
121
|
customer {
|
|
@@ -302,6 +333,8 @@ export function mapOrder(order: ApiOrder): Order {
|
|
|
302
333
|
scheduledDelivery: order.scheduledDelivery ? new Date(order.scheduledDelivery) : undefined,
|
|
303
334
|
vehicleId: order.vehicleId ?? undefined,
|
|
304
335
|
driverId: order.driverId ?? undefined,
|
|
336
|
+
routeId: order.routeId ?? undefined,
|
|
337
|
+
route: order.route ? mapRoute(order.route) : undefined,
|
|
305
338
|
createdAt: new Date(order.createdAt),
|
|
306
339
|
updatedAt: new Date(order.updatedAt),
|
|
307
340
|
};
|
|
@@ -409,6 +442,7 @@ export function useOrders(options: UseOrdersOptions = {}): UseOrdersResult {
|
|
|
409
442
|
scheduledDelivery: orderData.scheduledDelivery?.toISOString(),
|
|
410
443
|
vehicleId: orderData.vehicleId,
|
|
411
444
|
driverId: orderData.driverId,
|
|
445
|
+
routeId: orderData.routeId,
|
|
412
446
|
},
|
|
413
447
|
});
|
|
414
448
|
|
|
@@ -440,6 +474,7 @@ export function useOrders(options: UseOrdersOptions = {}): UseOrdersResult {
|
|
|
440
474
|
updates.scheduledDelivery === null ? null : updates.scheduledDelivery?.toISOString(),
|
|
441
475
|
vehicleId: updates.vehicleId,
|
|
442
476
|
driverId: updates.driverId,
|
|
477
|
+
routeId: updates.routeId,
|
|
443
478
|
},
|
|
444
479
|
});
|
|
445
480
|
|
|
@@ -6,7 +6,17 @@
|
|
|
6
6
|
|
|
7
7
|
import { useEffect, useState } from 'react';
|
|
8
8
|
import { useParams, useSearchParams } from 'react-router';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
Package,
|
|
11
|
+
ArrowLeft,
|
|
12
|
+
Save,
|
|
13
|
+
Plus,
|
|
14
|
+
Trash2,
|
|
15
|
+
Users,
|
|
16
|
+
MapPin,
|
|
17
|
+
CalendarClock,
|
|
18
|
+
Route as RouteIcon,
|
|
19
|
+
} from 'lucide-react';
|
|
10
20
|
import { PageLayout, EmptyState } from '../components/PageLayout';
|
|
11
21
|
import { FormError } from '../components/FormError';
|
|
12
22
|
import {
|
|
@@ -28,6 +38,7 @@ import {
|
|
|
28
38
|
import { EmphasisPanel, NextSteps, PagePurpose } from '@burdenoff/fe-libs/ui';
|
|
29
39
|
import { useOrder, useOrders } from '../hooks/useOrders';
|
|
30
40
|
import { useCustomer, useCustomers } from '../hooks/useCustomers';
|
|
41
|
+
import { useRoutes } from '../hooks/useRoutes';
|
|
31
42
|
import { useDebouncedValue } from '../hooks/useDebouncedValue';
|
|
32
43
|
import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
|
|
33
44
|
import { joinPath, buildCustomerCreatePath } from '../utils/navigation';
|
|
@@ -70,6 +81,14 @@ export default function CreateOrderPage() {
|
|
|
70
81
|
filters: { search: debouncedCustomerSearch || undefined },
|
|
71
82
|
});
|
|
72
83
|
const { customer: linkedCustomer } = useCustomer(prefilledCustomerId ?? order?.customerId);
|
|
84
|
+
const {
|
|
85
|
+
routes,
|
|
86
|
+
isLoading: routesLoading,
|
|
87
|
+
error: routesError,
|
|
88
|
+
} = useRoutes({
|
|
89
|
+
status: 'planned',
|
|
90
|
+
limit: 20,
|
|
91
|
+
});
|
|
73
92
|
|
|
74
93
|
const isEditing = !!orderId && !!order;
|
|
75
94
|
|
|
@@ -77,6 +96,7 @@ export default function CreateOrderPage() {
|
|
|
77
96
|
const [formData, setFormData] = useState({
|
|
78
97
|
customerId: prefilledCustomerId || order?.customerId || '',
|
|
79
98
|
priority: order?.priority || 'normal',
|
|
99
|
+
routeId: order?.routeId || '',
|
|
80
100
|
pickupAddress: {
|
|
81
101
|
street: order?.pickupAddress.street || '',
|
|
82
102
|
city: order?.pickupAddress.city || '',
|
|
@@ -121,6 +141,7 @@ export default function CreateOrderPage() {
|
|
|
121
141
|
setFormData({
|
|
122
142
|
customerId: order.customerId || '',
|
|
123
143
|
priority: order.priority || 'normal',
|
|
144
|
+
routeId: order.routeId || '',
|
|
124
145
|
pickupAddress: {
|
|
125
146
|
street: order.pickupAddress.street || '',
|
|
126
147
|
city: order.pickupAddress.city || '',
|
|
@@ -212,6 +233,7 @@ export default function CreateOrderPage() {
|
|
|
212
233
|
items: formData.items,
|
|
213
234
|
// `null` clears an existing slot on edit; the service field is nullable.
|
|
214
235
|
scheduledDelivery: formData.scheduledDelivery ? new Date(formData.scheduledDelivery) : null,
|
|
236
|
+
routeId: formData.routeId || undefined,
|
|
215
237
|
specialInstructions: formData.specialInstructions,
|
|
216
238
|
};
|
|
217
239
|
|
|
@@ -252,6 +274,35 @@ export default function CreateOrderPage() {
|
|
|
252
274
|
}));
|
|
253
275
|
};
|
|
254
276
|
|
|
277
|
+
const selectSavedRoute = (value: string) => {
|
|
278
|
+
if (value === 'none') {
|
|
279
|
+
updateField('routeId', '');
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
const route = routes.find((candidate) => candidate.id === value);
|
|
283
|
+
if (!route) return;
|
|
284
|
+
|
|
285
|
+
const pickup = route.stops.find((stop) => stop.type === 'pickup')?.address;
|
|
286
|
+
const delivery = [...route.stops].reverse().find((stop) => stop.type === 'delivery')?.address;
|
|
287
|
+
const mergeAddress = (current: typeof formData.pickupAddress, saved: typeof pickup) =>
|
|
288
|
+
saved
|
|
289
|
+
? {
|
|
290
|
+
street: current.street.trim() ? current.street : saved.street,
|
|
291
|
+
city: current.city.trim() ? current.city : saved.city,
|
|
292
|
+
state: current.state.trim() ? current.state : saved.state,
|
|
293
|
+
postalCode: current.postalCode.trim() ? current.postalCode : saved.postalCode,
|
|
294
|
+
country: current.country.trim() ? current.country : saved.country,
|
|
295
|
+
}
|
|
296
|
+
: current;
|
|
297
|
+
|
|
298
|
+
setFormData((previous) => ({
|
|
299
|
+
...previous,
|
|
300
|
+
routeId: route.id,
|
|
301
|
+
pickupAddress: mergeAddress(previous.pickupAddress, pickup),
|
|
302
|
+
deliveryAddress: mergeAddress(previous.deliveryAddress, delivery),
|
|
303
|
+
}));
|
|
304
|
+
};
|
|
305
|
+
|
|
255
306
|
const addItem = () => {
|
|
256
307
|
setFormData((prev) => ({
|
|
257
308
|
...prev,
|
|
@@ -404,6 +455,38 @@ export default function CreateOrderPage() {
|
|
|
404
455
|
</div>
|
|
405
456
|
</EmphasisPanel>
|
|
406
457
|
|
|
458
|
+
{/* Saved route — optional shortcut; manual addresses remain authoritative. */}
|
|
459
|
+
<Card>
|
|
460
|
+
<CardHeader>
|
|
461
|
+
<CardTitle className="flex items-center gap-2">
|
|
462
|
+
<RouteIcon size={18} />
|
|
463
|
+
Saved Route (Optional)
|
|
464
|
+
</CardTitle>
|
|
465
|
+
</CardHeader>
|
|
466
|
+
<CardContent className="space-y-2">
|
|
467
|
+
<Select value={formData.routeId || 'none'} onValueChange={selectSavedRoute}>
|
|
468
|
+
<SelectTrigger id="saved-route">
|
|
469
|
+
<SelectValue placeholder="Choose a saved route" />
|
|
470
|
+
</SelectTrigger>
|
|
471
|
+
<SelectContent>
|
|
472
|
+
<SelectItem value="none">No saved route</SelectItem>
|
|
473
|
+
{routes.map((route) => (
|
|
474
|
+
<SelectItem key={route.id} value={route.id}>
|
|
475
|
+
{route.name} · {route.stops.length} stops
|
|
476
|
+
</SelectItem>
|
|
477
|
+
))}
|
|
478
|
+
</SelectContent>
|
|
479
|
+
</Select>
|
|
480
|
+
<p className="text-xs text-text-secondary">
|
|
481
|
+
{routesLoading
|
|
482
|
+
? 'Loading planned routes…'
|
|
483
|
+
: routesError
|
|
484
|
+
? 'Saved routes are unavailable; enter pickup and delivery addresses manually.'
|
|
485
|
+
: 'A saved route fills any blank address fields. You can always edit both addresses below.'}
|
|
486
|
+
</p>
|
|
487
|
+
</CardContent>
|
|
488
|
+
</Card>
|
|
489
|
+
|
|
407
490
|
{/* Addresses */}
|
|
408
491
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
409
492
|
{/* Pickup Address */}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Displays detailed information about a specific order.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { useState } from 'react';
|
|
7
|
+
import { useEffect, useState } from 'react';
|
|
8
8
|
import { useParams } from 'react-router';
|
|
9
9
|
import {
|
|
10
10
|
Package,
|
|
@@ -99,19 +99,27 @@ export default function OrderDetailsPage() {
|
|
|
99
99
|
const { order, isLoading, error, refetch } = useOrder(orderId);
|
|
100
100
|
const { updateOrder, updateOrderStatus } = useOrders();
|
|
101
101
|
const [fleetSearch, setFleetSearch] = useState('');
|
|
102
|
-
const debouncedFleetSearch = useDebouncedValue(fleetSearch);
|
|
103
|
-
const { vehicles, drivers } = useFleet({
|
|
104
|
-
limit: 20,
|
|
105
|
-
filters: { search: debouncedFleetSearch || undefined },
|
|
106
|
-
});
|
|
107
|
-
const { message: notice, notify } = useNotice();
|
|
108
|
-
|
|
109
102
|
const [selectedVehicle, setSelectedVehicle] = useState('');
|
|
110
103
|
const [selectedDriver, setSelectedDriver] = useState('');
|
|
111
104
|
const [assigning, setAssigning] = useState(false);
|
|
112
105
|
const [advancing, setAdvancing] = useState(false);
|
|
113
106
|
const [actionError, setActionError] = useState<string | null>(null);
|
|
114
|
-
|
|
107
|
+
const debouncedFleetSearch = useDebouncedValue(fleetSearch);
|
|
108
|
+
const { vehicles, isLoading: vehiclesLoading } = useFleet({
|
|
109
|
+
limit: 20,
|
|
110
|
+
filters: {
|
|
111
|
+
search: debouncedFleetSearch || undefined,
|
|
112
|
+
driverId: selectedDriver || undefined,
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
const { drivers, isLoading: driversLoading } = useFleet({
|
|
116
|
+
limit: 20,
|
|
117
|
+
filters: {
|
|
118
|
+
search: debouncedFleetSearch || undefined,
|
|
119
|
+
vehicleId: selectedVehicle || undefined,
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
const { message: notice, notify } = useNotice();
|
|
115
123
|
const availableVehicles = vehicles.filter(
|
|
116
124
|
(vehicle) => vehicle.status === 'available' || vehicle.id === order?.vehicleId
|
|
117
125
|
);
|
|
@@ -119,6 +127,26 @@ export default function OrderDetailsPage() {
|
|
|
119
127
|
(driver) => driver.status === 'available' || driver.id === order?.driverId
|
|
120
128
|
);
|
|
121
129
|
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
if (
|
|
132
|
+
!driversLoading &&
|
|
133
|
+
selectedDriver &&
|
|
134
|
+
!drivers.some((driver) => driver.id === selectedDriver)
|
|
135
|
+
) {
|
|
136
|
+
setSelectedDriver('');
|
|
137
|
+
}
|
|
138
|
+
}, [drivers, driversLoading, selectedDriver]);
|
|
139
|
+
|
|
140
|
+
useEffect(() => {
|
|
141
|
+
if (
|
|
142
|
+
!vehiclesLoading &&
|
|
143
|
+
selectedVehicle &&
|
|
144
|
+
!vehicles.some((vehicle) => vehicle.id === selectedVehicle)
|
|
145
|
+
) {
|
|
146
|
+
setSelectedVehicle('');
|
|
147
|
+
}
|
|
148
|
+
}, [selectedVehicle, vehicles, vehiclesLoading]);
|
|
149
|
+
|
|
122
150
|
const handleAssign = async () => {
|
|
123
151
|
if (!orderId || (!selectedVehicle && !selectedDriver)) {
|
|
124
152
|
setActionError('Pick a vehicle and/or a driver to assign.');
|
|
@@ -194,7 +222,7 @@ export default function OrderDetailsPage() {
|
|
|
194
222
|
<ArrowLeft size={16} />
|
|
195
223
|
Back
|
|
196
224
|
</Button>
|
|
197
|
-
<Button variant="outline">
|
|
225
|
+
<Button variant="outline" onClick={() => window.print()}>
|
|
198
226
|
<Printer size={16} />
|
|
199
227
|
Print
|
|
200
228
|
</Button>
|
|
@@ -340,6 +368,47 @@ export default function OrderDetailsPage() {
|
|
|
340
368
|
</CardContent>
|
|
341
369
|
</Card>
|
|
342
370
|
|
|
371
|
+
{/* Saved route */}
|
|
372
|
+
<Card>
|
|
373
|
+
<CardHeader>
|
|
374
|
+
<CardTitle className="flex items-center gap-2">
|
|
375
|
+
<Truck size={18} />
|
|
376
|
+
Saved Route
|
|
377
|
+
</CardTitle>
|
|
378
|
+
</CardHeader>
|
|
379
|
+
<CardContent>
|
|
380
|
+
{order.route ? (
|
|
381
|
+
<div className="space-y-3">
|
|
382
|
+
<div className="flex items-center justify-between gap-3">
|
|
383
|
+
<div>
|
|
384
|
+
<p className="font-medium">{order.route.name}</p>
|
|
385
|
+
<p className="text-sm text-text-secondary">
|
|
386
|
+
{order.route.stops.length} stops ·{' '}
|
|
387
|
+
{order.route.status.replace('_', ' ').toLowerCase()}
|
|
388
|
+
</p>
|
|
389
|
+
</div>
|
|
390
|
+
<Badge variant="outline">Reusable route</Badge>
|
|
391
|
+
</div>
|
|
392
|
+
<div className="space-y-2">
|
|
393
|
+
{order.route.stops.map((stop, index) => (
|
|
394
|
+
<div key={stop.id} className="flex items-start gap-2 text-sm">
|
|
395
|
+
<span className="text-text-secondary">{index + 1}.</span>
|
|
396
|
+
<span>
|
|
397
|
+
<span className="font-medium capitalize">{stop.type}</span> ·{' '}
|
|
398
|
+
{formatAddress(stop.address)}
|
|
399
|
+
</span>
|
|
400
|
+
</div>
|
|
401
|
+
))}
|
|
402
|
+
</div>
|
|
403
|
+
</div>
|
|
404
|
+
) : (
|
|
405
|
+
<p className="text-sm text-text-secondary">
|
|
406
|
+
No saved route was selected for this order.
|
|
407
|
+
</p>
|
|
408
|
+
)}
|
|
409
|
+
</CardContent>
|
|
410
|
+
</Card>
|
|
411
|
+
|
|
343
412
|
{/* Order Items */}
|
|
344
413
|
<Card>
|
|
345
414
|
<CardHeader>
|
|
@@ -74,10 +74,6 @@ function NewRouteForm({ editId }: { editId?: string }) {
|
|
|
74
74
|
const { route } = useRoute(editId);
|
|
75
75
|
const [fleetSearch, setFleetSearch] = useState('');
|
|
76
76
|
const debouncedFleetSearch = useDebouncedValue(fleetSearch);
|
|
77
|
-
const { vehicles, drivers } = useFleet({
|
|
78
|
-
limit: 20,
|
|
79
|
-
filters: { search: debouncedFleetSearch || undefined },
|
|
80
|
-
});
|
|
81
77
|
const isEditing = !!editId;
|
|
82
78
|
const [form, setForm] = useState<{
|
|
83
79
|
name: string;
|
|
@@ -92,6 +88,20 @@ function NewRouteForm({ editId }: { editId?: string }) {
|
|
|
92
88
|
driverId: '',
|
|
93
89
|
stops: [{ address: '', type: 'delivery' }],
|
|
94
90
|
});
|
|
91
|
+
const { vehicles } = useFleet({
|
|
92
|
+
limit: 20,
|
|
93
|
+
filters: {
|
|
94
|
+
search: debouncedFleetSearch || undefined,
|
|
95
|
+
driverId: form.driverId || undefined,
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
const { drivers } = useFleet({
|
|
99
|
+
limit: 20,
|
|
100
|
+
filters: {
|
|
101
|
+
search: debouncedFleetSearch || undefined,
|
|
102
|
+
vehicleId: form.vehicleId || undefined,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
95
105
|
// The selected vehicle/driver may fall outside the current search page (e.g. when
|
|
96
106
|
// editing a route or after the assignee no longer matches the search term); fetch
|
|
97
107
|
// them directly so the Select can still render the current selection.
|
|
@@ -280,6 +280,8 @@ export interface Order {
|
|
|
280
280
|
actualDelivery?: Date;
|
|
281
281
|
driverId?: string;
|
|
282
282
|
vehicleId?: string;
|
|
283
|
+
routeId?: string;
|
|
284
|
+
route?: Route;
|
|
283
285
|
trackingNumber: string;
|
|
284
286
|
specialInstructions?: string;
|
|
285
287
|
pricing: OrderPricing;
|
|
@@ -757,7 +759,10 @@ export interface OrderFilter {
|
|
|
757
759
|
export interface FleetFilter {
|
|
758
760
|
vehicleType?: VehicleType;
|
|
759
761
|
status?: VehicleStatus;
|
|
762
|
+
/** Filter vehicles to those linked to this driver. */
|
|
760
763
|
driverId?: string;
|
|
764
|
+
/** Filter drivers to those linked to this vehicle. */
|
|
765
|
+
vehicleId?: string;
|
|
761
766
|
search?: string;
|
|
762
767
|
}
|
|
763
768
|
|