@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,115 @@
1
+ /**
2
+ * Customers Page
3
+ */
4
+
5
+ import { Users, Plus, RefreshCw, Download, Star } from 'lucide-react';
6
+ import { PageLayout } from '../components/PageLayout';
7
+ import { DataTable, type Column } from '../components/DataTable';
8
+ import { TypeBadge } from '../components/StatusBadge';
9
+ import { Button, Badge, Avatar, AvatarFallback } from '../components/ui';
10
+ import { useCustomers } from '../hooks/useCustomers';
11
+ import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
12
+ import { formatDate } from '../utils/formatters';
13
+ import { joinPath } from '../utils/navigation';
14
+ import type { Customer } from '../types';
15
+
16
+ export default function CustomersPage() {
17
+ const { basePath, navigate } = useMoveTheWheels();
18
+ const { customers, totalCustomers, isLoading, refetch } = useCustomers({ limit: 100 });
19
+
20
+ const goTo = (path: string) => navigate?.(joinPath(basePath, path));
21
+
22
+ const columns: Column<Customer>[] = [
23
+ {
24
+ id: 'customer',
25
+ header: 'Customer',
26
+ cell: (row) => (
27
+ <div className="flex items-center gap-3">
28
+ <Avatar>
29
+ <AvatarFallback>
30
+ {row.name
31
+ .split(' ')
32
+ .map((n) => n[0])
33
+ .join('')}
34
+ </AvatarFallback>
35
+ </Avatar>
36
+ <div>
37
+ <p className="font-medium">{row.name}</p>
38
+ <p className="text-sm text-muted-foreground">{row.email}</p>
39
+ </div>
40
+ </div>
41
+ ),
42
+ },
43
+ {
44
+ id: 'type',
45
+ header: 'Type',
46
+ accessorKey: 'type',
47
+ cell: (row) => <TypeBadge type={row.type} />,
48
+ },
49
+ { id: 'company', header: 'Company', accessorKey: 'company', cell: (row) => row.company || '-' },
50
+ { id: 'phone', header: 'Phone', accessorKey: 'phone' },
51
+ {
52
+ id: 'location',
53
+ header: 'Location',
54
+ cell: (row) => `${row.address.city}, ${row.address.state}`,
55
+ },
56
+ {
57
+ id: 'rating',
58
+ header: 'Rating',
59
+ cell: (row) => (
60
+ <div className="flex items-center gap-1">
61
+ <Star size={14} className="text-yellow-500 fill-yellow-500" />
62
+ <span>{row.rating.toFixed(1)}</span>
63
+ </div>
64
+ ),
65
+ },
66
+ {
67
+ id: 'status',
68
+ header: 'Status',
69
+ cell: (row) => (
70
+ <Badge variant={row.isActive ? 'default' : 'secondary'}>
71
+ {row.isActive ? 'Active' : 'Inactive'}
72
+ </Badge>
73
+ ),
74
+ },
75
+ {
76
+ id: 'created',
77
+ header: 'Created',
78
+ accessorKey: 'createdAt',
79
+ sortable: true,
80
+ cell: (row) => formatDate(row.createdAt, 'short'),
81
+ },
82
+ ];
83
+
84
+ return (
85
+ <PageLayout
86
+ title="Customers"
87
+ subtitle={`${totalCustomers} customers`}
88
+ icon={<Users size={24} />}
89
+ headerActions={
90
+ <div className="flex gap-2">
91
+ <Button variant="outline" onClick={refetch}>
92
+ <RefreshCw size={16} /> Refresh
93
+ </Button>
94
+ <Button variant="outline">
95
+ <Download size={16} /> Export
96
+ </Button>
97
+ <Button onClick={() => goTo('customers/new')}>
98
+ <Plus size={16} /> Add Customer
99
+ </Button>
100
+ </div>
101
+ }
102
+ >
103
+ <DataTable
104
+ columns={columns}
105
+ data={customers}
106
+ isLoading={isLoading}
107
+ searchable
108
+ searchPlaceholder="Search customers..."
109
+ searchFields={['name', 'email', 'company'] as (keyof Customer)[]}
110
+ onRowClick={(row) => goTo(`customers/${row.id}`)}
111
+ getRowId={(row) => row.id}
112
+ />
113
+ </PageLayout>
114
+ );
115
+ }
@@ -0,0 +1,414 @@
1
+ /**
2
+ * Dashboard Page
3
+ *
4
+ * Main overview page with key metrics and quick actions.
5
+ */
6
+
7
+ import {
8
+ Package,
9
+ Truck,
10
+ Users,
11
+ DollarSign,
12
+ Clock,
13
+ AlertTriangle,
14
+ TrendingUp,
15
+ MapPin,
16
+ ChevronRight,
17
+ } from 'lucide-react';
18
+ import { PageLayout, PageSection } from '../components/PageLayout';
19
+ import { MetricCard, MetricGrid } from '../components/MetricCard';
20
+ import { StatusBadge } from '../components/StatusBadge';
21
+ import {
22
+ Card,
23
+ CardContent,
24
+ CardHeader,
25
+ CardTitle,
26
+ Button,
27
+ Badge,
28
+ Progress,
29
+ } from '../components/ui';
30
+ import { useDashboardMetrics } from '../hooks/useAnalytics';
31
+ import { useOrders, useOrderStats } from '../hooks/useOrders';
32
+ import { useFleetStats } from '../hooks/useFleet';
33
+ import { useLiveTracking } from '../hooks/useTracking';
34
+ import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
35
+ import { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';
36
+ import { formatCurrency, formatDate } from '../utils/formatters';
37
+ import { joinPath } from '../utils/navigation';
38
+
39
+ export default function DashboardPage() {
40
+ const { t: translate } = useI18n();
41
+ const t = (key: string, fallback: string): string => {
42
+ const value = translate(key);
43
+ return value === key ? fallback : value;
44
+ };
45
+ const { basePath, navigate } = useMoveTheWheels();
46
+ const { metrics } = useDashboardMetrics();
47
+ const { orders } = useOrders({ limit: 5 });
48
+ const { stats: orderStats } = useOrderStats();
49
+ const { stats: fleetStats } = useFleetStats();
50
+ const { activeDeliveries } = useLiveTracking();
51
+
52
+ const goTo = (path: string) => {
53
+ if (navigate) {
54
+ navigate(joinPath(basePath, path));
55
+ }
56
+ };
57
+
58
+ return (
59
+ <PageLayout
60
+ title={t('movethewheels.dashboard.title', 'Dashboard')}
61
+ subtitle={t('movethewheels.dashboard.subtitle', 'Overview of your logistics operations')}
62
+ icon={<TrendingUp size={24} />}
63
+ headerActions={
64
+ <div className="flex gap-2">
65
+ <Button variant="outline" onClick={() => goTo('tracking/live')}>
66
+ <MapPin size={16} />
67
+ {t('movethewheels.dashboard.actions.liveMap', 'Live Map')}
68
+ </Button>
69
+ <Button onClick={() => goTo('orders/new')}>
70
+ <Package size={16} />
71
+ {t('movethewheels.dashboard.actions.newOrder', 'New Order')}
72
+ </Button>
73
+ </div>
74
+ }
75
+ >
76
+ {/* Key Metrics */}
77
+ <MetricGrid columns={4}>
78
+ <MetricCard
79
+ label={t('movethewheels.dashboard.metrics.totalOrders', 'Total Orders')}
80
+ value={metrics.orders.total}
81
+ icon={<Package size={20} />}
82
+ change={`+${metrics.orders.today} ${t('movethewheels.dashboard.metrics.today', 'today')}`}
83
+ changeType="positive"
84
+ trend="up"
85
+ onClick={() => goTo('orders')}
86
+ />
87
+ <MetricCard
88
+ label={t('movethewheels.dashboard.metrics.activeDeliveries', 'Active Deliveries')}
89
+ value={metrics.orders.inTransit}
90
+ icon={<Truck size={20} />}
91
+ subtitle={`${metrics.orders.pending} ${t('movethewheels.dashboard.metrics.pending', 'pending')}`}
92
+ onClick={() => goTo('tracking')}
93
+ />
94
+ <MetricCard
95
+ label={t('movethewheels.dashboard.metrics.fleetUtilization', 'Fleet Utilization')}
96
+ value={`${metrics.fleet.activeVehicles}/${metrics.fleet.totalVehicles}`}
97
+ icon={<Truck size={20} />}
98
+ subtitle={`${metrics.fleet.availableDrivers} ${t('movethewheels.dashboard.metrics.driversAvailable', 'drivers available')}`}
99
+ onClick={() => goTo('fleet')}
100
+ />
101
+ <MetricCard
102
+ label={t('movethewheels.dashboard.metrics.revenue', 'Revenue')}
103
+ value={formatCurrency(metrics.revenue.total)}
104
+ icon={<DollarSign size={20} />}
105
+ change="+12.5%"
106
+ changeType="positive"
107
+ trend="up"
108
+ onClick={() => goTo('analytics')}
109
+ />
110
+ </MetricGrid>
111
+
112
+ {/* Quick Stats Row */}
113
+ <MetricGrid columns={4}>
114
+ <MetricCard
115
+ size="sm"
116
+ label={t('movethewheels.dashboard.stats.onTimeDelivery', 'On-Time Delivery')}
117
+ value={`${metrics.performance.onTimeDeliveryRate.toFixed(1)}%`}
118
+ changeType={metrics.performance.onTimeDeliveryRate >= 90 ? 'positive' : 'negative'}
119
+ />
120
+ <MetricCard
121
+ size="sm"
122
+ label={t('movethewheels.dashboard.stats.avgOrderValue', 'Avg Order Value')}
123
+ value={formatCurrency(metrics.revenue.avgOrderValue)}
124
+ />
125
+ <MetricCard
126
+ size="sm"
127
+ label={t('movethewheels.dashboard.stats.driverRating', 'Driver Rating')}
128
+ value={metrics.performance.avgDriverRating.toFixed(1)}
129
+ subtitle={t('movethewheels.dashboard.stats.outOfFive', 'out of 5')}
130
+ />
131
+ <MetricCard
132
+ size="sm"
133
+ label={t('movethewheels.dashboard.stats.deliveredToday', 'Delivered Today')}
134
+ value={metrics.orders.delivered}
135
+ />
136
+ </MetricGrid>
137
+
138
+ <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
139
+ {/* Recent Orders */}
140
+ <PageSection
141
+ title={t('movethewheels.dashboard.recentOrders.title', 'Recent Orders')}
142
+ actions={
143
+ <Button variant="ghost" size="sm" onClick={() => goTo('orders')}>
144
+ {t('movethewheels.dashboard.common.viewAll', 'View all')} <ChevronRight size={16} />
145
+ </Button>
146
+ }
147
+ >
148
+ <Card>
149
+ <CardContent className="p-0">
150
+ <div className="divide-y">
151
+ {orders.slice(0, 5).map((order) => (
152
+ <div
153
+ key={order.id}
154
+ className="p-4 hover:bg-muted/50 cursor-pointer transition-colors"
155
+ onClick={() => goTo(`orders/${order.id}`)}
156
+ >
157
+ <div className="flex items-center justify-between">
158
+ <div>
159
+ <p className="font-medium">{order.orderNumber}</p>
160
+ <p className="text-sm text-muted-foreground">{order.customerInfo.name}</p>
161
+ </div>
162
+ <div className="text-right">
163
+ <StatusBadge status={order.status} type="order" size="sm" />
164
+ <p className="text-sm text-muted-foreground mt-1">
165
+ {formatCurrency(order.pricing.total)}
166
+ </p>
167
+ </div>
168
+ </div>
169
+ </div>
170
+ ))}
171
+ {orders.length === 0 && (
172
+ <div className="p-8 text-center text-muted-foreground">
173
+ {t('movethewheels.dashboard.recentOrders.empty', 'No recent orders')}
174
+ </div>
175
+ )}
176
+ </div>
177
+ </CardContent>
178
+ </Card>
179
+ </PageSection>
180
+
181
+ {/* Active Deliveries */}
182
+ <PageSection
183
+ title={t('movethewheels.dashboard.activeDeliveries.title', 'Active Deliveries')}
184
+ actions={
185
+ <Button variant="ghost" size="sm" onClick={() => goTo('tracking/live')}>
186
+ {t('movethewheels.dashboard.activeDeliveries.liveTracking', 'Live tracking')}{' '}
187
+ <ChevronRight size={16} />
188
+ </Button>
189
+ }
190
+ >
191
+ <Card>
192
+ <CardContent className="p-0">
193
+ <div className="divide-y">
194
+ {activeDeliveries.slice(0, 5).map((delivery) =>
195
+ delivery.order ? (
196
+ <div
197
+ key={delivery.order.id}
198
+ className="p-4 hover:bg-muted/50 cursor-pointer transition-colors"
199
+ onClick={() => goTo(`tracking?order=${delivery.order.id}`)}
200
+ >
201
+ <div className="flex items-center justify-between">
202
+ <div>
203
+ <p className="font-medium">{delivery.order.orderNumber}</p>
204
+ <p className="text-sm text-muted-foreground">
205
+ {delivery.driver?.fullName ||
206
+ t(
207
+ 'movethewheels.dashboard.activeDeliveries.unassigned',
208
+ 'Unassigned'
209
+ )}
210
+ </p>
211
+ </div>
212
+ <div className="text-right">
213
+ <StatusBadge status={delivery.order.status} type="order" size="sm" />
214
+ <p className="text-sm text-muted-foreground mt-1">
215
+ {t('movethewheels.dashboard.activeDeliveries.eta', 'ETA:')}{' '}
216
+ {delivery.estimatedArrival
217
+ ? formatDate(delivery.estimatedArrival, 'time')
218
+ : t('movethewheels.dashboard.activeDeliveries.na', 'N/A')}
219
+ </p>
220
+ </div>
221
+ </div>
222
+ </div>
223
+ ) : null
224
+ )}
225
+ {activeDeliveries.length === 0 && (
226
+ <div className="p-8 text-center text-muted-foreground">
227
+ {t('movethewheels.dashboard.activeDeliveries.empty', 'No active deliveries')}
228
+ </div>
229
+ )}
230
+ </div>
231
+ </CardContent>
232
+ </Card>
233
+ </PageSection>
234
+ </div>
235
+
236
+ <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
237
+ {/* Order Status Summary */}
238
+ <Card>
239
+ <CardHeader>
240
+ <CardTitle className="text-base">
241
+ {t('movethewheels.dashboard.orderStatus.title', 'Order Status')}
242
+ </CardTitle>
243
+ </CardHeader>
244
+ <CardContent className="space-y-4">
245
+ <div className="space-y-3">
246
+ {[
247
+ { status: 'pending', count: orderStats.byStatus.pending, color: 'bg-yellow-500' },
248
+ {
249
+ status: 'in_transit',
250
+ count: orderStats.byStatus.in_transit,
251
+ color: 'bg-blue-500',
252
+ },
253
+ {
254
+ status: 'delivered',
255
+ count: orderStats.byStatus.delivered,
256
+ color: 'bg-green-500',
257
+ },
258
+ { status: 'cancelled', count: orderStats.byStatus.cancelled, color: 'bg-red-500' },
259
+ ].map(({ status, count, color }) => (
260
+ <div key={status} className="flex items-center justify-between">
261
+ <div className="flex items-center gap-2">
262
+ <div className={`w-2 h-2 rounded-full ${color}`} />
263
+ <span className="text-sm capitalize">
264
+ {t(
265
+ `movethewheels.dashboard.orderStatus.status.${status}`,
266
+ status.replace('_', ' ')
267
+ )}
268
+ </span>
269
+ </div>
270
+ <Badge variant="secondary">{count}</Badge>
271
+ </div>
272
+ ))}
273
+ </div>
274
+ </CardContent>
275
+ </Card>
276
+
277
+ {/* Fleet Status */}
278
+ <Card>
279
+ <CardHeader>
280
+ <CardTitle className="text-base">
281
+ {t('movethewheels.dashboard.fleetStatus.title', 'Fleet Status')}
282
+ </CardTitle>
283
+ </CardHeader>
284
+ <CardContent className="space-y-4">
285
+ <div className="space-y-2">
286
+ <div className="flex justify-between text-sm">
287
+ <span>
288
+ {t(
289
+ 'movethewheels.dashboard.fleetStatus.vehicleUtilization',
290
+ 'Vehicle Utilization'
291
+ )}
292
+ </span>
293
+ <span>{fleetStats.utilization.toFixed(0)}%</span>
294
+ </div>
295
+ <Progress value={fleetStats.utilization} />
296
+ </div>
297
+ <div className="grid grid-cols-2 gap-4 text-sm">
298
+ <div>
299
+ <p className="text-muted-foreground">
300
+ {t('movethewheels.dashboard.fleetStatus.available', 'Available')}
301
+ </p>
302
+ <p className="text-lg font-semibold text-green-600">
303
+ {fleetStats.vehiclesByStatus.available}
304
+ </p>
305
+ </div>
306
+ <div>
307
+ <p className="text-muted-foreground">
308
+ {t('movethewheels.dashboard.fleetStatus.inUse', 'In Use')}
309
+ </p>
310
+ <p className="text-lg font-semibold text-blue-600">
311
+ {fleetStats.vehiclesByStatus.assigned}
312
+ </p>
313
+ </div>
314
+ <div>
315
+ <p className="text-muted-foreground">
316
+ {t('movethewheels.dashboard.fleetStatus.maintenance', 'Maintenance')}
317
+ </p>
318
+ <p className="text-lg font-semibold text-yellow-600">
319
+ {fleetStats.vehiclesByStatus.maintenance}
320
+ </p>
321
+ </div>
322
+ <div>
323
+ <p className="text-muted-foreground">
324
+ {t('movethewheels.dashboard.fleetStatus.avgFuel', 'Avg Fuel')}
325
+ </p>
326
+ <p className="text-lg font-semibold">{fleetStats.avgFuelLevel.toFixed(0)}%</p>
327
+ </div>
328
+ </div>
329
+ </CardContent>
330
+ </Card>
331
+
332
+ {/* Alerts & Notifications */}
333
+ <Card>
334
+ <CardHeader>
335
+ <CardTitle className="text-base flex items-center gap-2">
336
+ <AlertTriangle size={16} className="text-yellow-500" />
337
+ {t('movethewheels.dashboard.alerts.title', 'Alerts')}
338
+ </CardTitle>
339
+ </CardHeader>
340
+ <CardContent>
341
+ <div className="space-y-3">
342
+ {orderStats.byStatus.pending > 5 && (
343
+ <div className="flex items-start gap-3 p-2 rounded bg-yellow-50 dark:bg-yellow-900/20">
344
+ <Clock size={16} className="text-yellow-600 mt-0.5" />
345
+ <div>
346
+ <p className="text-sm font-medium">
347
+ {t('movethewheels.dashboard.alerts.pendingOrders.title', 'Pending Orders')}
348
+ </p>
349
+ <p className="text-xs text-muted-foreground">
350
+ {orderStats.byStatus.pending}{' '}
351
+ {t(
352
+ 'movethewheels.dashboard.alerts.pendingOrders.description',
353
+ 'orders awaiting confirmation'
354
+ )}
355
+ </p>
356
+ </div>
357
+ </div>
358
+ )}
359
+ {fleetStats.vehiclesByStatus.maintenance > 0 && (
360
+ <div className="flex items-start gap-3 p-2 rounded bg-orange-50 dark:bg-orange-900/20">
361
+ <Truck size={16} className="text-orange-600 mt-0.5" />
362
+ <div>
363
+ <p className="text-sm font-medium">
364
+ {t(
365
+ 'movethewheels.dashboard.alerts.maintenanceVehicles.title',
366
+ 'Vehicles in Maintenance'
367
+ )}
368
+ </p>
369
+ <p className="text-xs text-muted-foreground">
370
+ {fleetStats.vehiclesByStatus.maintenance}{' '}
371
+ {t(
372
+ 'movethewheels.dashboard.alerts.maintenanceVehicles.description',
373
+ 'vehicles unavailable'
374
+ )}
375
+ </p>
376
+ </div>
377
+ </div>
378
+ )}
379
+ {fleetStats.driversByStatus.offline > 0 && (
380
+ <div className="flex items-start gap-3 p-2 rounded bg-gray-50 dark:bg-gray-800">
381
+ <Users size={16} className="text-gray-600 mt-0.5" />
382
+ <div>
383
+ <p className="text-sm font-medium">
384
+ {t('movethewheels.dashboard.alerts.offlineDrivers.title', 'Offline Drivers')}
385
+ </p>
386
+ <p className="text-xs text-muted-foreground">
387
+ {fleetStats.driversByStatus.offline}{' '}
388
+ {t(
389
+ 'movethewheels.dashboard.alerts.offlineDrivers.description',
390
+ 'drivers currently offline'
391
+ )}
392
+ </p>
393
+ </div>
394
+ </div>
395
+ )}
396
+ {orderStats.byStatus.pending <= 5 &&
397
+ fleetStats.vehiclesByStatus.maintenance === 0 &&
398
+ fleetStats.driversByStatus.offline === 0 && (
399
+ <div className="text-center py-4 text-muted-foreground">
400
+ <p className="text-sm">
401
+ {t(
402
+ 'movethewheels.dashboard.alerts.allOperational',
403
+ 'All systems operational'
404
+ )}
405
+ </p>
406
+ </div>
407
+ )}
408
+ </div>
409
+ </CardContent>
410
+ </Card>
411
+ </div>
412
+ </PageLayout>
413
+ );
414
+ }