@burdenoff/microfe-movethewheels 2026.726.1 → 2026.731.1

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 (41) hide show
  1. package/dist/MoveTheWheelsRoutes.js +11 -3
  2. package/dist/components/ProofOfDeliveryCard.js +155 -0
  3. package/dist/components/SignaturePad.js +82 -0
  4. package/dist/hooks/index.js +1 -0
  5. package/dist/hooks/useEpod.js +208 -0
  6. package/dist/hooks/useMultiModalShipments.js +124 -0
  7. package/dist/index.js +22 -21
  8. package/dist/movethewheels/components/ProofOfDeliveryCard.d.ts +5 -0
  9. package/dist/movethewheels/components/SignaturePad.d.ts +11 -0
  10. package/dist/movethewheels/hooks/index.d.ts +1 -0
  11. package/dist/movethewheels/hooks/useEpod.d.ts +59 -0
  12. package/dist/movethewheels/hooks/useMultiModalShipments.d.ts +76 -0
  13. package/dist/movethewheels/pages/DeliveryCapturePage.d.ts +1 -0
  14. package/dist/movethewheels/pages/MultiModalShipmentPage.d.ts +8 -0
  15. package/dist/movethewheels/types/index.d.ts +18 -0
  16. package/dist/node_modules/lucide-react/dist/esm/icons/calculator.js +56 -0
  17. package/dist/node_modules/lucide-react/dist/esm/icons/loader-circle.js +8 -0
  18. package/dist/node_modules/lucide-react/dist/esm/icons/pen-line.js +11 -0
  19. package/dist/node_modules/lucide-react/dist/esm/icons/plane.js +8 -0
  20. package/dist/node_modules/lucide-react/dist/esm/icons/ship.js +26 -0
  21. package/dist/node_modules/lucide-react/dist/esm/icons/train-front.js +30 -0
  22. package/dist/node_modules/lucide-react/dist/esm/icons/type.js +24 -0
  23. package/dist/pages/DashboardPage.js +156 -151
  24. package/dist/pages/DeliveryCapturePage.js +245 -0
  25. package/dist/pages/MultiModalShipmentPage.js +420 -0
  26. package/dist/pages/OrderDetailsPage.js +14 -12
  27. package/dist/pages/TrackingPage.js +156 -154
  28. package/dist/utils/formatters.js +13 -2
  29. package/package.json +1 -1
  30. package/src/movethewheels/MoveTheWheelsRoutes.tsx +8 -0
  31. package/src/movethewheels/components/ProofOfDeliveryCard.tsx +149 -0
  32. package/src/movethewheels/components/SignaturePad.tsx +157 -0
  33. package/src/movethewheels/hooks/index.ts +12 -0
  34. package/src/movethewheels/hooks/useEpod.ts +410 -0
  35. package/src/movethewheels/hooks/useMultiModalShipments.ts +323 -0
  36. package/src/movethewheels/pages/DashboardPage.tsx +6 -0
  37. package/src/movethewheels/pages/DeliveryCapturePage.tsx +297 -0
  38. package/src/movethewheels/pages/MultiModalShipmentPage.tsx +552 -0
  39. package/src/movethewheels/pages/OrderDetailsPage.tsx +4 -0
  40. package/src/movethewheels/pages/TrackingPage.tsx +4 -0
  41. package/src/movethewheels/types/index.ts +21 -0
@@ -0,0 +1,245 @@
1
+ import { CircleCheck as e } from "../node_modules/lucide-react/dist/esm/icons/circle-check.js";
2
+ import { LoaderCircle as t } from "../node_modules/lucide-react/dist/esm/icons/loader-circle.js";
3
+ import { MapPin as n } from "../node_modules/lucide-react/dist/esm/icons/map-pin.js";
4
+ import { Package as r } from "../node_modules/lucide-react/dist/esm/icons/package.js";
5
+ import { PenLine as i } from "../node_modules/lucide-react/dist/esm/icons/pen-line.js";
6
+ import { Truck as a } from "../node_modules/lucide-react/dist/esm/icons/truck.js";
7
+ import { Type as o } from "../node_modules/lucide-react/dist/esm/icons/type.js";
8
+ import { Upload as s } from "../node_modules/lucide-react/dist/esm/icons/upload.js";
9
+ import { useCaptureEpod as c, useEpodPhotoUpload as l, useMyPendingEpodDeliveryJobs as u } from "../hooks/useEpod.js";
10
+ import { Button as d, Card as f, CardContent as p, CardHeader as m, CardTitle as h, Input as g, Label as _, Textarea as v } from "../components/ui.js";
11
+ import { PageLayout as y } from "../components/PageLayout.js";
12
+ import { FormError as b } from "../components/FormError.js";
13
+ import { Notice as x, useNotice as S } from "../components/Notice.js";
14
+ import { formatAddress as C, formatDate as w } from "../utils/formatters.js";
15
+ import { SignaturePad as T } from "../components/SignaturePad.js";
16
+ import { useRef as E, useState as D } from "react";
17
+ import { Fragment as O, jsx as k, jsxs as A } from "react/jsx-runtime";
18
+ //#region src/movethewheels/pages/DeliveryCapturePage.tsx
19
+ function j() {
20
+ return new Promise((e) => {
21
+ if (!navigator.geolocation) {
22
+ e(null);
23
+ return;
24
+ }
25
+ navigator.geolocation.getCurrentPosition((t) => e(t), () => e(null), {
26
+ enableHighAccuracy: !0,
27
+ timeout: 8e3,
28
+ maximumAge: 3e4
29
+ });
30
+ });
31
+ }
32
+ function M({ job: r, onCaptured: u, onCancel: y }) {
33
+ let { captureEpod: x, isSubmitting: S, error: w } = c(), { upload: M, isUploading: N, error: P } = l(), F = E(null), [I, L] = D(""), [R, z] = D("drawn"), [B, V] = D(""), [H, U] = D(null), [W, G] = D(""), [K, q] = D(null), J = async () => {
34
+ q(null);
35
+ let e = I.trim();
36
+ if (!e) {
37
+ q("Recipient name is required.");
38
+ return;
39
+ }
40
+ let t = R === "typed" ? B.trim() : F.current?.toDataUrl() ?? null;
41
+ if (!t) {
42
+ q(R === "typed" ? "Type the recipient full name as their signature." : "A signature is required.");
43
+ return;
44
+ }
45
+ try {
46
+ let n;
47
+ H && (n = [(await M(H)).fileId]);
48
+ let i = await j();
49
+ await x({
50
+ deliveryJobId: r.id,
51
+ recipientName: e,
52
+ signatureType: R,
53
+ signatureData: t,
54
+ photoFileIds: n,
55
+ latitude: i?.coords.latitude,
56
+ longitude: i?.coords.longitude,
57
+ locationAccuracy: i?.coords.accuracy,
58
+ notes: W.trim() || void 0
59
+ }), u();
60
+ } catch {}
61
+ }, Y = S || N;
62
+ return /* @__PURE__ */ A(f, { children: [/* @__PURE__ */ k(m, { children: /* @__PURE__ */ A(h, {
63
+ className: "flex items-center gap-2",
64
+ children: [
65
+ /* @__PURE__ */ k(a, { size: 18 }),
66
+ " Capture delivery for ",
67
+ r.deliveryJobNumber
68
+ ]
69
+ }) }), /* @__PURE__ */ A(p, {
70
+ className: "space-y-4",
71
+ children: [
72
+ /* @__PURE__ */ A("div", {
73
+ className: "text-sm text-text-secondary space-y-1",
74
+ children: [r.customerName && /* @__PURE__ */ A("p", { children: ["Recipient on file: ", r.customerName] }), r.deliveryAddress && /* @__PURE__ */ k("p", { children: C(r.deliveryAddress) })]
75
+ }),
76
+ /* @__PURE__ */ A("div", {
77
+ className: "space-y-1.5",
78
+ children: [/* @__PURE__ */ k(_, {
79
+ htmlFor: "epod-recipient-name",
80
+ children: "Recipient name"
81
+ }), /* @__PURE__ */ k(g, {
82
+ id: "epod-recipient-name",
83
+ value: I,
84
+ onChange: (e) => L(e.target.value),
85
+ placeholder: "Who received the delivery?"
86
+ })]
87
+ }),
88
+ /* @__PURE__ */ A("div", {
89
+ className: "space-y-1.5",
90
+ children: [
91
+ /* @__PURE__ */ k(_, { children: "Signature" }),
92
+ /* @__PURE__ */ A("div", {
93
+ className: "flex gap-2",
94
+ children: [/* @__PURE__ */ A(d, {
95
+ type: "button",
96
+ variant: R === "drawn" ? "default" : "outline",
97
+ size: "sm",
98
+ onClick: () => z("drawn"),
99
+ children: [/* @__PURE__ */ k(i, { size: 14 }), " Draw"]
100
+ }), /* @__PURE__ */ A(d, {
101
+ type: "button",
102
+ variant: R === "typed" ? "default" : "outline",
103
+ size: "sm",
104
+ onClick: () => z("typed"),
105
+ children: [/* @__PURE__ */ k(o, { size: 14 }), " Type name instead"]
106
+ })]
107
+ }),
108
+ R === "drawn" ? /* @__PURE__ */ k(T, { ref: F }) : /* @__PURE__ */ k(g, {
109
+ value: B,
110
+ onChange: (e) => V(e.target.value),
111
+ placeholder: "Type full name as signature"
112
+ })
113
+ ]
114
+ }),
115
+ /* @__PURE__ */ A("div", {
116
+ className: "space-y-1.5",
117
+ children: [
118
+ /* @__PURE__ */ k(_, {
119
+ htmlFor: "epod-photo",
120
+ children: "Delivery photo (optional)"
121
+ }),
122
+ /* @__PURE__ */ A("div", {
123
+ className: "flex items-center gap-2",
124
+ children: [/* @__PURE__ */ k("input", {
125
+ id: "epod-photo",
126
+ type: "file",
127
+ accept: "image/*",
128
+ capture: "environment",
129
+ onChange: (e) => U(e.target.files?.[0] ?? null),
130
+ className: "text-sm"
131
+ }), H && /* @__PURE__ */ k(s, {
132
+ size: 14,
133
+ className: "text-text-secondary"
134
+ })]
135
+ }),
136
+ H && /* @__PURE__ */ k("p", {
137
+ className: "text-xs text-text-secondary",
138
+ children: H.name
139
+ })
140
+ ]
141
+ }),
142
+ /* @__PURE__ */ A("div", {
143
+ className: "space-y-1.5",
144
+ children: [/* @__PURE__ */ k(_, {
145
+ htmlFor: "epod-notes",
146
+ children: "Notes (optional)"
147
+ }), /* @__PURE__ */ k(v, {
148
+ id: "epod-notes",
149
+ value: W,
150
+ onChange: (e) => G(e.target.value),
151
+ placeholder: "e.g. Left with front desk, gate code used, etc.",
152
+ rows: 2
153
+ })]
154
+ }),
155
+ /* @__PURE__ */ A("p", {
156
+ className: "flex items-center gap-1.5 text-xs text-text-secondary",
157
+ children: [/* @__PURE__ */ k(n, { size: 12 }), " Device GPS is captured automatically when permitted by the browser."]
158
+ }),
159
+ K && /* @__PURE__ */ k(b, { message: K }),
160
+ w && /* @__PURE__ */ k(b, { message: w.message }),
161
+ P && /* @__PURE__ */ k(b, { message: P.message }),
162
+ /* @__PURE__ */ A("div", {
163
+ className: "flex gap-2 justify-end",
164
+ children: [/* @__PURE__ */ k(d, {
165
+ type: "button",
166
+ variant: "outline",
167
+ onClick: y,
168
+ disabled: Y,
169
+ children: "Cancel"
170
+ }), /* @__PURE__ */ k(d, {
171
+ type: "button",
172
+ onClick: () => void J(),
173
+ disabled: Y,
174
+ children: Y ? /* @__PURE__ */ A(O, { children: [/* @__PURE__ */ k(t, {
175
+ size: 14,
176
+ className: "animate-spin"
177
+ }), " Submitting…"] }) : /* @__PURE__ */ A(O, { children: [/* @__PURE__ */ k(e, { size: 14 }), " Confirm delivery"] })
178
+ })]
179
+ })
180
+ ]
181
+ })] });
182
+ }
183
+ function N() {
184
+ let { jobs: t, isLoading: n, error: i, refetch: o } = u(), [s, c] = D(null), { message: l, notify: m } = S();
185
+ return /* @__PURE__ */ k(y, {
186
+ title: "My Deliveries",
187
+ subtitle: "Capture proof of delivery for your assigned stops",
188
+ icon: /* @__PURE__ */ k(a, { size: 24 }),
189
+ children: /* @__PURE__ */ A("div", {
190
+ className: "space-y-4",
191
+ children: [/* @__PURE__ */ k(x, { message: l }), s ? /* @__PURE__ */ k(M, {
192
+ job: s,
193
+ onCaptured: () => {
194
+ m("Proof of delivery captured — delivery marked complete."), c(null), o();
195
+ },
196
+ onCancel: () => c(null)
197
+ }) : n ? /* @__PURE__ */ k("p", {
198
+ className: "text-text-secondary text-center py-8",
199
+ children: "Loading your deliveries…"
200
+ }) : i ? /* @__PURE__ */ k(b, { message: i.message }) : t.length > 0 ? /* @__PURE__ */ k("div", {
201
+ className: "space-y-3",
202
+ children: t.map((e) => /* @__PURE__ */ k(f, { children: /* @__PURE__ */ A(p, {
203
+ className: "flex items-center justify-between gap-3 py-4",
204
+ children: [/* @__PURE__ */ A("div", {
205
+ className: "min-w-0",
206
+ children: [
207
+ /* @__PURE__ */ A("p", {
208
+ className: "font-medium flex items-center gap-2",
209
+ children: [
210
+ /* @__PURE__ */ k(r, { size: 16 }),
211
+ " ",
212
+ e.deliveryJobNumber
213
+ ]
214
+ }),
215
+ e.deliveryAddress && /* @__PURE__ */ k("p", {
216
+ className: "text-sm text-text-secondary truncate",
217
+ children: C(e.deliveryAddress)
218
+ }),
219
+ e.scheduledDelivery && /* @__PURE__ */ A("p", {
220
+ className: "text-xs text-text-secondary",
221
+ children: ["Scheduled ", w(e.scheduledDelivery, "short")]
222
+ })
223
+ ]
224
+ }), /* @__PURE__ */ k(d, {
225
+ type: "button",
226
+ size: "sm",
227
+ onClick: () => c(e),
228
+ children: "Capture"
229
+ })]
230
+ }) }, e.id))
231
+ }) : /* @__PURE__ */ A("div", {
232
+ className: "text-center py-12",
233
+ children: [/* @__PURE__ */ k(e, {
234
+ size: 40,
235
+ className: "mx-auto mb-3 text-text-secondary opacity-50"
236
+ }), /* @__PURE__ */ k("p", {
237
+ className: "text-text-secondary",
238
+ children: "No deliveries awaiting proof of delivery."
239
+ })]
240
+ })]
241
+ })
242
+ });
243
+ }
244
+ //#endregion
245
+ export { N as default };
@@ -0,0 +1,420 @@
1
+ import { Calculator as e } from "../node_modules/lucide-react/dist/esm/icons/calculator.js";
2
+ import { Plane as t } from "../node_modules/lucide-react/dist/esm/icons/plane.js";
3
+ import { Plus as n } from "../node_modules/lucide-react/dist/esm/icons/plus.js";
4
+ import { Ship as r } from "../node_modules/lucide-react/dist/esm/icons/ship.js";
5
+ import { TrainFront as i } from "../node_modules/lucide-react/dist/esm/icons/train-front.js";
6
+ import { Trash2 as ee } from "../node_modules/lucide-react/dist/esm/icons/trash-2.js";
7
+ import { Truck as a } from "../node_modules/lucide-react/dist/esm/icons/truck.js";
8
+ import { Badge as o, Button as s, Card as c, CardContent as l, CardHeader as u, CardTitle as d, Input as f, Label as p, Select as m, SelectContent as h, SelectItem as g, SelectTrigger as _, SelectValue as v, Separator as te } from "../components/ui.js";
9
+ import { EmptyState as ne, LoadingState as y, PageLayout as b, PageSection as x } from "../components/PageLayout.js";
10
+ import { FormError as S } from "../components/FormError.js";
11
+ import { useMultiModalShipments as re } from "../hooks/useMultiModalShipments.js";
12
+ import { useState as C } from "react";
13
+ import { Fragment as w, jsx as T, jsxs as E } from "react/jsx-runtime";
14
+ import { EmphasisPanel as D, PagePurpose as O } from "@burdenoff/fe-libs/ui";
15
+ //#region src/movethewheels/pages/MultiModalShipmentPage.tsx
16
+ var k = {
17
+ ROAD: a,
18
+ AIR: t,
19
+ OCEAN: r,
20
+ RAIL: i
21
+ }, A = {
22
+ ROAD: "Road",
23
+ AIR: "Air",
24
+ OCEAN: "Ocean",
25
+ RAIL: "Rail"
26
+ };
27
+ function j(e = "ROAD") {
28
+ return {
29
+ mode: e,
30
+ origin: {},
31
+ destination: {}
32
+ };
33
+ }
34
+ function M(e, t) {
35
+ if (e == null) return "—";
36
+ try {
37
+ return new Intl.NumberFormat("en-US", {
38
+ style: "currency",
39
+ currency: t ?? "USD"
40
+ }).format(e);
41
+ } catch {
42
+ return `${e.toFixed(2)} ${t ?? "USD"}`;
43
+ }
44
+ }
45
+ function N() {
46
+ let { shipments: t, isLoading: i, error: a, calculateFreightRate: N, planMultiModalShipment: P } = re(), [F, I] = C(""), [L, R] = C(""), [z, B] = C(""), [V, H] = C([j()]), [U, W] = C({}), [G, K] = C({}), [q, J] = C(!1), [Y, X] = C(null), [Z, Q] = C(null), $ = (e, t) => {
47
+ H((n) => n.map((n, r) => r === e ? {
48
+ ...n,
49
+ ...t
50
+ } : n)), W((t) => ({
51
+ ...t,
52
+ [e]: null
53
+ }));
54
+ }, ie = () => H((e) => [...e, j()]), ae = (e) => {
55
+ H((t) => t.filter((t, n) => n !== e)), W((t) => {
56
+ let n = { ...t };
57
+ return delete n[e], n;
58
+ });
59
+ }, oe = async (e) => {
60
+ let t = V[e];
61
+ if (t) {
62
+ K((t) => ({
63
+ ...t,
64
+ [e]: null
65
+ }));
66
+ try {
67
+ let n = await N(t);
68
+ W((t) => ({
69
+ ...t,
70
+ [e]: n
71
+ }));
72
+ } catch (t) {
73
+ K((n) => ({
74
+ ...n,
75
+ [e]: t instanceof Error ? t.message : "Failed to calculate rate"
76
+ }));
77
+ }
78
+ }
79
+ }, se = Object.values(U).reduce((e, t) => e + (t?.calculatedCost ?? 0), 0), ce = new Set(V.map((e) => e.mode));
80
+ return /* @__PURE__ */ E(b, {
81
+ hero: !0,
82
+ titleAccent: "Multi-Modal Freight",
83
+ title: "Multi-Modal Freight",
84
+ subtitle: "Plan a shipment across road, air, ocean and rail legs with real per-mode rate calculation",
85
+ icon: /* @__PURE__ */ T(r, { size: 24 }),
86
+ children: [
87
+ /* @__PURE__ */ T(O, {
88
+ icon: /* @__PURE__ */ T(r, { size: 18 }),
89
+ children: "Compose a single shipment from multiple real transport legs — each leg picks its own mode (road/air/ocean/rail) and gets priced with that mode's real pricing driver (air: chargeable weight; ocean: revenue-ton or per-container; rail: tonne-km; road: distance + weight). Calculate a leg's rate before booking, then plan the full multi-leg shipment in one step."
90
+ }),
91
+ /* @__PURE__ */ T(D, { children: "Live carrier booking/API integration is out of scope for this core (it needs named-carrier partnership agreements) — this plans the shipment and its legs with real calculated costs that your ops team can then execute against your chosen carriers." }),
92
+ /* @__PURE__ */ T(x, {
93
+ title: "Plan a New Multi-Modal Shipment",
94
+ children: /* @__PURE__ */ T(c, { children: /* @__PURE__ */ T(l, { children: /* @__PURE__ */ E("form", {
95
+ onSubmit: async (e) => {
96
+ if (e.preventDefault(), X(null), Q(null), !F.trim()) {
97
+ X("Shipment number is required.");
98
+ return;
99
+ }
100
+ if (V.length === 0) {
101
+ X("Add at least one transport leg.");
102
+ return;
103
+ }
104
+ J(!0);
105
+ try {
106
+ let e = await P({
107
+ shipmentNumber: F.trim(),
108
+ origin: { address: L },
109
+ destination: { address: z },
110
+ legs: V
111
+ });
112
+ Q(`Shipment ${e.shipmentNumber} planned with ${e.legs.length} leg(s).`), I(""), R(""), B(""), H([j()]), W({});
113
+ } catch (e) {
114
+ X(e instanceof Error ? e.message : "Failed to plan shipment");
115
+ } finally {
116
+ J(!1);
117
+ }
118
+ },
119
+ className: "space-y-6 pt-4",
120
+ children: [
121
+ /* @__PURE__ */ T(S, { message: Y }),
122
+ Z && /* @__PURE__ */ T("div", {
123
+ className: "rounded-lg border border-status-success-border bg-status-success-bg-subtle px-4 py-3 text-sm text-status-success-text",
124
+ children: Z
125
+ }),
126
+ /* @__PURE__ */ E("div", {
127
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-3",
128
+ children: [
129
+ /* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T(p, {
130
+ htmlFor: "shipmentNumber",
131
+ children: "Shipment Number"
132
+ }), /* @__PURE__ */ T(f, {
133
+ id: "shipmentNumber",
134
+ value: F,
135
+ onChange: (e) => I(e.target.value),
136
+ placeholder: "SHP-MM-0001",
137
+ required: !0
138
+ })] }),
139
+ /* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T(p, {
140
+ htmlFor: "originAddress",
141
+ children: "Origin"
142
+ }), /* @__PURE__ */ T(f, {
143
+ id: "originAddress",
144
+ value: L,
145
+ onChange: (e) => R(e.target.value),
146
+ placeholder: "Shanghai, CN"
147
+ })] }),
148
+ /* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T(p, {
149
+ htmlFor: "destinationAddress",
150
+ children: "Destination"
151
+ }), /* @__PURE__ */ T(f, {
152
+ id: "destinationAddress",
153
+ value: z,
154
+ onChange: (e) => B(e.target.value),
155
+ placeholder: "Los Angeles, US"
156
+ })] })
157
+ ]
158
+ }),
159
+ /* @__PURE__ */ T(te, {}),
160
+ /* @__PURE__ */ T("div", {
161
+ className: "space-y-4",
162
+ children: V.map((t, n) => {
163
+ let r = k[t.mode], i = U[n], a = G[n];
164
+ return /* @__PURE__ */ E(c, {
165
+ className: "border-border-subtle",
166
+ children: [/* @__PURE__ */ E(u, {
167
+ className: "flex flex-row items-center justify-between",
168
+ children: [/* @__PURE__ */ E(d, {
169
+ className: "flex items-center gap-2 text-base",
170
+ children: [
171
+ /* @__PURE__ */ T(r, { size: 16 }),
172
+ " Leg ",
173
+ n + 1
174
+ ]
175
+ }), V.length > 1 && /* @__PURE__ */ T(s, {
176
+ type: "button",
177
+ variant: "ghost",
178
+ size: "sm",
179
+ onClick: () => ae(n),
180
+ "aria-label": `Remove leg ${n + 1}`,
181
+ children: /* @__PURE__ */ T(ee, { size: 14 })
182
+ })]
183
+ }), /* @__PURE__ */ E(l, {
184
+ className: "space-y-4",
185
+ children: [
186
+ /* @__PURE__ */ E("div", {
187
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-3",
188
+ children: [
189
+ /* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T(p, { children: "Mode" }), /* @__PURE__ */ E(m, {
190
+ value: t.mode,
191
+ onValueChange: (e) => $(n, { mode: e }),
192
+ children: [/* @__PURE__ */ T(_, { children: /* @__PURE__ */ T(v, {}) }), /* @__PURE__ */ T(h, { children: [
193
+ "ROAD",
194
+ "AIR",
195
+ "OCEAN",
196
+ "RAIL"
197
+ ].map((e) => /* @__PURE__ */ T(g, {
198
+ value: e,
199
+ children: A[e]
200
+ }, e)) })]
201
+ })] }),
202
+ /* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T(p, { children: "Leg Origin" }), /* @__PURE__ */ T(f, {
203
+ value: t.origin.address ?? "",
204
+ onChange: (e) => $(n, { origin: { address: e.target.value } }),
205
+ placeholder: "Origin port/airport/terminal"
206
+ })] }),
207
+ /* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T(p, { children: "Leg Destination" }), /* @__PURE__ */ T(f, {
208
+ value: t.destination.address ?? "",
209
+ onChange: (e) => $(n, { destination: { address: e.target.value } }),
210
+ placeholder: "Destination port/airport/terminal"
211
+ })] })
212
+ ]
213
+ }),
214
+ (t.mode === "ROAD" || t.mode === "RAIL") && /* @__PURE__ */ E("div", {
215
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
216
+ children: [/* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T(p, { children: "Distance (km)" }), /* @__PURE__ */ T(f, {
217
+ type: "number",
218
+ min: 0,
219
+ value: t.distanceKm ?? "",
220
+ onChange: (e) => $(n, { distanceKm: Number(e.target.value) || void 0 })
221
+ })] }), /* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T(p, { children: "Weight (kg)" }), /* @__PURE__ */ T(f, {
222
+ type: "number",
223
+ min: 0,
224
+ value: t.weightKg ?? "",
225
+ onChange: (e) => $(n, { weightKg: Number(e.target.value) || void 0 })
226
+ })] })]
227
+ }),
228
+ t.mode === "AIR" && /* @__PURE__ */ E("div", {
229
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-4",
230
+ children: [
231
+ /* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T(p, { children: "Weight (kg)" }), /* @__PURE__ */ T(f, {
232
+ type: "number",
233
+ min: 0,
234
+ value: t.weightKg ?? "",
235
+ onChange: (e) => $(n, { weightKg: Number(e.target.value) || void 0 })
236
+ })] }),
237
+ /* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T(p, { children: "Length (cm)" }), /* @__PURE__ */ T(f, {
238
+ type: "number",
239
+ min: 0,
240
+ value: t.lengthCm ?? "",
241
+ onChange: (e) => $(n, { lengthCm: Number(e.target.value) || void 0 })
242
+ })] }),
243
+ /* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T(p, { children: "Width (cm)" }), /* @__PURE__ */ T(f, {
244
+ type: "number",
245
+ min: 0,
246
+ value: t.widthCm ?? "",
247
+ onChange: (e) => $(n, { widthCm: Number(e.target.value) || void 0 })
248
+ })] }),
249
+ /* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T(p, { children: "Height (cm)" }), /* @__PURE__ */ T(f, {
250
+ type: "number",
251
+ min: 0,
252
+ value: t.heightCm ?? "",
253
+ onChange: (e) => $(n, { heightCm: Number(e.target.value) || void 0 })
254
+ })] })
255
+ ]
256
+ }),
257
+ t.mode === "OCEAN" && /* @__PURE__ */ E("div", {
258
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-4",
259
+ children: [/* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T(p, { children: "Container Type" }), /* @__PURE__ */ E(m, {
260
+ value: t.containerType ?? "LCL",
261
+ onValueChange: (e) => $(n, { containerType: e }),
262
+ children: [/* @__PURE__ */ T(_, { children: /* @__PURE__ */ T(v, {}) }), /* @__PURE__ */ E(h, { children: [
263
+ /* @__PURE__ */ T(g, {
264
+ value: "LCL",
265
+ children: "LCL (shared container)"
266
+ }),
267
+ /* @__PURE__ */ T(g, {
268
+ value: "FCL_20FT",
269
+ children: "FCL 20ft"
270
+ }),
271
+ /* @__PURE__ */ T(g, {
272
+ value: "FCL_40FT",
273
+ children: "FCL 40ft"
274
+ }),
275
+ /* @__PURE__ */ T(g, {
276
+ value: "FCL_40FT_HC",
277
+ children: "FCL 40ft High-Cube"
278
+ })
279
+ ] })]
280
+ })] }), (t.containerType ?? "LCL") === "LCL" ? /* @__PURE__ */ E(w, { children: [/* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T(p, { children: "Weight (kg)" }), /* @__PURE__ */ T(f, {
281
+ type: "number",
282
+ min: 0,
283
+ value: t.weightKg ?? "",
284
+ onChange: (e) => $(n, { weightKg: Number(e.target.value) || void 0 })
285
+ })] }), /* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T(p, { children: "Volume (CBM)" }), /* @__PURE__ */ T(f, {
286
+ type: "number",
287
+ min: 0,
288
+ value: t.volumeCbm ?? "",
289
+ onChange: (e) => $(n, { volumeCbm: Number(e.target.value) || void 0 })
290
+ })] })] }) : /* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T(p, { children: "Container Count" }), /* @__PURE__ */ T(f, {
291
+ type: "number",
292
+ min: 1,
293
+ value: t.containerCount ?? 1,
294
+ onChange: (e) => $(n, { containerCount: Number(e.target.value) || 1 })
295
+ })] })]
296
+ }),
297
+ /* @__PURE__ */ E("div", {
298
+ className: "flex items-center gap-3",
299
+ children: [
300
+ /* @__PURE__ */ E(s, {
301
+ type: "button",
302
+ variant: "secondary",
303
+ size: "sm",
304
+ onClick: () => void oe(n),
305
+ children: [/* @__PURE__ */ T(e, {
306
+ size: 14,
307
+ className: "mr-1.5"
308
+ }), " Calculate Rate"]
309
+ }),
310
+ i && /* @__PURE__ */ E("span", {
311
+ className: "text-sm font-medium text-text-primary",
312
+ children: [M(i.calculatedCost, i.currency), i.chargeableWeightKg != null && /* @__PURE__ */ E("span", {
313
+ className: "ml-2 text-xs text-text-secondary",
314
+ children: [
315
+ "(",
316
+ i.chargeableWeightKg.toFixed(1),
317
+ "kg chargeable)"
318
+ ]
319
+ })]
320
+ }),
321
+ a && /* @__PURE__ */ T("span", {
322
+ className: "text-sm text-status-error-text",
323
+ children: a
324
+ })
325
+ ]
326
+ }),
327
+ i && i.breakdown.length > 0 && /* @__PURE__ */ T("ul", {
328
+ className: "space-y-1 rounded-md bg-surface-subtle px-3 py-2 text-xs text-text-secondary",
329
+ children: i.breakdown.map((e) => /* @__PURE__ */ E("li", {
330
+ className: "flex justify-between",
331
+ children: [/* @__PURE__ */ T("span", { children: e.label }), /* @__PURE__ */ T("span", { children: M(e.amount, i.currency) })]
332
+ }, e.label))
333
+ })
334
+ ]
335
+ })]
336
+ }, n);
337
+ })
338
+ }),
339
+ /* @__PURE__ */ E("div", {
340
+ className: "flex items-center justify-between",
341
+ children: [/* @__PURE__ */ E(s, {
342
+ type: "button",
343
+ variant: "outline",
344
+ size: "sm",
345
+ onClick: ie,
346
+ children: [/* @__PURE__ */ T(n, {
347
+ size: 14,
348
+ className: "mr-1.5"
349
+ }), " Add Leg"]
350
+ }), /* @__PURE__ */ E("div", {
351
+ className: "flex items-center gap-3",
352
+ children: [ce.size > 1 && /* @__PURE__ */ T(o, {
353
+ variant: "secondary",
354
+ children: "Multi-modal"
355
+ }), /* @__PURE__ */ E("span", {
356
+ className: "text-sm text-text-secondary",
357
+ children: [
358
+ "Estimated total:",
359
+ " ",
360
+ /* @__PURE__ */ T("strong", { children: M(se, U[0]?.currency ?? "USD") })
361
+ ]
362
+ })]
363
+ })]
364
+ }),
365
+ /* @__PURE__ */ T(s, {
366
+ type: "submit",
367
+ disabled: q,
368
+ children: q ? "Planning shipment..." : "Plan Shipment"
369
+ })
370
+ ]
371
+ }) }) })
372
+ }),
373
+ /* @__PURE__ */ T(x, {
374
+ title: "Planned Multi-Modal Shipments",
375
+ children: i ? /* @__PURE__ */ T(y, { message: "Loading multi-modal shipments..." }) : a ? /* @__PURE__ */ T(S, { message: a.message }) : t.length === 0 ? /* @__PURE__ */ T(ne, {
376
+ icon: /* @__PURE__ */ T(r, { size: 32 }),
377
+ title: "No multi-modal shipments yet",
378
+ description: "Plan a shipment above to see it here once it spans more than one transport mode."
379
+ }) : /* @__PURE__ */ T("div", {
380
+ className: "space-y-4",
381
+ children: t.map((e) => /* @__PURE__ */ E(c, { children: [/* @__PURE__ */ E(u, {
382
+ className: "flex flex-row items-center justify-between",
383
+ children: [/* @__PURE__ */ T(d, {
384
+ className: "text-base",
385
+ children: e.shipmentNumber
386
+ }), /* @__PURE__ */ E("div", {
387
+ className: "flex items-center gap-2",
388
+ children: [/* @__PURE__ */ T(o, {
389
+ variant: "outline",
390
+ children: e.status
391
+ }), /* @__PURE__ */ T("span", {
392
+ className: "text-sm font-medium",
393
+ children: M(e.totalFreightCost, e.freightCurrency)
394
+ })]
395
+ })]
396
+ }), /* @__PURE__ */ T(l, { children: /* @__PURE__ */ T("div", {
397
+ className: "flex flex-wrap gap-2",
398
+ children: e.legs.map((e) => {
399
+ let t = k[e.mode];
400
+ return /* @__PURE__ */ E(o, {
401
+ variant: "secondary",
402
+ className: "flex items-center gap-1",
403
+ children: [
404
+ /* @__PURE__ */ T(t, { size: 12 }),
405
+ " ",
406
+ A[e.mode],
407
+ ":",
408
+ " ",
409
+ M(e.calculatedCost, e.currency)
410
+ ]
411
+ }, e.id);
412
+ })
413
+ }) })] }, e.id))
414
+ })
415
+ })
416
+ ]
417
+ });
418
+ }
419
+ //#endregion
420
+ export { N as default };