@burdenoff/microfe-movethewheels 2026.719.2 → 2026.722.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.
@@ -18,16 +18,16 @@ import { Warehouse as g } from "./node_modules/lucide-react/dist/esm/icons/wareh
18
18
  import { MoveTheWheelsProvider as _ } from "./providers/MoveTheWheelsProvider.js";
19
19
  import { MoveTheWheelsRoutes as v } from "./MoveTheWheelsRoutes.js";
20
20
  import { useEffect as y } from "react";
21
- import { jsx as b } from "react/jsx-runtime";
22
- import { FeatureFlagProvider as x } from "@burdenoff/fe-libs/shared/feature-flags";
21
+ import { jsx as b, jsxs as x } from "react/jsx-runtime";
22
+ import { FeatureFlagProvider as S, useFeatureFlag as C } from "@burdenoff/fe-libs/shared/feature-flags";
23
23
  //#region src/movethewheels/MoveTheWheelsRoot.tsx
24
- var S = (S) => {
25
- let { registerNavItems: C, registerFooterItems: w, basePath: T = "/" } = S, E = (e, t) => (e.endsWith("/") ? e.slice(0, -1) : e) + (t.startsWith("/") ? t : `/${t}`);
24
+ var w = ({ registerNavItems: _, basePath: v = "/" }) => {
25
+ let x = C("movethewheels.marketplace", !1), S = (e, t) => (e.endsWith("/") ? e.slice(0, -1) : e) + (t.startsWith("/") ? t : `/${t}`);
26
26
  return y(() => {
27
- if (C) return C({
27
+ if (_) return _({
28
28
  id: "movethewheels",
29
29
  label: "MoveTheWheels",
30
- path: T,
30
+ path: v,
31
31
  icon: /* @__PURE__ */ b(p, { size: 20 }),
32
32
  order: 25,
33
33
  group: "workspace",
@@ -35,49 +35,49 @@ var S = (S) => {
35
35
  {
36
36
  id: "mtw-dashboard",
37
37
  label: "Dashboard",
38
- path: T,
38
+ path: v,
39
39
  icon: /* @__PURE__ */ b(s, { size: 16 }),
40
40
  order: 1
41
41
  },
42
42
  {
43
43
  id: "mtw-orders",
44
44
  label: "Orders",
45
- path: E(T, "orders"),
45
+ path: S(v, "orders"),
46
46
  icon: /* @__PURE__ */ b(l, { size: 16 }),
47
47
  order: 2
48
48
  },
49
49
  {
50
50
  id: "mtw-tracking",
51
51
  label: "Tracking",
52
- path: E(T, "tracking"),
52
+ path: S(v, "tracking"),
53
53
  icon: /* @__PURE__ */ b(c, { size: 16 }),
54
54
  order: 3
55
55
  },
56
56
  {
57
57
  id: "mtw-fleet",
58
58
  label: "Fleet",
59
- path: E(T, "fleet"),
59
+ path: S(v, "fleet"),
60
60
  icon: /* @__PURE__ */ b(p, { size: 16 }),
61
61
  order: 4,
62
62
  children: [
63
63
  {
64
64
  id: "mtw-fleet-overview",
65
65
  label: "Overview",
66
- path: E(T, "fleet"),
66
+ path: S(v, "fleet"),
67
67
  icon: /* @__PURE__ */ b(s, { size: 14 }),
68
68
  order: 1
69
69
  },
70
70
  {
71
71
  id: "mtw-vehicles",
72
72
  label: "Vehicles",
73
- path: E(T, "fleet/vehicles"),
73
+ path: S(v, "fleet/vehicles"),
74
74
  icon: /* @__PURE__ */ b(n, { size: 14 }),
75
75
  order: 2
76
76
  },
77
77
  {
78
78
  id: "mtw-drivers",
79
79
  label: "Drivers",
80
- path: E(T, "fleet/drivers"),
80
+ path: S(v, "fleet/drivers"),
81
81
  icon: /* @__PURE__ */ b(m, { size: 14 }),
82
82
  order: 3
83
83
  }
@@ -86,28 +86,28 @@ var S = (S) => {
86
86
  {
87
87
  id: "mtw-inventory",
88
88
  label: "Inventory",
89
- path: E(T, "inventory"),
89
+ path: S(v, "inventory"),
90
90
  icon: /* @__PURE__ */ b(g, { size: 16 }),
91
91
  order: 5,
92
92
  children: [
93
93
  {
94
94
  id: "mtw-inventory-overview",
95
95
  label: "Overview",
96
- path: E(T, "inventory"),
96
+ path: S(v, "inventory"),
97
97
  icon: /* @__PURE__ */ b(s, { size: 14 }),
98
98
  order: 1
99
99
  },
100
100
  {
101
101
  id: "mtw-products",
102
102
  label: "Products",
103
- path: E(T, "inventory/products"),
103
+ path: S(v, "inventory/products"),
104
104
  icon: /* @__PURE__ */ b(t, { size: 14 }),
105
105
  order: 2
106
106
  },
107
107
  {
108
108
  id: "mtw-warehouses",
109
109
  label: "Warehouses",
110
- path: E(T, "inventory/warehouses"),
110
+ path: S(v, "inventory/warehouses"),
111
111
  icon: /* @__PURE__ */ b(g, { size: 14 }),
112
112
  order: 3
113
113
  }
@@ -116,88 +116,98 @@ var S = (S) => {
116
116
  {
117
117
  id: "mtw-customers",
118
118
  label: "Customers",
119
- path: E(T, "customers"),
119
+ path: S(v, "customers"),
120
120
  icon: /* @__PURE__ */ b(h, { size: 16 }),
121
121
  order: 6
122
122
  },
123
123
  {
124
124
  id: "mtw-routes",
125
125
  label: "Routes",
126
- path: E(T, "routes"),
126
+ path: S(v, "routes"),
127
127
  icon: /* @__PURE__ */ b(u, { size: 16 }),
128
128
  order: 7
129
129
  },
130
130
  {
131
131
  id: "mtw-analytics",
132
132
  label: "Analytics",
133
- path: E(T, "analytics"),
133
+ path: S(v, "analytics"),
134
134
  icon: /* @__PURE__ */ b(r, { size: 16 }),
135
135
  order: 8
136
136
  },
137
137
  {
138
138
  id: "mtw-finance",
139
139
  label: "Finance",
140
- path: E(T, "finance"),
140
+ path: S(v, "finance"),
141
141
  icon: /* @__PURE__ */ b(i, { size: 16 }),
142
142
  order: 9
143
143
  },
144
- {
144
+ ...x ? [{
145
145
  id: "mtw-marketplace",
146
146
  label: "Marketplace",
147
- path: E(T, "marketplace"),
147
+ path: S(v, "marketplace"),
148
148
  icon: /* @__PURE__ */ b(f, { size: 16 }),
149
149
  order: 10
150
- },
150
+ }] : [],
151
151
  {
152
152
  id: "mtw-import-export",
153
153
  label: "Import/Export",
154
- path: E(T, "import-export"),
154
+ path: S(v, "import-export"),
155
155
  icon: /* @__PURE__ */ b(o, { size: 16 }),
156
156
  order: 11
157
157
  },
158
158
  {
159
159
  id: "mtw-reports",
160
160
  label: "Reports",
161
- path: E(T, "reports"),
161
+ path: S(v, "reports"),
162
162
  icon: /* @__PURE__ */ b(a, { size: 16 }),
163
163
  order: 12
164
164
  },
165
165
  {
166
166
  id: "mtw-ai-assistant",
167
167
  label: "AI Assistant",
168
- path: E(T, "ai-assistant"),
168
+ path: S(v, "ai-assistant"),
169
169
  icon: /* @__PURE__ */ b(e, { size: 16 }),
170
170
  order: 13
171
171
  },
172
172
  {
173
173
  id: "mtw-settings",
174
174
  label: "Settings",
175
- path: E(T, "settings"),
175
+ path: S(v, "settings"),
176
176
  icon: /* @__PURE__ */ b(d, { size: 16 }),
177
177
  order: 99
178
178
  }
179
179
  ]
180
180
  });
181
- }, [C, T]), y(() => {
182
- if (w) return w([{
181
+ }, [
182
+ _,
183
+ v,
184
+ x
185
+ ]), null;
186
+ }, T = (e) => {
187
+ let { registerNavItems: t, registerFooterItems: n, basePath: r = "/" } = e;
188
+ return y(() => {
189
+ if (n) return n([{
183
190
  id: "mtw-status",
184
191
  label: "Logistics Ready",
185
192
  type: "status",
186
193
  order: 20,
187
194
  section: "left"
188
195
  }]);
189
- }, [w]), /* @__PURE__ */ b(x, {
196
+ }, [n]), /* @__PURE__ */ x(S, {
190
197
  workspaceId: null,
191
198
  gateway: "global",
192
199
  defaultEnabled: !0,
193
- children: /* @__PURE__ */ b(_, {
194
- ...S,
200
+ children: [/* @__PURE__ */ b(w, {
201
+ registerNavItems: t,
202
+ basePath: r
203
+ }), /* @__PURE__ */ b(_, {
204
+ ...e,
195
205
  children: /* @__PURE__ */ b("div", {
196
206
  className: "movethewheels-root h-full",
197
207
  children: /* @__PURE__ */ b(v, {})
198
208
  })
199
- })
209
+ })]
200
210
  });
201
211
  };
202
212
  //#endregion
203
- export { S as MoveTheWheelsRoot };
213
+ export { T as MoveTheWheelsRoot };
@@ -55,7 +55,7 @@ function g() {
55
55
  /* @__PURE__ */ f(a, { children: [/* @__PURE__ */ d(s, { children: /* @__PURE__ */ d(c, { children: "On the roadmap" }) }), /* @__PURE__ */ f(o, { children: [/* @__PURE__ */ d(l, {
56
56
  illustration: "empty-agents",
57
57
  title: "Autonomous dispatch operations aren't live yet",
58
- description: "These capabilities depend on the shared multi-model AI gateway and agent-run ledger (BOFF-3601), which hasn't shipped across the platform yet. Nothing below is available today."
58
+ description: "Autonomous dispatch isn't available yet — these capabilities are still in development. Nothing below is available today."
59
59
  }), /* @__PURE__ */ d("ul", {
60
60
  className: "mt-4 space-y-4",
61
61
  children: h.map((e) => /* @__PURE__ */ f("li", {
@@ -11,13 +11,14 @@ import { Store as i } from "../node_modules/lucide-react/dist/esm/icons/store.js
11
11
  import { useMoveTheWheels as ae } from "../providers/MoveTheWheelsProvider.js";
12
12
  import { executeGraphQL as a } from "../utils/graphqlClient.js";
13
13
  import { Badge as o, Button as s, Card as c, CardContent as l, CardHeader as oe, CardTitle as se, Input as ce, Select as u, SelectContent as d, SelectItem as f, SelectTrigger as p, SelectValue as m, Skeleton as le } from "../components/ui.js";
14
- import { PageLayout as ue } from "../components/PageLayout.js";
15
- import { formatCurrency as h } from "../utils/formatters.js";
16
- import { useCallback as g, useEffect as de, useMemo as _, useState as v } from "react";
17
- import { Fragment as y, jsx as b, jsxs as x } from "react/jsx-runtime";
18
- import { EmphasisPanel as S, IllustratedEmptyState as C, PagePurpose as fe } from "@burdenoff/fe-libs/ui";
14
+ import { PageLayout as h } from "../components/PageLayout.js";
15
+ import { formatCurrency as g } from "../utils/formatters.js";
16
+ import { useCallback as _, useEffect as ue, useMemo as v, useState as y } from "react";
17
+ import { Fragment as b, jsx as x, jsxs as S } from "react/jsx-runtime";
18
+ import { useFeatureFlag as de } from "@burdenoff/fe-libs/shared/feature-flags";
19
+ import { EmphasisPanel as fe, IllustratedEmptyState as C, PagePurpose as pe } from "@burdenoff/fe-libs/ui";
19
20
  //#region src/movethewheels/pages/MarketplacePage.tsx
20
- var pe = "\n query ListServiceProviders($filter: ServiceProviderFilterInput, $pagination: PaginationInput) {\n serviceProviders(filter: $filter, pagination: $pagination) {\n id\n name\n type\n description\n rating\n isVerified\n isActive\n services\n contactInfo\n }\n }\n", me = "\n query ListServiceOfferings($filter: ServiceOfferingFilterInput, $pagination: PaginationInput) {\n serviceOfferings(filter: $filter, pagination: $pagination) {\n id\n providerId\n name\n description\n category\n price\n currency\n availability\n provider {\n id\n name\n type\n rating\n }\n }\n }\n", w = 12, T = [
21
+ var me = "movethewheels.marketplace", he = "\n query ListServiceProviders($filter: ServiceProviderFilterInput, $pagination: PaginationInput) {\n serviceProviders(filter: $filter, pagination: $pagination) {\n id\n name\n type\n description\n rating\n isVerified\n isActive\n services\n contactInfo\n }\n }\n", ge = "\n query ListServiceOfferings($filter: ServiceOfferingFilterInput, $pagination: PaginationInput) {\n serviceOfferings(filter: $filter, pagination: $pagination) {\n id\n providerId\n name\n description\n category\n price\n currency\n availability\n provider {\n id\n name\n type\n rating\n }\n }\n }\n", w = 12, _e = [
21
22
  {
22
23
  value: "0",
23
24
  label: "Any rating"
@@ -35,8 +36,8 @@ var pe = "\n query ListServiceProviders($filter: ServiceProviderFilterInput, $p
35
36
  label: "4.5+"
36
37
  }
37
38
  ];
38
- function E() {
39
- let { apiGatewayUrl: E, authToken: D, workspaceToken: O, workspaceId: k, tenantId: A, currentUser: j } = ae(), [M, he] = v([]), [N, ge] = v([]), [P, _e] = v(""), [F, I] = v(!1), [L, R] = v(null), [z, B] = v(0), [ve, ye] = v(!1), [V, be] = v(!1), [H, U] = v("all"), [W, G] = v(!1), [K, q] = v("0"), [xe, J] = v(null), Y = _(() => ({
39
+ function T() {
40
+ let T = de(me, !1), { apiGatewayUrl: E, authToken: D, workspaceToken: O, workspaceId: k, tenantId: A, currentUser: j } = ae(), [M, ve] = y([]), [N, ye] = y([]), [P, be] = y(""), [F, I] = y(!1), [L, R] = y(null), [z, B] = y(0), [xe, Se] = y(!1), [V, Ce] = y(!1), [H, U] = y("all"), [W, G] = y(!1), [K, q] = y("0"), [we, J] = y(null), Y = v(() => ({
40
41
  apiGatewayUrl: E,
41
42
  authToken: D,
42
43
  workspaceToken: O,
@@ -50,30 +51,36 @@ function E() {
50
51
  k,
51
52
  A,
52
53
  j?.id
53
- ]), X = g(async () => {
54
- I(!0), R(null);
55
- try {
56
- let [e, t] = await Promise.all([a(Y, pe, { pagination: {
57
- limit: w,
58
- offset: z * w
59
- } }), a(Y, me, { pagination: {
60
- limit: 200,
61
- offset: 0
62
- } })]);
63
- he(e.serviceProviders), ye(e.serviceProviders.length === w), ge(t.serviceOfferings);
64
- } catch (e) {
65
- R(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load marketplace"));
66
- } finally {
67
- I(!1);
54
+ ]), X = _(async () => {
55
+ if (T) {
56
+ I(!0), R(null);
57
+ try {
58
+ let [e, t] = await Promise.all([a(Y, he, { pagination: {
59
+ limit: w,
60
+ offset: z * w
61
+ } }), a(Y, ge, { pagination: {
62
+ limit: 200,
63
+ offset: 0
64
+ } })]);
65
+ ve(e.serviceProviders), Se(e.serviceProviders.length === w), ye(t.serviceOfferings);
66
+ } catch (e) {
67
+ R(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load marketplace"));
68
+ } finally {
69
+ I(!1);
70
+ }
68
71
  }
69
- }, [Y, z]);
70
- de(() => {
72
+ }, [
73
+ Y,
74
+ z,
75
+ T
76
+ ]);
77
+ ue(() => {
71
78
  X();
72
79
  }, [X]);
73
- let Se = _(() => {
80
+ let Te = v(() => {
74
81
  let e = /* @__PURE__ */ new Set();
75
82
  return M.forEach((t) => e.add(t.type)), Array.from(e).sort();
76
- }, [M]), Z = _(() => {
83
+ }, [M]), Z = v(() => {
77
84
  let e = P.trim().toLowerCase(), t = Number(K);
78
85
  return M.filter((n) => !(e && !(n.name.toLowerCase().includes(e) || (n.description ?? "").toLowerCase().includes(e) || n.type.toLowerCase().includes(e)) || H !== "all" && n.type !== H || W && !n.isVerified || t > 0 && (n.rating ?? 0) < t));
79
86
  }, [
@@ -82,84 +89,84 @@ function E() {
82
89
  H,
83
90
  W,
84
91
  K
85
- ]), Q = _(() => {
92
+ ]), Q = v(() => {
86
93
  let e = P.trim().toLowerCase();
87
94
  return e ? N.filter((t) => t.name.toLowerCase().includes(e) || (t.description ?? "").toLowerCase().includes(e) || (t.category ?? "").toLowerCase().includes(e)) : N;
88
- }, [N, P]), Ce = g((e) => N.filter((t) => t.providerId === e), [N]), $ = H !== "all" || W || K !== "0";
89
- return /* @__PURE__ */ x(ue, {
95
+ }, [N, P]), Ee = _((e) => N.filter((t) => t.providerId === e), [N]), $ = H !== "all" || W || K !== "0";
96
+ return T ? /* @__PURE__ */ S(h, {
90
97
  title: "Marketplace",
91
98
  subtitle: "Find logistics service providers",
92
- icon: /* @__PURE__ */ b(i, { size: 24 }),
93
- headerActions: /* @__PURE__ */ x(s, {
99
+ icon: /* @__PURE__ */ x(i, { size: 24 }),
100
+ headerActions: /* @__PURE__ */ S(s, {
94
101
  variant: V || $ ? "default" : "outline",
95
- onClick: () => be((e) => !e),
96
- children: [/* @__PURE__ */ b(r, { size: 16 }), " Filters"]
102
+ onClick: () => Ce((e) => !e),
103
+ children: [/* @__PURE__ */ x(r, { size: 16 }), " Filters"]
97
104
  }),
98
105
  children: [
99
- /* @__PURE__ */ b(fe, {
100
- icon: /* @__PURE__ */ b(i, { size: 18 }),
106
+ /* @__PURE__ */ x(pe, {
107
+ icon: /* @__PURE__ */ x(i, { size: 18 }),
101
108
  children: "Don't own every leg of the journey? Find vetted third-party logistics providers and service offerings here — compare ratings, verification status and pricing, then engage a partner to cover routes, warehousing or specialised handling you can't do in-house."
102
109
  }),
103
- /* @__PURE__ */ b(c, { children: /* @__PURE__ */ x(l, {
110
+ /* @__PURE__ */ x(c, { children: /* @__PURE__ */ S(l, {
104
111
  className: "p-4 space-y-4",
105
- children: [/* @__PURE__ */ x("div", {
112
+ children: [/* @__PURE__ */ S("div", {
106
113
  className: "relative",
107
- children: [/* @__PURE__ */ b(re, {
114
+ children: [/* @__PURE__ */ x(re, {
108
115
  className: "absolute left-3 top-1/2 -translate-y-1/2 text-text-secondary",
109
116
  size: 20
110
- }), /* @__PURE__ */ b(ce, {
117
+ }), /* @__PURE__ */ x(ce, {
111
118
  placeholder: "Search services, providers, locations...",
112
119
  className: "pl-10",
113
120
  value: P,
114
- onChange: (e) => _e(e.target.value)
121
+ onChange: (e) => be(e.target.value)
115
122
  })]
116
- }), V && /* @__PURE__ */ x("div", {
123
+ }), V && /* @__PURE__ */ S("div", {
117
124
  className: "flex flex-wrap items-center gap-3 border-t border-border-seam pt-4",
118
125
  children: [
119
- /* @__PURE__ */ x("div", {
126
+ /* @__PURE__ */ S("div", {
120
127
  className: "flex items-center gap-2",
121
- children: [/* @__PURE__ */ b("span", {
128
+ children: [/* @__PURE__ */ x("span", {
122
129
  className: "text-sm font-medium text-text-secondary",
123
130
  children: "Type"
124
- }), /* @__PURE__ */ x(u, {
131
+ }), /* @__PURE__ */ S(u, {
125
132
  value: H,
126
133
  onValueChange: U,
127
- children: [/* @__PURE__ */ b(p, {
134
+ children: [/* @__PURE__ */ x(p, {
128
135
  className: "w-[160px]",
129
- children: /* @__PURE__ */ b(m, { placeholder: "All types" })
130
- }), /* @__PURE__ */ x(d, { children: [/* @__PURE__ */ b(f, {
136
+ children: /* @__PURE__ */ x(m, { placeholder: "All types" })
137
+ }), /* @__PURE__ */ S(d, { children: [/* @__PURE__ */ x(f, {
131
138
  value: "all",
132
139
  children: "All types"
133
- }), Se.map((e) => /* @__PURE__ */ b(f, {
140
+ }), Te.map((e) => /* @__PURE__ */ x(f, {
134
141
  value: e,
135
142
  children: e
136
143
  }, e))] })]
137
144
  })]
138
145
  }),
139
- /* @__PURE__ */ x("div", {
146
+ /* @__PURE__ */ S("div", {
140
147
  className: "flex items-center gap-2",
141
- children: [/* @__PURE__ */ b("span", {
148
+ children: [/* @__PURE__ */ x("span", {
142
149
  className: "text-sm font-medium text-text-secondary",
143
150
  children: "Min rating"
144
- }), /* @__PURE__ */ x(u, {
151
+ }), /* @__PURE__ */ S(u, {
145
152
  value: K,
146
153
  onValueChange: q,
147
- children: [/* @__PURE__ */ b(p, {
154
+ children: [/* @__PURE__ */ x(p, {
148
155
  className: "w-[130px]",
149
- children: /* @__PURE__ */ b(m, {})
150
- }), /* @__PURE__ */ b(d, { children: T.map((e) => /* @__PURE__ */ b(f, {
156
+ children: /* @__PURE__ */ x(m, {})
157
+ }), /* @__PURE__ */ x(d, { children: _e.map((e) => /* @__PURE__ */ x(f, {
151
158
  value: e.value,
152
159
  children: e.label
153
160
  }, e.value)) })]
154
161
  })]
155
162
  }),
156
- /* @__PURE__ */ b(s, {
163
+ /* @__PURE__ */ x(s, {
157
164
  variant: W ? "default" : "outline",
158
165
  size: "sm",
159
166
  onClick: () => G((e) => !e),
160
167
  children: "Verified only"
161
168
  }),
162
- $ && /* @__PURE__ */ b(s, {
169
+ $ && /* @__PURE__ */ x(s, {
163
170
  variant: "ghost",
164
171
  size: "sm",
165
172
  onClick: () => {
@@ -170,12 +177,12 @@ function E() {
170
177
  ]
171
178
  })]
172
179
  }) }),
173
- /* @__PURE__ */ x("div", {
180
+ /* @__PURE__ */ S("div", {
174
181
  className: "grid grid-cols-1 lg:grid-cols-3 gap-6",
175
- children: [/* @__PURE__ */ x("div", {
182
+ children: [/* @__PURE__ */ S("div", {
176
183
  className: "lg:col-span-2 space-y-4",
177
184
  children: [
178
- /* @__PURE__ */ x("h3", {
185
+ /* @__PURE__ */ S("h3", {
179
186
  className: "font-semibold",
180
187
  children: [
181
188
  "Service Providers (",
@@ -183,20 +190,20 @@ function E() {
183
190
  ")"
184
191
  ]
185
192
  }),
186
- L && !F && /* @__PURE__ */ b(c, {
193
+ L && !F && /* @__PURE__ */ x(c, {
187
194
  className: "border-status-error-border",
188
- children: /* @__PURE__ */ x(l, {
195
+ children: /* @__PURE__ */ S(l, {
189
196
  className: "p-6 text-center space-y-3",
190
197
  children: [
191
- /* @__PURE__ */ b("p", {
198
+ /* @__PURE__ */ x("p", {
192
199
  className: "text-status-error-text font-medium",
193
200
  children: "Couldn't load providers"
194
201
  }),
195
- /* @__PURE__ */ b("p", {
202
+ /* @__PURE__ */ x("p", {
196
203
  className: "text-sm text-text-secondary",
197
204
  children: L.message
198
205
  }),
199
- /* @__PURE__ */ b(s, {
206
+ /* @__PURE__ */ x(s, {
200
207
  variant: "outline",
201
208
  onClick: () => void X(),
202
209
  children: "Retry"
@@ -204,57 +211,57 @@ function E() {
204
211
  ]
205
212
  })
206
213
  }),
207
- F && Array.from({ length: 3 }).map((e, t) => /* @__PURE__ */ b(le, { className: "h-32 w-full rounded-lg" }, t)),
208
- !F && !L && Z.length === 0 && /* @__PURE__ */ b(c, { children: /* @__PURE__ */ b(l, {
214
+ F && Array.from({ length: 3 }).map((e, t) => /* @__PURE__ */ x(le, { className: "h-32 w-full rounded-lg" }, t)),
215
+ !F && !L && Z.length === 0 && /* @__PURE__ */ x(c, { children: /* @__PURE__ */ x(l, {
209
216
  className: "p-0",
210
- children: /* @__PURE__ */ b(C, {
217
+ children: /* @__PURE__ */ x(C, {
211
218
  illustration: P.trim() || $ ? "empty-search" : "empty-people",
212
219
  title: P.trim() || $ ? "No providers match your filters" : "No providers yet",
213
220
  description: P.trim() || $ ? "Adjust your search or filters to find logistics partners." : "Verified logistics service providers will appear here as they join the marketplace."
214
221
  })
215
222
  }) }),
216
223
  !F && !L && Z.map((t) => {
217
- let n = xe === t.id, r = Ce(t.id);
218
- return /* @__PURE__ */ x(c, { children: [/* @__PURE__ */ b("button", {
224
+ let n = we === t.id, r = Ee(t.id);
225
+ return /* @__PURE__ */ S(c, { children: [/* @__PURE__ */ x("button", {
219
226
  type: "button",
220
227
  "aria-expanded": n,
221
228
  className: "w-full text-left",
222
229
  onClick: () => J(n ? null : t.id),
223
- children: /* @__PURE__ */ b(l, {
230
+ children: /* @__PURE__ */ x(l, {
224
231
  className: "p-6",
225
- children: /* @__PURE__ */ x("div", {
232
+ children: /* @__PURE__ */ S("div", {
226
233
  className: "flex items-start justify-between gap-3",
227
- children: [/* @__PURE__ */ x("div", {
234
+ children: [/* @__PURE__ */ S("div", {
228
235
  className: "min-w-0",
229
236
  children: [
230
- /* @__PURE__ */ x("div", {
237
+ /* @__PURE__ */ S("div", {
231
238
  className: "flex items-center gap-2 flex-wrap",
232
239
  children: [
233
- /* @__PURE__ */ b("h4", {
240
+ /* @__PURE__ */ x("h4", {
234
241
  className: "font-semibold text-lg",
235
242
  children: t.name
236
243
  }),
237
- t.isVerified && /* @__PURE__ */ b(o, {
244
+ t.isVerified && /* @__PURE__ */ x(o, {
238
245
  variant: "default",
239
246
  children: "Verified"
240
247
  }),
241
- /* @__PURE__ */ b(o, {
248
+ /* @__PURE__ */ x(o, {
242
249
  variant: t.isActive ? "default" : "secondary",
243
250
  children: t.isActive ? "active" : "inactive"
244
251
  })
245
252
  ]
246
253
  }),
247
- /* @__PURE__ */ b("p", {
254
+ /* @__PURE__ */ x("p", {
248
255
  className: "text-text-secondary mt-1",
249
256
  children: t.description
250
257
  }),
251
- /* @__PURE__ */ x("div", {
258
+ /* @__PURE__ */ S("div", {
252
259
  className: "flex items-center gap-4 mt-3 text-sm text-text-secondary",
253
260
  children: [
254
- /* @__PURE__ */ x("span", {
261
+ /* @__PURE__ */ S("span", {
255
262
  className: "flex items-center gap-1",
256
263
  children: [
257
- /* @__PURE__ */ b(ie, {
264
+ /* @__PURE__ */ x(ie, {
258
265
  size: 14,
259
266
  className: "text-status-warning-text fill-current"
260
267
  }),
@@ -262,65 +269,65 @@ function E() {
262
269
  t.rating ?? 0
263
270
  ]
264
271
  }),
265
- /* @__PURE__ */ x("span", {
272
+ /* @__PURE__ */ S("span", {
266
273
  className: "flex items-center gap-1",
267
274
  children: [
268
- /* @__PURE__ */ b(ne, { size: 14 }),
275
+ /* @__PURE__ */ x(ne, { size: 14 }),
269
276
  " ",
270
277
  t.type
271
278
  ]
272
279
  }),
273
- /* @__PURE__ */ x("span", {
280
+ /* @__PURE__ */ S("span", {
274
281
  className: "flex items-center gap-1",
275
- children: [/* @__PURE__ */ b(te, { size: 14 }), " Listed"]
282
+ children: [/* @__PURE__ */ x(te, { size: 14 }), " Listed"]
276
283
  })
277
284
  ]
278
285
  })
279
286
  ]
280
- }), /* @__PURE__ */ x("div", {
287
+ }), /* @__PURE__ */ S("div", {
281
288
  className: "text-right shrink-0",
282
289
  children: [
283
- /* @__PURE__ */ b("p", {
290
+ /* @__PURE__ */ x("p", {
284
291
  className: "text-sm text-text-secondary",
285
292
  children: "Services"
286
293
  }),
287
- /* @__PURE__ */ b("p", {
294
+ /* @__PURE__ */ x("p", {
288
295
  className: "text-lg font-bold",
289
296
  children: r.length
290
297
  }),
291
- /* @__PURE__ */ b("span", {
298
+ /* @__PURE__ */ x("span", {
292
299
  className: "mt-1 inline-flex items-center gap-1 text-xs text-primary",
293
- children: n ? /* @__PURE__ */ x(y, { children: ["Hide ", /* @__PURE__ */ b(ee, { size: 14 })] }) : /* @__PURE__ */ x(y, { children: ["View ", /* @__PURE__ */ b(e, { size: 14 })] })
300
+ children: n ? /* @__PURE__ */ S(b, { children: ["Hide ", /* @__PURE__ */ x(ee, { size: 14 })] }) : /* @__PURE__ */ S(b, { children: ["View ", /* @__PURE__ */ x(e, { size: 14 })] })
294
301
  })
295
302
  ]
296
303
  })]
297
304
  })
298
305
  })
299
- }), n && /* @__PURE__ */ x("div", {
306
+ }), n && /* @__PURE__ */ S("div", {
300
307
  className: "border-t border-border-seam px-6 py-4 space-y-3",
301
- children: [/* @__PURE__ */ x("p", {
308
+ children: [/* @__PURE__ */ S("p", {
302
309
  className: "text-sm font-medium text-text-secondary",
303
310
  children: ["Offerings from ", t.name]
304
- }), r.length === 0 ? /* @__PURE__ */ b("p", {
311
+ }), r.length === 0 ? /* @__PURE__ */ x("p", {
305
312
  className: "text-sm text-text-secondary",
306
313
  children: "This provider hasn't listed any offerings yet."
307
- }) : r.map((e) => /* @__PURE__ */ x("div", {
314
+ }) : r.map((e) => /* @__PURE__ */ S("div", {
308
315
  className: "flex items-center justify-between gap-3 rounded-lg border border-border-seam p-3",
309
- children: [/* @__PURE__ */ x("div", {
316
+ children: [/* @__PURE__ */ S("div", {
310
317
  className: "min-w-0",
311
- children: [/* @__PURE__ */ b("p", {
318
+ children: [/* @__PURE__ */ x("p", {
312
319
  className: "font-medium truncate",
313
320
  children: e.name
314
- }), /* @__PURE__ */ b("p", {
321
+ }), /* @__PURE__ */ x("p", {
315
322
  className: "text-sm text-text-secondary truncate",
316
323
  children: e.category ?? "general"
317
324
  })]
318
- }), /* @__PURE__ */ x("div", {
325
+ }), /* @__PURE__ */ S("div", {
319
326
  className: "text-right shrink-0",
320
- children: [/* @__PURE__ */ b("p", {
327
+ children: [/* @__PURE__ */ x("p", {
321
328
  className: "font-bold",
322
- children: h(e.price)
323
- }), /* @__PURE__ */ b("p", {
329
+ children: g(e.price)
330
+ }), /* @__PURE__ */ x("p", {
324
331
  className: "text-xs text-text-secondary",
325
332
  children: e.currency
326
333
  })]
@@ -328,9 +335,9 @@ function E() {
328
335
  }, e.id))]
329
336
  })] }, t.id);
330
337
  }),
331
- !F && !L && (M.length > 0 || z > 0) && /* @__PURE__ */ x("div", {
338
+ !F && !L && (M.length > 0 || z > 0) && /* @__PURE__ */ S("div", {
332
339
  className: "flex flex-wrap items-center justify-between gap-3 pt-1",
333
- children: [/* @__PURE__ */ x("span", {
340
+ children: [/* @__PURE__ */ S("span", {
334
341
  className: "text-sm text-text-secondary",
335
342
  children: [
336
343
  "Showing ",
@@ -339,10 +346,10 @@ function E() {
339
346
  " ",
340
347
  z * w + M.length
341
348
  ]
342
- }), /* @__PURE__ */ x("div", {
349
+ }), /* @__PURE__ */ S("div", {
343
350
  className: "flex items-center gap-1",
344
351
  children: [
345
- /* @__PURE__ */ b(s, {
352
+ /* @__PURE__ */ x(s, {
346
353
  variant: "outline",
347
354
  size: "icon",
348
355
  className: "h-8 w-8",
@@ -351,13 +358,13 @@ function E() {
351
358
  J(null), B((e) => Math.max(0, e - 1));
352
359
  },
353
360
  disabled: z === 0,
354
- children: /* @__PURE__ */ b(t, { className: "h-4 w-4" })
361
+ children: /* @__PURE__ */ x(t, { className: "h-4 w-4" })
355
362
  }),
356
- /* @__PURE__ */ x("span", {
363
+ /* @__PURE__ */ S("span", {
357
364
  className: "px-3 text-sm",
358
365
  children: ["Page ", z + 1]
359
366
  }),
360
- /* @__PURE__ */ b(s, {
367
+ /* @__PURE__ */ x(s, {
361
368
  variant: "outline",
362
369
  size: "icon",
363
370
  className: "h-8 w-8",
@@ -365,51 +372,51 @@ function E() {
365
372
  onClick: () => {
366
373
  J(null), B((e) => e + 1);
367
374
  },
368
- disabled: !ve,
369
- children: /* @__PURE__ */ b(n, { className: "h-4 w-4" })
375
+ disabled: !xe,
376
+ children: /* @__PURE__ */ x(n, { className: "h-4 w-4" })
370
377
  })
371
378
  ]
372
379
  })]
373
380
  })
374
381
  ]
375
- }), /* @__PURE__ */ x(S, {
382
+ }), /* @__PURE__ */ S(fe, {
376
383
  className: "space-y-4",
377
384
  children: [
378
- /* @__PURE__ */ b("h3", {
385
+ /* @__PURE__ */ x("h3", {
379
386
  className: "text-base font-semibold text-text-primary",
380
387
  children: "Popular Services"
381
388
  }),
382
- Q.length === 0 && /* @__PURE__ */ b(C, {
389
+ Q.length === 0 && /* @__PURE__ */ x(C, {
383
390
  illustration: P.trim() ? "empty-search" : "empty-generic",
384
391
  title: P.trim() ? "No matching services" : "No services listed yet",
385
392
  description: P.trim() ? "Adjust your search to discover service offerings." : "Service offerings from providers will be listed here."
386
393
  }),
387
- Q.map((e) => /* @__PURE__ */ x(c, { children: [/* @__PURE__ */ b(oe, { children: /* @__PURE__ */ b(se, {
394
+ Q.map((e) => /* @__PURE__ */ S(c, { children: [/* @__PURE__ */ x(oe, { children: /* @__PURE__ */ x(se, {
388
395
  className: "text-base",
389
396
  children: e.name
390
- }) }), /* @__PURE__ */ x(l, { children: [
391
- /* @__PURE__ */ b("p", {
397
+ }) }), /* @__PURE__ */ S(l, { children: [
398
+ /* @__PURE__ */ x("p", {
392
399
  className: "text-sm text-text-secondary mb-3",
393
400
  children: e.description
394
401
  }),
395
- /* @__PURE__ */ x("div", {
402
+ /* @__PURE__ */ S("div", {
396
403
  className: "flex flex-wrap gap-1 mb-3",
397
- children: [/* @__PURE__ */ b(o, {
404
+ children: [/* @__PURE__ */ x(o, {
398
405
  variant: "outline",
399
406
  className: "text-xs",
400
407
  children: e.category ?? "general"
401
- }), /* @__PURE__ */ b(o, {
408
+ }), /* @__PURE__ */ x(o, {
402
409
  variant: "outline",
403
410
  className: "text-xs",
404
411
  children: e.provider?.name ?? "provider"
405
412
  })]
406
413
  }),
407
- /* @__PURE__ */ x("div", {
414
+ /* @__PURE__ */ S("div", {
408
415
  className: "flex items-center justify-between",
409
- children: [/* @__PURE__ */ b("span", {
416
+ children: [/* @__PURE__ */ x("span", {
410
417
  className: "font-bold",
411
- children: h(e.price)
412
- }), /* @__PURE__ */ b("span", {
418
+ children: g(e.price)
419
+ }), /* @__PURE__ */ x("span", {
413
420
  className: "text-sm text-text-secondary",
414
421
  children: e.currency
415
422
  })]
@@ -419,7 +426,19 @@ function E() {
419
426
  })]
420
427
  })
421
428
  ]
429
+ }) : /* @__PURE__ */ x(h, {
430
+ title: "Marketplace",
431
+ subtitle: "Find logistics service providers",
432
+ icon: /* @__PURE__ */ x(i, { size: 24 }),
433
+ children: /* @__PURE__ */ x(c, { children: /* @__PURE__ */ x(l, {
434
+ className: "p-0",
435
+ children: /* @__PURE__ */ x(C, {
436
+ illustration: "empty-people",
437
+ title: "Marketplace is coming soon",
438
+ description: "The collaborative logistics marketplace is not open yet. Check back after it launches to browse verified third-party service providers."
439
+ })
440
+ }) })
422
441
  });
423
442
  }
424
443
  //#endregion
425
- export { E as default };
444
+ export { T as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-movethewheels",
3
- "version": "2026.719.2",
3
+ "version": "2026.722.1",
4
4
  "description": "Burdenoff MoveTheWheels Microfrontend - Logistics & Supply Chain Management Platform",
5
5
  "type": "module",
6
6
  "files": [
@@ -91,6 +91,7 @@
91
91
  "lefthook": "^2.1.1",
92
92
  "postcss": "^8.4.49",
93
93
  "prettier": "^3.4.2",
94
+ "storybook": "^8.6.0",
94
95
  "tailwindcss": "^4.0.0",
95
96
  "typescript": "^5.9.0",
96
97
  "typescript-eslint": "^8.54.0",
@@ -27,33 +27,27 @@ import {
27
27
  Bot,
28
28
  } from 'lucide-react';
29
29
  import { MoveTheWheelsProvider } from './providers/MoveTheWheelsProvider';
30
- import { FeatureFlagProvider } from '@burdenoff/fe-libs/shared/feature-flags';
30
+ import { FeatureFlagProvider, useFeatureFlag } from '@burdenoff/fe-libs/shared/feature-flags';
31
31
  import type { NavItem, MoveTheWheelsRootProps } from './types';
32
32
  import { MoveTheWheelsRoutes } from './MoveTheWheelsRoutes';
33
33
 
34
34
  /**
35
- * Root component for the MoveTheWheels microfrontend.
36
- *
37
- * @example
38
- * ```tsx
39
- * import { MoveTheWheelsRoot } from '@burdenoff/microfe-movethewheels';
35
+ * Registers the MoveTheWheels sidebar nav tree with the host shell.
40
36
  *
41
- * function App() {
42
- * return (
43
- * <MoveTheWheelsRoot
44
- * basePath="/movethewheels"
45
- * navigate={(path) => router.push(path)}
46
- * currentUser={currentUser}
47
- * workspaceId="ws-123"
48
- * apiGatewayUrl="https://api.example.com"
49
- * authToken="token"
50
- * />
51
- * );
52
- * }
53
- * ```
37
+ * Split out from `MoveTheWheelsRoot` so it renders as a descendant of the
38
+ * `<FeatureFlagProvider>` below — `useFeatureFlag` requires a Provider
39
+ * ancestor, and the Provider is only established once `MoveTheWheelsRoot`'s
40
+ * own JSX (which includes this component) has mounted.
54
41
  */
55
- export const MoveTheWheelsRoot: FC<MoveTheWheelsRootProps> = (props) => {
56
- const { registerNavItems, registerFooterItems, basePath = '/' } = props;
42
+ const NavRegistrar: FC<Pick<MoveTheWheelsRootProps, 'registerNavItems' | 'basePath'>> = ({
43
+ registerNavItems,
44
+ basePath = '/',
45
+ }) => {
46
+ // The backend has no ServiceProvider/ServiceOffering model (dropped by
47
+ // migration 20260707000001_movethewheels_reuse_cleanup) — hide the
48
+ // Marketplace nav entry until a serviceProviders/serviceOfferings resolver
49
+ // ships. Defaults to disabled (fails closed).
50
+ const marketplaceEnabled = useFeatureFlag('movethewheels.marketplace', false);
57
51
 
58
52
  // Helper to join paths correctly, avoiding double slashes
59
53
  const joinPath = (base: string, path: string): string => {
@@ -183,13 +177,19 @@ export const MoveTheWheelsRoot: FC<MoveTheWheelsRootProps> = (props) => {
183
177
  icon: <DollarSign size={16} />,
184
178
  order: 9,
185
179
  },
186
- {
187
- id: 'mtw-marketplace',
188
- label: 'Marketplace',
189
- path: joinPath(basePath, 'marketplace'),
190
- icon: <Store size={16} />,
191
- order: 10,
192
- },
180
+ // Hidden until a serviceProviders/serviceOfferings backend resolver
181
+ // ships — see the marketplaceEnabled flag check above.
182
+ ...(marketplaceEnabled
183
+ ? [
184
+ {
185
+ id: 'mtw-marketplace',
186
+ label: 'Marketplace',
187
+ path: joinPath(basePath, 'marketplace'),
188
+ icon: <Store size={16} />,
189
+ order: 10,
190
+ },
191
+ ]
192
+ : []),
193
193
  {
194
194
  id: 'mtw-import-export',
195
195
  label: 'Import/Export',
@@ -226,7 +226,34 @@ export const MoveTheWheelsRoot: FC<MoveTheWheelsRootProps> = (props) => {
226
226
 
227
227
  // Return cleanup function to unregister on unmount
228
228
  return cleanup;
229
- }, [registerNavItems, basePath]);
229
+ }, [registerNavItems, basePath, marketplaceEnabled]);
230
+
231
+ return null;
232
+ };
233
+
234
+ /**
235
+ * Root component for the MoveTheWheels microfrontend.
236
+ *
237
+ * @example
238
+ * ```tsx
239
+ * import { MoveTheWheelsRoot } from '@burdenoff/microfe-movethewheels';
240
+ *
241
+ * function App() {
242
+ * return (
243
+ * <MoveTheWheelsRoot
244
+ * basePath="/movethewheels"
245
+ * navigate={(path) => router.push(path)}
246
+ * currentUser={currentUser}
247
+ * workspaceId="ws-123"
248
+ * apiGatewayUrl="https://api.example.com"
249
+ * authToken="token"
250
+ * />
251
+ * );
252
+ * }
253
+ * ```
254
+ */
255
+ export const MoveTheWheelsRoot: FC<MoveTheWheelsRootProps> = (props) => {
256
+ const { registerNavItems, registerFooterItems, basePath = '/' } = props;
230
257
 
231
258
  // Register footer items
232
259
  useEffect(() => {
@@ -248,6 +275,7 @@ export const MoveTheWheelsRoot: FC<MoveTheWheelsRootProps> = (props) => {
248
275
 
249
276
  return (
250
277
  <FeatureFlagProvider workspaceId={null} gateway="global" defaultEnabled={true}>
278
+ <NavRegistrar registerNavItems={registerNavItems} basePath={basePath} />
251
279
  <MoveTheWheelsProvider {...props}>
252
280
  <div className="movethewheels-root h-full">
253
281
  <MoveTheWheelsRoutes />
@@ -82,7 +82,7 @@ export default function AIAssistantPage() {
82
82
  <EmptyState
83
83
  illustration="empty-agents"
84
84
  title="Autonomous dispatch operations aren't live yet"
85
- description="These capabilities depend on the shared multi-model AI gateway and agent-run ledger (BOFF-3601), which hasn't shipped across the platform yet. Nothing below is available today."
85
+ description="Autonomous dispatch isn't available yet — these capabilities are still in development. Nothing below is available today."
86
86
  />
87
87
  <ul className="mt-4 space-y-4">
88
88
  {roadmapItems.map((item) => (
@@ -37,10 +37,21 @@ import {
37
37
  SelectValue,
38
38
  } from '../components/ui';
39
39
  import { EmphasisPanel, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';
40
+ import { useFeatureFlag } from '@burdenoff/fe-libs/shared/feature-flags';
40
41
  import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
41
42
  import { formatCurrency } from '../utils/formatters';
42
43
  import { executeGraphQL } from '../utils/graphqlClient';
43
44
 
45
+ /**
46
+ * The backend has no ServiceProvider/ServiceOffering model (dropped by
47
+ * migration 20260707000001_movethewheels_reuse_cleanup) — `serviceProviders`
48
+ * and `serviceOfferings` are not resolvable fields today. Gate the whole page
49
+ * behind a flag that defaults to **disabled** so it fails closed (an empty
50
+ * "coming soon" state) instead of erroring on every load. Flip this on only
51
+ * once a serviceProviders/serviceOfferings resolver ships.
52
+ */
53
+ const MARKETPLACE_FEATURE_FLAG = 'movethewheels.marketplace';
54
+
44
55
  interface ApiServiceProvider {
45
56
  id: string;
46
57
  name: string;
@@ -117,6 +128,7 @@ const RATING_OPTIONS: { value: string; label: string }[] = [
117
128
  ];
118
129
 
119
130
  export default function MarketplacePage() {
131
+ const marketplaceEnabled = useFeatureFlag(MARKETPLACE_FEATURE_FLAG, false);
120
132
  const { apiGatewayUrl, authToken, workspaceToken, workspaceId, tenantId, currentUser } =
121
133
  useMoveTheWheels();
122
134
  const [providers, setProviders] = useState<ApiServiceProvider[]>([]);
@@ -149,6 +161,7 @@ export default function MarketplacePage() {
149
161
  );
150
162
 
151
163
  const load = useCallback(async () => {
164
+ if (!marketplaceEnabled) return;
152
165
  setIsLoading(true);
153
166
  setError(null);
154
167
  try {
@@ -177,7 +190,7 @@ export default function MarketplacePage() {
177
190
  } finally {
178
191
  setIsLoading(false);
179
192
  }
180
- }, [graphQLOptions, page]);
193
+ }, [graphQLOptions, page, marketplaceEnabled]);
181
194
 
182
195
  useEffect(() => {
183
196
  void load();
@@ -225,6 +238,26 @@ export default function MarketplacePage() {
225
238
 
226
239
  const filtersActive = typeFilter !== 'all' || verifiedOnly || minRating !== '0';
227
240
 
241
+ if (!marketplaceEnabled) {
242
+ return (
243
+ <PageLayout
244
+ title="Marketplace"
245
+ subtitle="Find logistics service providers"
246
+ icon={<Store size={24} />}
247
+ >
248
+ <Card>
249
+ <CardContent className="p-0">
250
+ <IllustratedEmptyState
251
+ illustration="empty-people"
252
+ title="Marketplace is coming soon"
253
+ description="The collaborative logistics marketplace is not open yet. Check back after it launches to browse verified third-party service providers."
254
+ />
255
+ </CardContent>
256
+ </Card>
257
+ </PageLayout>
258
+ );
259
+ }
260
+
228
261
  return (
229
262
  <PageLayout
230
263
  title="Marketplace"