@burdenoff/microfe-movethewheels 2026.924.1 → 2026.924.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.
@@ -0,0 +1,124 @@
1
+ import { Trash2 as e } from "../node_modules/lucide-react/dist/esm/icons/trash-2.js";
2
+ import { useProduct as t, useProductStockLevels as n } from "../hooks/useInventory.js";
3
+ import { Button as r, Input as i, Label as a, Separator as o } from "./ui.js";
4
+ import { EntityCombobox as s } from "./EntityCombobox.js";
5
+ import { Fragment as c, jsx as l, jsxs as u } from "react/jsx-runtime";
6
+ //#region src/movethewheels/components/OrderItemRow.tsx
7
+ function d(e, t) {
8
+ return e <= 0 ? "No stock recorded for this item." : t.length === 1 ? `${e.toLocaleString()} available at ${t[0].warehouseName}` : `${e.toLocaleString()} available across ${t.length} warehouses`;
9
+ }
10
+ function f({ item: f, index: p, isFirst: m, products: h, productsLoading: g, onUpdate: _, onRemove: v }) {
11
+ let { product: y, isLoading: b } = t(f.productId || void 0), { levels: x, totalAvailable: S, isLoading: C } = n(f.productId || void 0);
12
+ return /* @__PURE__ */ u("div", { children: [
13
+ !m && /* @__PURE__ */ l(o, { className: "my-4" }),
14
+ /* @__PURE__ */ u("div", {
15
+ className: "mb-3 space-y-2",
16
+ children: [
17
+ /* @__PURE__ */ l(a, {
18
+ htmlFor: `item-product-${f.id}`,
19
+ children: "Catalog item (optional)"
20
+ }),
21
+ /* @__PURE__ */ l(s, {
22
+ id: `item-product-${f.id}`,
23
+ value: f.productId,
24
+ onChange: (e) => {
25
+ if (!e) {
26
+ _(p, "productId", "");
27
+ return;
28
+ }
29
+ let t = h.find((t) => t.id === e);
30
+ t && (_(p, "productId", t.id), _(p, "name", t.name), _(p, "sku", t.sku), _(p, "weight", t.weight), _(p, "value", t.value), _(p, "dimensions", t.dimensions));
31
+ },
32
+ options: h,
33
+ loading: g,
34
+ getId: (e) => e.id,
35
+ getLabel: (e) => `${e.name} (${e.sku})`,
36
+ renderOption: (e) => /* @__PURE__ */ u(c, { children: [
37
+ e.name,
38
+ " ",
39
+ /* @__PURE__ */ u("span", {
40
+ className: "text-text-tertiary",
41
+ children: [
42
+ "(",
43
+ e.sku,
44
+ ")"
45
+ ]
46
+ })
47
+ ] }),
48
+ selectedOption: y,
49
+ selectedLoading: b,
50
+ placeholder: "Pick from your product catalog",
51
+ emptyText: "No products found.",
52
+ noneLabel: "Enter details manually"
53
+ }),
54
+ f.productId && !C && /* @__PURE__ */ l("p", {
55
+ className: "text-xs text-text-secondary",
56
+ children: d(S, x)
57
+ })
58
+ ]
59
+ }),
60
+ /* @__PURE__ */ u("div", {
61
+ className: "grid grid-cols-1 gap-4 md:grid-cols-7",
62
+ children: [
63
+ /* @__PURE__ */ u("div", {
64
+ className: "space-y-2 md:col-span-2",
65
+ children: [/* @__PURE__ */ l(a, { children: "Item Name" }), /* @__PURE__ */ l(i, {
66
+ value: f.name,
67
+ onChange: (e) => _(p, "name", e.target.value),
68
+ placeholder: "Product name"
69
+ })]
70
+ }),
71
+ /* @__PURE__ */ u("div", {
72
+ className: "space-y-2",
73
+ children: [/* @__PURE__ */ l(a, { children: "SKU" }), /* @__PURE__ */ l(i, {
74
+ value: f.sku,
75
+ onChange: (e) => _(p, "sku", e.target.value),
76
+ placeholder: "SKU-001"
77
+ })]
78
+ }),
79
+ /* @__PURE__ */ u("div", {
80
+ className: "space-y-2",
81
+ children: [/* @__PURE__ */ l(a, { children: "Quantity" }), /* @__PURE__ */ l(i, {
82
+ type: "number",
83
+ min: "1",
84
+ value: f.quantity,
85
+ onChange: (e) => _(p, "quantity", parseInt(e.target.value) || 1)
86
+ })]
87
+ }),
88
+ /* @__PURE__ */ u("div", {
89
+ className: "space-y-2",
90
+ children: [/* @__PURE__ */ l(a, { children: "Weight (kg)" }), /* @__PURE__ */ l(i, {
91
+ type: "number",
92
+ min: "0",
93
+ step: "0.1",
94
+ value: f.weight,
95
+ onChange: (e) => _(p, "weight", parseFloat(e.target.value) || 0)
96
+ })]
97
+ }),
98
+ /* @__PURE__ */ u("div", {
99
+ className: "space-y-2",
100
+ children: [/* @__PURE__ */ l(a, { children: "Value ($)" }), /* @__PURE__ */ l(i, {
101
+ type: "number",
102
+ min: "0",
103
+ step: "0.01",
104
+ value: f.value,
105
+ onChange: (e) => _(p, "value", parseFloat(e.target.value) || 0)
106
+ })]
107
+ }),
108
+ /* @__PURE__ */ l("div", {
109
+ className: "flex items-end",
110
+ children: /* @__PURE__ */ l(r, {
111
+ type: "button",
112
+ variant: "ghost",
113
+ size: "icon",
114
+ className: "text-status-error-text",
115
+ onClick: () => v(p),
116
+ children: /* @__PURE__ */ l(e, { size: 16 })
117
+ })
118
+ })
119
+ ]
120
+ })
121
+ ] });
122
+ }
123
+ //#endregion
124
+ export { f as OrderItemRow };
@@ -0,0 +1,13 @@
1
+ import { OrderItem, Product } from '../types';
2
+
3
+ interface OrderItemRowProps {
4
+ item: OrderItem;
5
+ index: number;
6
+ isFirst: boolean;
7
+ products: Product[];
8
+ productsLoading: boolean;
9
+ onUpdate: (index: number, field: string, value: unknown) => void;
10
+ onRemove: (index: number) => void;
11
+ }
12
+ export declare function OrderItemRow({ item, index, isFirst, products, productsLoading, onUpdate, onRemove, }: OrderItemRowProps): import("react").JSX.Element;
13
+ export {};
@@ -4,148 +4,152 @@ import { MapPin as n } from "../node_modules/lucide-react/dist/esm/icons/map-pin
4
4
  import { Package as r } from "../node_modules/lucide-react/dist/esm/icons/package.js";
5
5
  import { Plus as i } from "../node_modules/lucide-react/dist/esm/icons/plus.js";
6
6
  import { Route as a } from "../node_modules/lucide-react/dist/esm/icons/route.js";
7
- import { Save as o } from "../node_modules/lucide-react/dist/esm/icons/save.js";
8
- import { Trash2 as ee } from "../node_modules/lucide-react/dist/esm/icons/trash-2.js";
7
+ import { Save as ee } from "../node_modules/lucide-react/dist/esm/icons/save.js";
9
8
  import { Users as te } from "../node_modules/lucide-react/dist/esm/icons/users.js";
10
- import { buildCustomerCreatePath as ne, joinPath as s } from "../utils/navigation.js";
11
- import { useMoveTheWheels as re } from "../providers/MoveTheWheelsProvider.js";
12
- import { useRoute as ie, useRoutes as ae } from "../hooks/useRoutes.js";
13
- import { useOrder as oe, useOrders as c } from "../hooks/useOrders.js";
14
- import { useCustomer as l, useCustomers as u } from "../hooks/useCustomers.js";
15
- import { Button as d, Card as f, CardContent as p, CardHeader as m, CardTitle as h, Input as g, Label as _, Select as se, SelectContent as ce, SelectItem as v, SelectTrigger as le, SelectValue as ue, Separator as de, Textarea as y } from "../components/ui.js";
9
+ import { buildCustomerCreatePath as ne, joinPath as o } from "../utils/navigation.js";
10
+ import { useMoveTheWheels as s } from "../providers/MoveTheWheelsProvider.js";
11
+ import { useRoute as c, useRoutes as l } from "../hooks/useRoutes.js";
12
+ import { useOrder as re, useOrders as ie } from "../hooks/useOrders.js";
13
+ import { useProducts as ae } from "../hooks/useInventory.js";
14
+ import { useCustomer as oe, useCustomers as se } from "../hooks/useCustomers.js";
15
+ import { Button as u, Card as d, CardContent as f, CardHeader as p, CardTitle as m, Input as h, Label as g, Select as ce, SelectContent as le, SelectItem as _, SelectTrigger as v, SelectValue as ue, Textarea as de } from "../components/ui.js";
16
16
  import { EmptyState as fe, PageLayout as pe } from "../components/PageLayout.js";
17
17
  import { FormError as me } from "../components/FormError.js";
18
18
  import { EntityCombobox as he } from "../components/EntityCombobox.js";
19
19
  import { CustomerPicker as ge } from "../components/CustomerPicker.js";
20
- import { useEffect as b, useState as x } from "react";
21
- import { useParams as _e, useSearchParams as ve } from "react-router";
22
- import { Fragment as ye, jsx as S, jsxs as C } from "react/jsx-runtime";
23
- import { EmphasisPanel as be, NextSteps as xe, PagePurpose as Se } from "@burdenoff/fe-libs/ui";
20
+ import { OrderItemRow as _e } from "../components/OrderItemRow.js";
21
+ import { useEffect as y, useState as b } from "react";
22
+ import { useParams as ve, useSearchParams as ye } from "react-router";
23
+ import { Fragment as be, jsx as x, jsxs as S } from "react/jsx-runtime";
24
+ import { EmphasisPanel as xe, NextSteps as Se, PagePurpose as Ce } from "@burdenoff/fe-libs/ui";
24
25
  //#region src/movethewheels/pages/CreateOrderPage.tsx
25
- function w(e) {
26
+ function C(e) {
26
27
  if (!e || Number.isNaN(e.getTime())) return "";
27
28
  let t = (e) => String(e).padStart(2, "0");
28
29
  return `${e.getFullYear()}-${t(e.getMonth() + 1)}-${t(e.getDate())}T${t(e.getHours())}:${t(e.getMinutes())}`;
29
30
  }
30
- function T() {
31
- let { orderId: T } = _e(), [E] = ve(), D = E.get("customerId")?.trim() || void 0, { basePath: O, navigate: k } = re(), { order: A } = oe(T), { createOrder: j, updateOrder: Ce } = c(), [we, Te] = x(""), { customers: M, createCustomer: Ee, isLoading: N, error: P, refetch: De } = u({
31
+ function w() {
32
+ let { orderId: w } = ve(), [T] = ye(), E = T.get("customerId")?.trim() || void 0, { basePath: D, navigate: O } = s(), { order: k } = re(w), { createOrder: A, updateOrder: we } = ie(), [Te, Ee] = b(""), { customers: j, createCustomer: M, isLoading: N, error: P, refetch: De } = se({
32
33
  limit: 20,
33
- filters: { search: we || void 0 }
34
- }), { customer: F } = l(D ?? A?.customerId), [Oe, ke] = x(""), { routes: I, isLoading: L, error: R, hasMore: Ae, totalRoutes: je } = ae({
34
+ filters: { search: Te || void 0 }
35
+ }), { customer: F } = oe(E ?? k?.customerId), [Oe, ke] = b(""), { routes: I, isLoading: L, error: R, hasMore: Ae, totalRoutes: je } = l({
35
36
  status: "planned",
36
37
  search: Oe || void 0,
37
38
  limit: 20
38
- }), z = !!T && !!A, [B, V] = x(null), [H, U] = x({
39
- customerId: D || A?.customerId || "",
40
- priority: A?.priority || "normal",
41
- routeId: A?.routeId || "",
39
+ }), [z, Me] = b(""), { products: Ne, isLoading: Pe } = ae({
40
+ search: z || void 0,
41
+ limit: 20
42
+ }), B = !!w && !!k, [V, H] = b(null), [U, W] = b({
43
+ customerId: E || k?.customerId || "",
44
+ priority: k?.priority || "normal",
45
+ routeId: k?.routeId || "",
42
46
  pickupAddress: {
43
- street: A?.pickupAddress.street || "",
44
- city: A?.pickupAddress.city || "",
45
- state: A?.pickupAddress.state || "",
46
- postalCode: A?.pickupAddress.postalCode || "",
47
- country: A?.pickupAddress.country || "USA"
47
+ street: k?.pickupAddress.street || "",
48
+ city: k?.pickupAddress.city || "",
49
+ state: k?.pickupAddress.state || "",
50
+ postalCode: k?.pickupAddress.postalCode || "",
51
+ country: k?.pickupAddress.country || "USA"
48
52
  },
49
53
  deliveryAddress: {
50
- street: A?.deliveryAddress.street || "",
51
- city: A?.deliveryAddress.city || "",
52
- state: A?.deliveryAddress.state || "",
53
- postalCode: A?.deliveryAddress.postalCode || "",
54
- country: A?.deliveryAddress.country || "USA"
54
+ street: k?.deliveryAddress.street || "",
55
+ city: k?.deliveryAddress.city || "",
56
+ state: k?.deliveryAddress.state || "",
57
+ postalCode: k?.deliveryAddress.postalCode || "",
58
+ country: k?.deliveryAddress.country || "USA"
55
59
  },
56
- items: A?.items || [],
57
- scheduledDelivery: w(A?.scheduledDelivery),
58
- specialInstructions: A?.specialInstructions || ""
59
- }), { route: Me, isLoading: Ne } = ie(H.routeId || void 0), [W, G] = x(!1), [Pe, K] = x(null);
60
- b(() => {
61
- F && (V((e) => e?.id === F.id ? e : F), U((e) => e.customerId ? e : {
60
+ items: k?.items || [],
61
+ scheduledDelivery: C(k?.scheduledDelivery),
62
+ specialInstructions: k?.specialInstructions || ""
63
+ }), { route: Fe, isLoading: Ie } = c(U.routeId || void 0), [G, K] = b(!1), [Le, q] = b(null);
64
+ y(() => {
65
+ F && (H((e) => e?.id === F.id ? e : F), W((e) => e.customerId ? e : {
62
66
  ...e,
63
67
  customerId: F.id
64
68
  }));
65
- }, [F]), b(() => {
66
- A && U({
67
- customerId: A.customerId || "",
68
- priority: A.priority || "normal",
69
- routeId: A.routeId || "",
69
+ }, [F]), y(() => {
70
+ k && W({
71
+ customerId: k.customerId || "",
72
+ priority: k.priority || "normal",
73
+ routeId: k.routeId || "",
70
74
  pickupAddress: {
71
- street: A.pickupAddress.street || "",
72
- city: A.pickupAddress.city || "",
73
- state: A.pickupAddress.state || "",
74
- postalCode: A.pickupAddress.postalCode || "",
75
- country: A.pickupAddress.country || "USA"
75
+ street: k.pickupAddress.street || "",
76
+ city: k.pickupAddress.city || "",
77
+ state: k.pickupAddress.state || "",
78
+ postalCode: k.pickupAddress.postalCode || "",
79
+ country: k.pickupAddress.country || "USA"
76
80
  },
77
81
  deliveryAddress: {
78
- street: A.deliveryAddress.street || "",
79
- city: A.deliveryAddress.city || "",
80
- state: A.deliveryAddress.state || "",
81
- postalCode: A.deliveryAddress.postalCode || "",
82
- country: A.deliveryAddress.country || "USA"
82
+ street: k.deliveryAddress.street || "",
83
+ city: k.deliveryAddress.city || "",
84
+ state: k.deliveryAddress.state || "",
85
+ postalCode: k.deliveryAddress.postalCode || "",
86
+ country: k.deliveryAddress.country || "USA"
83
87
  },
84
- items: A.items || [],
85
- scheduledDelivery: w(A.scheduledDelivery),
86
- specialInstructions: A.specialInstructions || ""
88
+ items: k.items || [],
89
+ scheduledDelivery: C(k.scheduledDelivery),
90
+ specialInstructions: k.specialInstructions || ""
87
91
  });
88
- }, [A]);
89
- let q = () => {
90
- if (k) {
91
- if (!z && D) {
92
- k(s(O, `customers/${D}`));
92
+ }, [k]);
93
+ let J = () => {
94
+ if (O) {
95
+ if (!B && E) {
96
+ O(o(D, `customers/${E}`));
93
97
  return;
94
98
  }
95
- k(s(O, "orders"));
99
+ O(o(D, "orders"));
96
100
  }
97
- }, J = () => B ?? M.find((e) => e.id === H.customerId), Fe = () => !H.customerId || !J() ? P ? "Customers could not be loaded. Retry or create a customer before continuing." : "Select a customer for this order." : H.pickupAddress.street.trim() ? H.deliveryAddress.street.trim() ? H.items.length === 0 ? "Add at least one item to the order." : H.scheduledDelivery && Number.isNaN(Date.parse(H.scheduledDelivery)) ? "Enter a valid scheduled delivery date and time." : null : "Enter a delivery street address." : "Enter a pickup street address.", Y = async (e) => {
98
- e.preventDefault(), K(null);
99
- let t = Fe();
101
+ }, Y = () => V ?? j.find((e) => e.id === U.customerId), Re = () => !U.customerId || !Y() ? P ? "Customers could not be loaded. Retry or create a customer before continuing." : "Select a customer for this order." : U.pickupAddress.street.trim() ? U.deliveryAddress.street.trim() ? U.items.length === 0 ? "Add at least one item to the order." : U.scheduledDelivery && Number.isNaN(Date.parse(U.scheduledDelivery)) ? "Enter a valid scheduled delivery date and time." : null : "Enter a delivery street address." : "Enter a pickup street address.", X = async (e) => {
102
+ e.preventDefault(), q(null);
103
+ let t = Re();
100
104
  if (t) {
101
- K(t);
105
+ q(t);
102
106
  return;
103
107
  }
104
- let n = J();
108
+ let n = Y();
105
109
  if (!n) {
106
- K(P ? "Customers could not be loaded. Retry or create a customer before continuing." : "Select a customer for this order.");
110
+ q(P ? "Customers could not be loaded. Retry or create a customer before continuing." : "Select a customer for this order.");
107
111
  return;
108
112
  }
109
- G(!0);
113
+ K(!0);
110
114
  try {
111
115
  let e = {
112
- customerId: H.customerId,
116
+ customerId: U.customerId,
113
117
  customerInfo: {
114
118
  name: n.name,
115
119
  email: n.email,
116
120
  phone: n.phone,
117
121
  company: n.company
118
122
  },
119
- priority: H.priority,
120
- pickupAddress: H.pickupAddress,
121
- deliveryAddress: H.deliveryAddress,
122
- items: H.items,
123
- scheduledDelivery: H.scheduledDelivery ? new Date(H.scheduledDelivery) : null,
124
- routeId: H.routeId || void 0,
125
- specialInstructions: H.specialInstructions
123
+ priority: U.priority,
124
+ pickupAddress: U.pickupAddress,
125
+ deliveryAddress: U.deliveryAddress,
126
+ items: U.items,
127
+ scheduledDelivery: U.scheduledDelivery ? new Date(U.scheduledDelivery) : null,
128
+ routeId: U.routeId || void 0,
129
+ specialInstructions: U.specialInstructions
126
130
  };
127
- z && T ? (await Ce(T, e), k && k(s(O, `orders/${T}`))) : (await j(e), q());
131
+ B && w ? (await we(w, e), O && O(o(D, `orders/${w}`))) : (await A(e), J());
128
132
  } catch (e) {
129
- K(e instanceof Error ? e.message : z ? "Could not update the order. Please try again." : "Could not create the order. Please try again.");
133
+ q(e instanceof Error ? e.message : B ? "Could not update the order. Please try again." : "Could not create the order. Please try again.");
130
134
  } finally {
131
- G(!1);
135
+ K(!1);
132
136
  }
133
- }, X = (e, t) => {
134
- U((n) => ({
137
+ }, Z = (e, t) => {
138
+ W((n) => ({
135
139
  ...n,
136
140
  [e]: t
137
141
  }));
138
- }, Z = (e, t, n) => {
139
- U((r) => ({
142
+ }, Q = (e, t, n) => {
143
+ W((r) => ({
140
144
  ...r,
141
145
  [e]: {
142
146
  ...r[e],
143
147
  [t]: n
144
148
  }
145
149
  }));
146
- }, Ie = (e) => {
150
+ }, ze = (e) => {
147
151
  if (!e) {
148
- X("routeId", "");
152
+ Z("routeId", "");
149
153
  return;
150
154
  }
151
155
  let t = I.find((t) => t.id === e);
@@ -157,14 +161,14 @@ function T() {
157
161
  postalCode: e.postalCode.trim() ? e.postalCode : t.postalCode,
158
162
  country: e.country.trim() ? e.country : t.country
159
163
  } : e;
160
- U((e) => ({
164
+ W((e) => ({
161
165
  ...e,
162
166
  routeId: t.id,
163
167
  pickupAddress: i(e.pickupAddress, n),
164
168
  deliveryAddress: i(e.deliveryAddress, r)
165
169
  }));
166
- }, Q = () => {
167
- U((e) => ({
170
+ }, $ = () => {
171
+ W((e) => ({
168
172
  ...e,
169
173
  items: [...e.items, {
170
174
  id: `item-${Date.now()}`,
@@ -182,13 +186,13 @@ function T() {
182
186
  sku: ""
183
187
  }]
184
188
  }));
185
- }, Le = (e) => {
186
- U((t) => ({
189
+ }, Be = (e) => {
190
+ W((t) => ({
187
191
  ...t,
188
192
  items: t.items.filter((t, n) => n !== e)
189
193
  }));
190
- }, $ = (e, t, n) => {
191
- U((r) => ({
194
+ }, Ve = (e, t, n) => {
195
+ W((r) => ({
192
196
  ...r,
193
197
  items: r.items.map((r, i) => i === e ? {
194
198
  ...r,
@@ -196,111 +200,111 @@ function T() {
196
200
  } : r)
197
201
  }));
198
202
  };
199
- return /* @__PURE__ */ C(pe, {
200
- title: z ? "Edit Order" : "Create Order",
201
- subtitle: z ? `Editing ${A?.orderNumber}` : "Create a new delivery order",
202
- icon: /* @__PURE__ */ S(r, { size: 24 }),
203
- headerActions: /* @__PURE__ */ C("div", {
203
+ return /* @__PURE__ */ S(pe, {
204
+ title: B ? "Edit Order" : "Create Order",
205
+ subtitle: B ? `Editing ${k?.orderNumber}` : "Create a new delivery order",
206
+ icon: /* @__PURE__ */ x(r, { size: 24 }),
207
+ headerActions: /* @__PURE__ */ S("div", {
204
208
  className: "flex gap-2",
205
- children: [/* @__PURE__ */ C(d, {
209
+ children: [/* @__PURE__ */ S(u, {
206
210
  variant: "outline",
207
- onClick: q,
208
- children: [/* @__PURE__ */ S(e, { size: 16 }), "Cancel"]
209
- }), /* @__PURE__ */ C(d, {
210
- onClick: Y,
211
- disabled: W || N,
212
- children: [/* @__PURE__ */ S(o, { size: 16 }), W ? "Saving..." : z ? "Save Changes" : "Create Order"]
211
+ onClick: J,
212
+ children: [/* @__PURE__ */ x(e, { size: 16 }), "Cancel"]
213
+ }), /* @__PURE__ */ S(u, {
214
+ onClick: X,
215
+ disabled: G || N,
216
+ children: [/* @__PURE__ */ x(ee, { size: 16 }), G ? "Saving..." : B ? "Save Changes" : "Create Order"]
213
217
  })]
214
218
  }),
215
219
  children: [
216
- /* @__PURE__ */ S(Se, {
217
- icon: /* @__PURE__ */ S(r, { size: 18 }),
218
- children: z ? "Update this delivery before it goes out — change the customer, addresses, items or handling notes, then save." : "Book a new delivery in a few steps: choose who it’s for, set pickup and drop-off addresses, list what’s being shipped, and add any handling notes. Once created it joins the orders pipeline ready to assign and track."
220
+ /* @__PURE__ */ x(Ce, {
221
+ icon: /* @__PURE__ */ x(r, { size: 18 }),
222
+ children: B ? "Update this delivery before it goes out — change the customer, addresses, items or handling notes, then save." : "Book a new delivery in a few steps: choose who it’s for, set pickup and drop-off addresses, list what’s being shipped, and add any handling notes. Once created it joins the orders pipeline ready to assign and track."
219
223
  }),
220
- /* @__PURE__ */ S(xe, {
224
+ /* @__PURE__ */ x(Se, {
221
225
  storageKey: "movethewheels-create-order",
222
226
  steps: [
223
227
  {
224
228
  id: "customer",
225
229
  label: "Pick the customer first",
226
230
  description: "Their saved contact details auto-fill the order.",
227
- icon: /* @__PURE__ */ S(te, { size: 16 }),
228
- done: !!H.customerId,
231
+ icon: /* @__PURE__ */ x(te, { size: 16 }),
232
+ done: !!U.customerId,
229
233
  onClick: () => document.getElementById("customer")?.focus()
230
234
  },
231
235
  {
232
236
  id: "addresses",
233
237
  label: "Set pickup & delivery addresses",
234
238
  description: "Where the shipment is collected and dropped off.",
235
- icon: /* @__PURE__ */ S(n, { size: 16 }),
236
- done: !!H.pickupAddress.street && !!H.deliveryAddress.street,
239
+ icon: /* @__PURE__ */ x(n, { size: 16 }),
240
+ done: !!U.pickupAddress.street && !!U.deliveryAddress.street,
237
241
  onClick: () => document.getElementById("pickupStreet")?.focus()
238
242
  },
239
243
  {
240
244
  id: "items",
241
245
  label: "Add the items to ship",
242
246
  description: "List each product with its quantity and value.",
243
- icon: /* @__PURE__ */ S(r, { size: 16 }),
244
- done: H.items.length > 0,
245
- onClick: Q
247
+ icon: /* @__PURE__ */ x(r, { size: 16 }),
248
+ done: U.items.length > 0,
249
+ onClick: $
246
250
  }
247
251
  ]
248
252
  }),
249
- /* @__PURE__ */ C("form", {
250
- onSubmit: Y,
253
+ /* @__PURE__ */ S("form", {
254
+ onSubmit: X,
251
255
  className: "space-y-6",
252
256
  children: [
253
- /* @__PURE__ */ S(me, { message: Pe }),
254
- /* @__PURE__ */ C(be, { children: [/* @__PURE__ */ S("h2", {
257
+ /* @__PURE__ */ x(me, { message: Le }),
258
+ /* @__PURE__ */ S(xe, { children: [/* @__PURE__ */ x("h2", {
255
259
  className: "text-base font-semibold text-text-primary mb-4",
256
260
  children: "Order Details"
257
- }), /* @__PURE__ */ S("div", {
261
+ }), /* @__PURE__ */ x("div", {
258
262
  className: "space-y-4",
259
- children: /* @__PURE__ */ C("div", {
263
+ children: /* @__PURE__ */ S("div", {
260
264
  className: "grid grid-cols-1 md:grid-cols-2 gap-4",
261
- children: [/* @__PURE__ */ S(ge, {
262
- customers: M,
263
- value: H.customerId,
265
+ children: [/* @__PURE__ */ x(ge, {
266
+ customers: j,
267
+ value: U.customerId,
264
268
  onValueChange: (e) => {
265
- e && (X("customerId", e), V(M.find((t) => t.id === e) ?? (B?.id === e ? B : null)), K(null));
269
+ e && (Z("customerId", e), H(j.find((t) => t.id === e) ?? (V?.id === e ? V : null)), q(null));
266
270
  },
267
271
  onCreated: (e) => {
268
- V(e), X("customerId", e.id), K(null);
272
+ H(e), Z("customerId", e.id), q(null);
269
273
  },
270
- createCustomer: Ee,
274
+ createCustomer: M,
271
275
  isLoading: N,
272
276
  error: P,
273
277
  onRetry: De,
274
278
  onOpenCustomers: () => {
275
- k && k(s(O, ne(z && T ? `orders/${T}/edit` : "orders/new")));
279
+ O && O(o(D, ne(B && w ? `orders/${w}/edit` : "orders/new")));
276
280
  },
277
- selectedCustomer: B,
278
- onSearchQueryChange: Te
279
- }), /* @__PURE__ */ C("div", {
281
+ selectedCustomer: V,
282
+ onSearchQueryChange: Ee
283
+ }), /* @__PURE__ */ S("div", {
280
284
  className: "space-y-2",
281
- children: [/* @__PURE__ */ S(_, {
285
+ children: [/* @__PURE__ */ x(g, {
282
286
  htmlFor: "priority",
283
287
  children: "Priority"
284
- }), /* @__PURE__ */ C(se, {
285
- value: H.priority,
286
- onValueChange: (e) => X("priority", e),
287
- children: [/* @__PURE__ */ S(le, {
288
+ }), /* @__PURE__ */ S(ce, {
289
+ value: U.priority,
290
+ onValueChange: (e) => Z("priority", e),
291
+ children: [/* @__PURE__ */ x(v, {
288
292
  id: "priority",
289
- children: /* @__PURE__ */ S(ue, {})
290
- }), /* @__PURE__ */ C(ce, { children: [
291
- /* @__PURE__ */ S(v, {
293
+ children: /* @__PURE__ */ x(ue, {})
294
+ }), /* @__PURE__ */ S(le, { children: [
295
+ /* @__PURE__ */ x(_, {
292
296
  value: "low",
293
297
  children: "Low"
294
298
  }),
295
- /* @__PURE__ */ S(v, {
299
+ /* @__PURE__ */ x(_, {
296
300
  value: "normal",
297
301
  children: "Normal"
298
302
  }),
299
- /* @__PURE__ */ S(v, {
303
+ /* @__PURE__ */ x(_, {
300
304
  value: "high",
301
305
  children: "High"
302
306
  }),
303
- /* @__PURE__ */ S(v, {
307
+ /* @__PURE__ */ x(_, {
304
308
  value: "urgent",
305
309
  children: "Urgent"
306
310
  })
@@ -309,27 +313,27 @@ function T() {
309
313
  })]
310
314
  })
311
315
  })] }),
312
- /* @__PURE__ */ C(f, { children: [/* @__PURE__ */ S(m, { children: /* @__PURE__ */ C(h, {
316
+ /* @__PURE__ */ S(d, { children: [/* @__PURE__ */ x(p, { children: /* @__PURE__ */ S(m, {
313
317
  className: "flex items-center gap-2",
314
- children: [/* @__PURE__ */ S(a, { size: 18 }), "Saved Route (Optional)"]
315
- }) }), /* @__PURE__ */ C(p, {
318
+ children: [/* @__PURE__ */ x(a, { size: 18 }), "Saved Route (Optional)"]
319
+ }) }), /* @__PURE__ */ S(f, {
316
320
  className: "space-y-2",
317
- children: [/* @__PURE__ */ S(he, {
321
+ children: [/* @__PURE__ */ x(he, {
318
322
  id: "saved-route",
319
- value: H.routeId,
320
- onChange: Ie,
323
+ value: U.routeId,
324
+ onChange: ze,
321
325
  options: I,
322
326
  loading: L,
323
327
  getId: (e) => e.id,
324
328
  getLabel: (e) => `${e.name} · ${e.stops.length} stops`,
325
- renderOption: (e) => /* @__PURE__ */ C(ye, { children: [
329
+ renderOption: (e) => /* @__PURE__ */ S(be, { children: [
326
330
  e.name,
327
331
  " · ",
328
332
  e.stops.length,
329
333
  " stops"
330
334
  ] }),
331
- selectedOption: Me,
332
- selectedLoading: Ne,
335
+ selectedOption: Fe,
336
+ selectedLoading: Ie,
333
337
  placeholder: "Choose a saved route",
334
338
  searchPlaceholder: "Search saved routes",
335
339
  emptyText: "No saved routes found.",
@@ -338,144 +342,144 @@ function T() {
338
342
  onSearchChange: ke,
339
343
  hasMore: Ae,
340
344
  totalCount: je
341
- }), /* @__PURE__ */ S("p", {
345
+ }), /* @__PURE__ */ x("p", {
342
346
  className: "text-xs text-text-secondary",
343
347
  children: L ? "Loading planned routes…" : R ? "Saved routes are unavailable; enter pickup and delivery addresses manually." : "A saved route fills any blank address fields. You can always edit both addresses below."
344
348
  })]
345
349
  })] }),
346
- /* @__PURE__ */ C("div", {
350
+ /* @__PURE__ */ S("div", {
347
351
  className: "grid grid-cols-1 md:grid-cols-2 gap-6",
348
- children: [/* @__PURE__ */ C(f, { children: [/* @__PURE__ */ S(m, { children: /* @__PURE__ */ S(h, { children: "Pickup Address" }) }), /* @__PURE__ */ C(p, {
352
+ children: [/* @__PURE__ */ S(d, { children: [/* @__PURE__ */ x(p, { children: /* @__PURE__ */ x(m, { children: "Pickup Address" }) }), /* @__PURE__ */ S(f, {
349
353
  className: "space-y-4",
350
354
  children: [
351
- /* @__PURE__ */ C("div", {
355
+ /* @__PURE__ */ S("div", {
352
356
  className: "space-y-2",
353
- children: [/* @__PURE__ */ S(_, {
357
+ children: [/* @__PURE__ */ x(g, {
354
358
  htmlFor: "pickupStreet",
355
359
  children: "Street Address"
356
- }), /* @__PURE__ */ S(g, {
360
+ }), /* @__PURE__ */ x(h, {
357
361
  id: "pickupStreet",
358
- value: H.pickupAddress.street,
359
- onChange: (e) => Z("pickupAddress", "street", e.target.value),
362
+ value: U.pickupAddress.street,
363
+ onChange: (e) => Q("pickupAddress", "street", e.target.value),
360
364
  placeholder: "123 Main St"
361
365
  })]
362
366
  }),
363
- /* @__PURE__ */ C("div", {
367
+ /* @__PURE__ */ S("div", {
364
368
  className: "grid grid-cols-1 sm:grid-cols-2 gap-4",
365
- children: [/* @__PURE__ */ C("div", {
369
+ children: [/* @__PURE__ */ S("div", {
366
370
  className: "space-y-2",
367
- children: [/* @__PURE__ */ S(_, {
371
+ children: [/* @__PURE__ */ x(g, {
368
372
  htmlFor: "pickupCity",
369
373
  children: "City"
370
- }), /* @__PURE__ */ S(g, {
374
+ }), /* @__PURE__ */ x(h, {
371
375
  id: "pickupCity",
372
- value: H.pickupAddress.city,
373
- onChange: (e) => Z("pickupAddress", "city", e.target.value),
376
+ value: U.pickupAddress.city,
377
+ onChange: (e) => Q("pickupAddress", "city", e.target.value),
374
378
  placeholder: "San Francisco"
375
379
  })]
376
- }), /* @__PURE__ */ C("div", {
380
+ }), /* @__PURE__ */ S("div", {
377
381
  className: "space-y-2",
378
- children: [/* @__PURE__ */ S(_, {
382
+ children: [/* @__PURE__ */ x(g, {
379
383
  htmlFor: "pickupState",
380
384
  children: "State"
381
- }), /* @__PURE__ */ S(g, {
385
+ }), /* @__PURE__ */ x(h, {
382
386
  id: "pickupState",
383
- value: H.pickupAddress.state,
384
- onChange: (e) => Z("pickupAddress", "state", e.target.value),
387
+ value: U.pickupAddress.state,
388
+ onChange: (e) => Q("pickupAddress", "state", e.target.value),
385
389
  placeholder: "CA"
386
390
  })]
387
391
  })]
388
392
  }),
389
- /* @__PURE__ */ C("div", {
393
+ /* @__PURE__ */ S("div", {
390
394
  className: "grid grid-cols-1 sm:grid-cols-2 gap-4",
391
- children: [/* @__PURE__ */ C("div", {
395
+ children: [/* @__PURE__ */ S("div", {
392
396
  className: "space-y-2",
393
- children: [/* @__PURE__ */ S(_, {
397
+ children: [/* @__PURE__ */ x(g, {
394
398
  htmlFor: "pickupPostal",
395
399
  children: "Postal Code"
396
- }), /* @__PURE__ */ S(g, {
400
+ }), /* @__PURE__ */ x(h, {
397
401
  id: "pickupPostal",
398
- value: H.pickupAddress.postalCode,
399
- onChange: (e) => Z("pickupAddress", "postalCode", e.target.value),
402
+ value: U.pickupAddress.postalCode,
403
+ onChange: (e) => Q("pickupAddress", "postalCode", e.target.value),
400
404
  placeholder: "94103"
401
405
  })]
402
- }), /* @__PURE__ */ C("div", {
406
+ }), /* @__PURE__ */ S("div", {
403
407
  className: "space-y-2",
404
- children: [/* @__PURE__ */ S(_, {
408
+ children: [/* @__PURE__ */ x(g, {
405
409
  htmlFor: "pickupCountry",
406
410
  children: "Country"
407
- }), /* @__PURE__ */ S(g, {
411
+ }), /* @__PURE__ */ x(h, {
408
412
  id: "pickupCountry",
409
- value: H.pickupAddress.country,
410
- onChange: (e) => Z("pickupAddress", "country", e.target.value),
413
+ value: U.pickupAddress.country,
414
+ onChange: (e) => Q("pickupAddress", "country", e.target.value),
411
415
  placeholder: "USA"
412
416
  })]
413
417
  })]
414
418
  })
415
419
  ]
416
- })] }), /* @__PURE__ */ C(f, { children: [/* @__PURE__ */ S(m, { children: /* @__PURE__ */ S(h, { children: "Delivery Address" }) }), /* @__PURE__ */ C(p, {
420
+ })] }), /* @__PURE__ */ S(d, { children: [/* @__PURE__ */ x(p, { children: /* @__PURE__ */ x(m, { children: "Delivery Address" }) }), /* @__PURE__ */ S(f, {
417
421
  className: "space-y-4",
418
422
  children: [
419
- /* @__PURE__ */ C("div", {
423
+ /* @__PURE__ */ S("div", {
420
424
  className: "space-y-2",
421
- children: [/* @__PURE__ */ S(_, {
425
+ children: [/* @__PURE__ */ x(g, {
422
426
  htmlFor: "deliveryStreet",
423
427
  children: "Street Address"
424
- }), /* @__PURE__ */ S(g, {
428
+ }), /* @__PURE__ */ x(h, {
425
429
  id: "deliveryStreet",
426
- value: H.deliveryAddress.street,
427
- onChange: (e) => Z("deliveryAddress", "street", e.target.value),
430
+ value: U.deliveryAddress.street,
431
+ onChange: (e) => Q("deliveryAddress", "street", e.target.value),
428
432
  placeholder: "456 Oak Ave"
429
433
  })]
430
434
  }),
431
- /* @__PURE__ */ C("div", {
435
+ /* @__PURE__ */ S("div", {
432
436
  className: "grid grid-cols-1 sm:grid-cols-2 gap-4",
433
- children: [/* @__PURE__ */ C("div", {
437
+ children: [/* @__PURE__ */ S("div", {
434
438
  className: "space-y-2",
435
- children: [/* @__PURE__ */ S(_, {
439
+ children: [/* @__PURE__ */ x(g, {
436
440
  htmlFor: "deliveryCity",
437
441
  children: "City"
438
- }), /* @__PURE__ */ S(g, {
442
+ }), /* @__PURE__ */ x(h, {
439
443
  id: "deliveryCity",
440
- value: H.deliveryAddress.city,
441
- onChange: (e) => Z("deliveryAddress", "city", e.target.value),
444
+ value: U.deliveryAddress.city,
445
+ onChange: (e) => Q("deliveryAddress", "city", e.target.value),
442
446
  placeholder: "Los Angeles"
443
447
  })]
444
- }), /* @__PURE__ */ C("div", {
448
+ }), /* @__PURE__ */ S("div", {
445
449
  className: "space-y-2",
446
- children: [/* @__PURE__ */ S(_, {
450
+ children: [/* @__PURE__ */ x(g, {
447
451
  htmlFor: "deliveryState",
448
452
  children: "State"
449
- }), /* @__PURE__ */ S(g, {
453
+ }), /* @__PURE__ */ x(h, {
450
454
  id: "deliveryState",
451
- value: H.deliveryAddress.state,
452
- onChange: (e) => Z("deliveryAddress", "state", e.target.value),
455
+ value: U.deliveryAddress.state,
456
+ onChange: (e) => Q("deliveryAddress", "state", e.target.value),
453
457
  placeholder: "CA"
454
458
  })]
455
459
  })]
456
460
  }),
457
- /* @__PURE__ */ C("div", {
461
+ /* @__PURE__ */ S("div", {
458
462
  className: "grid grid-cols-1 sm:grid-cols-2 gap-4",
459
- children: [/* @__PURE__ */ C("div", {
463
+ children: [/* @__PURE__ */ S("div", {
460
464
  className: "space-y-2",
461
- children: [/* @__PURE__ */ S(_, {
465
+ children: [/* @__PURE__ */ x(g, {
462
466
  htmlFor: "deliveryPostal",
463
467
  children: "Postal Code"
464
- }), /* @__PURE__ */ S(g, {
468
+ }), /* @__PURE__ */ x(h, {
465
469
  id: "deliveryPostal",
466
- value: H.deliveryAddress.postalCode,
467
- onChange: (e) => Z("deliveryAddress", "postalCode", e.target.value),
470
+ value: U.deliveryAddress.postalCode,
471
+ onChange: (e) => Q("deliveryAddress", "postalCode", e.target.value),
468
472
  placeholder: "90210"
469
473
  })]
470
- }), /* @__PURE__ */ C("div", {
474
+ }), /* @__PURE__ */ S("div", {
471
475
  className: "space-y-2",
472
- children: [/* @__PURE__ */ S(_, {
476
+ children: [/* @__PURE__ */ x(g, {
473
477
  htmlFor: "deliveryCountry",
474
478
  children: "Country"
475
- }), /* @__PURE__ */ S(g, {
479
+ }), /* @__PURE__ */ x(h, {
476
480
  id: "deliveryCountry",
477
- value: H.deliveryAddress.country,
478
- onChange: (e) => Z("deliveryAddress", "country", e.target.value),
481
+ value: U.deliveryAddress.country,
482
+ onChange: (e) => Q("deliveryAddress", "country", e.target.value),
479
483
  placeholder: "USA"
480
484
  })]
481
485
  })]
@@ -483,125 +487,91 @@ function T() {
483
487
  ]
484
488
  })] })]
485
489
  }),
486
- /* @__PURE__ */ C(f, { children: [/* @__PURE__ */ C(m, {
490
+ /* @__PURE__ */ S(d, { children: [/* @__PURE__ */ S(p, {
487
491
  className: "flex flex-row items-center justify-between",
488
- children: [/* @__PURE__ */ S(h, { children: "Order Items" }), /* @__PURE__ */ C(d, {
492
+ children: [/* @__PURE__ */ x(m, { children: "Order Items" }), /* @__PURE__ */ S(u, {
489
493
  type: "button",
490
494
  variant: "outline",
491
495
  size: "sm",
492
- onClick: Q,
493
- children: [/* @__PURE__ */ S(i, { size: 16 }), "Add Item"]
496
+ onClick: $,
497
+ children: [/* @__PURE__ */ x(i, { size: 16 }), "Add Item"]
494
498
  })]
495
- }), /* @__PURE__ */ S(p, { children: H.items.length === 0 ? /* @__PURE__ */ S(fe, {
499
+ }), /* @__PURE__ */ x(f, { children: U.items.length === 0 ? /* @__PURE__ */ x(fe, {
496
500
  illustration: "empty-files",
497
501
  title: "No items added yet",
498
502
  description: "Add the products this order will ship — each with a name, SKU, quantity and value.",
499
- action: /* @__PURE__ */ C(d, {
503
+ action: /* @__PURE__ */ S(u, {
500
504
  type: "button",
501
505
  variant: "outline",
502
- onClick: Q,
503
- children: [/* @__PURE__ */ S(i, {
506
+ onClick: $,
507
+ children: [/* @__PURE__ */ x(i, {
504
508
  size: 16,
505
509
  className: "mr-1.5"
506
510
  }), "Add your first item"]
507
511
  })
508
512
  }) : /* @__PURE__ */ S("div", {
509
513
  className: "space-y-4",
510
- children: H.items.map((e, t) => /* @__PURE__ */ C("div", { children: [t > 0 && /* @__PURE__ */ S(de, { className: "my-4" }), /* @__PURE__ */ C("div", {
511
- className: "grid grid-cols-1 md:grid-cols-7 gap-4",
514
+ children: [/* @__PURE__ */ S("div", {
515
+ className: "space-y-2",
512
516
  children: [
513
- /* @__PURE__ */ C("div", {
514
- className: "md:col-span-2 space-y-2",
515
- children: [/* @__PURE__ */ S(_, { children: "Item Name" }), /* @__PURE__ */ S(g, {
516
- value: e.name,
517
- onChange: (e) => $(t, "name", e.target.value),
518
- placeholder: "Product name"
519
- })]
520
- }),
521
- /* @__PURE__ */ C("div", {
522
- className: "space-y-2",
523
- children: [/* @__PURE__ */ S(_, { children: "SKU" }), /* @__PURE__ */ S(g, {
524
- value: e.sku,
525
- onChange: (e) => $(t, "sku", e.target.value),
526
- placeholder: "SKU-001"
527
- })]
517
+ /* @__PURE__ */ x(g, {
518
+ htmlFor: "item-product-search",
519
+ children: "Search product catalog"
528
520
  }),
529
- /* @__PURE__ */ C("div", {
530
- className: "space-y-2",
531
- children: [/* @__PURE__ */ S(_, { children: "Quantity" }), /* @__PURE__ */ S(g, {
532
- type: "number",
533
- min: "1",
534
- value: e.quantity,
535
- onChange: (e) => $(t, "quantity", parseInt(e.target.value) || 1)
536
- })]
537
- }),
538
- /* @__PURE__ */ C("div", {
539
- className: "space-y-2",
540
- children: [/* @__PURE__ */ S(_, { children: "Weight (kg)" }), /* @__PURE__ */ S(g, {
541
- type: "number",
542
- min: "0",
543
- step: "0.1",
544
- value: e.weight,
545
- onChange: (e) => $(t, "weight", parseFloat(e.target.value) || 0)
546
- })]
547
- }),
548
- /* @__PURE__ */ C("div", {
549
- className: "space-y-2",
550
- children: [/* @__PURE__ */ S(_, { children: "Value ($)" }), /* @__PURE__ */ S(g, {
551
- type: "number",
552
- min: "0",
553
- step: "0.01",
554
- value: e.value,
555
- onChange: (e) => $(t, "value", parseFloat(e.target.value) || 0)
556
- })]
521
+ /* @__PURE__ */ x(h, {
522
+ id: "item-product-search",
523
+ value: z,
524
+ onChange: (e) => Me(e.target.value),
525
+ placeholder: "Search by name or SKU"
557
526
  }),
558
- /* @__PURE__ */ S("div", {
559
- className: "flex items-end",
560
- children: /* @__PURE__ */ S(d, {
561
- type: "button",
562
- variant: "ghost",
563
- size: "icon",
564
- className: "text-status-error-text",
565
- onClick: () => Le(t),
566
- children: /* @__PURE__ */ S(ee, { size: 16 })
567
- })
527
+ /* @__PURE__ */ x("p", {
528
+ className: "text-xs text-text-secondary",
529
+ children: "Narrows the \"Catalog item\" picker below for every row. Picking a catalog item fills in name, SKU, weight, and value — you can still edit them, or skip the picker and enter details manually."
568
530
  })
569
531
  ]
570
- })] }, e.id))
532
+ }), U.items.map((e, t) => /* @__PURE__ */ x(_e, {
533
+ item: e,
534
+ index: t,
535
+ isFirst: t === 0,
536
+ products: Ne,
537
+ productsLoading: Pe,
538
+ onUpdate: Ve,
539
+ onRemove: Be
540
+ }, e.id))]
571
541
  }) })] }),
572
- /* @__PURE__ */ C(f, { children: [/* @__PURE__ */ S(m, { children: /* @__PURE__ */ S(h, { children: "Scheduling & Handling" }) }), /* @__PURE__ */ S(p, { children: /* @__PURE__ */ C("div", {
542
+ /* @__PURE__ */ S(d, { children: [/* @__PURE__ */ x(p, { children: /* @__PURE__ */ x(m, { children: "Scheduling & Handling" }) }), /* @__PURE__ */ x(f, { children: /* @__PURE__ */ S("div", {
573
543
  className: "grid grid-cols-1 md:grid-cols-3 gap-6",
574
- children: [/* @__PURE__ */ C("div", {
544
+ children: [/* @__PURE__ */ S("div", {
575
545
  className: "space-y-2",
576
546
  children: [
577
- /* @__PURE__ */ C(_, {
547
+ /* @__PURE__ */ S(g, {
578
548
  htmlFor: "scheduledDelivery",
579
549
  className: "flex items-center gap-1.5",
580
- children: [/* @__PURE__ */ S(t, {
550
+ children: [/* @__PURE__ */ x(t, {
581
551
  size: 14,
582
552
  className: "text-text-secondary"
583
553
  }), "Scheduled Delivery"]
584
554
  }),
585
- /* @__PURE__ */ S(g, {
555
+ /* @__PURE__ */ x(h, {
586
556
  id: "scheduledDelivery",
587
557
  type: "datetime-local",
588
- value: H.scheduledDelivery,
589
- onChange: (e) => X("scheduledDelivery", e.target.value)
558
+ value: U.scheduledDelivery,
559
+ onChange: (e) => Z("scheduledDelivery", e.target.value)
590
560
  }),
591
- /* @__PURE__ */ S("p", {
561
+ /* @__PURE__ */ x("p", {
592
562
  className: "text-xs text-text-secondary",
593
563
  children: "The delivery window promised to the customer. Leave blank to dispatch as soon as a driver is free."
594
564
  })
595
565
  ]
596
- }), /* @__PURE__ */ C("div", {
566
+ }), /* @__PURE__ */ S("div", {
597
567
  className: "md:col-span-2 space-y-2",
598
- children: [/* @__PURE__ */ S(_, {
568
+ children: [/* @__PURE__ */ x(g, {
599
569
  htmlFor: "specialInstructions",
600
570
  children: "Special Instructions"
601
- }), /* @__PURE__ */ S(y, {
571
+ }), /* @__PURE__ */ x(de, {
602
572
  id: "specialInstructions",
603
- value: H.specialInstructions,
604
- onChange: (e) => X("specialInstructions", e.target.value),
573
+ value: U.specialInstructions,
574
+ onChange: (e) => Z("specialInstructions", e.target.value),
605
575
  placeholder: "Any special handling or delivery instructions...",
606
576
  rows: 4
607
577
  })]
@@ -613,4 +583,4 @@ function T() {
613
583
  });
614
584
  }
615
585
  //#endregion
616
- export { T as default };
586
+ export { w as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-movethewheels",
3
- "version": "2026.924.1",
3
+ "version": "2026.924.2",
4
4
  "description": "Burdenoff MoveTheWheels Microfrontend - Logistics & Supply Chain Management Platform",
5
5
  "type": "module",
6
6
  "files": [
@@ -0,0 +1,172 @@
1
+ /**
2
+ * OrderItemRow — one order-item line in CreateOrderPage's "Order Items" card.
3
+ *
4
+ * Its own component (not inlined in a `.map()`) because it needs one
5
+ * `useProduct`/`useProductStockLevels` hook call per row to resolve the
6
+ * selected catalog item's label and stock hint independently of the shared,
7
+ * search-filtered `products` list passed down from the page — the Rules of
8
+ * Hooks don't allow that from inside a loop in the parent.
9
+ */
10
+ import type { ChangeEvent } from 'react';
11
+ import { Trash2 } from 'lucide-react';
12
+ import { Button, Input, Label, Separator } from './ui';
13
+ import { EntityCombobox } from './EntityCombobox';
14
+ import { useProduct, useProductStockLevels } from '../hooks/useInventory';
15
+ import type { OrderItem, Product } from '../types';
16
+
17
+ interface OrderItemRowProps {
18
+ item: OrderItem;
19
+ index: number;
20
+ isFirst: boolean;
21
+ products: Product[];
22
+ productsLoading: boolean;
23
+ onUpdate: (index: number, field: string, value: unknown) => void;
24
+ onRemove: (index: number) => void;
25
+ }
26
+
27
+ function stockHintText(totalAvailable: number, levels: { warehouseName: string }[]): string {
28
+ if (totalAvailable <= 0) {
29
+ return 'No stock recorded for this item.';
30
+ }
31
+ if (levels.length === 1) {
32
+ return `${totalAvailable.toLocaleString()} available at ${levels[0].warehouseName}`;
33
+ }
34
+ return `${totalAvailable.toLocaleString()} available across ${levels.length} warehouses`;
35
+ }
36
+
37
+ export function OrderItemRow({
38
+ item,
39
+ index,
40
+ isFirst,
41
+ products,
42
+ productsLoading,
43
+ onUpdate,
44
+ onRemove,
45
+ }: OrderItemRowProps) {
46
+ // Resolved independently of the (search-filtered) `products` list so the
47
+ // trigger still shows the right label once a pick scrolls out of the
48
+ // current search results.
49
+ const { product: selectedProduct, isLoading: selectedProductLoading } = useProduct(
50
+ item.productId || undefined
51
+ );
52
+ const {
53
+ levels,
54
+ totalAvailable,
55
+ isLoading: stockLoading,
56
+ } = useProductStockLevels(item.productId || undefined);
57
+
58
+ const selectProduct = (productId: string) => {
59
+ if (!productId) {
60
+ onUpdate(index, 'productId', '');
61
+ return;
62
+ }
63
+ const product = products.find((candidate) => candidate.id === productId);
64
+ if (!product) return;
65
+
66
+ onUpdate(index, 'productId', product.id);
67
+ onUpdate(index, 'name', product.name);
68
+ onUpdate(index, 'sku', product.sku);
69
+ onUpdate(index, 'weight', product.weight);
70
+ onUpdate(index, 'value', product.value);
71
+ onUpdate(index, 'dimensions', product.dimensions);
72
+ // Quantity is never set from the catalog — there's no per-unit default
73
+ // quantity on a cargo item, it's always this specific order's own call.
74
+ };
75
+
76
+ return (
77
+ <div>
78
+ {!isFirst && <Separator className="my-4" />}
79
+ <div className="mb-3 space-y-2">
80
+ <Label htmlFor={`item-product-${item.id}`}>Catalog item (optional)</Label>
81
+ <EntityCombobox
82
+ id={`item-product-${item.id}`}
83
+ value={item.productId}
84
+ onChange={selectProduct}
85
+ options={products}
86
+ loading={productsLoading}
87
+ getId={(product) => product.id}
88
+ getLabel={(product) => `${product.name} (${product.sku})`}
89
+ renderOption={(product) => (
90
+ <>
91
+ {product.name} <span className="text-text-tertiary">({product.sku})</span>
92
+ </>
93
+ )}
94
+ selectedOption={selectedProduct}
95
+ selectedLoading={selectedProductLoading}
96
+ placeholder="Pick from your product catalog"
97
+ emptyText="No products found."
98
+ noneLabel="Enter details manually"
99
+ // Search is driven by the shared "Search product catalog" box above
100
+ // this list — no second input inside the popover.
101
+ />
102
+ {item.productId && !stockLoading && (
103
+ <p className="text-xs text-text-secondary">{stockHintText(totalAvailable, levels)}</p>
104
+ )}
105
+ </div>
106
+ <div className="grid grid-cols-1 gap-4 md:grid-cols-7">
107
+ <div className="space-y-2 md:col-span-2">
108
+ <Label>Item Name</Label>
109
+ <Input
110
+ value={item.name}
111
+ onChange={(e: ChangeEvent<HTMLInputElement>) => onUpdate(index, 'name', e.target.value)}
112
+ placeholder="Product name"
113
+ />
114
+ </div>
115
+ <div className="space-y-2">
116
+ <Label>SKU</Label>
117
+ <Input
118
+ value={item.sku}
119
+ onChange={(e: ChangeEvent<HTMLInputElement>) => onUpdate(index, 'sku', e.target.value)}
120
+ placeholder="SKU-001"
121
+ />
122
+ </div>
123
+ <div className="space-y-2">
124
+ <Label>Quantity</Label>
125
+ <Input
126
+ type="number"
127
+ min="1"
128
+ value={item.quantity}
129
+ onChange={(e: ChangeEvent<HTMLInputElement>) =>
130
+ onUpdate(index, 'quantity', parseInt(e.target.value) || 1)
131
+ }
132
+ />
133
+ </div>
134
+ <div className="space-y-2">
135
+ <Label>Weight (kg)</Label>
136
+ <Input
137
+ type="number"
138
+ min="0"
139
+ step="0.1"
140
+ value={item.weight}
141
+ onChange={(e: ChangeEvent<HTMLInputElement>) =>
142
+ onUpdate(index, 'weight', parseFloat(e.target.value) || 0)
143
+ }
144
+ />
145
+ </div>
146
+ <div className="space-y-2">
147
+ <Label>Value ($)</Label>
148
+ <Input
149
+ type="number"
150
+ min="0"
151
+ step="0.01"
152
+ value={item.value}
153
+ onChange={(e: ChangeEvent<HTMLInputElement>) =>
154
+ onUpdate(index, 'value', parseFloat(e.target.value) || 0)
155
+ }
156
+ />
157
+ </div>
158
+ <div className="flex items-end">
159
+ <Button
160
+ type="button"
161
+ variant="ghost"
162
+ size="icon"
163
+ className="text-status-error-text"
164
+ onClick={() => onRemove(index)}
165
+ >
166
+ <Trash2 size={16} />
167
+ </Button>
168
+ </div>
169
+ </div>
170
+ </div>
171
+ );
172
+ }
@@ -11,7 +11,6 @@ import {
11
11
  ArrowLeft,
12
12
  Save,
13
13
  Plus,
14
- Trash2,
15
14
  Users,
16
15
  MapPin,
17
16
  CalendarClock,
@@ -33,16 +32,17 @@ import {
33
32
  SelectItem,
34
33
  SelectTrigger,
35
34
  SelectValue,
36
- Separator,
37
35
  } from '../components/ui';
38
36
  import { EmphasisPanel, NextSteps, PagePurpose } from '@burdenoff/fe-libs/ui';
39
37
  import { useOrder, useOrders } from '../hooks/useOrders';
40
38
  import { useCustomer, useCustomers } from '../hooks/useCustomers';
41
39
  import { useRoute, useRoutes } from '../hooks/useRoutes';
40
+ import { useProducts } from '../hooks/useInventory';
42
41
  import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
43
42
  import { joinPath, buildCustomerCreatePath } from '../utils/navigation';
44
43
  import { CustomerPicker } from '../components/CustomerPicker';
45
44
  import { EntityCombobox } from '../components/EntityCombobox';
45
+ import { OrderItemRow } from '../components/OrderItemRow';
46
46
  import type { Customer } from '../types';
47
47
 
48
48
  /**
@@ -92,6 +92,11 @@ export default function CreateOrderPage() {
92
92
  search: routeSearch || undefined,
93
93
  limit: 20,
94
94
  });
95
+ const [productSearch, setProductSearch] = useState('');
96
+ const { products, isLoading: productsLoading } = useProducts({
97
+ search: productSearch || undefined,
98
+ limit: 20,
99
+ });
95
100
 
96
101
  const isEditing = !!orderId && !!order;
97
102
 
@@ -650,74 +655,31 @@ export default function CreateOrderPage() {
650
655
  />
651
656
  ) : (
652
657
  <div className="space-y-4">
658
+ <div className="space-y-2">
659
+ <Label htmlFor="item-product-search">Search product catalog</Label>
660
+ <Input
661
+ id="item-product-search"
662
+ value={productSearch}
663
+ onChange={(e) => setProductSearch(e.target.value)}
664
+ placeholder="Search by name or SKU"
665
+ />
666
+ <p className="text-xs text-text-secondary">
667
+ Narrows the "Catalog item" picker below for every row. Picking a catalog item
668
+ fills in name, SKU, weight, and value — you can still edit them, or skip the
669
+ picker and enter details manually.
670
+ </p>
671
+ </div>
653
672
  {formData.items.map((item, index) => (
654
- <div key={item.id}>
655
- {index > 0 && <Separator className="my-4" />}
656
- <div className="grid grid-cols-1 md:grid-cols-7 gap-4">
657
- <div className="md:col-span-2 space-y-2">
658
- <Label>Item Name</Label>
659
- <Input
660
- value={item.name}
661
- onChange={(e) => updateItem(index, 'name', e.target.value)}
662
- placeholder="Product name"
663
- />
664
- </div>
665
- <div className="space-y-2">
666
- <Label>SKU</Label>
667
- <Input
668
- value={item.sku}
669
- onChange={(e) => updateItem(index, 'sku', e.target.value)}
670
- placeholder="SKU-001"
671
- />
672
- </div>
673
- <div className="space-y-2">
674
- <Label>Quantity</Label>
675
- <Input
676
- type="number"
677
- min="1"
678
- value={item.quantity}
679
- onChange={(e) =>
680
- updateItem(index, 'quantity', parseInt(e.target.value) || 1)
681
- }
682
- />
683
- </div>
684
- <div className="space-y-2">
685
- <Label>Weight (kg)</Label>
686
- <Input
687
- type="number"
688
- min="0"
689
- step="0.1"
690
- value={item.weight}
691
- onChange={(e) =>
692
- updateItem(index, 'weight', parseFloat(e.target.value) || 0)
693
- }
694
- />
695
- </div>
696
- <div className="space-y-2">
697
- <Label>Value ($)</Label>
698
- <Input
699
- type="number"
700
- min="0"
701
- step="0.01"
702
- value={item.value}
703
- onChange={(e) =>
704
- updateItem(index, 'value', parseFloat(e.target.value) || 0)
705
- }
706
- />
707
- </div>
708
- <div className="flex items-end">
709
- <Button
710
- type="button"
711
- variant="ghost"
712
- size="icon"
713
- className="text-status-error-text"
714
- onClick={() => removeItem(index)}
715
- >
716
- <Trash2 size={16} />
717
- </Button>
718
- </div>
719
- </div>
720
- </div>
673
+ <OrderItemRow
674
+ key={item.id}
675
+ item={item}
676
+ index={index}
677
+ isFirst={index === 0}
678
+ products={products}
679
+ productsLoading={productsLoading}
680
+ onUpdate={updateItem}
681
+ onRemove={removeItem}
682
+ />
721
683
  ))}
722
684
  </div>
723
685
  )}