@burdenoff/microfe-movethewheels 2026.626.2 → 2026.703.2

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 (135) hide show
  1. package/dist/{AIAssistantPage-AvsMbunM.js → AIAssistantPage-C3cPsWt-.js} +100 -73
  2. package/dist/AnalyticsPage-Dz6g2MvK.js +215 -0
  3. package/dist/{CreateOrderPage-CjlnEtk3.js → CreateOrderPage-C5iwnjp4.js} +36 -67
  4. package/dist/CustomerDetailsPage-B6nwFyLO.js +406 -0
  5. package/dist/{CustomersPage-CGGfD4ki.js → CustomersPage-2Y05LVyh.js} +26 -28
  6. package/dist/{DashboardPage-D2HRqwg9.js → DashboardPage-BVjQi0EB.js} +85 -83
  7. package/dist/{DataTable-CD9ZhpLB.js → DataTable-DmciIKKM.js} +3 -3
  8. package/dist/DriverDetailsPage-CN3WQ0B9.js +507 -0
  9. package/dist/{DriversPage-DKiynISH.js → DriversPage-B0Zpx8OQ.js} +25 -27
  10. package/dist/{FinancePage-Vg8WPs38.js → FinancePage-DEDykSOP.js} +9 -9
  11. package/dist/FleetPage-DqkFi3s3.js +365 -0
  12. package/dist/FormError-BlOjnXOq.js +15 -0
  13. package/dist/ImportExportPage-DKJRCezl.js +290 -0
  14. package/dist/InventoryPage-DwfgCUQq.js +253 -0
  15. package/dist/{LiveTrackingPage-DQ1q4Id3.js → LiveTrackingPage-DCX-K-LR.js} +60 -56
  16. package/dist/MarketplacePage-CIQ97_zp.js +247 -0
  17. package/dist/{MetricCard-B7yMyvMX.js → MetricCard-BY0QrMD4.js} +1 -1
  18. package/dist/{OrderDetailsPage-CFASgsYX.js → OrderDetailsPage-DYiZ-9UK.js} +83 -85
  19. package/dist/{OrdersListPage-BHeT8S5o.js → OrdersListPage-BjDlCKJd.js} +31 -33
  20. package/dist/{PageLayout-D3N8MCTm.js → PageLayout-D4LDHJJq.js} +483 -422
  21. package/dist/ProductDetailsPage-C9uOiYLp.js +350 -0
  22. package/dist/{ProductsPage--xEpbQ8A.js → ProductsPage-C1G9h7Xd.js} +22 -24
  23. package/dist/ReportsPage-Zp53q3_8.js +284 -0
  24. package/dist/RouteDetailsPage-DUStXSf9.js +531 -0
  25. package/dist/RoutesPage-DMfoicM1.js +144 -0
  26. package/dist/SettingsPage-Bn-v0mbQ.js +421 -0
  27. package/dist/StatusBadge-BZurYHMy.js +152 -0
  28. package/dist/{TrackingPage-CcRc_dva.js → TrackingPage-W-jtdM3Y.js} +59 -61
  29. package/dist/VehicleDetailsPage-Bceo5oz3.js +410 -0
  30. package/dist/{VehiclesPage-UlxPWP9K.js → VehiclesPage-VBtOep91.js} +20 -22
  31. package/dist/WarehouseDetailsPage-L_6sWigM.js +493 -0
  32. package/dist/{WarehousesPage-CuTO-OPp.js → WarehousesPage-DCbXXXWE.js} +16 -18
  33. package/dist/{arrow-left-CBpZKkpq.js → arrow-left-n48Y-Wis.js} +1 -1
  34. package/dist/{box-CAaiElsb.js → box-D9Pal4HM.js} +1 -1
  35. package/dist/{chart-column-D1Ym15-S.js → chart-column-BFIJysDR.js} +1 -1
  36. package/dist/{chevron-right-BIFGi0UA.js → chevron-right-EMIIyyJ1.js} +1 -1
  37. package/dist/{circle-alert-DjmNo5_L.js → circle-alert-iY24lSlp.js} +1 -1
  38. package/dist/{circle-check-big-CjuPVo3_.js → circle-check-big-w0TrLKMF.js} +1 -1
  39. package/dist/{clock-BjkdnddD.js → clock-DJZtdl8u.js} +1 -1
  40. package/dist/{dollar-sign-IB4O0wuQ.js → dollar-sign-CgKQRz_e.js} +1 -1
  41. package/dist/{download-Dpa9vqoG.js → download-DRXxoiQR.js} +1 -1
  42. package/dist/{file-text-C8Uioy11.js → file-text-DWWY6_f5.js} +1 -1
  43. package/dist/{filter-Da5OZaHI.js → filter-DloLC2eE.js} +1 -1
  44. package/dist/index.js +186 -162
  45. package/dist/{map-_Per4sT9.js → map-CkJaULb2.js} +1 -1
  46. package/dist/{map-pin-BSaf5IDL.js → map-pin-BGiCvyCs.js} +1 -1
  47. package/dist/{navigation-DaTbrhw2.js → navigation-D36prnAn.js} +1 -1
  48. package/dist/{package-BE7U0wQE.js → package-BChUzpJS.js} +1 -1
  49. package/dist/{phone-DV4StZiA.js → phone-Ac9s3mo_.js} +1 -1
  50. package/dist/{plus-Dl1rLeJR.js → plus-Z76q-FZm.js} +1 -1
  51. package/dist/{refresh-cw-CWfERAit.js → refresh-cw-DKt6f5T6.js} +1 -1
  52. package/dist/{save-XH8vydOn.js → save-CojywNhG.js} +1 -1
  53. package/dist/{search-OxoIiL_C.js → search-CDGefqb3.js} +1 -1
  54. package/dist/{square-pen-hLIbFQFV.js → square-pen-CopE9GmB.js} +1 -1
  55. package/dist/{star-YsVV3MNQ.js → star-nHlLjDKR.js} +1 -1
  56. package/dist/{store-RCBl7HB-.js → store-BR9Voi5E.js} +1 -1
  57. package/dist/trash-2-BKhar6Hs.js +32 -0
  58. package/dist/{trending-up-C-85AwGT.js → trending-up-Dohgd4t_.js} +1 -1
  59. package/dist/{triangle-alert-BOhfGgmh.js → triangle-alert-i-XQL9Rd.js} +1 -1
  60. package/dist/{truck-CtDjNFbi.js → truck-C0v_hbLR.js} +1 -1
  61. package/dist/{useAnalytics-ph7eTIK6.js → useAnalytics-DS8n0xgg.js} +40 -40
  62. package/dist/useAssistant-D4v3oxD3.js +84 -0
  63. package/dist/{useCustomers-bS3a4ytk.js → useCustomers-BmTNGxiI.js} +24 -24
  64. package/dist/{useFleet-BdETplNE.js → useFleet-DKqXZ16m.js} +133 -109
  65. package/dist/useImportExport-DHr-SWSw.js +55 -0
  66. package/dist/{useInventory-Dwn18FPz.js → useInventory-DkyiVY_A.js} +95 -75
  67. package/dist/{useOrders-D_3_hGMp.js → useOrders-Cfk1GLiq.js} +42 -42
  68. package/dist/useReports-CTqZr-AB.js +78 -0
  69. package/dist/{useRoutes-v4aBaS-E.js → useRoutes-BQWO607N.js} +31 -31
  70. package/dist/useSettings-CkDH_-gM.js +81 -0
  71. package/dist/{useTracking-De2KIUNu.js → useTracking-B-va1kO3.js} +22 -22
  72. package/dist/{user-Dz5TJZFs.js → user-jyFU3lXk.js} +1 -1
  73. package/dist/{users-g2N0eL-Z.js → users-DZ-ilS6B.js} +1 -1
  74. package/dist/{warehouse-D3WWDeTX.js → warehouse-6m5kXMLu.js} +1 -1
  75. package/dist/{wrench-CmxY1n4I.js → wrench-CANXWxF-.js} +1 -1
  76. package/package.json +1 -1
  77. package/src/movethewheels/MoveTheWheelsRoutes.tsx +31 -3
  78. package/src/movethewheels/components/FormError.tsx +25 -0
  79. package/src/movethewheels/components/StatusBadge.tsx +18 -37
  80. package/src/movethewheels/constants/index.ts +67 -26
  81. package/src/movethewheels/hooks/index.ts +12 -0
  82. package/src/movethewheels/hooks/useAnalytics.ts +20 -6
  83. package/src/movethewheels/hooks/useAssistant.ts +74 -0
  84. package/src/movethewheels/hooks/useFleet.ts +170 -59
  85. package/src/movethewheels/hooks/useImportExport.ts +101 -0
  86. package/src/movethewheels/hooks/useInventory.ts +107 -0
  87. package/src/movethewheels/hooks/useReports.ts +158 -0
  88. package/src/movethewheels/hooks/useSettings.ts +120 -0
  89. package/src/movethewheels/pages/AIAssistantPage.tsx +53 -15
  90. package/src/movethewheels/pages/AnalyticsPage.tsx +67 -64
  91. package/src/movethewheels/pages/CustomerDetailsPage.tsx +154 -21
  92. package/src/movethewheels/pages/CustomersPage.tsx +1 -1
  93. package/src/movethewheels/pages/DashboardPage.tsx +42 -22
  94. package/src/movethewheels/pages/DriverDetailsPage.tsx +160 -3
  95. package/src/movethewheels/pages/DriversPage.tsx +6 -2
  96. package/src/movethewheels/pages/FleetPage.tsx +96 -38
  97. package/src/movethewheels/pages/ImportExportPage.tsx +174 -68
  98. package/src/movethewheels/pages/InventoryPage.tsx +66 -28
  99. package/src/movethewheels/pages/LiveTrackingPage.tsx +12 -3
  100. package/src/movethewheels/pages/MarketplacePage.tsx +87 -45
  101. package/src/movethewheels/pages/OrderDetailsPage.tsx +2 -2
  102. package/src/movethewheels/pages/ProductDetailsPage.tsx +146 -3
  103. package/src/movethewheels/pages/ProductsPage.tsx +5 -1
  104. package/src/movethewheels/pages/ReportsPage.tsx +194 -90
  105. package/src/movethewheels/pages/RouteDetailsPage.tsx +290 -36
  106. package/src/movethewheels/pages/RoutesPage.tsx +4 -9
  107. package/src/movethewheels/pages/SettingsPage.tsx +234 -56
  108. package/src/movethewheels/pages/TrackingPage.tsx +6 -6
  109. package/src/movethewheels/pages/VehicleDetailsPage.tsx +158 -2
  110. package/src/movethewheels/pages/VehiclesPage.tsx +5 -1
  111. package/src/movethewheels/pages/WarehouseDetailsPage.tsx +224 -2
  112. package/src/movethewheels/pages/WarehousesPage.tsx +5 -1
  113. package/src/movethewheels/providers/MoveTheWheelsProvider.tsx +7 -6
  114. package/src/movethewheels/store/movethewheelsStore.ts +1 -1
  115. package/dist/AnalyticsPage-CCLfHgQZ.js +0 -212
  116. package/dist/CustomerDetailsPage-I6cdDHUi.js +0 -265
  117. package/dist/DriverDetailsPage-rg_pGNuP.js +0 -330
  118. package/dist/FleetPage-DddXt8r8.js +0 -332
  119. package/dist/ImportExportPage-BW6qO3kc.js +0 -248
  120. package/dist/InventoryPage-rMGuaJN-.js +0 -222
  121. package/dist/MarketplacePage-DKrXAv62.js +0 -219
  122. package/dist/ProductDetailsPage-CFGcbaHo.js +0 -195
  123. package/dist/ReportsPage-Bb7_90rK.js +0 -235
  124. package/dist/RouteDetailsPage-CVtDVb1N.js +0 -282
  125. package/dist/RoutesPage-s57PtgcQ.js +0 -163
  126. package/dist/SettingsPage-BYNCBOpN.js +0 -298
  127. package/dist/StatusBadge-CijYQXtb.js +0 -209
  128. package/dist/VehicleDetailsPage-3YDMPsPs.js +0 -220
  129. package/dist/WarehouseDetailsPage-Db7KeN-d.js +0 -238
  130. package/dist/graphqlClient-CdJyR_ed.js +0 -55
  131. package/dist/navigation-BgnOfsVd.js +0 -6
  132. package/dist/route-Dp9JiN_E.js +0 -51
  133. package/dist/settings-3Rw5NwFF.js +0 -28
  134. package/src/movethewheels/constants/mockData.ts +0 -1342
  135. /package/dist/{formatters-_vJlC-47.js → formatters-CF2S2l1m.js} +0 -0
@@ -2,8 +2,9 @@
2
2
  * Warehouse Details Page
3
3
  */
4
4
 
5
+ import { useState } from 'react';
5
6
  import { useParams } from 'react-router-dom';
6
- import { Warehouse, ArrowLeft, Edit, MapPin, Clock, Users, Box } from 'lucide-react';
7
+ import { Warehouse, ArrowLeft, Edit, MapPin, Clock, Users, Box, Save } from 'lucide-react';
7
8
  import { PageLayout, LoadingState, ErrorState } from '../components/PageLayout';
8
9
  import {
9
10
  Card,
@@ -13,12 +14,232 @@ import {
13
14
  Button,
14
15
  Badge,
15
16
  Progress,
17
+ Input,
18
+ Label,
19
+ Select,
20
+ SelectContent,
21
+ SelectItem,
22
+ SelectTrigger,
23
+ SelectValue,
16
24
  } from '../components/ui';
17
25
  import { EmphasisPanel, NextSteps, PagePurpose } from '@burdenoff/fe-libs/ui';
18
- import { useWarehouse } from '../hooks/useInventory';
26
+ import { useWarehouse, useInventory } from '../hooks/useInventory';
19
27
  import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
20
28
  import { formatAddress } from '../utils/formatters';
21
29
  import { joinPath } from '../utils/navigation';
30
+ import { FormError } from '../components/FormError';
31
+
32
+ const WAREHOUSE_TYPE_OPTIONS = [
33
+ { value: 'DISTRIBUTION', label: 'Distribution' },
34
+ { value: 'FULFILLMENT', label: 'Fulfillment' },
35
+ { value: 'COLD_STORAGE', label: 'Cold Storage' },
36
+ { value: 'CROSS_DOCK', label: 'Cross-Dock' },
37
+ { value: 'RETAIL', label: 'Retail' },
38
+ ];
39
+
40
+ function NewWarehouseForm() {
41
+ const { basePath, navigate } = useMoveTheWheels();
42
+ const { createWarehouse } = useInventory();
43
+ const [form, setForm] = useState({
44
+ code: '',
45
+ name: '',
46
+ type: 'DISTRIBUTION',
47
+ street: '',
48
+ city: '',
49
+ state: '',
50
+ postalCode: '',
51
+ country: 'USA',
52
+ totalCapacity: '',
53
+ });
54
+ const [submitting, setSubmitting] = useState(false);
55
+ const [error, setError] = useState<string | null>(null);
56
+
57
+ const goBack = () => navigate?.(joinPath(basePath, 'inventory/warehouses'));
58
+
59
+ const update = (field: keyof typeof form, value: string) =>
60
+ setForm((prev) => ({ ...prev, [field]: value }));
61
+
62
+ const handleSubmit = async (e: React.FormEvent) => {
63
+ e.preventDefault();
64
+ if (!form.code.trim() || !form.name.trim()) {
65
+ setError('Warehouse code and name are required.');
66
+ return;
67
+ }
68
+ if (!form.street.trim() || !form.city.trim()) {
69
+ setError('A street and city are required for the warehouse address.');
70
+ return;
71
+ }
72
+ setSubmitting(true);
73
+ setError(null);
74
+ try {
75
+ const totalCapacity = form.totalCapacity.trim() ? Number(form.totalCapacity) : undefined;
76
+ const created = await createWarehouse({
77
+ code: form.code.trim(),
78
+ name: form.name.trim(),
79
+ type: form.type,
80
+ address: {
81
+ street: form.street.trim(),
82
+ city: form.city.trim(),
83
+ state: form.state.trim(),
84
+ postalCode: form.postalCode.trim(),
85
+ country: form.country.trim(),
86
+ },
87
+ totalCapacity:
88
+ totalCapacity !== undefined && !Number.isNaN(totalCapacity) ? totalCapacity : undefined,
89
+ });
90
+ navigate?.(joinPath(basePath, `inventory/warehouses/${created.id}`));
91
+ } catch (err) {
92
+ console.error('Failed to create warehouse:', err);
93
+ setError(err instanceof Error ? err.message : 'Failed to create warehouse. Please try again.');
94
+ setSubmitting(false);
95
+ }
96
+ };
97
+
98
+ return (
99
+ <PageLayout
100
+ title="Add Warehouse"
101
+ subtitle="Register a storage and fulfilment site"
102
+ icon={<Warehouse size={24} />}
103
+ headerActions={
104
+ <div className="flex gap-2">
105
+ <Button variant="outline" onClick={goBack} disabled={submitting}>
106
+ <ArrowLeft size={16} /> Cancel
107
+ </Button>
108
+ <Button onClick={handleSubmit} disabled={submitting}>
109
+ <Save size={16} /> {submitting ? 'Saving...' : 'Add Warehouse'}
110
+ </Button>
111
+ </div>
112
+ }
113
+ >
114
+ <PagePurpose icon={<Warehouse size={18} />}>
115
+ Add a warehouse so you can store inventory and fulfil orders from it. A code, name, type and
116
+ location get it on the network — set a total capacity to track utilization.
117
+ </PagePurpose>
118
+
119
+ <form onSubmit={handleSubmit} className="max-w-2xl space-y-6">
120
+ <FormError message={error} />
121
+ <EmphasisPanel>
122
+ <h2 className="text-base font-semibold text-text-primary mb-4">Warehouse Details</h2>
123
+ <div className="space-y-4">
124
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
125
+ <div className="space-y-2">
126
+ <Label htmlFor="code">
127
+ Code <span className="text-status-error-text">*</span>
128
+ </Label>
129
+ <Input
130
+ id="code"
131
+ value={form.code}
132
+ onChange={(e) => update('code', e.target.value)}
133
+ placeholder="WH-SF-01"
134
+ required
135
+ />
136
+ </div>
137
+ <div className="space-y-2">
138
+ <Label htmlFor="name">
139
+ Name <span className="text-status-error-text">*</span>
140
+ </Label>
141
+ <Input
142
+ id="name"
143
+ value={form.name}
144
+ onChange={(e) => update('name', e.target.value)}
145
+ placeholder="San Francisco DC"
146
+ required
147
+ />
148
+ </div>
149
+ <div className="space-y-2">
150
+ <Label htmlFor="type">
151
+ Type <span className="text-status-error-text">*</span>
152
+ </Label>
153
+ <Select value={form.type} onValueChange={(value) => update('type', value)}>
154
+ <SelectTrigger id="type">
155
+ <SelectValue />
156
+ </SelectTrigger>
157
+ <SelectContent>
158
+ {WAREHOUSE_TYPE_OPTIONS.map((option) => (
159
+ <SelectItem key={option.value} value={option.value}>
160
+ {option.label}
161
+ </SelectItem>
162
+ ))}
163
+ </SelectContent>
164
+ </Select>
165
+ </div>
166
+ </div>
167
+ <div className="space-y-2">
168
+ <Label htmlFor="totalCapacity">Total Capacity (sq ft)</Label>
169
+ <Input
170
+ id="totalCapacity"
171
+ type="number"
172
+ min="0"
173
+ value={form.totalCapacity}
174
+ onChange={(e) => update('totalCapacity', e.target.value)}
175
+ placeholder="50000"
176
+ />
177
+ </div>
178
+ </div>
179
+ </EmphasisPanel>
180
+
181
+ <Card>
182
+ <CardHeader>
183
+ <CardTitle className="flex items-center gap-2">
184
+ <MapPin size={18} /> Address <span className="text-status-error-text">*</span>
185
+ </CardTitle>
186
+ </CardHeader>
187
+ <CardContent className="space-y-4">
188
+ <div className="space-y-2">
189
+ <Label htmlFor="street">Street</Label>
190
+ <Input
191
+ id="street"
192
+ value={form.street}
193
+ onChange={(e) => update('street', e.target.value)}
194
+ placeholder="500 Industrial Way"
195
+ />
196
+ </div>
197
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
198
+ <div className="space-y-2">
199
+ <Label htmlFor="city">City</Label>
200
+ <Input
201
+ id="city"
202
+ value={form.city}
203
+ onChange={(e) => update('city', e.target.value)}
204
+ placeholder="San Francisco"
205
+ />
206
+ </div>
207
+ <div className="space-y-2">
208
+ <Label htmlFor="state">State</Label>
209
+ <Input
210
+ id="state"
211
+ value={form.state}
212
+ onChange={(e) => update('state', e.target.value)}
213
+ placeholder="CA"
214
+ />
215
+ </div>
216
+ </div>
217
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
218
+ <div className="space-y-2">
219
+ <Label htmlFor="postalCode">ZIP / Postal Code</Label>
220
+ <Input
221
+ id="postalCode"
222
+ value={form.postalCode}
223
+ onChange={(e) => update('postalCode', e.target.value)}
224
+ placeholder="94103"
225
+ />
226
+ </div>
227
+ <div className="space-y-2">
228
+ <Label htmlFor="country">Country</Label>
229
+ <Input
230
+ id="country"
231
+ value={form.country}
232
+ onChange={(e) => update('country', e.target.value)}
233
+ placeholder="USA"
234
+ />
235
+ </div>
236
+ </div>
237
+ </CardContent>
238
+ </Card>
239
+ </form>
240
+ </PageLayout>
241
+ );
242
+ }
22
243
 
23
244
  export default function WarehouseDetailsPage() {
24
245
  const { warehouseId } = useParams<{ warehouseId: string }>();
@@ -28,6 +249,7 @@ export default function WarehouseDetailsPage() {
28
249
  const goBack = () => navigate?.(joinPath(basePath, 'inventory/warehouses'));
29
250
  const goTo = (path: string) => navigate?.(joinPath(basePath, path));
30
251
 
252
+ if (!warehouseId) return <NewWarehouseForm />;
31
253
  if (isLoading) return <LoadingState message="Loading warehouse details..." />;
32
254
  if (error || !warehouse) return <ErrorState title="Warehouse not found" onRetry={refetch} />;
33
255
 
@@ -99,7 +99,11 @@ export default function WarehousesPage() {
99
99
  icon={<Warehouse size={24} />}
100
100
  headerActions={
101
101
  <CTAOverflowMenu
102
- primary={{ label: 'Add Warehouse', icon: <Plus size={16} />, onSelect: () => {} }}
102
+ primary={{
103
+ label: 'Add Warehouse',
104
+ icon: <Plus size={16} />,
105
+ onSelect: () => goTo('inventory/warehouses/new'),
106
+ }}
103
107
  actions={[{ label: 'Refresh', icon: <RefreshCw size={16} />, onSelect: () => refetch() }]}
104
108
  />
105
109
  }
@@ -8,6 +8,7 @@
8
8
  import { createContext, useContext, useMemo, type FC, type PropsWithChildren } from 'react';
9
9
  import { MemoryRouter } from 'react-router-dom';
10
10
  import type { MoveTheWheelsRootProps, MoveTheWheelsContextValue } from '../types';
11
+ import { joinPath } from '../utils/navigation';
11
12
 
12
13
  const MoveTheWheelsContext = createContext<MoveTheWheelsContextValue | null>(null);
13
14
 
@@ -54,13 +55,13 @@ export function useMoveTheWheelsNavigate(): (path: string) => void {
54
55
  const { navigate, basePath } = useMoveTheWheels();
55
56
 
56
57
  return (path: string) => {
57
- // If path is absolute (starts with /), use it directly
58
- // Otherwise, prepend basePath
59
- if (path.startsWith('/')) {
58
+ // Genuine external URLs (http/https or protocol-relative) pass through
59
+ // untouched. Everything else is an in-app path and MUST be resolved against
60
+ // basePath — otherwise a leading "/" would escape the microfrontend mount.
61
+ if (/^(https?:)?\/\//i.test(path)) {
60
62
  navigate(path);
61
- } else {
62
- const cleanBase = basePath.endsWith('/') ? basePath.slice(0, -1) : basePath;
63
- navigate(`${cleanBase}/${path}`);
63
+ return;
64
64
  }
65
+ navigate(joinPath(basePath, path));
65
66
  };
66
67
  }
@@ -2,7 +2,7 @@
2
2
  * MoveTheWheels Zustand Store
3
3
  *
4
4
  * Manages UI state for the microfrontend.
5
- * Server/entity data comes from hooks with mock data (ready for GraphQL replacement).
5
+ * Server/entity data comes from hooks that query the live backend via GraphQL.
6
6
  */
7
7
 
8
8
  import { create } from 'zustand';
@@ -1,212 +0,0 @@
1
- import { M as e, d as t, f as n, g as r, h as i, i as a } from "./PageLayout-D3N8MCTm.js";
2
- import { t as o } from "./chart-column-D1Ym15-S.js";
3
- import { t as s } from "./dollar-sign-IB4O0wuQ.js";
4
- import { t as c } from "./package-BE7U0wQE.js";
5
- import { t as l } from "./trending-up-C-85AwGT.js";
6
- import { t as u } from "./truck-CtDjNFbi.js";
7
- import { t as d } from "./users-g2N0eL-Z.js";
8
- import { i as f, r as p, t as m } from "./useAnalytics-ph7eTIK6.js";
9
- import { r as h, t as g } from "./MetricCard-B7yMyvMX.js";
10
- import { n as _ } from "./formatters-_vJlC-47.js";
11
- import { jsx as v, jsxs as y } from "react/jsx-runtime";
12
- import { EmphasisPanel as b, PagePurpose as x } from "@burdenoff/fe-libs/ui";
13
- //#region src/movethewheels/pages/AnalyticsPage.tsx
14
- function S() {
15
- let { analytics: S } = m(), { orderData: C } = f(), { fleetData: w } = p();
16
- return /* @__PURE__ */ y(a, {
17
- title: "Analytics",
18
- subtitle: "Business performance and insights",
19
- icon: /* @__PURE__ */ v(o, { size: 24 }),
20
- children: [
21
- /* @__PURE__ */ v(x, {
22
- icon: /* @__PURE__ */ v(o, { size: 18 }),
23
- children: "See how the operation is really performing. Track order volume, revenue, on-time rate and customer satisfaction over time so you can spot trends, find bottlenecks, and decide where to invest — whether that's more vehicles, better routes, or new customers."
24
- }),
25
- /* @__PURE__ */ y(h, {
26
- columns: 5,
27
- children: [
28
- /* @__PURE__ */ v(g, {
29
- label: "Total Orders",
30
- value: S.overview.totalOrders.toLocaleString(),
31
- icon: /* @__PURE__ */ v(c, { size: 20 }),
32
- change: "+8.2%",
33
- changeType: "positive",
34
- trend: "up"
35
- }),
36
- /* @__PURE__ */ v(g, {
37
- treatment: "glass",
38
- glow: !0,
39
- label: "Revenue",
40
- value: _(S.overview.totalRevenue),
41
- icon: /* @__PURE__ */ v(s, { size: 20 }),
42
- change: "+12.5%",
43
- changeType: "positive",
44
- trend: "up"
45
- }),
46
- /* @__PURE__ */ v(g, {
47
- label: "Active Vehicles",
48
- value: S.overview.activeVehicles,
49
- icon: /* @__PURE__ */ v(u, { size: 20 })
50
- }),
51
- /* @__PURE__ */ v(g, {
52
- label: "On-Time Rate",
53
- value: `${S.overview.onTimeDeliveryRate}%`,
54
- icon: /* @__PURE__ */ v(l, { size: 20 }),
55
- changeType: S.overview.onTimeDeliveryRate >= 90 ? "positive" : "negative"
56
- }),
57
- /* @__PURE__ */ v(g, {
58
- label: "Satisfaction",
59
- value: S.overview.customerSatisfaction.toFixed(1),
60
- icon: /* @__PURE__ */ v(d, { size: 20 }),
61
- subtitle: "out of 5"
62
- })
63
- ]
64
- }),
65
- /* @__PURE__ */ y("div", {
66
- className: "grid grid-cols-1 lg:grid-cols-2 gap-6",
67
- children: [/* @__PURE__ */ y(t, { children: [/* @__PURE__ */ v(i, { children: /* @__PURE__ */ v(r, { children: "Order Trends" }) }), /* @__PURE__ */ y(n, { children: [/* @__PURE__ */ v("div", {
68
- className: "h-64 flex items-center justify-center bg-bg-sunken/50 rounded-lg",
69
- children: /* @__PURE__ */ y("div", {
70
- className: "text-center text-text-secondary",
71
- children: [
72
- /* @__PURE__ */ v(o, {
73
- size: 48,
74
- className: "mx-auto mb-2 opacity-50"
75
- }),
76
- /* @__PURE__ */ v("p", { children: "Order trend chart" }),
77
- /* @__PURE__ */ v("p", {
78
- className: "text-xs",
79
- children: "(Chart library integration needed)"
80
- })
81
- ]
82
- })
83
- }), /* @__PURE__ */ v("div", {
84
- className: "mt-4 grid grid-cols-4 gap-2",
85
- children: C.trends.slice(-4).map((e) => /* @__PURE__ */ y("div", {
86
- className: "text-center p-2 bg-bg-sunken/50 rounded",
87
- children: [/* @__PURE__ */ v("p", {
88
- className: "text-xs text-text-secondary",
89
- children: e.date.split("-").slice(1).join("/")
90
- }), /* @__PURE__ */ v("p", {
91
- className: "font-medium",
92
- children: e.orders
93
- })]
94
- }, e.date))
95
- })] })] }), /* @__PURE__ */ y(t, { children: [/* @__PURE__ */ v(i, { children: /* @__PURE__ */ v(r, { children: "Revenue Trends" }) }), /* @__PURE__ */ y(n, { children: [/* @__PURE__ */ v("div", {
96
- className: "h-64 flex items-center justify-center bg-bg-sunken/50 rounded-lg",
97
- children: /* @__PURE__ */ y("div", {
98
- className: "text-center text-text-secondary",
99
- children: [/* @__PURE__ */ v(l, {
100
- size: 48,
101
- className: "mx-auto mb-2 opacity-50"
102
- }), /* @__PURE__ */ v("p", { children: "Revenue trend chart" })]
103
- })
104
- }), /* @__PURE__ */ v("div", {
105
- className: "mt-4 grid grid-cols-5 gap-2",
106
- children: S.trends.revenue.map((e) => /* @__PURE__ */ y("div", {
107
- className: "text-center p-2 bg-bg-sunken/50 rounded",
108
- children: [/* @__PURE__ */ v("p", {
109
- className: "text-xs text-text-secondary",
110
- children: e.month
111
- }), /* @__PURE__ */ y("p", {
112
- className: "font-medium text-sm",
113
- children: [_(e.revenue / 1e3), "k"]
114
- })]
115
- }, e.month))
116
- })] })] })]
117
- }),
118
- /* @__PURE__ */ y("div", {
119
- className: "grid grid-cols-1 lg:grid-cols-3 gap-6",
120
- children: [
121
- /* @__PURE__ */ y(t, { children: [/* @__PURE__ */ v(i, { children: /* @__PURE__ */ v(r, { children: "Orders by Status" }) }), /* @__PURE__ */ v(n, {
122
- className: "space-y-3",
123
- children: C.byStatus.filter((e) => e.count > 0).map(({ status: t, count: n }) => /* @__PURE__ */ y("div", {
124
- className: "flex items-center justify-between",
125
- children: [/* @__PURE__ */ v("span", {
126
- className: "text-sm capitalize",
127
- children: t.replace("_", " ")
128
- }), /* @__PURE__ */ y("div", {
129
- className: "flex items-center gap-2",
130
- children: [/* @__PURE__ */ v(e, {
131
- value: n / S.overview.totalOrders * 100,
132
- className: "w-20 h-2"
133
- }), /* @__PURE__ */ v("span", {
134
- className: "font-medium w-8 text-right",
135
- children: n
136
- })]
137
- })]
138
- }, t))
139
- })] }),
140
- /* @__PURE__ */ y(t, { children: [/* @__PURE__ */ v(i, { children: /* @__PURE__ */ v(r, { children: "Fleet Performance" }) }), /* @__PURE__ */ y(n, {
141
- className: "space-y-4",
142
- children: [
143
- /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ y("div", {
144
- className: "flex justify-between text-sm mb-1",
145
- children: [/* @__PURE__ */ v("span", { children: "Vehicle Utilization" }), /* @__PURE__ */ y("span", { children: [w.vehicleUtilization.toFixed(0), "%"] })]
146
- }), /* @__PURE__ */ v(e, { value: w.vehicleUtilization })] }),
147
- /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ y("div", {
148
- className: "flex justify-between text-sm mb-1",
149
- children: [/* @__PURE__ */ v("span", { children: "Avg Fuel Level" }), /* @__PURE__ */ y("span", { children: [w.avgFuelLevel.toFixed(0), "%"] })]
150
- }), /* @__PURE__ */ v(e, { value: w.avgFuelLevel })] }),
151
- /* @__PURE__ */ y("div", {
152
- className: "pt-2",
153
- children: [/* @__PURE__ */ v("p", {
154
- className: "text-sm text-text-secondary mb-2",
155
- children: "Vehicles by Type"
156
- }), w.vehiclesByType.map(({ type: e, count: t }) => /* @__PURE__ */ y("div", {
157
- className: "flex justify-between text-sm py-1",
158
- children: [/* @__PURE__ */ v("span", {
159
- className: "capitalize",
160
- children: e
161
- }), /* @__PURE__ */ v("span", {
162
- className: "font-medium",
163
- children: t
164
- })]
165
- }, e))]
166
- })
167
- ]
168
- })] }),
169
- /* @__PURE__ */ y(b, {
170
- className: "space-y-4",
171
- children: [
172
- /* @__PURE__ */ v("h2", {
173
- className: "text-base font-semibold text-text-primary",
174
- children: "Performance Metrics"
175
- }),
176
- /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("p", {
177
- className: "text-sm text-text-secondary",
178
- children: "On-Time Pickup"
179
- }), /* @__PURE__ */ y("p", {
180
- className: "text-2xl font-bold",
181
- children: [S.performance.onTimePickup, "%"]
182
- })] }),
183
- /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("p", {
184
- className: "text-sm text-text-secondary",
185
- children: "On-Time Delivery"
186
- }), /* @__PURE__ */ y("p", {
187
- className: "text-2xl font-bold",
188
- children: [S.performance.onTimeDelivery, "%"]
189
- })] }),
190
- /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("p", {
191
- className: "text-sm text-text-secondary",
192
- children: "Damaged Items"
193
- }), /* @__PURE__ */ y("p", {
194
- className: "text-2xl font-bold text-status-success-text",
195
- children: [S.performance.damagedItems, "%"]
196
- })] }),
197
- /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("p", {
198
- className: "text-sm text-text-secondary",
199
- children: "Driver Ratings"
200
- }), /* @__PURE__ */ y("p", {
201
- className: "text-2xl font-bold",
202
- children: [S.performance.driverRatings, "/5"]
203
- })] })
204
- ]
205
- })
206
- ]
207
- })
208
- ]
209
- });
210
- }
211
- //#endregion
212
- export { S as default };