@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,387 @@
1
+ /**
2
+ * Order Details Page
3
+ *
4
+ * Displays detailed information about a specific order.
5
+ */
6
+
7
+ import { useParams } from 'react-router-dom';
8
+ import {
9
+ Package,
10
+ ArrowLeft,
11
+ MapPin,
12
+ User,
13
+ Truck,
14
+ Clock,
15
+ DollarSign,
16
+ Phone,
17
+ Mail,
18
+ FileText,
19
+ CheckCircle,
20
+ Edit,
21
+ Printer,
22
+ } from 'lucide-react';
23
+ import { PageLayout, LoadingState, ErrorState } from '../components/PageLayout';
24
+ import {
25
+ StatusBadge,
26
+ PriorityBadge,
27
+ TypeBadge,
28
+ PaymentStatusBadge,
29
+ } from '../components/StatusBadge';
30
+ import {
31
+ Card,
32
+ CardContent,
33
+ CardHeader,
34
+ CardTitle,
35
+ Button,
36
+ Badge,
37
+ Separator,
38
+ Table,
39
+ TableBody,
40
+ TableCell,
41
+ TableHead,
42
+ TableHeader,
43
+ TableRow,
44
+ } from '../components/ui';
45
+ import { useOrder } from '../hooks/useOrders';
46
+ import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
47
+ import { formatCurrency, formatDate, formatAddress } from '../utils/formatters';
48
+ import { joinPath } from '../utils/navigation';
49
+
50
+ export default function OrderDetailsPage() {
51
+ const { orderId } = useParams<{ orderId: string }>();
52
+ const { basePath, navigate } = useMoveTheWheels();
53
+ const { order, isLoading, error, refetch } = useOrder(orderId);
54
+
55
+ const goTo = (path: string) => {
56
+ if (navigate) {
57
+ navigate(joinPath(basePath, path));
58
+ }
59
+ };
60
+
61
+ const goBack = () => {
62
+ if (navigate) {
63
+ navigate(joinPath(basePath, 'orders'));
64
+ }
65
+ };
66
+
67
+ if (isLoading) {
68
+ return <LoadingState message="Loading order details..." />;
69
+ }
70
+
71
+ if (error || !order) {
72
+ return (
73
+ <ErrorState
74
+ title="Order not found"
75
+ message="The order you're looking for doesn't exist or has been removed."
76
+ onRetry={refetch}
77
+ />
78
+ );
79
+ }
80
+
81
+ return (
82
+ <PageLayout
83
+ title={order.orderNumber}
84
+ subtitle={`Created ${formatDate(order.createdAt, 'full')}`}
85
+ icon={<Package size={24} />}
86
+ headerActions={
87
+ <div className="flex gap-2">
88
+ <Button variant="outline" onClick={goBack}>
89
+ <ArrowLeft size={16} />
90
+ Back
91
+ </Button>
92
+ <Button variant="outline">
93
+ <Printer size={16} />
94
+ Print
95
+ </Button>
96
+ <Button onClick={() => goTo(`orders/${orderId}/edit`)}>
97
+ <Edit size={16} />
98
+ Edit
99
+ </Button>
100
+ </div>
101
+ }
102
+ headerContent={
103
+ <div className="flex flex-wrap gap-2">
104
+ <StatusBadge status={order.status} type="order" />
105
+ <PriorityBadge priority={order.priority} />
106
+ <TypeBadge type={order.orderType} />
107
+ <PaymentStatusBadge status={order.pricing.paymentStatus} />
108
+ </div>
109
+ }
110
+ >
111
+ <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
112
+ {/* Main Content */}
113
+ <div className="lg:col-span-2 space-y-6">
114
+ {/* Customer Information */}
115
+ <Card>
116
+ <CardHeader>
117
+ <CardTitle className="flex items-center gap-2">
118
+ <User size={18} />
119
+ Customer Information
120
+ </CardTitle>
121
+ </CardHeader>
122
+ <CardContent>
123
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
124
+ <div>
125
+ <h4 className="font-medium mb-2">{order.customerInfo.name}</h4>
126
+ {order.customerInfo.company && (
127
+ <p className="text-sm text-muted-foreground mb-2">
128
+ {order.customerInfo.company}
129
+ </p>
130
+ )}
131
+ <div className="space-y-1 text-sm">
132
+ <p className="flex items-center gap-2">
133
+ <Mail size={14} className="text-muted-foreground" />
134
+ {order.customerInfo.email}
135
+ </p>
136
+ <p className="flex items-center gap-2">
137
+ <Phone size={14} className="text-muted-foreground" />
138
+ {order.customerInfo.phone}
139
+ </p>
140
+ </div>
141
+ </div>
142
+ <div>
143
+ {order.customerInfo.preferredDeliveryTime && (
144
+ <div className="mb-2">
145
+ <p className="text-sm text-muted-foreground">Preferred Delivery Time</p>
146
+ <p className="text-sm">{order.customerInfo.preferredDeliveryTime}</p>
147
+ </div>
148
+ )}
149
+ {order.customerInfo.deliveryInstructions && (
150
+ <div>
151
+ <p className="text-sm text-muted-foreground">Delivery Instructions</p>
152
+ <p className="text-sm">{order.customerInfo.deliveryInstructions}</p>
153
+ </div>
154
+ )}
155
+ </div>
156
+ </div>
157
+ </CardContent>
158
+ </Card>
159
+
160
+ {/* Addresses */}
161
+ <Card>
162
+ <CardHeader>
163
+ <CardTitle className="flex items-center gap-2">
164
+ <MapPin size={18} />
165
+ Addresses
166
+ </CardTitle>
167
+ </CardHeader>
168
+ <CardContent>
169
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
170
+ <div>
171
+ <h4 className="font-medium mb-2 flex items-center gap-2">
172
+ <Badge variant="outline">Pickup</Badge>
173
+ </h4>
174
+ <p className="text-sm">{formatAddress(order.pickupAddress)}</p>
175
+ {order.scheduledPickup && (
176
+ <p className="text-sm text-muted-foreground mt-2">
177
+ Scheduled: {formatDate(order.scheduledPickup, 'full')}
178
+ </p>
179
+ )}
180
+ {order.actualPickup && (
181
+ <p className="text-sm text-green-600 mt-1">
182
+ <CheckCircle size={14} className="inline mr-1" />
183
+ Picked up: {formatDate(order.actualPickup, 'full')}
184
+ </p>
185
+ )}
186
+ </div>
187
+ <div>
188
+ <h4 className="font-medium mb-2 flex items-center gap-2">
189
+ <Badge variant="outline">Delivery</Badge>
190
+ </h4>
191
+ <p className="text-sm">{formatAddress(order.deliveryAddress)}</p>
192
+ {order.scheduledDelivery && (
193
+ <p className="text-sm text-muted-foreground mt-2">
194
+ Scheduled: {formatDate(order.scheduledDelivery, 'full')}
195
+ </p>
196
+ )}
197
+ {order.actualDelivery && (
198
+ <p className="text-sm text-green-600 mt-1">
199
+ <CheckCircle size={14} className="inline mr-1" />
200
+ Delivered: {formatDate(order.actualDelivery, 'full')}
201
+ </p>
202
+ )}
203
+ </div>
204
+ </div>
205
+ </CardContent>
206
+ </Card>
207
+
208
+ {/* Order Items */}
209
+ <Card>
210
+ <CardHeader>
211
+ <CardTitle className="flex items-center gap-2">
212
+ <Package size={18} />
213
+ Order Items ({order.items.length})
214
+ </CardTitle>
215
+ </CardHeader>
216
+ <CardContent className="p-0">
217
+ <Table>
218
+ <TableHeader>
219
+ <TableRow>
220
+ <TableHead>Item</TableHead>
221
+ <TableHead>SKU</TableHead>
222
+ <TableHead className="text-center">Qty</TableHead>
223
+ <TableHead className="text-right">Unit Price</TableHead>
224
+ <TableHead className="text-right">Total</TableHead>
225
+ </TableRow>
226
+ </TableHeader>
227
+ <TableBody>
228
+ {order.items.map((item) => (
229
+ <TableRow key={item.id}>
230
+ <TableCell>
231
+ <div>
232
+ <p className="font-medium">{item.name}</p>
233
+ {item.description && (
234
+ <p className="text-sm text-muted-foreground">{item.description}</p>
235
+ )}
236
+ </div>
237
+ </TableCell>
238
+ <TableCell className="font-mono text-sm">{item.sku}</TableCell>
239
+ <TableCell className="text-center">{item.quantity}</TableCell>
240
+ <TableCell className="text-right">{formatCurrency(item.value)}</TableCell>
241
+ <TableCell className="text-right font-medium">
242
+ {formatCurrency(item.value * item.quantity)}
243
+ </TableCell>
244
+ </TableRow>
245
+ ))}
246
+ </TableBody>
247
+ </Table>
248
+ </CardContent>
249
+ </Card>
250
+
251
+ {/* Timeline */}
252
+ <Card>
253
+ <CardHeader>
254
+ <CardTitle className="flex items-center gap-2">
255
+ <Clock size={18} />
256
+ Order Timeline
257
+ </CardTitle>
258
+ </CardHeader>
259
+ <CardContent>
260
+ <div className="relative">
261
+ {order.timeline.map((event, index) => (
262
+ <div key={index} className="flex gap-4 pb-6 last:pb-0">
263
+ <div className="relative">
264
+ <div className="w-3 h-3 rounded-full bg-primary mt-1.5" />
265
+ {index < order.timeline.length - 1 && (
266
+ <div className="absolute top-4 left-1.5 w-px h-full -ml-px bg-border" />
267
+ )}
268
+ </div>
269
+ <div className="flex-1">
270
+ <div className="flex items-center gap-2 mb-1">
271
+ <StatusBadge status={event.status} type="order" size="sm" />
272
+ <span className="text-sm text-muted-foreground">
273
+ {formatDate(event.timestamp, 'full')}
274
+ </span>
275
+ </div>
276
+ {event.notes && <p className="text-sm">{event.notes}</p>}
277
+ <p className="text-xs text-muted-foreground">by {event.performedBy}</p>
278
+ </div>
279
+ </div>
280
+ ))}
281
+ </div>
282
+ </CardContent>
283
+ </Card>
284
+ </div>
285
+
286
+ {/* Sidebar */}
287
+ <div className="space-y-6">
288
+ {/* Order Summary */}
289
+ <Card>
290
+ <CardHeader>
291
+ <CardTitle className="flex items-center gap-2">
292
+ <DollarSign size={18} />
293
+ Order Summary
294
+ </CardTitle>
295
+ </CardHeader>
296
+ <CardContent>
297
+ <div className="space-y-3">
298
+ <div className="flex justify-between text-sm">
299
+ <span className="text-muted-foreground">Subtotal</span>
300
+ <span>{formatCurrency(order.pricing.subtotal)}</span>
301
+ </div>
302
+ <div className="flex justify-between text-sm">
303
+ <span className="text-muted-foreground">Delivery</span>
304
+ <span>{formatCurrency(order.pricing.fees.delivery)}</span>
305
+ </div>
306
+ <div className="flex justify-between text-sm">
307
+ <span className="text-muted-foreground">Handling</span>
308
+ <span>{formatCurrency(order.pricing.fees.handling)}</span>
309
+ </div>
310
+ {order.pricing.fees.insurance && (
311
+ <div className="flex justify-between text-sm">
312
+ <span className="text-muted-foreground">Insurance</span>
313
+ <span>{formatCurrency(order.pricing.fees.insurance)}</span>
314
+ </div>
315
+ )}
316
+ <div className="flex justify-between text-sm">
317
+ <span className="text-muted-foreground">Taxes</span>
318
+ <span>{formatCurrency(order.pricing.taxes)}</span>
319
+ </div>
320
+ <Separator />
321
+ <div className="flex justify-between font-medium">
322
+ <span>Total</span>
323
+ <span className="text-lg">{formatCurrency(order.pricing.total)}</span>
324
+ </div>
325
+ <div className="pt-2">
326
+ <p className="text-sm text-muted-foreground">Payment Method</p>
327
+ <p className="text-sm capitalize">
328
+ {order.pricing.paymentMethod.replace('_', ' ')}
329
+ </p>
330
+ </div>
331
+ </div>
332
+ </CardContent>
333
+ </Card>
334
+
335
+ {/* Assignment Info */}
336
+ <Card>
337
+ <CardHeader>
338
+ <CardTitle className="flex items-center gap-2">
339
+ <Truck size={18} />
340
+ Assignment
341
+ </CardTitle>
342
+ </CardHeader>
343
+ <CardContent>
344
+ <div className="space-y-4">
345
+ <div>
346
+ <p className="text-sm text-muted-foreground">Driver</p>
347
+ <p className="text-sm">{order.driverId || 'Not assigned'}</p>
348
+ </div>
349
+ <div>
350
+ <p className="text-sm text-muted-foreground">Vehicle</p>
351
+ <p className="text-sm">{order.vehicleId || 'Not assigned'}</p>
352
+ </div>
353
+ <div>
354
+ <p className="text-sm text-muted-foreground">Tracking Number</p>
355
+ <p className="text-sm font-mono">{order.trackingNumber}</p>
356
+ </div>
357
+ <Button
358
+ variant="outline"
359
+ className="w-full"
360
+ onClick={() => goTo(`tracking?order=${order.id}`)}
361
+ >
362
+ <MapPin size={16} />
363
+ Track Order
364
+ </Button>
365
+ </div>
366
+ </CardContent>
367
+ </Card>
368
+
369
+ {/* Special Instructions */}
370
+ {order.specialInstructions && (
371
+ <Card>
372
+ <CardHeader>
373
+ <CardTitle className="flex items-center gap-2">
374
+ <FileText size={18} />
375
+ Special Instructions
376
+ </CardTitle>
377
+ </CardHeader>
378
+ <CardContent>
379
+ <p className="text-sm">{order.specialInstructions}</p>
380
+ </CardContent>
381
+ </Card>
382
+ )}
383
+ </div>
384
+ </div>
385
+ </PageLayout>
386
+ );
387
+ }
@@ -0,0 +1,241 @@
1
+ /**
2
+ * Orders List Page
3
+ *
4
+ * Displays all orders with filtering, search, and pagination.
5
+ */
6
+
7
+ import { useState } from 'react';
8
+ import { Package, Plus, Filter, Download, RefreshCw } from 'lucide-react';
9
+ import { PageLayout } from '../components/PageLayout';
10
+ import { DataTable, type Column } from '../components/DataTable';
11
+ import { StatusBadge, PriorityBadge, TypeBadge } from '../components/StatusBadge';
12
+ import {
13
+ Button,
14
+ Card,
15
+ CardContent,
16
+ Select,
17
+ SelectContent,
18
+ SelectItem,
19
+ SelectTrigger,
20
+ SelectValue,
21
+ Badge,
22
+ } from '../components/ui';
23
+ import { useOrders } from '../hooks/useOrders';
24
+ import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
25
+ import { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';
26
+ import { formatCurrency, formatDate } from '../utils/formatters';
27
+ import { joinPath } from '../utils/navigation';
28
+ import type { Order, OrderStatus } from '../types';
29
+
30
+ export default function OrdersListPage() {
31
+ const { t: translate } = useI18n();
32
+ const t = (key: string, fallback: string): string => {
33
+ const value = translate(key);
34
+ return value === key ? fallback : value;
35
+ };
36
+ const { basePath, navigate } = useMoveTheWheels();
37
+ const [statusFilter, setStatusFilter] = useState<OrderStatus | 'all'>('all');
38
+ const [typeFilter, setTypeFilter] = useState<'b2b' | 'b2c' | 'all'>('all');
39
+
40
+ const { orders, totalOrders, isLoading, refetch } = useOrders({
41
+ filters: {
42
+ status: statusFilter === 'all' ? undefined : statusFilter,
43
+ orderType: typeFilter === 'all' ? undefined : typeFilter,
44
+ },
45
+ limit: 50,
46
+ });
47
+
48
+ const goTo = (path: string) => {
49
+ if (navigate) {
50
+ navigate(joinPath(basePath, path));
51
+ }
52
+ };
53
+
54
+ const columns: Column<Order>[] = [
55
+ {
56
+ id: 'orderNumber',
57
+ header: t('movethewheels.orders.table.orderNumber', 'Order #'),
58
+ accessorKey: 'orderNumber',
59
+ sortable: true,
60
+ className: 'min-w-[100px] whitespace-nowrap',
61
+ cell: (row) => <span className="font-medium text-primary">{row.orderNumber}</span>,
62
+ },
63
+ {
64
+ id: 'customer',
65
+ header: t('movethewheels.orders.table.customer', 'Customer'),
66
+ className: 'min-w-[180px] max-w-[220px]',
67
+ cell: (row) => (
68
+ <div className="min-w-0">
69
+ <p className="font-medium truncate">{row.customerInfo.name}</p>
70
+ <p className="text-sm text-muted-foreground truncate">{row.customerInfo.email}</p>
71
+ </div>
72
+ ),
73
+ },
74
+ {
75
+ id: 'status',
76
+ header: t('movethewheels.orders.table.status', 'Status'),
77
+ accessorKey: 'status',
78
+ sortable: true,
79
+ className: 'min-w-[130px] whitespace-nowrap',
80
+ cell: (row) => <StatusBadge status={row.status} type="order" />,
81
+ },
82
+ {
83
+ id: 'type',
84
+ header: t('movethewheels.orders.table.type', 'Type'),
85
+ accessorKey: 'orderType',
86
+ className: 'min-w-[70px] whitespace-nowrap',
87
+ cell: (row) => <TypeBadge type={row.orderType} />,
88
+ },
89
+ {
90
+ id: 'priority',
91
+ header: t('movethewheels.orders.table.priority', 'Priority'),
92
+ accessorKey: 'priority',
93
+ sortable: true,
94
+ className: 'min-w-[90px] whitespace-nowrap',
95
+ cell: (row) => <PriorityBadge priority={row.priority} />,
96
+ },
97
+ {
98
+ id: 'items',
99
+ header: t('movethewheels.orders.table.items', 'Items'),
100
+ className: 'min-w-[80px] whitespace-nowrap',
101
+ cell: (row) => (
102
+ <Badge variant="secondary">
103
+ {row.items.length} {t('movethewheels.orders.table.itemsSuffix', 'items')}
104
+ </Badge>
105
+ ),
106
+ },
107
+ {
108
+ id: 'total',
109
+ header: t('movethewheels.orders.table.total', 'Total'),
110
+ accessorKey: 'pricing',
111
+ sortable: true,
112
+ className: 'min-w-[100px] whitespace-nowrap text-right',
113
+ cell: (row) => <span className="font-medium">{formatCurrency(row.pricing.total)}</span>,
114
+ },
115
+ {
116
+ id: 'scheduledDelivery',
117
+ header: t('movethewheels.orders.table.deliveryDate', 'Delivery Date'),
118
+ accessorKey: 'scheduledDelivery',
119
+ sortable: true,
120
+ className: 'min-w-[110px] whitespace-nowrap',
121
+ cell: (row) => (row.scheduledDelivery ? formatDate(row.scheduledDelivery) : '-'),
122
+ },
123
+ {
124
+ id: 'createdAt',
125
+ header: t('movethewheels.orders.table.created', 'Created'),
126
+ accessorKey: 'createdAt',
127
+ sortable: true,
128
+ className: 'min-w-[100px] whitespace-nowrap',
129
+ cell: (row) => formatDate(row.createdAt, 'relative'),
130
+ },
131
+ ];
132
+
133
+ const statusOptions: { value: OrderStatus | 'all'; label: string }[] = [
134
+ { value: 'all', label: t('movethewheels.orders.filters.allStatuses', 'All Statuses') },
135
+ { value: 'pending', label: t('movethewheels.orders.status.pending', 'Pending') },
136
+ { value: 'confirmed', label: t('movethewheels.orders.status.confirmed', 'Confirmed') },
137
+ { value: 'assigned', label: t('movethewheels.orders.status.assigned', 'Assigned') },
138
+ { value: 'picked_up', label: t('movethewheels.orders.status.pickedUp', 'Picked Up') },
139
+ { value: 'in_transit', label: t('movethewheels.orders.status.inTransit', 'In Transit') },
140
+ {
141
+ value: 'out_for_delivery',
142
+ label: t('movethewheels.orders.status.outForDelivery', 'Out for Delivery'),
143
+ },
144
+ { value: 'delivered', label: t('movethewheels.orders.status.delivered', 'Delivered') },
145
+ { value: 'cancelled', label: t('movethewheels.orders.status.cancelled', 'Cancelled') },
146
+ { value: 'failed', label: t('movethewheels.orders.status.failed', 'Failed') },
147
+ ];
148
+
149
+ return (
150
+ <PageLayout
151
+ title={t('movethewheels.orders.title', 'Orders')}
152
+ subtitle={`${totalOrders} ${t('movethewheels.orders.subtitle', 'total orders')}`}
153
+ icon={<Package size={24} />}
154
+ headerActions={
155
+ <div className="flex gap-2">
156
+ <Button variant="outline" onClick={refetch}>
157
+ <RefreshCw size={16} />
158
+ {t('movethewheels.orders.actions.refresh', 'Refresh')}
159
+ </Button>
160
+ <Button variant="outline">
161
+ <Download size={16} />
162
+ {t('movethewheels.orders.actions.export', 'Export')}
163
+ </Button>
164
+ <Button onClick={() => goTo('orders/new')}>
165
+ <Plus size={16} />
166
+ {t('movethewheels.orders.actions.newOrder', 'New Order')}
167
+ </Button>
168
+ </div>
169
+ }
170
+ >
171
+ {/* Filters */}
172
+ <Card>
173
+ <CardContent className="p-4">
174
+ <div className="flex flex-wrap items-center gap-4">
175
+ <div className="flex items-center gap-2">
176
+ <Filter size={16} className="text-muted-foreground" />
177
+ <span className="text-sm font-medium">
178
+ {t('movethewheels.orders.filters.label', 'Filters:')}
179
+ </span>
180
+ </div>
181
+ <Select
182
+ value={statusFilter}
183
+ onValueChange={(value) => setStatusFilter(value as OrderStatus | 'all')}
184
+ >
185
+ <SelectTrigger className="w-[180px]">
186
+ <SelectValue placeholder={t('movethewheels.orders.filters.status', 'Status')} />
187
+ </SelectTrigger>
188
+ <SelectContent>
189
+ {statusOptions.map((option) => (
190
+ <SelectItem key={option.value} value={option.value}>
191
+ {option.label}
192
+ </SelectItem>
193
+ ))}
194
+ </SelectContent>
195
+ </Select>
196
+ <Select
197
+ value={typeFilter}
198
+ onValueChange={(value) => setTypeFilter(value as 'b2b' | 'b2c' | 'all')}
199
+ >
200
+ <SelectTrigger className="w-[150px]">
201
+ <SelectValue placeholder={t('movethewheels.orders.filters.type', 'Type')} />
202
+ </SelectTrigger>
203
+ <SelectContent>
204
+ <SelectItem value="all">
205
+ {t('movethewheels.orders.filters.allTypes', 'All Types')}
206
+ </SelectItem>
207
+ <SelectItem value="b2b">B2B</SelectItem>
208
+ <SelectItem value="b2c">B2C</SelectItem>
209
+ </SelectContent>
210
+ </Select>
211
+ {(statusFilter !== 'all' || typeFilter !== 'all') && (
212
+ <Button
213
+ variant="ghost"
214
+ size="sm"
215
+ onClick={() => {
216
+ setStatusFilter('all');
217
+ setTypeFilter('all');
218
+ }}
219
+ >
220
+ {t('movethewheels.orders.filters.clear', 'Clear filters')}
221
+ </Button>
222
+ )}
223
+ </div>
224
+ </CardContent>
225
+ </Card>
226
+
227
+ {/* Orders Table */}
228
+ <DataTable
229
+ columns={columns}
230
+ data={orders}
231
+ isLoading={isLoading}
232
+ searchable
233
+ searchPlaceholder={t('movethewheels.orders.searchPlaceholder', 'Search orders...')}
234
+ searchFields={['orderNumber', 'customerInfo'] as (keyof Order)[]}
235
+ onRowClick={(row) => goTo(`orders/${row.id}`)}
236
+ getRowId={(row) => row.id}
237
+ emptyMessage={t('movethewheels.orders.empty', 'No orders found')}
238
+ />
239
+ </PageLayout>
240
+ );
241
+ }