@burdenoff/microfe-movethewheels 2026.510.105

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 (208) hide show
  1. package/README.md +82 -0
  2. package/dist/AIAssistantPage-hD0VYJdH.js +210 -0
  3. package/dist/AnalyticsPage-DHTHCUtr.js +201 -0
  4. package/dist/CreateOrderPage-Cprg4Y9V.js +471 -0
  5. package/dist/CustomerDetailsPage-DNDEw7IW.js +239 -0
  6. package/dist/CustomersPage-CDjjeCEL.js +119 -0
  7. package/dist/DashboardPage-8iTPXRAG.js +374 -0
  8. package/dist/DataTable-CRIKfdIN.js +239 -0
  9. package/dist/DriverDetailsPage-CRyRCno7.js +297 -0
  10. package/dist/DriversPage-16O8fVmf.js +127 -0
  11. package/dist/FinancePage-BYUxK5dR.js +154 -0
  12. package/dist/FleetPage-CHYETCWT.js +293 -0
  13. package/dist/ImportExportPage-C3MKKxfc.js +232 -0
  14. package/dist/InventoryPage--822AxZM.js +223 -0
  15. package/dist/LiveTrackingPage-Dp3rTJDr.js +332 -0
  16. package/dist/MarketplacePage-DjEqudfM.js +192 -0
  17. package/dist/MetricCard-GTbxAk1a.js +135 -0
  18. package/dist/OrderDetailsPage-BIuYG0ub.js +398 -0
  19. package/dist/OrdersListPage-CW5V0Uvh.js +257 -0
  20. package/dist/PageLayout-B7b0vl0R.js +1894 -0
  21. package/dist/ProductDetailsPage-Q3X7AT-7.js +168 -0
  22. package/dist/ProductsPage-CUj9JpnW.js +131 -0
  23. package/dist/ReportsPage-DblO5CdJ.js +227 -0
  24. package/dist/RouteDetailsPage-CLctgk6A.js +240 -0
  25. package/dist/RoutesPage-8hrv6RWT.js +116 -0
  26. package/dist/SettingsPage-BJ5BQeqn.js +247 -0
  27. package/dist/StatusBadge-BrrwraIA.js +206 -0
  28. package/dist/TrackingPage-BGqHDh-w.js +322 -0
  29. package/dist/VehicleDetailsPage-XnDH4iQR.js +194 -0
  30. package/dist/VehiclesPage-Cs4XxHkA.js +127 -0
  31. package/dist/WarehouseDetailsPage-GemdMvr_.js +215 -0
  32. package/dist/WarehousesPage-QTiuDuXy.js +121 -0
  33. package/dist/arrow-left-6CiLhqVp.js +11 -0
  34. package/dist/box-BunB_4UH.js +18 -0
  35. package/dist/chart-column-DWwVEVQ-.js +22 -0
  36. package/dist/chevron-right-DhZVf20o.js +8 -0
  37. package/dist/circle-alert-D5f6RZxt.js +26 -0
  38. package/dist/circle-check-big-D-JMHcTe.js +11 -0
  39. package/dist/clock-CvwBKbQP.js +13 -0
  40. package/dist/dev/main.d.ts +1 -0
  41. package/dist/dollar-sign-CP9qeU5d.js +14 -0
  42. package/dist/download-CIuG04pJ.js +21 -0
  43. package/dist/file-text-Dd_thxkn.js +26 -0
  44. package/dist/filter-DyRMX9CU.js +8 -0
  45. package/dist/formatters-_vJlC-47.js +50 -0
  46. package/dist/generated/global-operations.d.ts +1 -0
  47. package/dist/generated/global-types.d.ts +20715 -0
  48. package/dist/generated/wspace-operations.d.ts +3704 -0
  49. package/dist/generated/wspace-types.d.ts +53362 -0
  50. package/dist/graphqlClient-CdJyR_ed.js +55 -0
  51. package/dist/index.d.ts +4 -0
  52. package/dist/index.js +772 -0
  53. package/dist/map-BqH1cBJi.js +18 -0
  54. package/dist/map-pin-CFBOmh-A.js +13 -0
  55. package/dist/movethewheels/MoveTheWheelsRoot.d.ts +25 -0
  56. package/dist/movethewheels/MoveTheWheelsRoutes.d.ts +7 -0
  57. package/dist/movethewheels/components/DataTable.d.ts +32 -0
  58. package/dist/movethewheels/components/MetricCard.d.ts +43 -0
  59. package/dist/movethewheels/components/PageLayout.d.ts +68 -0
  60. package/dist/movethewheels/components/StatusBadge.d.ts +49 -0
  61. package/dist/movethewheels/components/index.d.ts +10 -0
  62. package/dist/movethewheels/components/ui.d.ts +22 -0
  63. package/dist/movethewheels/constants/index.d.ts +24 -0
  64. package/dist/movethewheels/constants/mockData.d.ts +33 -0
  65. package/dist/movethewheels/hooks/index.d.ts +12 -0
  66. package/dist/movethewheels/hooks/useAnalytics.d.ts +118 -0
  67. package/dist/movethewheels/hooks/useCustomers.d.ts +37 -0
  68. package/dist/movethewheels/hooks/useFleet.d.ts +71 -0
  69. package/dist/movethewheels/hooks/useInventory.d.ts +60 -0
  70. package/dist/movethewheels/hooks/useOrders.d.ts +47 -0
  71. package/dist/movethewheels/hooks/useRoutes.d.ts +41 -0
  72. package/dist/movethewheels/hooks/useTracking.d.ts +69 -0
  73. package/dist/movethewheels/index.d.ts +30 -0
  74. package/dist/movethewheels/pages/AIAssistantPage.d.ts +4 -0
  75. package/dist/movethewheels/pages/AnalyticsPage.d.ts +4 -0
  76. package/dist/movethewheels/pages/CreateOrderPage.d.ts +6 -0
  77. package/dist/movethewheels/pages/CustomerDetailsPage.d.ts +4 -0
  78. package/dist/movethewheels/pages/CustomersPage.d.ts +4 -0
  79. package/dist/movethewheels/pages/DashboardPage.d.ts +6 -0
  80. package/dist/movethewheels/pages/DriverDetailsPage.d.ts +4 -0
  81. package/dist/movethewheels/pages/DriversPage.d.ts +4 -0
  82. package/dist/movethewheels/pages/FinancePage.d.ts +4 -0
  83. package/dist/movethewheels/pages/FleetPage.d.ts +6 -0
  84. package/dist/movethewheels/pages/ImportExportPage.d.ts +4 -0
  85. package/dist/movethewheels/pages/InventoryPage.d.ts +4 -0
  86. package/dist/movethewheels/pages/LiveTrackingPage.d.ts +6 -0
  87. package/dist/movethewheels/pages/MarketplacePage.d.ts +4 -0
  88. package/dist/movethewheels/pages/OrderDetailsPage.d.ts +6 -0
  89. package/dist/movethewheels/pages/OrdersListPage.d.ts +6 -0
  90. package/dist/movethewheels/pages/ProductDetailsPage.d.ts +4 -0
  91. package/dist/movethewheels/pages/ProductsPage.d.ts +4 -0
  92. package/dist/movethewheels/pages/ReportsPage.d.ts +4 -0
  93. package/dist/movethewheels/pages/RouteDetailsPage.d.ts +4 -0
  94. package/dist/movethewheels/pages/RoutesPage.d.ts +4 -0
  95. package/dist/movethewheels/pages/SettingsPage.d.ts +4 -0
  96. package/dist/movethewheels/pages/TrackingPage.d.ts +6 -0
  97. package/dist/movethewheels/pages/VehicleDetailsPage.d.ts +4 -0
  98. package/dist/movethewheels/pages/VehiclesPage.d.ts +4 -0
  99. package/dist/movethewheels/pages/WarehouseDetailsPage.d.ts +4 -0
  100. package/dist/movethewheels/pages/WarehousesPage.d.ts +4 -0
  101. package/dist/movethewheels/providers/MoveTheWheelsProvider.d.ts +16 -0
  102. package/dist/movethewheels/store/movethewheelsStore.d.ts +73 -0
  103. package/dist/movethewheels/types/index.d.ts +655 -0
  104. package/dist/movethewheels/utils/cn.d.ts +6 -0
  105. package/dist/movethewheels/utils/formatters.d.ts +60 -0
  106. package/dist/movethewheels/utils/graphqlClient.d.ts +11 -0
  107. package/dist/movethewheels/utils/index.d.ts +7 -0
  108. package/dist/movethewheels/utils/navigation.d.ts +23 -0
  109. package/dist/navigation-BgnOfsVd.js +6 -0
  110. package/dist/navigation-C2fY_aS9.js +8 -0
  111. package/dist/package-DVZbDRcV.js +22 -0
  112. package/dist/phone-KdwpVmC4.js +18 -0
  113. package/dist/plus-Bl7uX6Ji.js +11 -0
  114. package/dist/refresh-cw-BYjl3K-8.js +22 -0
  115. package/dist/route-Ce_poKFi.js +51 -0
  116. package/dist/save-C-qDVat-.js +18 -0
  117. package/dist/search-5pdn5eOO.js +13 -0
  118. package/dist/settings-C4kIDsYg.js +28 -0
  119. package/dist/square-pen-BwQ67vLE.js +11 -0
  120. package/dist/star-BlVsC3Ad.js +8 -0
  121. package/dist/store-DTmQT5M0.js +26 -0
  122. package/dist/trending-up-C1faflCI.js +11 -0
  123. package/dist/triangle-alert-CUoVAA4L.js +18 -0
  124. package/dist/truck-BmDAzu05.js +30 -0
  125. package/dist/useAnalytics-ph7eTIK6.js +297 -0
  126. package/dist/useCustomers-bS3a4ytk.js +186 -0
  127. package/dist/useFleet-BdETplNE.js +398 -0
  128. package/dist/useInventory-Dwn18FPz.js +323 -0
  129. package/dist/useOrders-D_3_hGMp.js +324 -0
  130. package/dist/useRoutes-v4aBaS-E.js +224 -0
  131. package/dist/useTracking-De2KIUNu.js +261 -0
  132. package/dist/user-BplzDrLP.js +13 -0
  133. package/dist/users-i-igmsP4.js +24 -0
  134. package/dist/warehouse-DewG0PXh.js +25 -0
  135. package/dist/wrench-CoSDEIC7.js +31 -0
  136. package/package.json +107 -0
  137. package/src/dev/main.tsx +110 -0
  138. package/src/dev/styles.css +139 -0
  139. package/src/generated/global-operations.ts +2 -0
  140. package/src/generated/global-types.ts +24048 -0
  141. package/src/generated/wspace-operations.ts +3734 -0
  142. package/src/generated/wspace-types.ts +60715 -0
  143. package/src/index.ts +4 -0
  144. package/src/movethewheels/MoveTheWheelsRoot.tsx +258 -0
  145. package/src/movethewheels/MoveTheWheelsRoutes.tsx +119 -0
  146. package/src/movethewheels/components/DataTable.tsx +367 -0
  147. package/src/movethewheels/components/MetricCard.tsx +180 -0
  148. package/src/movethewheels/components/PageLayout.tsx +234 -0
  149. package/src/movethewheels/components/StatusBadge.tsx +243 -0
  150. package/src/movethewheels/components/index.ts +26 -0
  151. package/src/movethewheels/components/ui.tsx +124 -0
  152. package/src/movethewheels/constants/index.ts +65 -0
  153. package/src/movethewheels/constants/mockData.ts +1342 -0
  154. package/src/movethewheels/hooks/index.ts +55 -0
  155. package/src/movethewheels/hooks/useAnalytics.ts +476 -0
  156. package/src/movethewheels/hooks/useCustomers.ts +359 -0
  157. package/src/movethewheels/hooks/useFleet.ts +778 -0
  158. package/src/movethewheels/hooks/useInventory.ts +632 -0
  159. package/src/movethewheels/hooks/useOrders.ts +703 -0
  160. package/src/movethewheels/hooks/useRoutes.ts +453 -0
  161. package/src/movethewheels/hooks/useTracking.ts +505 -0
  162. package/src/movethewheels/index.ts +68 -0
  163. package/src/movethewheels/pages/AIAssistantPage.tsx +160 -0
  164. package/src/movethewheels/pages/AnalyticsPage.tsx +190 -0
  165. package/src/movethewheels/pages/CreateOrderPage.tsx +454 -0
  166. package/src/movethewheels/pages/CustomerDetailsPage.tsx +207 -0
  167. package/src/movethewheels/pages/CustomersPage.tsx +115 -0
  168. package/src/movethewheels/pages/DashboardPage.tsx +414 -0
  169. package/src/movethewheels/pages/DriverDetailsPage.tsx +261 -0
  170. package/src/movethewheels/pages/DriversPage.tsx +118 -0
  171. package/src/movethewheels/pages/FinancePage.tsx +141 -0
  172. package/src/movethewheels/pages/FleetPage.tsx +289 -0
  173. package/src/movethewheels/pages/ImportExportPage.tsx +165 -0
  174. package/src/movethewheels/pages/InventoryPage.tsx +212 -0
  175. package/src/movethewheels/pages/LiveTrackingPage.tsx +325 -0
  176. package/src/movethewheels/pages/MarketplacePage.tsx +235 -0
  177. package/src/movethewheels/pages/OrderDetailsPage.tsx +387 -0
  178. package/src/movethewheels/pages/OrdersListPage.tsx +241 -0
  179. package/src/movethewheels/pages/ProductDetailsPage.tsx +155 -0
  180. package/src/movethewheels/pages/ProductsPage.tsx +124 -0
  181. package/src/movethewheels/pages/ReportsPage.tsx +164 -0
  182. package/src/movethewheels/pages/RouteDetailsPage.tsx +245 -0
  183. package/src/movethewheels/pages/RoutesPage.tsx +104 -0
  184. package/src/movethewheels/pages/SettingsPage.tsx +242 -0
  185. package/src/movethewheels/pages/TrackingPage.tsx +419 -0
  186. package/src/movethewheels/pages/VehicleDetailsPage.tsx +218 -0
  187. package/src/movethewheels/pages/VehiclesPage.tsx +124 -0
  188. package/src/movethewheels/pages/WarehouseDetailsPage.tsx +216 -0
  189. package/src/movethewheels/pages/WarehousesPage.tsx +122 -0
  190. package/src/movethewheels/providers/MoveTheWheelsProvider.tsx +66 -0
  191. package/src/movethewheels/store/movethewheelsStore.ts +136 -0
  192. package/src/movethewheels/types/index.ts +744 -0
  193. package/src/movethewheels/utils/cn.ts +9 -0
  194. package/src/movethewheels/utils/formatters.ts +215 -0
  195. package/src/movethewheels/utils/graphqlClient.ts +63 -0
  196. package/src/movethewheels/utils/index.ts +8 -0
  197. package/src/movethewheels/utils/navigation.ts +70 -0
  198. package/src/operations/global/.gitkeep +0 -0
  199. package/src/operations/wspace/movethewheels/fragments/core.graphql +191 -0
  200. package/src/operations/wspace/movethewheels/mutations/entities.graphql +87 -0
  201. package/src/operations/wspace/movethewheels/mutations/logistics.graphql +86 -0
  202. package/src/operations/wspace/movethewheels/mutations/marketplace-reports.graphql +81 -0
  203. package/src/operations/wspace/movethewheels/mutations/orders.graphql +21 -0
  204. package/src/operations/wspace/movethewheels/queries/dashboard.graphql +61 -0
  205. package/src/operations/wspace/movethewheels/queries/entities.graphql +83 -0
  206. package/src/operations/wspace/movethewheels/queries/logistics.graphql +84 -0
  207. package/src/operations/wspace/movethewheels/queries/marketplace-reports.graphql +40 -0
  208. package/src/operations/wspace/movethewheels/queries/orders.graphql +43 -0
@@ -0,0 +1,778 @@
1
+ import { useCallback, useEffect, useMemo, useState } from 'react';
2
+ import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
3
+ import type { Driver, DriverStatus, FleetFilter, Vehicle, VehicleStatus } from '../types';
4
+ import { executeGraphQL } from '../utils/graphqlClient';
5
+
6
+ interface UseFleetOptions {
7
+ filters?: FleetFilter;
8
+ }
9
+
10
+ interface UseFleetResult {
11
+ vehicles: Vehicle[];
12
+ drivers: Driver[];
13
+ totalVehicles: number;
14
+ totalDrivers: number;
15
+ isLoading: boolean;
16
+ error: Error | null;
17
+ refetch: () => void;
18
+ }
19
+
20
+ interface ApiVehicle {
21
+ id: string;
22
+ vehicleNumber: string;
23
+ type: string;
24
+ make?: string | null;
25
+ model?: string | null;
26
+ year?: number | null;
27
+ capacity?: Record<string, unknown> | null;
28
+ status: string;
29
+ currentLocation?: Record<string, unknown> | null;
30
+ fuelLevel?: number | null;
31
+ mileage?: number | null;
32
+ createdAt: string;
33
+ updatedAt?: string;
34
+ }
35
+
36
+ interface ApiDriver {
37
+ id: string;
38
+ userId?: string | null;
39
+ firstName: string;
40
+ lastName: string;
41
+ employeeId: string;
42
+ licenseNumber?: string | null;
43
+ licenseClass?: string | null;
44
+ licenseExpiry?: string | null;
45
+ status: string;
46
+ currentLocation?: Record<string, unknown> | null;
47
+ rating?: number | null;
48
+ vehicleId?: string | null;
49
+ createdAt: string;
50
+ }
51
+
52
+ const LIST_VEHICLES_QUERY = `
53
+ query ListVehicles($filter: VehicleFilterInput, $pagination: PaginationInput) {
54
+ vehicles(filter: $filter, pagination: $pagination) {
55
+ id
56
+ vehicleNumber
57
+ type
58
+ make
59
+ model
60
+ year
61
+ capacity
62
+ status
63
+ currentLocation
64
+ fuelLevel
65
+ mileage
66
+ createdAt
67
+ updatedAt
68
+ }
69
+ }
70
+ `;
71
+
72
+ const LIST_DRIVERS_QUERY = `
73
+ query ListDrivers($filter: DriverFilterInput, $pagination: PaginationInput) {
74
+ drivers(filter: $filter, pagination: $pagination) {
75
+ id
76
+ userId
77
+ firstName
78
+ lastName
79
+ employeeId
80
+ licenseNumber
81
+ licenseClass
82
+ licenseExpiry
83
+ status
84
+ currentLocation
85
+ rating
86
+ vehicleId
87
+ createdAt
88
+ }
89
+ }
90
+ `;
91
+
92
+ const GET_VEHICLE_QUERY = `
93
+ query GetVehicle($id: ID!) {
94
+ vehicle(id: $id) {
95
+ id
96
+ vehicleNumber
97
+ type
98
+ make
99
+ model
100
+ year
101
+ capacity
102
+ status
103
+ currentLocation
104
+ fuelLevel
105
+ mileage
106
+ createdAt
107
+ updatedAt
108
+ }
109
+ }
110
+ `;
111
+
112
+ const GET_DRIVER_QUERY = `
113
+ query GetDriver($id: ID!) {
114
+ driver(id: $id) {
115
+ id
116
+ userId
117
+ firstName
118
+ lastName
119
+ employeeId
120
+ licenseNumber
121
+ licenseClass
122
+ licenseExpiry
123
+ status
124
+ currentLocation
125
+ rating
126
+ vehicleId
127
+ createdAt
128
+ }
129
+ }
130
+ `;
131
+
132
+ const UPDATE_VEHICLE_STATUS_MUTATION = `
133
+ mutation UpdateVehicleStatus($id: ID!, $status: VehicleStatus!) {
134
+ updateVehicleStatus(id: $id, status: $status) {
135
+ id
136
+ vehicleNumber
137
+ type
138
+ make
139
+ model
140
+ year
141
+ capacity
142
+ status
143
+ currentLocation
144
+ fuelLevel
145
+ mileage
146
+ createdAt
147
+ updatedAt
148
+ }
149
+ }
150
+ `;
151
+
152
+ const ASSIGN_DRIVER_VEHICLE_MUTATION = `
153
+ mutation AssignDriverVehicle($id: ID!, $vehicleId: ID) {
154
+ assignDriverVehicle(id: $id, vehicleId: $vehicleId) {
155
+ id
156
+ userId
157
+ firstName
158
+ lastName
159
+ employeeId
160
+ licenseNumber
161
+ licenseClass
162
+ licenseExpiry
163
+ status
164
+ currentLocation
165
+ rating
166
+ vehicleId
167
+ createdAt
168
+ }
169
+ }
170
+ `;
171
+
172
+ const UPDATE_DRIVER_STATUS_MUTATION = `
173
+ mutation UpdateDriverStatus($id: ID!, $status: DriverStatus!) {
174
+ updateDriverStatus(id: $id, status: $status) {
175
+ id
176
+ userId
177
+ firstName
178
+ lastName
179
+ employeeId
180
+ licenseNumber
181
+ licenseClass
182
+ licenseExpiry
183
+ status
184
+ currentLocation
185
+ rating
186
+ vehicleId
187
+ createdAt
188
+ }
189
+ }
190
+ `;
191
+
192
+ const FLEET_STATS_QUERY = `
193
+ query GetFleetStats {
194
+ fleetStats {
195
+ totalVehicles
196
+ activeVehicles
197
+ inTransitVehicles
198
+ maintenanceVehicles
199
+ totalDrivers
200
+ availableDrivers
201
+ onDeliveryDrivers
202
+ }
203
+ }
204
+ `;
205
+
206
+ function mapVehicleStatus(status: string): VehicleStatus {
207
+ switch (status) {
208
+ case 'ACTIVE':
209
+ return 'available';
210
+ case 'IN_TRANSIT':
211
+ return 'assigned';
212
+ case 'MAINTENANCE':
213
+ return 'maintenance';
214
+ default:
215
+ return 'out_of_service';
216
+ }
217
+ }
218
+
219
+ function toApiVehicleStatus(status: VehicleStatus): string {
220
+ switch (status) {
221
+ case 'available':
222
+ return 'ACTIVE';
223
+ case 'assigned':
224
+ return 'IN_TRANSIT';
225
+ case 'maintenance':
226
+ return 'MAINTENANCE';
227
+ default:
228
+ return 'INACTIVE';
229
+ }
230
+ }
231
+
232
+ function mapDriverStatus(status: string): DriverStatus {
233
+ switch (status) {
234
+ case 'AVAILABLE':
235
+ return 'available';
236
+ case 'ON_DELIVERY':
237
+ return 'busy';
238
+ case 'ON_BREAK':
239
+ return 'on_break';
240
+ default:
241
+ return 'offline';
242
+ }
243
+ }
244
+
245
+ function toApiDriverStatus(status: DriverStatus): string {
246
+ switch (status) {
247
+ case 'available':
248
+ return 'AVAILABLE';
249
+ case 'busy':
250
+ return 'ON_DELIVERY';
251
+ case 'on_break':
252
+ return 'ON_BREAK';
253
+ default:
254
+ return 'OFF_DUTY';
255
+ }
256
+ }
257
+
258
+ function mapVehicle(vehicle: ApiVehicle): Vehicle {
259
+ return {
260
+ id: vehicle.id,
261
+ vehicleNumber: vehicle.vehicleNumber,
262
+ type: (vehicle.type?.toLowerCase() ?? 'van') as Vehicle['type'],
263
+ make: vehicle.make ?? '',
264
+ model: vehicle.model ?? '',
265
+ year: vehicle.year ?? new Date().getFullYear(),
266
+ capacity: {
267
+ weight: 0,
268
+ volume: 0,
269
+ ...(vehicle.capacity ?? {}),
270
+ },
271
+ status: mapVehicleStatus(vehicle.status),
272
+ driverId: undefined,
273
+ currentLocation: vehicle.currentLocation
274
+ ? {
275
+ latitude: Number((vehicle.currentLocation.latitude as number | undefined) ?? 0),
276
+ longitude: Number((vehicle.currentLocation.longitude as number | undefined) ?? 0),
277
+ address: (vehicle.currentLocation.address as string | undefined) ?? undefined,
278
+ timestamp: new Date(),
279
+ }
280
+ : undefined,
281
+ lastMaintenance: undefined,
282
+ nextMaintenance: undefined,
283
+ fuelLevel: vehicle.fuelLevel ?? undefined,
284
+ mileage: vehicle.mileage ?? undefined,
285
+ documents: [],
286
+ createdAt: new Date(vehicle.createdAt),
287
+ };
288
+ }
289
+
290
+ function mapDriver(driver: ApiDriver): Driver {
291
+ return {
292
+ id: driver.id,
293
+ userId: driver.userId ?? driver.id,
294
+ fullName: `${driver.firstName} ${driver.lastName}`.trim(),
295
+ employeeId: driver.employeeId,
296
+ licenseNumber: driver.licenseNumber ?? '',
297
+ licenseType: driver.licenseClass ?? 'standard',
298
+ licenseExpiry: driver.licenseExpiry ? new Date(driver.licenseExpiry) : new Date(),
299
+ vehicleIds: driver.vehicleId ? [driver.vehicleId] : [],
300
+ assignedVehicle: driver.vehicleId ?? undefined,
301
+ status: mapDriverStatus(driver.status),
302
+ currentLocation: driver.currentLocation
303
+ ? {
304
+ latitude: Number((driver.currentLocation.latitude as number | undefined) ?? 0),
305
+ longitude: Number((driver.currentLocation.longitude as number | undefined) ?? 0),
306
+ address: (driver.currentLocation.address as string | undefined) ?? undefined,
307
+ timestamp: new Date(),
308
+ }
309
+ : undefined,
310
+ joinDate: new Date(driver.createdAt),
311
+ baseSalary: 0,
312
+ completedOrders: 0,
313
+ todayOrders: 0,
314
+ specializations: [],
315
+ workingHours: {
316
+ startTime: '09:00',
317
+ endTime: '18:00',
318
+ workingDays: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
319
+ maxHoursPerDay: 8,
320
+ maxHoursPerWeek: 40,
321
+ currentHoursToday: 0,
322
+ currentHoursThisWeek: 0,
323
+ },
324
+ ratings: {
325
+ overall: driver.rating ?? 0,
326
+ punctuality: driver.rating ?? 0,
327
+ communication: driver.rating ?? 0,
328
+ carefulHandling: driver.rating ?? 0,
329
+ professionalism: driver.rating ?? 0,
330
+ onTimeDelivery: driver.rating ?? 0,
331
+ totalRatings: 0,
332
+ },
333
+ documents: [],
334
+ earnings: {
335
+ totalEarnings: 0,
336
+ weeklyEarnings: 0,
337
+ monthlyEarnings: 0,
338
+ pendingPayments: 0,
339
+ completedDeliveries: 0,
340
+ bonuses: 0,
341
+ },
342
+ compliance: {
343
+ hoursOfService: true,
344
+ documentation: true,
345
+ vehicleInspection: true,
346
+ lastUpdate: new Date(),
347
+ },
348
+ createdAt: new Date(driver.createdAt),
349
+ };
350
+ }
351
+
352
+ function useGraphqlOptions() {
353
+ const { apiGatewayUrl, authToken, workspaceToken, workspaceId, tenantId, currentUser } =
354
+ useMoveTheWheels();
355
+ return useMemo(
356
+ () => ({
357
+ apiGatewayUrl,
358
+ authToken,
359
+ workspaceToken,
360
+ workspaceId,
361
+ tenantId,
362
+ actorId: currentUser?.id,
363
+ }),
364
+ [apiGatewayUrl, authToken, workspaceToken, workspaceId, tenantId, currentUser?.id]
365
+ );
366
+ }
367
+
368
+ export function useFleet(options: UseFleetOptions = {}): UseFleetResult {
369
+ const { filters: rawFilters } = options;
370
+ // Stabilize filters reference for React Compiler memoization.
371
+ const filters = useMemo(
372
+ () => rawFilters,
373
+ [rawFilters?.driverId, rawFilters?.status, rawFilters?.vehicleType]
374
+ );
375
+ const graphQLOptions = useGraphqlOptions();
376
+ const [vehicles, setVehicles] = useState<Vehicle[]>([]);
377
+ const [drivers, setDrivers] = useState<Driver[]>([]);
378
+ const [isLoading, setIsLoading] = useState(false);
379
+ const [error, setError] = useState<Error | null>(null);
380
+
381
+ const load = useCallback(async () => {
382
+ setIsLoading(true);
383
+ setError(null);
384
+ try {
385
+ const [vehicleData, driverData] = await Promise.all([
386
+ executeGraphQL<{ vehicles: ApiVehicle[] }>(graphQLOptions, LIST_VEHICLES_QUERY, {
387
+ filter: {
388
+ type: filters?.vehicleType?.toUpperCase(),
389
+ status: filters?.status ? toApiVehicleStatus(filters.status) : undefined,
390
+ },
391
+ pagination: { limit: 200, offset: 0 },
392
+ }),
393
+ executeGraphQL<{ drivers: ApiDriver[] }>(graphQLOptions, LIST_DRIVERS_QUERY, {
394
+ filter: {
395
+ vehicleId: filters?.driverId,
396
+ },
397
+ pagination: { limit: 200, offset: 0 },
398
+ }),
399
+ ]);
400
+
401
+ setVehicles(vehicleData.vehicles.map(mapVehicle));
402
+ setDrivers(driverData.drivers.map(mapDriver));
403
+ } catch (fetchError) {
404
+ setError(fetchError instanceof Error ? fetchError : new Error('Failed to load fleet data'));
405
+ } finally {
406
+ setIsLoading(false);
407
+ }
408
+ }, [filters, graphQLOptions]);
409
+
410
+ useEffect(() => {
411
+ void load();
412
+ }, [load]);
413
+
414
+ const refetch = useCallback(() => {
415
+ void load();
416
+ }, [load]);
417
+
418
+ return {
419
+ vehicles,
420
+ drivers,
421
+ totalVehicles: vehicles.length,
422
+ totalDrivers: drivers.length,
423
+ isLoading,
424
+ error,
425
+ refetch,
426
+ };
427
+ }
428
+
429
+ interface UseVehiclesResult {
430
+ vehicles: Vehicle[];
431
+ totalVehicles: number;
432
+ isLoading: boolean;
433
+ error: Error | null;
434
+ refetch: () => void;
435
+ updateVehicleStatus: (id: string, status: VehicleStatus) => Promise<Vehicle>;
436
+ assignDriver: (vehicleId: string, driverId: string) => Promise<Vehicle>;
437
+ }
438
+
439
+ export function useVehicles(): UseVehiclesResult {
440
+ const graphQLOptions = useGraphqlOptions();
441
+ const [vehicles, setVehicles] = useState<Vehicle[]>([]);
442
+ const [isLoading, setIsLoading] = useState(false);
443
+ const [error, setError] = useState<Error | null>(null);
444
+
445
+ const load = useCallback(async () => {
446
+ setIsLoading(true);
447
+ setError(null);
448
+ try {
449
+ const data = await executeGraphQL<{ vehicles: ApiVehicle[] }>(
450
+ graphQLOptions,
451
+ LIST_VEHICLES_QUERY,
452
+ {
453
+ pagination: { limit: 200, offset: 0 },
454
+ }
455
+ );
456
+ setVehicles(data.vehicles.map(mapVehicle));
457
+ } catch (fetchError) {
458
+ setError(fetchError instanceof Error ? fetchError : new Error('Failed to load vehicles'));
459
+ } finally {
460
+ setIsLoading(false);
461
+ }
462
+ }, [graphQLOptions]);
463
+
464
+ useEffect(() => {
465
+ void load();
466
+ }, [load]);
467
+
468
+ const refetch = useCallback(() => {
469
+ void load();
470
+ }, [load]);
471
+
472
+ const updateVehicleStatus = useCallback(
473
+ async (id: string, status: VehicleStatus): Promise<Vehicle> => {
474
+ const data = await executeGraphQL<{ updateVehicleStatus: ApiVehicle }>(
475
+ graphQLOptions,
476
+ UPDATE_VEHICLE_STATUS_MUTATION,
477
+ {
478
+ id,
479
+ status: toApiVehicleStatus(status),
480
+ }
481
+ );
482
+ const updated = mapVehicle(data.updateVehicleStatus);
483
+ setVehicles((previous) => previous.map((item) => (item.id === id ? updated : item)));
484
+ return updated;
485
+ },
486
+ [graphQLOptions]
487
+ );
488
+
489
+ const assignDriver = useCallback(
490
+ async (vehicleId: string, driverId: string): Promise<Vehicle> => {
491
+ await executeGraphQL<{ assignDriverVehicle: ApiDriver }>(
492
+ graphQLOptions,
493
+ ASSIGN_DRIVER_VEHICLE_MUTATION,
494
+ {
495
+ id: driverId,
496
+ vehicleId,
497
+ }
498
+ );
499
+ const next = vehicles.find((item) => item.id === vehicleId);
500
+ if (!next) {
501
+ throw new Error('Vehicle not found');
502
+ }
503
+ const updated = { ...next, driverId, status: 'assigned' as VehicleStatus };
504
+ setVehicles((previous) => previous.map((item) => (item.id === vehicleId ? updated : item)));
505
+ return updated;
506
+ },
507
+ [graphQLOptions, vehicles]
508
+ );
509
+
510
+ return {
511
+ vehicles,
512
+ totalVehicles: vehicles.length,
513
+ isLoading,
514
+ error,
515
+ refetch,
516
+ updateVehicleStatus,
517
+ assignDriver,
518
+ };
519
+ }
520
+
521
+ export function useVehicle(vehicleId: string | undefined) {
522
+ const graphQLOptions = useGraphqlOptions();
523
+ const [vehicle, setVehicle] = useState<Vehicle | null>(null);
524
+ const [isLoading, setIsLoading] = useState(false);
525
+ const [error, setError] = useState<Error | null>(null);
526
+
527
+ const load = useCallback(async () => {
528
+ if (!vehicleId) {
529
+ setVehicle(null);
530
+ return;
531
+ }
532
+
533
+ setIsLoading(true);
534
+ setError(null);
535
+ try {
536
+ const data = await executeGraphQL<{ vehicle: ApiVehicle | null }>(
537
+ graphQLOptions,
538
+ GET_VEHICLE_QUERY,
539
+ {
540
+ id: vehicleId,
541
+ }
542
+ );
543
+ setVehicle(data.vehicle ? mapVehicle(data.vehicle) : null);
544
+ } catch (fetchError) {
545
+ setError(fetchError instanceof Error ? fetchError : new Error('Failed to load vehicle'));
546
+ } finally {
547
+ setIsLoading(false);
548
+ }
549
+ }, [graphQLOptions, vehicleId]);
550
+
551
+ useEffect(() => {
552
+ void load();
553
+ }, [load]);
554
+
555
+ const refetch = useCallback(() => {
556
+ void load();
557
+ }, [load]);
558
+
559
+ return { vehicle, isLoading, error, refetch };
560
+ }
561
+
562
+ interface UseDriversResult {
563
+ drivers: Driver[];
564
+ totalDrivers: number;
565
+ isLoading: boolean;
566
+ error: Error | null;
567
+ refetch: () => void;
568
+ updateDriverStatus: (id: string, status: DriverStatus) => Promise<Driver>;
569
+ assignVehicle: (driverId: string, vehicleId: string) => Promise<Driver>;
570
+ }
571
+
572
+ export function useDrivers(): UseDriversResult {
573
+ const graphQLOptions = useGraphqlOptions();
574
+ const [drivers, setDrivers] = useState<Driver[]>([]);
575
+ const [isLoading, setIsLoading] = useState(false);
576
+ const [error, setError] = useState<Error | null>(null);
577
+
578
+ const load = useCallback(async () => {
579
+ setIsLoading(true);
580
+ setError(null);
581
+ try {
582
+ const data = await executeGraphQL<{ drivers: ApiDriver[] }>(
583
+ graphQLOptions,
584
+ LIST_DRIVERS_QUERY,
585
+ {
586
+ pagination: { limit: 200, offset: 0 },
587
+ }
588
+ );
589
+ setDrivers(data.drivers.map(mapDriver));
590
+ } catch (fetchError) {
591
+ setError(fetchError instanceof Error ? fetchError : new Error('Failed to load drivers'));
592
+ } finally {
593
+ setIsLoading(false);
594
+ }
595
+ }, [graphQLOptions]);
596
+
597
+ useEffect(() => {
598
+ void load();
599
+ }, [load]);
600
+
601
+ const refetch = useCallback(() => {
602
+ void load();
603
+ }, [load]);
604
+
605
+ const updateDriverStatus = useCallback(
606
+ async (id: string, status: DriverStatus): Promise<Driver> => {
607
+ const data = await executeGraphQL<{ updateDriverStatus: ApiDriver }>(
608
+ graphQLOptions,
609
+ UPDATE_DRIVER_STATUS_MUTATION,
610
+ {
611
+ id,
612
+ status: toApiDriverStatus(status),
613
+ }
614
+ );
615
+ const updated = mapDriver(data.updateDriverStatus);
616
+ setDrivers((previous) => previous.map((item) => (item.id === id ? updated : item)));
617
+ return updated;
618
+ },
619
+ [graphQLOptions]
620
+ );
621
+
622
+ const assignVehicle = useCallback(
623
+ async (driverId: string, vehicleId: string): Promise<Driver> => {
624
+ const data = await executeGraphQL<{ assignDriverVehicle: ApiDriver }>(
625
+ graphQLOptions,
626
+ ASSIGN_DRIVER_VEHICLE_MUTATION,
627
+ {
628
+ id: driverId,
629
+ vehicleId,
630
+ }
631
+ );
632
+ const updated = mapDriver(data.assignDriverVehicle);
633
+ setDrivers((previous) => previous.map((item) => (item.id === driverId ? updated : item)));
634
+ return updated;
635
+ },
636
+ [graphQLOptions]
637
+ );
638
+
639
+ return {
640
+ drivers,
641
+ totalDrivers: drivers.length,
642
+ isLoading,
643
+ error,
644
+ refetch,
645
+ updateDriverStatus,
646
+ assignVehicle,
647
+ };
648
+ }
649
+
650
+ export function useDriver(driverId: string | undefined) {
651
+ const graphQLOptions = useGraphqlOptions();
652
+ const [driver, setDriver] = useState<Driver | null>(null);
653
+ const [isLoading, setIsLoading] = useState(false);
654
+ const [error, setError] = useState<Error | null>(null);
655
+
656
+ const load = useCallback(async () => {
657
+ if (!driverId) {
658
+ setDriver(null);
659
+ return;
660
+ }
661
+
662
+ setIsLoading(true);
663
+ setError(null);
664
+ try {
665
+ const data = await executeGraphQL<{ driver: ApiDriver | null }>(
666
+ graphQLOptions,
667
+ GET_DRIVER_QUERY,
668
+ {
669
+ id: driverId,
670
+ }
671
+ );
672
+ setDriver(data.driver ? mapDriver(data.driver) : null);
673
+ } catch (fetchError) {
674
+ setError(fetchError instanceof Error ? fetchError : new Error('Failed to load driver'));
675
+ } finally {
676
+ setIsLoading(false);
677
+ }
678
+ }, [driverId, graphQLOptions]);
679
+
680
+ useEffect(() => {
681
+ void load();
682
+ }, [load]);
683
+
684
+ const refetch = useCallback(() => {
685
+ void load();
686
+ }, [load]);
687
+
688
+ return { driver, isLoading, error, refetch };
689
+ }
690
+
691
+ export function useFleetStats() {
692
+ const graphQLOptions = useGraphqlOptions();
693
+ const [stats, setStats] = useState({
694
+ totalVehicles: 0,
695
+ totalDrivers: 0,
696
+ vehiclesByStatus: {
697
+ available: 0,
698
+ assigned: 0,
699
+ maintenance: 0,
700
+ out_of_service: 0,
701
+ },
702
+ driversByStatus: {
703
+ available: 0,
704
+ busy: 0,
705
+ offline: 0,
706
+ on_break: 0,
707
+ },
708
+ avgFuelLevel: 0,
709
+ avgDriverRating: 0,
710
+ utilization: 0,
711
+ });
712
+ const [isLoading, setIsLoading] = useState(false);
713
+ const [error, setError] = useState<Error | null>(null);
714
+
715
+ useEffect(() => {
716
+ const load = async () => {
717
+ setIsLoading(true);
718
+ setError(null);
719
+ try {
720
+ const data = await executeGraphQL<{
721
+ fleetStats: {
722
+ totalVehicles: number;
723
+ activeVehicles: number;
724
+ inTransitVehicles: number;
725
+ maintenanceVehicles: number;
726
+ totalDrivers: number;
727
+ availableDrivers: number;
728
+ onDeliveryDrivers: number;
729
+ };
730
+ }>(graphQLOptions, FLEET_STATS_QUERY);
731
+
732
+ setStats({
733
+ totalVehicles: data.fleetStats.totalVehicles,
734
+ totalDrivers: data.fleetStats.totalDrivers,
735
+ vehiclesByStatus: {
736
+ available: data.fleetStats.activeVehicles,
737
+ assigned: data.fleetStats.inTransitVehicles,
738
+ maintenance: data.fleetStats.maintenanceVehicles,
739
+ out_of_service: Math.max(
740
+ data.fleetStats.totalVehicles -
741
+ data.fleetStats.activeVehicles -
742
+ data.fleetStats.inTransitVehicles -
743
+ data.fleetStats.maintenanceVehicles,
744
+ 0
745
+ ),
746
+ },
747
+ driversByStatus: {
748
+ available: data.fleetStats.availableDrivers,
749
+ busy: data.fleetStats.onDeliveryDrivers,
750
+ offline: Math.max(
751
+ data.fleetStats.totalDrivers -
752
+ data.fleetStats.availableDrivers -
753
+ data.fleetStats.onDeliveryDrivers,
754
+ 0
755
+ ),
756
+ on_break: 0,
757
+ },
758
+ avgFuelLevel: 0,
759
+ avgDriverRating: 0,
760
+ utilization:
761
+ data.fleetStats.totalVehicles > 0
762
+ ? (data.fleetStats.activeVehicles / data.fleetStats.totalVehicles) * 100
763
+ : 0,
764
+ });
765
+ } catch (fetchError) {
766
+ setError(
767
+ fetchError instanceof Error ? fetchError : new Error('Failed to load fleet stats')
768
+ );
769
+ } finally {
770
+ setIsLoading(false);
771
+ }
772
+ };
773
+
774
+ void load();
775
+ }, [graphQLOptions]);
776
+
777
+ return { stats, isLoading, error };
778
+ }