@burdenoff/microfe-movethewheels 2026.918.1 → 2026.920.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.
@@ -28,8 +28,8 @@ function d() {
28
28
  })
29
29
  });
30
30
  }
31
- var f = r(() => import("./pages/DashboardPage.js")), p = r(() => import("./pages/OrdersListPage.js")), m = r(() => import("./pages/OrderDetailsPage.js")), h = r(() => import("./pages/CreateOrderPage.js")), g = r(() => import("./pages/TrackingPage.js")), _ = r(() => import("./pages/LiveTrackingPage.js")), v = r(() => import("./pages/FleetPage.js")), y = r(() => import("./pages/VehiclesPage.js")), b = r(() => import("./pages/VehicleDetailsPage.js")), x = r(() => import("./pages/DriversPage.js")), S = r(() => import("./pages/DriverDetailsPage.js")), C = r(() => import("./pages/InventoryPage.js")), w = r(() => import("./pages/ProductsPage.js")), T = r(() => import("./pages/ProductDetailsPage.js")), E = r(() => import("./pages/WarehousesPage.js")), D = r(() => import("./pages/WarehouseDetailsPage.js")), O = r(() => import("./pages/CustomersPage.js")), k = r(() => import("./pages/CustomerDetailsPage.js")), A = r(() => import("./pages/RoutesPage.js")), j = r(() => import("./pages/RouteDetailsPage.js")), M = r(() => import("./pages/AnalyticsPage.js")), N = r(() => import("./pages/FinancePage.js")), P = r(() => import("./pages/MarketplacePage.js")), F = r(() => import("./pages/ImportExportPage.js")), I = r(() => import("./pages/ReportsPage.js")), L = r(() => import("./pages/SettingsPage.js")), R = r(() => import("./pages/AIAssistantPage.js")), z = r(() => import("./pages/DeliveryCapturePage.js")), B = r(() => import("./pages/MultiModalShipmentPage.js"));
32
- function V() {
31
+ var f = r(() => import("./pages/DashboardPage.js")), p = r(() => import("./pages/OrdersListPage.js")), m = r(() => import("./pages/OrderDetailsPage.js")), h = r(() => import("./pages/CreateOrderPage.js")), g = r(() => import("./pages/TrackingPage.js")), _ = r(() => import("./pages/LiveTrackingPage.js")), v = r(() => import("./pages/FleetPage.js")), y = r(() => import("./pages/VehiclesPage.js")), b = r(() => import("./pages/VehicleDetailsPage.js")), x = r(() => import("./pages/DriversPage.js")), S = r(() => import("./pages/DriverDetailsPage.js")), C = r(() => import("./pages/InventoryPage.js")), w = r(() => import("./pages/ProductsPage.js")), T = r(() => import("./pages/ProductDetailsPage.js")), E = r(() => import("./pages/WarehousesPage.js")), D = r(() => import("./pages/WarehouseDetailsPage.js")), O = r(() => import("./pages/CustomersPage.js")), k = r(() => import("./pages/CustomerDetailsPage.js")), A = r(() => import("./pages/RoutesPage.js")), j = r(() => import("./pages/RouteDetailsPage.js")), M = r(() => import("./pages/AnalyticsPage.js")), N = r(() => import("./pages/FinancePage.js")), P = r(() => import("./pages/MarketplacePage.js")), F = r(() => import("./pages/ImportExportPage.js")), I = r(() => import("./pages/ReportsPage.js")), L = r(() => import("./pages/SettingsPage.js")), R = r(() => import("./pages/AIAssistantPage.js")), z = r(() => import("./pages/DeliveryCapturePage.js")), B = r(() => import("./pages/MultiModalShipmentPage.js")), V = r(() => import("./pages/ShippingRatesPage.js"));
32
+ function H() {
33
33
  return /* @__PURE__ */ s(n, {
34
34
  fallback: /* @__PURE__ */ s(d, {}),
35
35
  children: /* @__PURE__ */ c(a, { children: [
@@ -69,6 +69,10 @@ function V() {
69
69
  path: "shipments/multi-modal",
70
70
  element: /* @__PURE__ */ s(B, {})
71
71
  }),
72
+ /* @__PURE__ */ s(i, {
73
+ path: "shipments/rates",
74
+ element: /* @__PURE__ */ s(V, {})
75
+ }),
72
76
  /* @__PURE__ */ s(i, {
73
77
  path: "fleet",
74
78
  element: /* @__PURE__ */ s(v, {})
@@ -205,4 +209,4 @@ function V() {
205
209
  });
206
210
  }
207
211
  //#endregion
208
- export { V as MoveTheWheelsRoutes };
212
+ export { H as MoveTheWheelsRoutes };
@@ -0,0 +1,195 @@
1
+ import { TriangleAlert as e } from "../node_modules/lucide-react/dist/esm/icons/triangle-alert.js";
2
+ import { Truck as t } from "../node_modules/lucide-react/dist/esm/icons/truck.js";
3
+ import { Card as n, CardContent as r, CardHeader as i, CardTitle as a, Table as o, TableBody as s, TableCell as c, TableHead as l, TableHeader as u, TableRow as d } from "./ui.js";
4
+ import { StatusBadge as f } from "./StatusBadge.js";
5
+ import { formatCurrency as p } from "../utils/formatters.js";
6
+ import { Fragment as m, jsx as h, jsxs as g } from "react/jsx-runtime";
7
+ //#region src/movethewheels/components/ShippingQuoteResults.tsx
8
+ var _ = {
9
+ bg: "bg-status-success-bg-subtle",
10
+ text: "text-status-success-text"
11
+ }, v = {
12
+ bg: "bg-status-info-bg-subtle",
13
+ text: "text-status-info-text"
14
+ };
15
+ function y(e, t) {
16
+ if (e.estimatedDeliveryDays === null) return e.estimatedDeliveryDate ?? "—";
17
+ let n = e.estimatedDeliveryDays === 1 ? t("movethewheels.shipping.results.day", "day") : t("movethewheels.shipping.results.days", "days"), r = `${e.estimatedDeliveryDays} ${n}`;
18
+ return e.estimatedDeliveryDate ? `${r} · ${e.estimatedDeliveryDate}` : r;
19
+ }
20
+ function b(e, t) {
21
+ return e.mode === "AIR" ? t("movethewheels.shipping.results.air", "Air") : e.mode === "SURFACE" ? t("movethewheels.shipping.results.surface", "Surface") : "—";
22
+ }
23
+ function x({ quote: e, t }) {
24
+ return /* @__PURE__ */ g(m, { children: [
25
+ e.isCheapest && /* @__PURE__ */ h(f, {
26
+ status: t("movethewheels.shipping.results.cheapest", "Cheapest"),
27
+ customColors: _,
28
+ size: "sm",
29
+ showDot: !1
30
+ }),
31
+ e.isFastest && /* @__PURE__ */ h(f, {
32
+ status: t("movethewheels.shipping.results.fastest", "Fastest"),
33
+ customColors: v,
34
+ size: "sm",
35
+ showDot: !1
36
+ }),
37
+ e.isRecommended && /* @__PURE__ */ h(f, {
38
+ status: t("movethewheels.shipping.results.recommended", "Recommended"),
39
+ customColors: v,
40
+ size: "sm",
41
+ showDot: !1
42
+ })
43
+ ] });
44
+ }
45
+ function S({ estimate: e, t: o }) {
46
+ let s = e.savingsVsCheapestCourier;
47
+ return /* @__PURE__ */ g(n, { children: [/* @__PURE__ */ h(i, { children: /* @__PURE__ */ g(a, {
48
+ className: "flex items-center gap-2",
49
+ children: [
50
+ /* @__PURE__ */ h(t, {
51
+ size: 18,
52
+ "aria-hidden": "true"
53
+ }),
54
+ o("movethewheels.shipping.ownFleet.title", "Your own vehicle"),
55
+ /* @__PURE__ */ h(f, {
56
+ status: o("movethewheels.shipping.ownFleet.estimate", "Your estimate"),
57
+ customColors: v,
58
+ size: "sm",
59
+ showDot: !1
60
+ })
61
+ ]
62
+ }) }), /* @__PURE__ */ g(r, {
63
+ className: "space-y-2",
64
+ children: [
65
+ /* @__PURE__ */ h("p", {
66
+ className: "text-2xl font-semibold",
67
+ children: p(e.cost, e.currency)
68
+ }),
69
+ /* @__PURE__ */ g("p", {
70
+ className: "text-sm text-text-secondary",
71
+ children: [
72
+ e.distanceKm,
73
+ " km × ",
74
+ p(e.costPerKm, e.currency),
75
+ "/km",
76
+ e.fixedCost > 0 && ` + ${p(e.fixedCost, e.currency)}`
77
+ ]
78
+ }),
79
+ s !== null && /* @__PURE__ */ h("p", {
80
+ className: `text-sm font-medium ${e.isCheaperThanCouriers ? "text-status-success-text" : "text-status-warning-text"}`,
81
+ children: e.isCheaperThanCouriers ? `${o("movethewheels.shipping.ownFleet.cheaper", "Your own vehicle is cheaper than the cheapest courier by")} ${p(s, e.currency)}` : s === 0 ? o("movethewheels.shipping.ownFleet.same", "Same cost as the cheapest courier") : `${o("movethewheels.shipping.ownFleet.dearer", "The cheapest courier is cheaper by")} ${p(-s, e.currency)}`
82
+ }),
83
+ /* @__PURE__ */ h("p", {
84
+ className: "text-xs text-text-secondary",
85
+ children: o("movethewheels.shipping.ownFleet.note", "Based only on the distance and cost per km you entered — not a quote.")
86
+ })
87
+ ]
88
+ })] });
89
+ }
90
+ function C({ result: t, t: f }) {
91
+ let _ = t.providers.filter((e) => !e.ok);
92
+ return /* @__PURE__ */ g("div", {
93
+ className: "space-y-4",
94
+ children: [
95
+ _.map((t) => /* @__PURE__ */ g("div", {
96
+ role: "alert",
97
+ className: "flex items-start gap-2 rounded-lg border border-status-warning-border bg-status-warning-bg-subtle px-4 py-3 text-sm text-status-warning-text",
98
+ children: [/* @__PURE__ */ h(e, {
99
+ size: 18,
100
+ className: "mt-0.5 shrink-0",
101
+ "aria-hidden": "true"
102
+ }), /* @__PURE__ */ h("span", { children: t.errorMessage })]
103
+ }, t.provider)),
104
+ t.ownFleet && /* @__PURE__ */ h(S, {
105
+ estimate: t.ownFleet,
106
+ t: f
107
+ }),
108
+ /* @__PURE__ */ g(n, { children: [/* @__PURE__ */ g(i, { children: [/* @__PURE__ */ g(a, { children: [
109
+ f("movethewheels.shipping.results.title", "Courier options"),
110
+ " (",
111
+ t.quotes.length,
112
+ ")"
113
+ ] }), /* @__PURE__ */ g("p", {
114
+ className: "text-sm text-text-secondary",
115
+ children: [
116
+ f("movethewheels.shipping.results.chargeableWeight", "Charged on"),
117
+ " ",
118
+ t.chargeableWeightKg,
119
+ " kg"
120
+ ]
121
+ })] }), /* @__PURE__ */ h(r, {
122
+ className: "p-0",
123
+ children: t.quotes.length === 0 ? /* @__PURE__ */ h("p", {
124
+ className: "px-6 pb-6 text-sm text-text-secondary",
125
+ children: _.length > 0 ? f("movethewheels.shipping.results.allFailed", "No rates could be fetched — see the message above.") : f("movethewheels.shipping.results.noServiceable", "No courier serves this pincode pair.")
126
+ }) : /* @__PURE__ */ g(m, { children: [/* @__PURE__ */ h("ul", {
127
+ className: "divide-y md:hidden",
128
+ "aria-label": f("movethewheels.shipping.results.title", "Courier options"),
129
+ children: t.quotes.map((e) => /* @__PURE__ */ g("li", {
130
+ className: "space-y-2 px-4 py-4",
131
+ children: [
132
+ /* @__PURE__ */ g("div", {
133
+ className: "flex items-start justify-between gap-3",
134
+ children: [/* @__PURE__ */ h("span", {
135
+ className: "min-w-0 font-medium",
136
+ children: e.courierName
137
+ }), /* @__PURE__ */ h("span", {
138
+ className: "shrink-0 text-lg font-semibold",
139
+ children: p(e.price, e.currency)
140
+ })]
141
+ }),
142
+ /* @__PURE__ */ h("div", {
143
+ className: "flex flex-wrap items-center gap-2",
144
+ children: /* @__PURE__ */ h(x, {
145
+ quote: e,
146
+ t: f
147
+ })
148
+ }),
149
+ /* @__PURE__ */ h("p", {
150
+ className: "text-sm text-text-secondary",
151
+ children: [
152
+ b(e, f),
153
+ y(e, f),
154
+ e.rating === null ? null : `${e.rating.toFixed(1)} ★`
155
+ ].filter((e) => e !== "—" && e !== null).join(" · ")
156
+ })
157
+ ]
158
+ }, `${e.provider}:${e.courierId}`))
159
+ }), /* @__PURE__ */ h("div", {
160
+ className: "hidden md:block",
161
+ children: /* @__PURE__ */ g(o, { children: [/* @__PURE__ */ h(u, { children: /* @__PURE__ */ g(d, { children: [
162
+ /* @__PURE__ */ h(l, { children: f("movethewheels.shipping.results.courier", "Courier") }),
163
+ /* @__PURE__ */ h(l, { children: f("movethewheels.shipping.results.mode", "Mode") }),
164
+ /* @__PURE__ */ h(l, { children: f("movethewheels.shipping.results.transit", "Estimated delivery") }),
165
+ /* @__PURE__ */ h(l, { children: f("movethewheels.shipping.results.rating", "Rating") }),
166
+ /* @__PURE__ */ h(l, {
167
+ className: "text-right",
168
+ children: f("movethewheels.shipping.results.price", "Price")
169
+ })
170
+ ] }) }), /* @__PURE__ */ h(s, { children: t.quotes.map((e) => /* @__PURE__ */ g(d, { children: [
171
+ /* @__PURE__ */ h(c, { children: /* @__PURE__ */ g("div", {
172
+ className: "flex flex-wrap items-center gap-2",
173
+ children: [/* @__PURE__ */ h("span", {
174
+ className: "font-medium",
175
+ children: e.courierName
176
+ }), /* @__PURE__ */ h(x, {
177
+ quote: e,
178
+ t: f
179
+ })]
180
+ }) }),
181
+ /* @__PURE__ */ h(c, { children: b(e, f) }),
182
+ /* @__PURE__ */ h(c, { children: y(e, f) }),
183
+ /* @__PURE__ */ h(c, { children: e.rating === null ? "—" : e.rating.toFixed(1) }),
184
+ /* @__PURE__ */ h(c, {
185
+ className: "text-right font-medium",
186
+ children: p(e.price, e.currency)
187
+ })
188
+ ] }, `${e.provider}:${e.courierId}`)) })] })
189
+ })] })
190
+ })] })
191
+ ]
192
+ });
193
+ }
194
+ //#endregion
195
+ export { C as ShippingQuoteResults };
@@ -0,0 +1,29 @@
1
+ import { useMoveTheWheels as e } from "../providers/MoveTheWheelsProvider.js";
2
+ import { executeGraphQL as t } from "../utils/graphqlClient.js";
3
+ import { useCallback as n, useMemo as r } from "react";
4
+ //#region src/movethewheels/hooks/useShippingCarriers.ts
5
+ var i = "\n query ShippingQuotes($input: ShippingQuoteInput!) {\n shippingQuotes(input: $input) {\n chargeableWeightKg\n ownFleet {\n distanceKm\n costPerKm\n fixedCost\n cost\n currency\n savingsVsCheapestCourier\n isCheaperThanCouriers\n }\n quotes {\n provider\n courierId\n courierName\n price\n currency\n estimatedDeliveryDays\n estimatedDeliveryDate\n rating\n mode\n isRecommended\n isCheapest\n isFastest\n }\n providers {\n provider\n ok\n quoteCount\n errorMessage\n }\n }\n }\n";
6
+ function a() {
7
+ let { apiGatewayUrl: t, authToken: n, workspaceToken: i, workspaceId: a, tenantId: o, currentUser: s } = e();
8
+ return r(() => ({
9
+ apiGatewayUrl: t,
10
+ authToken: n,
11
+ workspaceToken: i,
12
+ workspaceId: a,
13
+ tenantId: o,
14
+ actorId: s?.id
15
+ }), [
16
+ t,
17
+ n,
18
+ i,
19
+ a,
20
+ o,
21
+ s?.id
22
+ ]);
23
+ }
24
+ function o() {
25
+ let e = a();
26
+ return n(async (n) => (await t(e, i, { input: n })).shippingQuotes, [e]);
27
+ }
28
+ //#endregion
29
+ export { o as useShippingQuotes };
@@ -0,0 +1,8 @@
1
+ import { ShippingQuoteResult } from '../hooks/useShippingCarriers';
2
+
3
+ interface ShippingQuoteResultsProps {
4
+ result: ShippingQuoteResult;
5
+ t: (key: string, fallback: string) => string;
6
+ }
7
+ export declare function ShippingQuoteResults({ result, t }: ShippingQuoteResultsProps): import("react").JSX.Element;
8
+ export {};
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Shipping rate comparison — every carrier's price for one pincode pair, on top
3
+ * of wspace-movethewheels-svc's carrier module. The carrier accounts belong to
4
+ * the platform, so there is nothing for a workspace to configure.
5
+ */
6
+ export type CarrierProvider = 'SHIPROCKET';
7
+ export type CarrierServiceMode = 'SURFACE' | 'AIR';
8
+ export interface OwnFleetInput {
9
+ distanceKm: number;
10
+ costPerKm: number;
11
+ fixedCost?: number;
12
+ }
13
+ export interface OwnFleetEstimate {
14
+ distanceKm: number;
15
+ costPerKm: number;
16
+ fixedCost: number;
17
+ cost: number;
18
+ currency: string;
19
+ /** Cheapest courier price minus this estimate; positive = your own vehicle is cheaper. */
20
+ savingsVsCheapestCourier: number | null;
21
+ isCheaperThanCouriers: boolean;
22
+ }
23
+ export interface ShippingQuoteInput {
24
+ pickupPostcode: string;
25
+ deliveryPostcode: string;
26
+ weightKg: number;
27
+ lengthCm?: number;
28
+ widthCm?: number;
29
+ heightCm?: number;
30
+ cod?: boolean;
31
+ ownFleet?: OwnFleetInput;
32
+ }
33
+ export interface ShippingQuote {
34
+ provider: CarrierProvider;
35
+ courierId: string;
36
+ courierName: string;
37
+ price: number;
38
+ currency: string;
39
+ estimatedDeliveryDays: number | null;
40
+ estimatedDeliveryDate: string | null;
41
+ rating: number | null;
42
+ mode: CarrierServiceMode | null;
43
+ isRecommended: boolean;
44
+ isCheapest: boolean;
45
+ isFastest: boolean;
46
+ }
47
+ export interface CarrierOutcome {
48
+ provider: CarrierProvider;
49
+ ok: boolean;
50
+ quoteCount: number;
51
+ errorMessage: string | null;
52
+ }
53
+ export interface ShippingQuoteResult {
54
+ chargeableWeightKg: number;
55
+ ownFleet: OwnFleetEstimate | null;
56
+ quotes: ShippingQuote[];
57
+ providers: CarrierOutcome[];
58
+ }
59
+ /** Imperative: a comparison is something the operator asks for, not page-load data. */
60
+ export declare function useShippingQuotes(): (input: ShippingQuoteInput) => Promise<ShippingQuoteResult>;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Shipping Rates Page
3
+ *
4
+ * Compare live courier rates between two pincodes across the platform's
5
+ * carriers (Shiprocket first). Nothing to set up: the carrier accounts belong
6
+ * to the platform. Read-only — comparing never books a shipment or spends
7
+ * carrier credit.
8
+ */
9
+ export default function ShippingRatesPage(): import("react").JSX.Element;
@@ -0,0 +1,26 @@
1
+ import { createLucideIcon as e } from "../createLucideIcon.js";
2
+ //#region node_modules/lucide-react/dist/esm/icons/scale.js
3
+ var t = e("Scale", [
4
+ ["path", {
5
+ d: "m16 16 3-8 3 8c-.87.65-1.92 1-3 1s-2.13-.35-3-1Z",
6
+ key: "7g6ntu"
7
+ }],
8
+ ["path", {
9
+ d: "m2 16 3-8 3 8c-.87.65-1.92 1-3 1s-2.13-.35-3-1Z",
10
+ key: "ijws7r"
11
+ }],
12
+ ["path", {
13
+ d: "M7 21h10",
14
+ key: "1b0cd5"
15
+ }],
16
+ ["path", {
17
+ d: "M12 3v18",
18
+ key: "108xh3"
19
+ }],
20
+ ["path", {
21
+ d: "M3 7h2c2 0 5-1 7-2 2 1 5 2 7 2h2",
22
+ key: "3gwbw2"
23
+ }]
24
+ ]);
25
+ //#endregion
26
+ export { t as Scale };
@@ -0,0 +1,245 @@
1
+ import { Scale as e } from "../node_modules/lucide-react/dist/esm/icons/scale.js";
2
+ import { useTr as t } from "../shared/hooks/useTr.js";
3
+ import "../hooks/index.js";
4
+ import { Button as n, Card as r, CardContent as i, CardHeader as a, CardTitle as o, Input as s, Label as c, Switch as l } from "../components/ui.js";
5
+ import { PageLayout as u } from "../components/PageLayout.js";
6
+ import { FormError as d } from "../components/FormError.js";
7
+ import { ShippingQuoteResults as f } from "../components/ShippingQuoteResults.js";
8
+ import { useShippingQuotes as p } from "../hooks/useShippingCarriers.js";
9
+ import { useState as m } from "react";
10
+ import { jsx as h, jsxs as g } from "react/jsx-runtime";
11
+ //#region src/movethewheels/pages/ShippingRatesPage.tsx
12
+ var _ = /^[1-9]\d{5}$/, v = (e) => {
13
+ let t = Number(e);
14
+ return e.trim() !== "" && Number.isFinite(t) ? t : void 0;
15
+ };
16
+ function y() {
17
+ let y = t(), b = p(), [x, S] = m(""), [C, w] = m(""), [T, E] = m(""), [D, O] = m(""), [k, A] = m(""), [j, M] = m(""), [N, P] = m(!1), [F, I] = m(""), [L, R] = m(""), [z, B] = m(""), [V, H] = m(!1), [U, W] = m(null), [G, K] = m(null), q = async (e) => {
18
+ e.preventDefault(), W(null);
19
+ let t = v(T);
20
+ if (!_.test(x) || !_.test(C)) {
21
+ W(y("movethewheels.shipping.form.postcodeError", "Enter valid 6-digit pickup and delivery postcodes"));
22
+ return;
23
+ }
24
+ if (t === void 0 || t <= 0) {
25
+ W(y("movethewheels.shipping.form.weightError", "Enter the package weight in kg"));
26
+ return;
27
+ }
28
+ let n = [
29
+ v(D),
30
+ v(k),
31
+ v(j)
32
+ ], r = n.filter((e) => e !== void 0).length;
33
+ if (r !== 0 && r !== 3) {
34
+ W(y("movethewheels.shipping.form.dimensionsError", "Enter length, width and height together, or leave all three empty"));
35
+ return;
36
+ }
37
+ let i = v(F), a = v(L), o = v(z), s = i !== void 0 || a !== void 0;
38
+ if (s && (!i || i <= 0 || !a || a <= 0)) {
39
+ W(y("movethewheels.shipping.form.ownFleetError", "To compare with your own vehicle, enter both the distance and your cost per km"));
40
+ return;
41
+ }
42
+ if (o !== void 0 && o < 0) {
43
+ W(y("movethewheels.shipping.form.fixedCostError", "Fixed cost cannot be negative"));
44
+ return;
45
+ }
46
+ let c = {
47
+ pickupPostcode: x,
48
+ deliveryPostcode: C,
49
+ weightKg: t,
50
+ cod: N,
51
+ ...s && i && a ? { ownFleet: {
52
+ distanceKm: i,
53
+ costPerKm: a,
54
+ ...o ? { fixedCost: o } : {}
55
+ } } : {},
56
+ ...r === 3 ? {
57
+ lengthCm: n[0],
58
+ widthCm: n[1],
59
+ heightCm: n[2]
60
+ } : {}
61
+ };
62
+ H(!0);
63
+ try {
64
+ K(await b(c));
65
+ } catch (e) {
66
+ K(null), W(e instanceof Error ? e.message : y("movethewheels.shipping.form.failed", "Could not fetch rates"));
67
+ } finally {
68
+ H(!1);
69
+ }
70
+ };
71
+ return /* @__PURE__ */ h(u, {
72
+ title: y("movethewheels.shipping.title", "Compare Rates"),
73
+ subtitle: y("movethewheels.shipping.subtitle", "Enter a pickup and a delivery pincode to see every courier available for that route, with price and delivery time."),
74
+ icon: /* @__PURE__ */ h(e, { size: 24 }),
75
+ children: /* @__PURE__ */ g("div", {
76
+ className: "space-y-6",
77
+ children: [/* @__PURE__ */ g(r, { children: [/* @__PURE__ */ h(a, { children: /* @__PURE__ */ h(o, { children: y("movethewheels.shipping.form.title", "Shipment details") }) }), /* @__PURE__ */ h(i, { children: /* @__PURE__ */ g("form", {
78
+ onSubmit: (e) => void q(e),
79
+ className: "space-y-4",
80
+ children: [
81
+ /* @__PURE__ */ g("div", {
82
+ className: "grid gap-3 sm:grid-cols-3",
83
+ children: [
84
+ /* @__PURE__ */ g("div", {
85
+ className: "space-y-1",
86
+ children: [/* @__PURE__ */ h(c, {
87
+ htmlFor: "rate-pickup",
88
+ children: y("movethewheels.shipping.form.pickup", "Pickup postcode")
89
+ }), /* @__PURE__ */ h(s, {
90
+ id: "rate-pickup",
91
+ inputMode: "numeric",
92
+ maxLength: 6,
93
+ value: x,
94
+ onChange: (e) => S(e.target.value.trim())
95
+ })]
96
+ }),
97
+ /* @__PURE__ */ g("div", {
98
+ className: "space-y-1",
99
+ children: [/* @__PURE__ */ h(c, {
100
+ htmlFor: "rate-delivery",
101
+ children: y("movethewheels.shipping.form.delivery", "Delivery postcode")
102
+ }), /* @__PURE__ */ h(s, {
103
+ id: "rate-delivery",
104
+ inputMode: "numeric",
105
+ maxLength: 6,
106
+ value: C,
107
+ onChange: (e) => w(e.target.value.trim())
108
+ })]
109
+ }),
110
+ /* @__PURE__ */ g("div", {
111
+ className: "space-y-1",
112
+ children: [/* @__PURE__ */ h(c, {
113
+ htmlFor: "rate-weight",
114
+ children: y("movethewheels.shipping.form.weight", "Weight (kg)")
115
+ }), /* @__PURE__ */ h(s, {
116
+ id: "rate-weight",
117
+ inputMode: "decimal",
118
+ value: T,
119
+ onChange: (e) => E(e.target.value)
120
+ })]
121
+ })
122
+ ]
123
+ }),
124
+ /* @__PURE__ */ g("div", {
125
+ className: "grid gap-3 sm:grid-cols-3",
126
+ children: [
127
+ /* @__PURE__ */ g("div", {
128
+ className: "space-y-1",
129
+ children: [/* @__PURE__ */ h(c, {
130
+ htmlFor: "rate-length",
131
+ children: y("movethewheels.shipping.form.length", "Length (cm, optional)")
132
+ }), /* @__PURE__ */ h(s, {
133
+ id: "rate-length",
134
+ inputMode: "decimal",
135
+ value: D,
136
+ onChange: (e) => O(e.target.value)
137
+ })]
138
+ }),
139
+ /* @__PURE__ */ g("div", {
140
+ className: "space-y-1",
141
+ children: [/* @__PURE__ */ h(c, {
142
+ htmlFor: "rate-width",
143
+ children: y("movethewheels.shipping.form.width", "Width (cm, optional)")
144
+ }), /* @__PURE__ */ h(s, {
145
+ id: "rate-width",
146
+ inputMode: "decimal",
147
+ value: k,
148
+ onChange: (e) => A(e.target.value)
149
+ })]
150
+ }),
151
+ /* @__PURE__ */ g("div", {
152
+ className: "space-y-1",
153
+ children: [/* @__PURE__ */ h(c, {
154
+ htmlFor: "rate-height",
155
+ children: y("movethewheels.shipping.form.height", "Height (cm, optional)")
156
+ }), /* @__PURE__ */ h(s, {
157
+ id: "rate-height",
158
+ inputMode: "decimal",
159
+ value: j,
160
+ onChange: (e) => M(e.target.value)
161
+ })]
162
+ })
163
+ ]
164
+ }),
165
+ /* @__PURE__ */ g("fieldset", {
166
+ className: "space-y-3 rounded-lg border p-4",
167
+ children: [
168
+ /* @__PURE__ */ h("legend", {
169
+ className: "px-1 text-sm font-medium",
170
+ children: y("movethewheels.shipping.form.ownFleetTitle", "Compare with your own vehicle (optional)")
171
+ }),
172
+ /* @__PURE__ */ h("p", {
173
+ className: "text-sm text-text-secondary",
174
+ children: y("movethewheels.shipping.form.ownFleetHelp", "Enter the road distance and what it costs you to run a vehicle per km, and we will show it next to the courier prices.")
175
+ }),
176
+ /* @__PURE__ */ g("div", {
177
+ className: "grid gap-3 sm:grid-cols-3",
178
+ children: [
179
+ /* @__PURE__ */ g("div", {
180
+ className: "space-y-1",
181
+ children: [/* @__PURE__ */ h(c, {
182
+ htmlFor: "rate-distance",
183
+ children: y("movethewheels.shipping.form.distance", "Distance (km)")
184
+ }), /* @__PURE__ */ h(s, {
185
+ id: "rate-distance",
186
+ inputMode: "decimal",
187
+ value: F,
188
+ onChange: (e) => I(e.target.value)
189
+ })]
190
+ }),
191
+ /* @__PURE__ */ g("div", {
192
+ className: "space-y-1",
193
+ children: [/* @__PURE__ */ h(c, {
194
+ htmlFor: "rate-cost-per-km",
195
+ children: y("movethewheels.shipping.form.costPerKm", "Your cost per km (₹)")
196
+ }), /* @__PURE__ */ h(s, {
197
+ id: "rate-cost-per-km",
198
+ inputMode: "decimal",
199
+ value: L,
200
+ onChange: (e) => R(e.target.value)
201
+ })]
202
+ }),
203
+ /* @__PURE__ */ g("div", {
204
+ className: "space-y-1",
205
+ children: [/* @__PURE__ */ h(c, {
206
+ htmlFor: "rate-fixed-cost",
207
+ children: y("movethewheels.shipping.form.fixedCost", "Fixed cost per trip (₹, optional)")
208
+ }), /* @__PURE__ */ h(s, {
209
+ id: "rate-fixed-cost",
210
+ inputMode: "decimal",
211
+ value: z,
212
+ onChange: (e) => B(e.target.value)
213
+ })]
214
+ })
215
+ ]
216
+ })
217
+ ]
218
+ }),
219
+ /* @__PURE__ */ g("div", {
220
+ className: "flex items-center gap-2",
221
+ children: [/* @__PURE__ */ h(l, {
222
+ id: "rate-cod",
223
+ checked: N,
224
+ onCheckedChange: P
225
+ }), /* @__PURE__ */ h(c, {
226
+ htmlFor: "rate-cod",
227
+ children: y("movethewheels.shipping.form.cod", "Cash on delivery")
228
+ })]
229
+ }),
230
+ /* @__PURE__ */ h(d, { message: U }),
231
+ /* @__PURE__ */ h(n, {
232
+ type: "submit",
233
+ disabled: V,
234
+ children: V ? y("movethewheels.shipping.form.comparing", "Comparing…") : y("movethewheels.shipping.form.compare", "Compare rates")
235
+ })
236
+ ]
237
+ }) })] }), G && /* @__PURE__ */ h(f, {
238
+ result: G,
239
+ t: y
240
+ })]
241
+ })
242
+ });
243
+ }
244
+ //#endregion
245
+ export { y as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-movethewheels",
3
- "version": "2026.918.1",
3
+ "version": "2026.920.2",
4
4
  "description": "Burdenoff MoveTheWheels Microfrontend - Logistics & Supply Chain Management Platform",
5
5
  "type": "module",
6
6
  "files": [
@@ -79,6 +79,7 @@ const SettingsPage = lazy(() => import('./pages/SettingsPage'));
79
79
  const AIAssistantPage = lazy(() => import('./pages/AIAssistantPage'));
80
80
  const DeliveryCapturePage = lazy(() => import('./pages/DeliveryCapturePage'));
81
81
  const MultiModalShipmentPage = lazy(() => import('./pages/MultiModalShipmentPage'));
82
+ const ShippingRatesPage = lazy(() => import('./pages/ShippingRatesPage'));
82
83
 
83
84
  export function MoveTheWheelsRoutes() {
84
85
  return (
@@ -102,6 +103,7 @@ export function MoveTheWheelsRoutes() {
102
103
 
103
104
  {/* Multi-modal freight execution (BOFF-4398) */}
104
105
  <Route path="shipments/multi-modal" element={<MultiModalShipmentPage />} />
106
+ <Route path="shipments/rates" element={<ShippingRatesPage />} />
105
107
 
106
108
  {/* Fleet */}
107
109
  <Route path="fleet" element={<FleetPage />} />