@burdenoff/microfe-movethewheels 2026.626.2 → 2026.703.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/dist/{AIAssistantPage-AvsMbunM.js → AIAssistantPage-C3ovZ0Fh.js} +100 -73
  2. package/dist/AnalyticsPage-O8SpY-V4.js +215 -0
  3. package/dist/{CreateOrderPage-CjlnEtk3.js → CreateOrderPage-CB1_-_mN.js} +33 -35
  4. package/dist/{CustomerDetailsPage-I6cdDHUi.js → CustomerDetailsPage-BaeKEI1D.js} +42 -44
  5. package/dist/{CustomersPage-CGGfD4ki.js → CustomersPage-DRaLuHMC.js} +26 -28
  6. package/dist/{DashboardPage-D2HRqwg9.js → DashboardPage-DPjhNfKB.js} +85 -83
  7. package/dist/{DataTable-CD9ZhpLB.js → DataTable-DmciIKKM.js} +3 -3
  8. package/dist/{DriverDetailsPage-rg_pGNuP.js → DriverDetailsPage-CSSQTOzn.js} +52 -54
  9. package/dist/{DriversPage-DKiynISH.js → DriversPage-C2Bk0w4Q.js} +24 -26
  10. package/dist/{FinancePage-Vg8WPs38.js → FinancePage-lmp0Sdsw.js} +9 -9
  11. package/dist/FleetPage-DZn5pIqd.js +365 -0
  12. package/dist/ImportExportPage-BIUJZc7O.js +290 -0
  13. package/dist/InventoryPage-Cxh1zYJd.js +253 -0
  14. package/dist/{LiveTrackingPage-DQ1q4Id3.js → LiveTrackingPage-BY1yAkIt.js} +60 -56
  15. package/dist/MarketplacePage-RMuL17EA.js +247 -0
  16. package/dist/{MetricCard-B7yMyvMX.js → MetricCard-7aYgzZHK.js} +1 -1
  17. package/dist/{OrderDetailsPage-CFASgsYX.js → OrderDetailsPage-C2Mf4KSy.js} +83 -85
  18. package/dist/{OrdersListPage-BHeT8S5o.js → OrdersListPage-BrPBtnhp.js} +31 -33
  19. package/dist/{PageLayout-D3N8MCTm.js → PageLayout-D4LDHJJq.js} +483 -422
  20. package/dist/{ProductDetailsPage-CFGcbaHo.js → ProductDetailsPage-CezzzZcj.js} +27 -29
  21. package/dist/{ProductsPage--xEpbQ8A.js → ProductsPage-I5DilIoY.js} +21 -23
  22. package/dist/ReportsPage-BDXNmUng.js +284 -0
  23. package/dist/RouteDetailsPage-BcomL20M.js +263 -0
  24. package/dist/RoutesPage-lqX9ylHP.js +144 -0
  25. package/dist/SettingsPage-CQVIOaNs.js +421 -0
  26. package/dist/StatusBadge-NpTeHVlw.js +152 -0
  27. package/dist/{TrackingPage-CcRc_dva.js → TrackingPage-BXrjz7V8.js} +59 -61
  28. package/dist/{VehicleDetailsPage-3YDMPsPs.js → VehicleDetailsPage-DZjLcJgr.js} +40 -42
  29. package/dist/{VehiclesPage-UlxPWP9K.js → VehiclesPage-6W39XT5W.js} +19 -21
  30. package/dist/{WarehouseDetailsPage-Db7KeN-d.js → WarehouseDetailsPage-C10pgRGW.js} +38 -40
  31. package/dist/{WarehousesPage-CuTO-OPp.js → WarehousesPage-CHvBqNaQ.js} +15 -17
  32. package/dist/{arrow-left-CBpZKkpq.js → arrow-left-n48Y-Wis.js} +1 -1
  33. package/dist/{box-CAaiElsb.js → box-D9Pal4HM.js} +1 -1
  34. package/dist/{chart-column-D1Ym15-S.js → chart-column-BFIJysDR.js} +1 -1
  35. package/dist/{chevron-right-BIFGi0UA.js → chevron-right-EMIIyyJ1.js} +1 -1
  36. package/dist/{circle-alert-DjmNo5_L.js → circle-alert-iY24lSlp.js} +1 -1
  37. package/dist/{circle-check-big-CjuPVo3_.js → circle-check-big-w0TrLKMF.js} +1 -1
  38. package/dist/{clock-BjkdnddD.js → clock-DJZtdl8u.js} +1 -1
  39. package/dist/{dollar-sign-IB4O0wuQ.js → dollar-sign-CgKQRz_e.js} +1 -1
  40. package/dist/{download-Dpa9vqoG.js → download-DRXxoiQR.js} +1 -1
  41. package/dist/{file-text-C8Uioy11.js → file-text-DWWY6_f5.js} +1 -1
  42. package/dist/{filter-Da5OZaHI.js → filter-DloLC2eE.js} +1 -1
  43. package/dist/index.js +119 -111
  44. package/dist/{map-_Per4sT9.js → map-CkJaULb2.js} +1 -1
  45. package/dist/{map-pin-BSaf5IDL.js → map-pin-BGiCvyCs.js} +1 -1
  46. package/dist/{navigation-DaTbrhw2.js → navigation-D36prnAn.js} +1 -1
  47. package/dist/{package-BE7U0wQE.js → package-BChUzpJS.js} +1 -1
  48. package/dist/{phone-DV4StZiA.js → phone-Ac9s3mo_.js} +1 -1
  49. package/dist/{plus-Dl1rLeJR.js → plus-Z76q-FZm.js} +1 -1
  50. package/dist/{refresh-cw-CWfERAit.js → refresh-cw-DKt6f5T6.js} +1 -1
  51. package/dist/{save-XH8vydOn.js → save-CojywNhG.js} +1 -1
  52. package/dist/{search-OxoIiL_C.js → search-CDGefqb3.js} +1 -1
  53. package/dist/{square-pen-hLIbFQFV.js → square-pen-CopE9GmB.js} +1 -1
  54. package/dist/{star-YsVV3MNQ.js → star-nHlLjDKR.js} +1 -1
  55. package/dist/{store-RCBl7HB-.js → store-BR9Voi5E.js} +1 -1
  56. package/dist/{trending-up-C-85AwGT.js → trending-up-B7W-GL6P.js} +1 -1
  57. package/dist/{triangle-alert-BOhfGgmh.js → triangle-alert-BonHFFNz.js} +1 -1
  58. package/dist/{truck-CtDjNFbi.js → truck-DrlfSpRC.js} +1 -1
  59. package/dist/{useAnalytics-ph7eTIK6.js → useAnalytics-CgdzUfY_.js} +40 -40
  60. package/dist/useAssistant-D4v3oxD3.js +84 -0
  61. package/dist/{useCustomers-bS3a4ytk.js → useCustomers-QrlozybF.js} +24 -24
  62. package/dist/{useFleet-BdETplNE.js → useFleet-DiAC-IiH.js} +70 -67
  63. package/dist/useImportExport-BLMnAKCC.js +55 -0
  64. package/dist/{useInventory-Dwn18FPz.js → useInventory-DKoks37x.js} +33 -33
  65. package/dist/{useOrders-D_3_hGMp.js → useOrders-D3UZVy8Y.js} +42 -42
  66. package/dist/useReports-Puq4DCH9.js +78 -0
  67. package/dist/{useRoutes-v4aBaS-E.js → useRoutes-Do57LvRb.js} +31 -31
  68. package/dist/useSettings-CkDH_-gM.js +81 -0
  69. package/dist/{useTracking-De2KIUNu.js → useTracking-GJify4HN.js} +22 -22
  70. package/dist/{user-Dz5TJZFs.js → user-CjSoudeu.js} +1 -1
  71. package/dist/{users-g2N0eL-Z.js → users-BAM4gHTn.js} +1 -1
  72. package/dist/{warehouse-D3WWDeTX.js → warehouse-C7MSr47B.js} +1 -1
  73. package/dist/{wrench-CmxY1n4I.js → wrench-CANXWxF-.js} +1 -1
  74. package/package.json +1 -1
  75. package/src/movethewheels/MoveTheWheelsRoutes.tsx +27 -3
  76. package/src/movethewheels/components/StatusBadge.tsx +18 -37
  77. package/src/movethewheels/constants/index.ts +67 -26
  78. package/src/movethewheels/hooks/index.ts +12 -0
  79. package/src/movethewheels/hooks/useAnalytics.ts +20 -6
  80. package/src/movethewheels/hooks/useAssistant.ts +74 -0
  81. package/src/movethewheels/hooks/useFleet.ts +63 -59
  82. package/src/movethewheels/hooks/useImportExport.ts +101 -0
  83. package/src/movethewheels/hooks/useReports.ts +158 -0
  84. package/src/movethewheels/hooks/useSettings.ts +120 -0
  85. package/src/movethewheels/pages/AIAssistantPage.tsx +53 -15
  86. package/src/movethewheels/pages/AnalyticsPage.tsx +67 -64
  87. package/src/movethewheels/pages/CustomerDetailsPage.tsx +1 -1
  88. package/src/movethewheels/pages/CustomersPage.tsx +1 -1
  89. package/src/movethewheels/pages/DashboardPage.tsx +42 -22
  90. package/src/movethewheels/pages/DriverDetailsPage.tsx +1 -1
  91. package/src/movethewheels/pages/DriversPage.tsx +1 -1
  92. package/src/movethewheels/pages/FleetPage.tsx +96 -38
  93. package/src/movethewheels/pages/ImportExportPage.tsx +174 -68
  94. package/src/movethewheels/pages/InventoryPage.tsx +66 -28
  95. package/src/movethewheels/pages/LiveTrackingPage.tsx +12 -3
  96. package/src/movethewheels/pages/MarketplacePage.tsx +87 -45
  97. package/src/movethewheels/pages/OrderDetailsPage.tsx +2 -2
  98. package/src/movethewheels/pages/ReportsPage.tsx +194 -90
  99. package/src/movethewheels/pages/RouteDetailsPage.tsx +5 -11
  100. package/src/movethewheels/pages/RoutesPage.tsx +4 -9
  101. package/src/movethewheels/pages/SettingsPage.tsx +234 -56
  102. package/src/movethewheels/pages/TrackingPage.tsx +6 -6
  103. package/src/movethewheels/providers/MoveTheWheelsProvider.tsx +7 -6
  104. package/src/movethewheels/store/movethewheelsStore.ts +1 -1
  105. package/dist/AnalyticsPage-CCLfHgQZ.js +0 -212
  106. package/dist/FleetPage-DddXt8r8.js +0 -332
  107. package/dist/ImportExportPage-BW6qO3kc.js +0 -248
  108. package/dist/InventoryPage-rMGuaJN-.js +0 -222
  109. package/dist/MarketplacePage-DKrXAv62.js +0 -219
  110. package/dist/ReportsPage-Bb7_90rK.js +0 -235
  111. package/dist/RouteDetailsPage-CVtDVb1N.js +0 -282
  112. package/dist/RoutesPage-s57PtgcQ.js +0 -163
  113. package/dist/SettingsPage-BYNCBOpN.js +0 -298
  114. package/dist/StatusBadge-CijYQXtb.js +0 -209
  115. package/dist/graphqlClient-CdJyR_ed.js +0 -55
  116. package/dist/navigation-BgnOfsVd.js +0 -6
  117. package/dist/route-Dp9JiN_E.js +0 -51
  118. package/dist/settings-3Rw5NwFF.js +0 -28
  119. package/src/movethewheels/constants/mockData.ts +0 -1342
  120. /package/dist/{formatters-_vJlC-47.js → formatters-DhKZ-eA1.js} +0 -0
@@ -1,7 +1,12 @@
1
1
  import { cn } from '../utils/cn';
2
2
  import { Badge } from './ui';
3
3
  import type { OrderStatus, VehicleStatus, DriverStatus } from '../types';
4
- import { ORDER_STATUS_COLORS, VEHICLE_STATUS_COLORS, DRIVER_STATUS_COLORS } from '../constants';
4
+ import {
5
+ ORDER_STATUS_COLORS,
6
+ VEHICLE_STATUS_COLORS,
7
+ DRIVER_STATUS_COLORS,
8
+ PRIORITY_COLORS,
9
+ } from '../constants';
5
10
 
6
11
  type StatusType = 'order' | 'vehicle' | 'driver' | 'custom';
7
12
 
@@ -37,28 +42,20 @@ export function StatusBadge({
37
42
  // Get colors based on type
38
43
  let colors = customColors;
39
44
 
45
+ const neutral = { bg: 'bg-bg-sunken', text: 'text-text-secondary' };
40
46
  if (!colors) {
41
47
  switch (type) {
42
48
  case 'order':
43
- colors = ORDER_STATUS_COLORS[status as OrderStatus] || {
44
- bg: 'bg-gray-100',
45
- text: 'text-gray-700',
46
- };
49
+ colors = ORDER_STATUS_COLORS[status as OrderStatus] || neutral;
47
50
  break;
48
51
  case 'vehicle':
49
- colors = VEHICLE_STATUS_COLORS[status as VehicleStatus] || {
50
- bg: 'bg-gray-100',
51
- text: 'text-gray-700',
52
- };
52
+ colors = VEHICLE_STATUS_COLORS[status as VehicleStatus] || neutral;
53
53
  break;
54
54
  case 'driver':
55
- colors = DRIVER_STATUS_COLORS[status as DriverStatus] || {
56
- bg: 'bg-gray-100',
57
- text: 'text-gray-700',
58
- };
55
+ colors = DRIVER_STATUS_COLORS[status as DriverStatus] || neutral;
59
56
  break;
60
57
  default:
61
- colors = { bg: 'bg-gray-100 dark:bg-gray-800', text: 'text-gray-700 dark:text-gray-300' };
58
+ colors = neutral;
62
59
  }
63
60
  }
64
61
 
@@ -102,17 +99,7 @@ export function PriorityBadge({
102
99
  size?: 'sm' | 'md' | 'lg';
103
100
  className?: string;
104
101
  }) {
105
- const priorityColors = {
106
- low: { bg: 'bg-gray-100 dark:bg-gray-800', text: 'text-gray-600 dark:text-gray-400' },
107
- normal: { bg: 'bg-blue-100 dark:bg-blue-900/30', text: 'text-blue-700 dark:text-blue-400' },
108
- high: {
109
- bg: 'bg-orange-100 dark:bg-orange-900/30',
110
- text: 'text-orange-700 dark:text-orange-400',
111
- },
112
- urgent: { bg: 'bg-red-100 dark:bg-red-900/30', text: 'text-red-700 dark:text-red-400' },
113
- };
114
-
115
- const colors = priorityColors[priority];
102
+ const colors = PRIORITY_COLORS[priority];
116
103
 
117
104
  return (
118
105
  <Badge
@@ -143,11 +130,8 @@ export function TypeBadge({
143
130
  className?: string;
144
131
  }) {
145
132
  const typeColors = {
146
- b2b: {
147
- bg: 'bg-purple-100 dark:bg-purple-900/30',
148
- text: 'text-purple-700 dark:text-purple-400',
149
- },
150
- b2c: { bg: 'bg-teal-100 dark:bg-teal-900/30', text: 'text-teal-700 dark:text-teal-400' },
133
+ b2b: { bg: 'bg-status-info-bg-subtle', text: 'text-status-info-text' },
134
+ b2c: { bg: 'bg-status-success-bg-subtle', text: 'text-status-success-text' },
151
135
  };
152
136
 
153
137
  const colors = typeColors[type];
@@ -181,13 +165,10 @@ export function PaymentStatusBadge({
181
165
  className?: string;
182
166
  }) {
183
167
  const statusColors = {
184
- pending: {
185
- bg: 'bg-yellow-100 dark:bg-yellow-900/30',
186
- text: 'text-yellow-700 dark:text-yellow-400',
187
- },
188
- paid: { bg: 'bg-green-100 dark:bg-green-900/30', text: 'text-green-700 dark:text-green-400' },
189
- failed: { bg: 'bg-red-100 dark:bg-red-900/30', text: 'text-red-700 dark:text-red-400' },
190
- refunded: { bg: 'bg-gray-100 dark:bg-gray-800', text: 'text-gray-700 dark:text-gray-400' },
168
+ pending: { bg: 'bg-status-warning-bg-subtle', text: 'text-status-warning-text' },
169
+ paid: { bg: 'bg-status-success-bg-subtle', text: 'text-status-success-text' },
170
+ failed: { bg: 'bg-status-error-bg-subtle', text: 'text-status-error-text' },
171
+ refunded: { bg: 'bg-bg-sunken', text: 'text-text-secondary' },
191
172
  };
192
173
 
193
174
  const colors = statusColors[status];
@@ -1,44 +1,85 @@
1
1
  /**
2
2
  * Constants barrel export
3
+ *
4
+ * Status color maps use fe-libs semantic status tokens (never raw palette
5
+ * classes) so they adapt automatically across light/dark and product themes.
6
+ * Definitions live in fe-libs/src/shared/styles/app-shell.css.
3
7
  */
4
8
 
5
- export * from './mockData';
9
+ export interface StatusColor {
10
+ bg: string;
11
+ text: string;
12
+ border?: string;
13
+ }
14
+
15
+ const SUCCESS: StatusColor = {
16
+ bg: 'bg-status-success-bg-subtle',
17
+ text: 'text-status-success-text',
18
+ border: 'border-status-success-border',
19
+ };
20
+ const WARNING: StatusColor = {
21
+ bg: 'bg-status-warning-bg-subtle',
22
+ text: 'text-status-warning-text',
23
+ border: 'border-status-warning-border',
24
+ };
25
+ const ERROR: StatusColor = {
26
+ bg: 'bg-status-error-bg-subtle',
27
+ text: 'text-status-error-text',
28
+ border: 'border-status-error-border',
29
+ };
30
+ const INFO: StatusColor = {
31
+ bg: 'bg-status-info-bg-subtle',
32
+ text: 'text-status-info-text',
33
+ border: 'border-status-info-border',
34
+ };
35
+ const NEUTRAL: StatusColor = {
36
+ bg: 'bg-bg-sunken',
37
+ text: 'text-text-secondary',
38
+ };
6
39
 
7
40
  // Order status colors
8
- export const ORDER_STATUS_COLORS: Record<string, { bg: string; text: string; border: string }> = {
9
- pending: { bg: 'bg-yellow-100', text: 'text-yellow-800', border: 'border-yellow-200' },
10
- confirmed: { bg: 'bg-blue-100', text: 'text-blue-800', border: 'border-blue-200' },
11
- assigned: { bg: 'bg-purple-100', text: 'text-purple-800', border: 'border-purple-200' },
12
- picked_up: { bg: 'bg-indigo-100', text: 'text-indigo-800', border: 'border-indigo-200' },
13
- in_transit: { bg: 'bg-cyan-100', text: 'text-cyan-800', border: 'border-cyan-200' },
14
- out_for_delivery: { bg: 'bg-orange-100', text: 'text-orange-800', border: 'border-orange-200' },
15
- delivered: { bg: 'bg-green-100', text: 'text-green-800', border: 'border-green-200' },
16
- cancelled: { bg: 'bg-red-100', text: 'text-red-800', border: 'border-red-200' },
17
- failed: { bg: 'bg-red-100', text: 'text-red-800', border: 'border-red-200' },
41
+ export const ORDER_STATUS_COLORS: Record<string, StatusColor> = {
42
+ pending: WARNING,
43
+ confirmed: INFO,
44
+ assigned: INFO,
45
+ picked_up: INFO,
46
+ in_transit: INFO,
47
+ out_for_delivery: WARNING,
48
+ delivered: SUCCESS,
49
+ cancelled: ERROR,
50
+ failed: ERROR,
18
51
  };
19
52
 
20
53
  // Vehicle status colors
21
- export const VEHICLE_STATUS_COLORS: Record<string, { bg: string; text: string }> = {
22
- available: { bg: 'bg-green-100', text: 'text-green-800' },
23
- assigned: { bg: 'bg-blue-100', text: 'text-blue-800' },
24
- maintenance: { bg: 'bg-yellow-100', text: 'text-yellow-800' },
25
- out_of_service: { bg: 'bg-red-100', text: 'text-red-800' },
54
+ export const VEHICLE_STATUS_COLORS: Record<string, StatusColor> = {
55
+ available: SUCCESS,
56
+ assigned: INFO,
57
+ maintenance: WARNING,
58
+ out_of_service: ERROR,
26
59
  };
27
60
 
28
61
  // Driver status colors
29
- export const DRIVER_STATUS_COLORS: Record<string, { bg: string; text: string }> = {
30
- available: { bg: 'bg-green-100', text: 'text-green-800' },
31
- busy: { bg: 'bg-blue-100', text: 'text-blue-800' },
32
- offline: { bg: 'bg-gray-100', text: 'text-gray-800' },
33
- on_break: { bg: 'bg-yellow-100', text: 'text-yellow-800' },
62
+ export const DRIVER_STATUS_COLORS: Record<string, StatusColor> = {
63
+ available: SUCCESS,
64
+ busy: INFO,
65
+ offline: NEUTRAL,
66
+ on_break: WARNING,
34
67
  };
35
68
 
36
69
  // Priority colors
37
- export const PRIORITY_COLORS: Record<string, { bg: string; text: string }> = {
38
- low: { bg: 'bg-gray-100', text: 'text-gray-600' },
39
- normal: { bg: 'bg-blue-100', text: 'text-blue-600' },
40
- high: { bg: 'bg-orange-100', text: 'text-orange-600' },
41
- urgent: { bg: 'bg-red-100', text: 'text-red-600' },
70
+ export const PRIORITY_COLORS: Record<string, StatusColor> = {
71
+ low: NEUTRAL,
72
+ normal: INFO,
73
+ high: WARNING,
74
+ urgent: ERROR,
75
+ };
76
+
77
+ // Route status colors (shared by RoutesPage + RouteDetailsPage)
78
+ export const ROUTE_STATUS_COLORS: Record<string, StatusColor> = {
79
+ planned: INFO,
80
+ in_progress: WARNING,
81
+ completed: SUCCESS,
82
+ cancelled: ERROR,
42
83
  };
43
84
 
44
85
  // Customer type labels
@@ -53,3 +53,15 @@ export {
53
53
  useTrackingAlerts,
54
54
  useGeofence,
55
55
  } from './useTracking';
56
+
57
+ // Assistant
58
+ export { useAssistant } from './useAssistant';
59
+
60
+ // Reports
61
+ export { useReports } from './useReports';
62
+
63
+ // Import / Export
64
+ export { useImportExport } from './useImportExport';
65
+
66
+ // Module settings
67
+ export { useModuleSettings } from './useSettings';
@@ -40,11 +40,14 @@ const ANALYTICS_QUERY = `
40
40
  activeVehicles
41
41
  lowStockItems
42
42
  totalRevenue
43
+ onTimeDeliveryRate
44
+ customerSatisfaction
43
45
  }
44
46
  fleetStats {
45
47
  totalVehicles
46
48
  activeVehicles
47
49
  maintenanceVehicles
50
+ avgDriverRating
48
51
  }
49
52
  }
50
53
  `;
@@ -58,6 +61,8 @@ const DASHBOARD_QUERY = `
58
61
  activeVehicles
59
62
  lowStockItems
60
63
  totalRevenue
64
+ onTimeDeliveryRate
65
+ customerSatisfaction
61
66
  }
62
67
  orderStats {
63
68
  total
@@ -74,6 +79,7 @@ const DASHBOARD_QUERY = `
74
79
  totalDrivers
75
80
  availableDrivers
76
81
  onDeliveryDrivers
82
+ avgDriverRating
77
83
  }
78
84
  financeMetrics {
79
85
  revenue {
@@ -165,11 +171,14 @@ export function useAnalytics(_options: UseAnalyticsOptions = {}): UseAnalyticsRe
165
171
  totalOrders: number;
166
172
  totalRevenue: number;
167
173
  activeVehicles: number;
174
+ onTimeDeliveryRate: number;
175
+ customerSatisfaction: number;
168
176
  };
169
177
  fleetStats: {
170
178
  totalVehicles: number;
171
179
  activeVehicles: number;
172
180
  maintenanceVehicles: number;
181
+ avgDriverRating: number;
173
182
  };
174
183
  }>(graphQLOptions, ANALYTICS_QUERY);
175
184
 
@@ -178,8 +187,8 @@ export function useAnalytics(_options: UseAnalyticsOptions = {}): UseAnalyticsRe
178
187
  totalOrders: data.dashboardMetrics.totalOrders,
179
188
  totalRevenue: data.dashboardMetrics.totalRevenue,
180
189
  activeVehicles: data.dashboardMetrics.activeVehicles,
181
- onTimeDeliveryRate: 0,
182
- customerSatisfaction: 0,
190
+ onTimeDeliveryRate: data.dashboardMetrics.onTimeDeliveryRate,
191
+ customerSatisfaction: data.dashboardMetrics.customerSatisfaction,
183
192
  },
184
193
  trends: {
185
194
  dailyOrders: data.analytics.orderTrend.map((item) => ({
@@ -209,10 +218,10 @@ export function useAnalytics(_options: UseAnalyticsOptions = {}): UseAnalyticsRe
209
218
  },
210
219
  performance: {
211
220
  onTimePickup: 0,
212
- onTimeDelivery: 0,
221
+ onTimeDelivery: data.dashboardMetrics.onTimeDeliveryRate,
213
222
  damagedItems: 0,
214
223
  customerComplaints: 0,
215
- driverRatings: 0,
224
+ driverRatings: data.fleetStats.avgDriverRating,
216
225
  },
217
226
  });
218
227
  } catch (fetchError) {
@@ -281,6 +290,10 @@ export function useDashboardMetrics() {
281
290
  setError(null);
282
291
  try {
283
292
  const data = await executeGraphQL<{
293
+ dashboardMetrics: {
294
+ onTimeDeliveryRate: number;
295
+ customerSatisfaction: number;
296
+ };
284
297
  orderStats: {
285
298
  total: number;
286
299
  pending: number;
@@ -292,6 +305,7 @@ export function useDashboardMetrics() {
292
305
  activeVehicles: number;
293
306
  totalDrivers: number;
294
307
  availableDrivers: number;
308
+ avgDriverRating: number;
295
309
  };
296
310
  financeMetrics: {
297
311
  revenue: {
@@ -321,8 +335,8 @@ export function useDashboardMetrics() {
321
335
  currency: 'USD',
322
336
  },
323
337
  performance: {
324
- onTimeDeliveryRate: 0,
325
- avgDriverRating: 0,
338
+ onTimeDeliveryRate: data.dashboardMetrics.onTimeDeliveryRate,
339
+ avgDriverRating: data.fleetStats.avgDriverRating,
326
340
  },
327
341
  });
328
342
  } catch (fetchError) {
@@ -0,0 +1,74 @@
1
+ import { useCallback, useMemo, useState } from 'react';
2
+ import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
3
+ import { executeGraphQL } from '../utils/graphqlClient';
4
+
5
+ export interface AssistantAnswer {
6
+ answer: string;
7
+ generatedAt: string;
8
+ question: string;
9
+ }
10
+
11
+ const ASSISTANT_INSIGHTS_QUERY = `
12
+ query MovethewheelsAssistantInsights($question: String!) {
13
+ assistantInsights(question: $question) {
14
+ answer
15
+ generatedAt
16
+ question
17
+ }
18
+ }
19
+ `;
20
+
21
+ interface UseAssistantResult {
22
+ ask: (question: string) => Promise<AssistantAnswer>;
23
+ isLoading: boolean;
24
+ error: Error | null;
25
+ }
26
+
27
+ /**
28
+ * useAssistant — queries the real logistics assistant (Query.assistantInsights).
29
+ * The backend answers from the caller's own operational data; there is no
30
+ * client-side canned response.
31
+ */
32
+ export function useAssistant(): UseAssistantResult {
33
+ const { apiGatewayUrl, authToken, workspaceToken, workspaceId, tenantId, currentUser } =
34
+ useMoveTheWheels();
35
+ const [isLoading, setIsLoading] = useState(false);
36
+ const [error, setError] = useState<Error | null>(null);
37
+
38
+ const graphQLOptions = useMemo(
39
+ () => ({
40
+ apiGatewayUrl,
41
+ authToken,
42
+ workspaceToken,
43
+ workspaceId,
44
+ tenantId,
45
+ actorId: currentUser?.id,
46
+ }),
47
+ [apiGatewayUrl, authToken, workspaceToken, workspaceId, tenantId, currentUser?.id]
48
+ );
49
+
50
+ const ask = useCallback(
51
+ async (question: string): Promise<AssistantAnswer> => {
52
+ setIsLoading(true);
53
+ setError(null);
54
+ try {
55
+ const data = await executeGraphQL<{ assistantInsights: AssistantAnswer }>(
56
+ graphQLOptions,
57
+ ASSISTANT_INSIGHTS_QUERY,
58
+ { question }
59
+ );
60
+ return data.assistantInsights;
61
+ } catch (fetchError) {
62
+ const normalized =
63
+ fetchError instanceof Error ? fetchError : new Error('Failed to get assistant response');
64
+ setError(normalized);
65
+ throw normalized;
66
+ } finally {
67
+ setIsLoading(false);
68
+ }
69
+ },
70
+ [graphQLOptions]
71
+ );
72
+
73
+ return { ask, isLoading, error };
74
+ }
@@ -199,6 +199,7 @@ const FLEET_STATS_QUERY = `
199
199
  totalDrivers
200
200
  availableDrivers
201
201
  onDeliveryDrivers
202
+ avgDriverRating
202
203
  }
203
204
  }
204
205
  `;
@@ -712,67 +713,70 @@ export function useFleetStats() {
712
713
  const [isLoading, setIsLoading] = useState(false);
713
714
  const [error, setError] = useState<Error | null>(null);
714
715
 
716
+ const load = useCallback(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
+ avgDriverRating: number;
730
+ };
731
+ }>(graphQLOptions, FLEET_STATS_QUERY);
732
+
733
+ setStats({
734
+ totalVehicles: data.fleetStats.totalVehicles,
735
+ totalDrivers: data.fleetStats.totalDrivers,
736
+ vehiclesByStatus: {
737
+ available: data.fleetStats.activeVehicles,
738
+ assigned: data.fleetStats.inTransitVehicles,
739
+ maintenance: data.fleetStats.maintenanceVehicles,
740
+ out_of_service: Math.max(
741
+ data.fleetStats.totalVehicles -
742
+ data.fleetStats.activeVehicles -
743
+ data.fleetStats.inTransitVehicles -
744
+ data.fleetStats.maintenanceVehicles,
745
+ 0
746
+ ),
747
+ },
748
+ driversByStatus: {
749
+ available: data.fleetStats.availableDrivers,
750
+ busy: data.fleetStats.onDeliveryDrivers,
751
+ offline: Math.max(
752
+ data.fleetStats.totalDrivers -
753
+ data.fleetStats.availableDrivers -
754
+ data.fleetStats.onDeliveryDrivers,
755
+ 0
756
+ ),
757
+ on_break: 0,
758
+ },
759
+ avgFuelLevel: 0,
760
+ avgDriverRating: data.fleetStats.avgDriverRating,
761
+ utilization:
762
+ data.fleetStats.totalVehicles > 0
763
+ ? (data.fleetStats.activeVehicles / data.fleetStats.totalVehicles) * 100
764
+ : 0,
765
+ });
766
+ } catch (fetchError) {
767
+ setError(fetchError instanceof Error ? fetchError : new Error('Failed to load fleet stats'));
768
+ } finally {
769
+ setIsLoading(false);
770
+ }
771
+ }, [graphQLOptions]);
772
+
715
773
  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
- };
774
+ void load();
775
+ }, [load]);
773
776
 
777
+ const refetch = useCallback(() => {
774
778
  void load();
775
- }, [graphQLOptions]);
779
+ }, [load]);
776
780
 
777
- return { stats, isLoading, error };
781
+ return { stats, isLoading, error, refetch };
778
782
  }
@@ -0,0 +1,101 @@
1
+ import { useCallback, useMemo, useState } from 'react';
2
+ import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
3
+ import { executeGraphQL } from '../utils/graphqlClient';
4
+
5
+ export interface ImportExportResult {
6
+ success: boolean;
7
+ message: string;
8
+ payload?: Record<string, unknown> | null;
9
+ }
10
+
11
+ const EXPORT_DATA_MUTATION = `
12
+ mutation MovethewheelsExportData($input: MovethewheelsExportDataInput!) {
13
+ exportData(input: $input) {
14
+ success
15
+ message
16
+ payload
17
+ }
18
+ }
19
+ `;
20
+
21
+ const IMPORT_DATA_MUTATION = `
22
+ mutation MovethewheelsImportData($input: MovethewheelsImportDataInput!) {
23
+ importData(input: $input) {
24
+ success
25
+ message
26
+ payload
27
+ }
28
+ }
29
+ `;
30
+
31
+ interface UseImportExportResult {
32
+ exportData: (resource: string, format?: string) => Promise<ImportExportResult>;
33
+ importData: (resource: string, payload: Record<string, unknown>) => Promise<ImportExportResult>;
34
+ isBusy: boolean;
35
+ error: Error | null;
36
+ }
37
+
38
+ export function useImportExport(): UseImportExportResult {
39
+ const { apiGatewayUrl, authToken, workspaceToken, workspaceId, tenantId, currentUser } =
40
+ useMoveTheWheels();
41
+ const [isBusy, setIsBusy] = useState(false);
42
+ const [error, setError] = useState<Error | null>(null);
43
+
44
+ const graphQLOptions = useMemo(
45
+ () => ({
46
+ apiGatewayUrl,
47
+ authToken,
48
+ workspaceToken,
49
+ workspaceId,
50
+ tenantId,
51
+ actorId: currentUser?.id,
52
+ }),
53
+ [apiGatewayUrl, authToken, workspaceToken, workspaceId, tenantId, currentUser?.id]
54
+ );
55
+
56
+ const exportData = useCallback(
57
+ async (resource: string, format?: string): Promise<ImportExportResult> => {
58
+ setIsBusy(true);
59
+ setError(null);
60
+ try {
61
+ const data = await executeGraphQL<{ exportData: ImportExportResult }>(
62
+ graphQLOptions,
63
+ EXPORT_DATA_MUTATION,
64
+ { input: { resource, format } }
65
+ );
66
+ return data.exportData;
67
+ } catch (fetchError) {
68
+ const normalized = fetchError instanceof Error ? fetchError : new Error('Export failed');
69
+ setError(normalized);
70
+ throw normalized;
71
+ } finally {
72
+ setIsBusy(false);
73
+ }
74
+ },
75
+ [graphQLOptions]
76
+ );
77
+
78
+ const importData = useCallback(
79
+ async (resource: string, payload: Record<string, unknown>): Promise<ImportExportResult> => {
80
+ setIsBusy(true);
81
+ setError(null);
82
+ try {
83
+ const data = await executeGraphQL<{ importData: ImportExportResult }>(
84
+ graphQLOptions,
85
+ IMPORT_DATA_MUTATION,
86
+ { input: { resource, payload } }
87
+ );
88
+ return data.importData;
89
+ } catch (fetchError) {
90
+ const normalized = fetchError instanceof Error ? fetchError : new Error('Import failed');
91
+ setError(normalized);
92
+ throw normalized;
93
+ } finally {
94
+ setIsBusy(false);
95
+ }
96
+ },
97
+ [graphQLOptions]
98
+ );
99
+
100
+ return { exportData, importData, isBusy, error };
101
+ }