@burdenoff/microfe-movethewheels 2026.703.1 → 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 (69) hide show
  1. package/dist/{AIAssistantPage-C3ovZ0Fh.js → AIAssistantPage-C3cPsWt-.js} +1 -1
  2. package/dist/{AnalyticsPage-O8SpY-V4.js → AnalyticsPage-Dz6g2MvK.js} +6 -6
  3. package/dist/{CreateOrderPage-CB1_-_mN.js → CreateOrderPage-C5iwnjp4.js} +29 -58
  4. package/dist/CustomerDetailsPage-B6nwFyLO.js +406 -0
  5. package/dist/{CustomersPage-DRaLuHMC.js → CustomersPage-2Y05LVyh.js} +4 -4
  6. package/dist/{DashboardPage-DPjhNfKB.js → DashboardPage-BVjQi0EB.js} +11 -11
  7. package/dist/DriverDetailsPage-CN3WQ0B9.js +507 -0
  8. package/dist/{DriversPage-C2Bk0w4Q.js → DriversPage-B0Zpx8OQ.js} +5 -5
  9. package/dist/{FinancePage-lmp0Sdsw.js → FinancePage-DEDykSOP.js} +5 -5
  10. package/dist/{FleetPage-DZn5pIqd.js → FleetPage-DqkFi3s3.js} +5 -5
  11. package/dist/FormError-BlOjnXOq.js +15 -0
  12. package/dist/{ImportExportPage-BIUJZc7O.js → ImportExportPage-DKJRCezl.js} +1 -1
  13. package/dist/{InventoryPage-Cxh1zYJd.js → InventoryPage-DwfgCUQq.js} +5 -5
  14. package/dist/{LiveTrackingPage-BY1yAkIt.js → LiveTrackingPage-DCX-K-LR.js} +5 -5
  15. package/dist/{MarketplacePage-RMuL17EA.js → MarketplacePage-CIQ97_zp.js} +1 -1
  16. package/dist/{OrderDetailsPage-C2Mf4KSy.js → OrderDetailsPage-DYiZ-9UK.js} +5 -5
  17. package/dist/{OrdersListPage-BrPBtnhp.js → OrdersListPage-BjDlCKJd.js} +3 -3
  18. package/dist/ProductDetailsPage-C9uOiYLp.js +350 -0
  19. package/dist/{ProductsPage-I5DilIoY.js → ProductsPage-C1G9h7Xd.js} +3 -3
  20. package/dist/{ReportsPage-BDXNmUng.js → ReportsPage-Zp53q3_8.js} +2 -2
  21. package/dist/RouteDetailsPage-DUStXSf9.js +531 -0
  22. package/dist/{RoutesPage-lqX9ylHP.js → RoutesPage-DMfoicM1.js} +3 -3
  23. package/dist/{SettingsPage-CQVIOaNs.js → SettingsPage-Bn-v0mbQ.js} +1 -1
  24. package/dist/{TrackingPage-BXrjz7V8.js → TrackingPage-W-jtdM3Y.js} +4 -4
  25. package/dist/VehicleDetailsPage-Bceo5oz3.js +410 -0
  26. package/dist/{VehiclesPage-6W39XT5W.js → VehiclesPage-VBtOep91.js} +4 -4
  27. package/dist/WarehouseDetailsPage-L_6sWigM.js +493 -0
  28. package/dist/{WarehousesPage-CHvBqNaQ.js → WarehousesPage-DCbXXXWE.js} +3 -3
  29. package/dist/index.js +154 -138
  30. package/dist/trash-2-BKhar6Hs.js +32 -0
  31. package/dist/{useFleet-DiAC-IiH.js → useFleet-DKqXZ16m.js} +77 -56
  32. package/dist/{useInventory-DKoks37x.js → useInventory-DkyiVY_A.js} +73 -53
  33. package/dist/{useTracking-GJify4HN.js → useTracking-B-va1kO3.js} +2 -2
  34. package/package.json +1 -1
  35. package/src/movethewheels/MoveTheWheelsRoutes.tsx +4 -0
  36. package/src/movethewheels/components/FormError.tsx +25 -0
  37. package/src/movethewheels/hooks/useFleet.ts +107 -0
  38. package/src/movethewheels/hooks/useInventory.ts +107 -0
  39. package/src/movethewheels/pages/CustomerDetailsPage.tsx +153 -20
  40. package/src/movethewheels/pages/DriverDetailsPage.tsx +159 -2
  41. package/src/movethewheels/pages/DriversPage.tsx +5 -1
  42. package/src/movethewheels/pages/ProductDetailsPage.tsx +146 -3
  43. package/src/movethewheels/pages/ProductsPage.tsx +5 -1
  44. package/src/movethewheels/pages/RouteDetailsPage.tsx +285 -25
  45. package/src/movethewheels/pages/VehicleDetailsPage.tsx +158 -2
  46. package/src/movethewheels/pages/VehiclesPage.tsx +5 -1
  47. package/src/movethewheels/pages/WarehouseDetailsPage.tsx +224 -2
  48. package/src/movethewheels/pages/WarehousesPage.tsx +5 -1
  49. package/dist/CustomerDetailsPage-BaeKEI1D.js +0 -263
  50. package/dist/DriverDetailsPage-CSSQTOzn.js +0 -328
  51. package/dist/ProductDetailsPage-CezzzZcj.js +0 -193
  52. package/dist/RouteDetailsPage-BcomL20M.js +0 -263
  53. package/dist/VehicleDetailsPage-DZjLcJgr.js +0 -218
  54. package/dist/WarehouseDetailsPage-C10pgRGW.js +0 -236
  55. /package/dist/{MetricCard-7aYgzZHK.js → MetricCard-BY0QrMD4.js} +0 -0
  56. /package/dist/{StatusBadge-NpTeHVlw.js → StatusBadge-BZurYHMy.js} +0 -0
  57. /package/dist/{formatters-DhKZ-eA1.js → formatters-CF2S2l1m.js} +0 -0
  58. /package/dist/{trending-up-B7W-GL6P.js → trending-up-Dohgd4t_.js} +0 -0
  59. /package/dist/{triangle-alert-BonHFFNz.js → triangle-alert-i-XQL9Rd.js} +0 -0
  60. /package/dist/{truck-DrlfSpRC.js → truck-C0v_hbLR.js} +0 -0
  61. /package/dist/{useAnalytics-CgdzUfY_.js → useAnalytics-DS8n0xgg.js} +0 -0
  62. /package/dist/{useCustomers-QrlozybF.js → useCustomers-BmTNGxiI.js} +0 -0
  63. /package/dist/{useImportExport-BLMnAKCC.js → useImportExport-DHr-SWSw.js} +0 -0
  64. /package/dist/{useOrders-D3UZVy8Y.js → useOrders-Cfk1GLiq.js} +0 -0
  65. /package/dist/{useReports-Puq4DCH9.js → useReports-CTqZr-AB.js} +0 -0
  66. /package/dist/{useRoutes-Do57LvRb.js → useRoutes-BQWO607N.js} +0 -0
  67. /package/dist/{user-CjSoudeu.js → user-jyFU3lXk.js} +0 -0
  68. /package/dist/{users-BAM4gHTn.js → users-DZ-ilS6B.js} +0 -0
  69. /package/dist/{warehouse-C7MSr47B.js → warehouse-6m5kXMLu.js} +0 -0
@@ -2,8 +2,9 @@
2
2
  * Vehicle Details Page
3
3
  */
4
4
 
5
+ import { useState } from 'react';
5
6
  import { useParams } from 'react-router-dom';
6
- import { Truck, ArrowLeft, MapPin, Fuel, Wrench, FileText, Edit } from 'lucide-react';
7
+ import { Truck, ArrowLeft, MapPin, Fuel, Wrench, FileText, Edit, Save } from 'lucide-react';
7
8
  import { PageLayout, LoadingState, ErrorState } from '../components/PageLayout';
8
9
  import { StatusBadge, VehicleTypeBadge } from '../components/StatusBadge';
9
10
  import {
@@ -14,12 +15,166 @@ import {
14
15
  Button,
15
16
  Badge,
16
17
  Progress,
18
+ Input,
19
+ Label,
20
+ Select,
21
+ SelectContent,
22
+ SelectItem,
23
+ SelectTrigger,
24
+ SelectValue,
17
25
  } from '../components/ui';
18
26
  import { EmphasisPanel, NextSteps, PagePurpose } from '@burdenoff/fe-libs/ui';
19
- import { useVehicle } from '../hooks/useFleet';
27
+ import { useVehicle, useFleet } from '../hooks/useFleet';
20
28
  import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
21
29
  import { formatDate } from '../utils/formatters';
22
30
  import { joinPath } from '../utils/navigation';
31
+ import { FormError } from '../components/FormError';
32
+
33
+ const VEHICLE_TYPE_OPTIONS = [
34
+ { value: 'TRUCK', label: 'Truck' },
35
+ { value: 'VAN', label: 'Van' },
36
+ { value: 'MOTORCYCLE', label: 'Motorcycle' },
37
+ { value: 'BICYCLE', label: 'Bicycle' },
38
+ { value: 'FLATBED', label: 'Flatbed' },
39
+ { value: 'REFRIGERATED', label: 'Refrigerated' },
40
+ { value: 'SEMI_TRAILER', label: 'Semi-Trailer' },
41
+ { value: 'DRONE', label: 'Drone' },
42
+ ];
43
+
44
+ function NewVehicleForm() {
45
+ const { basePath, navigate } = useMoveTheWheels();
46
+ const { createVehicle } = useFleet();
47
+ const [form, setForm] = useState({
48
+ vehicleNumber: '',
49
+ type: 'VAN',
50
+ make: '',
51
+ model: '',
52
+ licensePlate: '',
53
+ });
54
+ const [submitting, setSubmitting] = useState(false);
55
+ const [error, setError] = useState<string | null>(null);
56
+
57
+ const goBack = () => navigate?.(joinPath(basePath, 'fleet/vehicles'));
58
+
59
+ const handleSubmit = async (e: React.FormEvent) => {
60
+ e.preventDefault();
61
+ if (!form.vehicleNumber.trim()) {
62
+ setError('Vehicle number is required.');
63
+ return;
64
+ }
65
+ setSubmitting(true);
66
+ setError(null);
67
+ try {
68
+ const created = await createVehicle({
69
+ vehicleNumber: form.vehicleNumber.trim(),
70
+ type: form.type,
71
+ make: form.make.trim() || undefined,
72
+ model: form.model.trim() || undefined,
73
+ licensePlate: form.licensePlate.trim() || undefined,
74
+ });
75
+ navigate?.(joinPath(basePath, `fleet/vehicles/${created.id}`));
76
+ } catch (err) {
77
+ console.error('Failed to create vehicle:', err);
78
+ setError(err instanceof Error ? err.message : 'Failed to create vehicle. Please try again.');
79
+ setSubmitting(false);
80
+ }
81
+ };
82
+
83
+ return (
84
+ <PageLayout
85
+ title="Add Vehicle"
86
+ subtitle="Register a new vehicle in your fleet"
87
+ icon={<Truck size={24} />}
88
+ headerActions={
89
+ <div className="flex gap-2">
90
+ <Button variant="outline" onClick={goBack} disabled={submitting}>
91
+ <ArrowLeft size={16} /> Cancel
92
+ </Button>
93
+ <Button onClick={handleSubmit} disabled={submitting}>
94
+ <Save size={16} /> {submitting ? 'Saving...' : 'Add Vehicle'}
95
+ </Button>
96
+ </div>
97
+ }
98
+ >
99
+ <PagePurpose icon={<Truck size={18} />}>
100
+ Add a vehicle so it can be assigned to deliveries and routes. Give it a fleet number and type
101
+ to start — make, model and plate help identify it on the road.
102
+ </PagePurpose>
103
+
104
+ <form onSubmit={handleSubmit} className="max-w-2xl space-y-6">
105
+ <FormError message={error} />
106
+ <EmphasisPanel>
107
+ <h2 className="text-base font-semibold text-text-primary mb-4">Vehicle Details</h2>
108
+ <div className="space-y-4">
109
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
110
+ <div className="space-y-2">
111
+ <Label htmlFor="vehicleNumber">
112
+ Vehicle Number <span className="text-status-error-text">*</span>
113
+ </Label>
114
+ <Input
115
+ id="vehicleNumber"
116
+ value={form.vehicleNumber}
117
+ onChange={(e) => setForm((prev) => ({ ...prev, vehicleNumber: e.target.value }))}
118
+ placeholder="MTW-001"
119
+ required
120
+ />
121
+ </div>
122
+ <div className="space-y-2">
123
+ <Label htmlFor="type">
124
+ Type <span className="text-status-error-text">*</span>
125
+ </Label>
126
+ <Select
127
+ value={form.type}
128
+ onValueChange={(value) => setForm((prev) => ({ ...prev, type: value }))}
129
+ >
130
+ <SelectTrigger id="type">
131
+ <SelectValue />
132
+ </SelectTrigger>
133
+ <SelectContent>
134
+ {VEHICLE_TYPE_OPTIONS.map((option) => (
135
+ <SelectItem key={option.value} value={option.value}>
136
+ {option.label}
137
+ </SelectItem>
138
+ ))}
139
+ </SelectContent>
140
+ </Select>
141
+ </div>
142
+ </div>
143
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
144
+ <div className="space-y-2">
145
+ <Label htmlFor="make">Make</Label>
146
+ <Input
147
+ id="make"
148
+ value={form.make}
149
+ onChange={(e) => setForm((prev) => ({ ...prev, make: e.target.value }))}
150
+ placeholder="Ford"
151
+ />
152
+ </div>
153
+ <div className="space-y-2">
154
+ <Label htmlFor="model">Model</Label>
155
+ <Input
156
+ id="model"
157
+ value={form.model}
158
+ onChange={(e) => setForm((prev) => ({ ...prev, model: e.target.value }))}
159
+ placeholder="Transit"
160
+ />
161
+ </div>
162
+ <div className="space-y-2">
163
+ <Label htmlFor="licensePlate">License Plate</Label>
164
+ <Input
165
+ id="licensePlate"
166
+ value={form.licensePlate}
167
+ onChange={(e) => setForm((prev) => ({ ...prev, licensePlate: e.target.value }))}
168
+ placeholder="ABC-1234"
169
+ />
170
+ </div>
171
+ </div>
172
+ </div>
173
+ </EmphasisPanel>
174
+ </form>
175
+ </PageLayout>
176
+ );
177
+ }
23
178
 
24
179
  export default function VehicleDetailsPage() {
25
180
  const { vehicleId } = useParams<{ vehicleId: string }>();
@@ -29,6 +184,7 @@ export default function VehicleDetailsPage() {
29
184
  const goBack = () => navigate?.(joinPath(basePath, 'fleet/vehicles'));
30
185
  const goTo = (path: string) => navigate?.(joinPath(basePath, path));
31
186
 
187
+ if (!vehicleId) return <NewVehicleForm />;
32
188
  if (isLoading) return <LoadingState message="Loading vehicle details..." />;
33
189
  if (error || !vehicle) return <ErrorState title="Vehicle not found" onRetry={refetch} />;
34
190
 
@@ -95,7 +95,11 @@ export default function VehiclesPage() {
95
95
  icon={<Truck size={24} />}
96
96
  headerActions={
97
97
  <CTAOverflowMenu
98
- primary={{ label: 'Add Vehicle', icon: <Plus size={16} />, onSelect: () => {} }}
98
+ primary={{
99
+ label: 'Add Vehicle',
100
+ icon: <Plus size={16} />,
101
+ onSelect: () => goTo('fleet/vehicles/new'),
102
+ }}
99
103
  actions={[
100
104
  { label: 'Refresh', icon: <RefreshCw size={16} />, onSelect: () => refetch() },
101
105
  { label: 'Export', icon: <Download size={16} />, onSelect: () => {} },
@@ -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
  }