@lodashventure/medusa-parcel-shipping 0.2.8 → 0.2.13

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.
@@ -3,30 +3,384 @@ const jsxRuntime = require("react/jsx-runtime");
3
3
  const adminSdk = require("@medusajs/admin-sdk");
4
4
  const icons = require("@medusajs/icons");
5
5
  const react = require("react");
6
+ const Medusa = require("@medusajs/js-sdk");
6
7
  const ui = require("@medusajs/ui");
7
- const requestJson = async (url, method = "GET", body) => {
8
- const response = await fetch(url, {
9
- method,
10
- headers: {
11
- "Content-Type": "application/json"
12
- },
13
- body: body ? JSON.stringify(body) : void 0,
14
- credentials: "include"
8
+ const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
9
+ const Medusa__default = /* @__PURE__ */ _interopDefault(Medusa);
10
+ const sdk$1 = new Medusa__default.default({
11
+ baseUrl: typeof window !== "undefined" ? window.location.origin : "/",
12
+ auth: {
13
+ type: "session"
14
+ }
15
+ });
16
+ const toNumber$1 = (value) => {
17
+ if (value.trim().length === 0) {
18
+ return null;
19
+ }
20
+ const parsed = Number(value);
21
+ return Number.isFinite(parsed) ? parsed : null;
22
+ };
23
+ function ParcelBoxesPage() {
24
+ const [boxes, setBoxes] = react.useState([]);
25
+ const [loading, setLoading] = react.useState(true);
26
+ const [formState, setFormState] = react.useState({
27
+ id: null,
28
+ name: "",
29
+ width_cm: "",
30
+ length_cm: "",
31
+ height_cm: "",
32
+ max_weight_kg: "",
33
+ price_thb: "",
34
+ active: true
15
35
  });
16
- if (!response.ok) {
17
- let message = response.statusText;
36
+ const [saving, setSaving] = react.useState(false);
37
+ const [deletingId, setDeletingId] = react.useState(null);
38
+ const refresh = react.useCallback(async () => {
39
+ setLoading(true);
18
40
  try {
19
- const payload = await response.json();
20
- message = (payload == null ? void 0 : payload.code) ?? (payload == null ? void 0 : payload.error) ?? message;
21
- } catch (_) {
41
+ const response = await sdk$1.client.fetch("/admin/parcel-boxes", {
42
+ method: "GET"
43
+ });
44
+ const data = await response.json();
45
+ setBoxes(data.boxes ?? []);
46
+ } catch (error) {
47
+ ui.toast.error(error.message ?? "Failed to load boxes", {
48
+ dismissable: true
49
+ });
50
+ } finally {
51
+ setLoading(false);
22
52
  }
23
- throw new Error(message);
24
- }
25
- if (response.status === 204) {
26
- return void 0;
27
- }
28
- return await response.json();
53
+ }, []);
54
+ react.useEffect(() => {
55
+ refresh();
56
+ }, [refresh]);
57
+ const resetForm = () => setFormState({
58
+ id: null,
59
+ name: "",
60
+ width_cm: "",
61
+ length_cm: "",
62
+ height_cm: "",
63
+ max_weight_kg: "",
64
+ price_thb: "",
65
+ active: true
66
+ });
67
+ const handleSubmit = async () => {
68
+ const width = toNumber$1(formState.width_cm);
69
+ const length = toNumber$1(formState.length_cm);
70
+ const height = toNumber$1(formState.height_cm);
71
+ const maxWeight = toNumber$1(formState.max_weight_kg);
72
+ const price = toNumber$1(formState.price_thb);
73
+ if (!formState.name.trim() || width === null || length === null || height === null || maxWeight === null || price === null) {
74
+ ui.toast.error("Fill all fields with valid numeric values", {
75
+ dismissable: true
76
+ });
77
+ return;
78
+ }
79
+ const payload = {
80
+ name: formState.name.trim(),
81
+ width_cm: width,
82
+ length_cm: length,
83
+ height_cm: height,
84
+ max_weight_kg: maxWeight,
85
+ price_thb: price,
86
+ active: formState.active
87
+ };
88
+ setSaving(true);
89
+ try {
90
+ if (formState.id) {
91
+ await sdk$1.client.fetch(`/admin/parcel-boxes/${formState.id}`, {
92
+ method: "PUT",
93
+ body: payload
94
+ });
95
+ ui.toast.success("Box updated", { dismissable: true });
96
+ } else {
97
+ await sdk$1.client.fetch("/admin/parcel-boxes", {
98
+ method: "POST",
99
+ body: payload
100
+ });
101
+ ui.toast.success("Box created", { dismissable: true });
102
+ }
103
+ await refresh();
104
+ resetForm();
105
+ } catch (error) {
106
+ ui.toast.error(error.message ?? "Failed to save box", {
107
+ dismissable: true
108
+ });
109
+ } finally {
110
+ setSaving(false);
111
+ }
112
+ };
113
+ const handleDelete = async (id) => {
114
+ setDeletingId(id);
115
+ try {
116
+ await sdk$1.client.fetch(`/admin/parcel-boxes/${id}`, {
117
+ method: "DELETE"
118
+ });
119
+ ui.toast.success("Box removed", { dismissable: true });
120
+ await refresh();
121
+ } catch (error) {
122
+ ui.toast.error(error.message ?? "Failed to delete box", {
123
+ dismissable: true
124
+ });
125
+ } finally {
126
+ setDeletingId(null);
127
+ }
128
+ };
129
+ const handleToggle = async (box) => {
130
+ try {
131
+ await sdk$1.client.fetch(`/admin/parcel-boxes/${box.id}`, {
132
+ method: "PUT",
133
+ body: { active: !box.active }
134
+ });
135
+ await refresh();
136
+ } catch (error) {
137
+ ui.toast.error(error.message ?? "Failed to update box status", {
138
+ dismissable: true
139
+ });
140
+ }
141
+ };
142
+ const tableRows = react.useMemo(() => {
143
+ if (loading) {
144
+ return /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Row, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { colSpan: 6, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-center text-ui-fg-subtle", children: "Loading boxes..." }) }) });
145
+ }
146
+ if (boxes.length === 0) {
147
+ return /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Row, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { colSpan: 6, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-center text-ui-fg-subtle", children: "No boxes configured yet." }) }) });
148
+ }
149
+ return boxes.map((box) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
150
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: box.name }) }),
151
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-sm text-ui-fg-subtle", children: [
152
+ box.width_cm,
153
+ " × ",
154
+ box.length_cm,
155
+ " × ",
156
+ box.height_cm
157
+ ] }) }),
158
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: box.max_weight_kg }),
159
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: box.price_thb }),
160
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: box.active ? "green" : "grey", children: box.active ? "Active" : "Inactive" }) }),
161
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-2", children: [
162
+ /* @__PURE__ */ jsxRuntime.jsx(
163
+ ui.Switch,
164
+ {
165
+ checked: box.active,
166
+ onCheckedChange: () => handleToggle(box)
167
+ }
168
+ ),
169
+ /* @__PURE__ */ jsxRuntime.jsx(
170
+ ui.Button,
171
+ {
172
+ variant: "secondary",
173
+ size: "small",
174
+ onClick: () => setFormState({
175
+ id: box.id,
176
+ name: box.name,
177
+ width_cm: String(box.width_cm),
178
+ length_cm: String(box.length_cm),
179
+ height_cm: String(box.height_cm),
180
+ max_weight_kg: String(box.max_weight_kg),
181
+ price_thb: String(box.price_thb),
182
+ active: box.active
183
+ }),
184
+ children: "Edit"
185
+ }
186
+ ),
187
+ /* @__PURE__ */ jsxRuntime.jsx(
188
+ ui.Button,
189
+ {
190
+ variant: "danger",
191
+ size: "small",
192
+ onClick: () => handleDelete(box.id),
193
+ disabled: deletingId === box.id,
194
+ children: "Delete"
195
+ }
196
+ )
197
+ ] }) })
198
+ ] }, box.id));
199
+ }, [boxes, deletingId, loading]);
200
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "space-y-6 p-6", children: [
201
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
202
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Parcel Boxes" }),
203
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Configure and manage parcel box sizes and pricing." })
204
+ ] }),
205
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 rounded-md border p-4", children: [
206
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: formState.id ? "Edit Box" : "Create Box" }),
207
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 md:grid-cols-3", children: [
208
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
209
+ /* @__PURE__ */ jsxRuntime.jsx(
210
+ ui.Label,
211
+ {
212
+ className: "text-sm font-medium text-ui-fg-base",
213
+ htmlFor: "parcel-box-name",
214
+ children: "Name"
215
+ }
216
+ ),
217
+ /* @__PURE__ */ jsxRuntime.jsx(
218
+ ui.Input,
219
+ {
220
+ id: "parcel-box-name",
221
+ placeholder: "Enter box name",
222
+ value: formState.name,
223
+ onChange: (event) => setFormState((prev) => ({ ...prev, name: event.target.value }))
224
+ }
225
+ )
226
+ ] }),
227
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
228
+ /* @__PURE__ */ jsxRuntime.jsx(
229
+ ui.Label,
230
+ {
231
+ className: "text-sm font-medium text-ui-fg-base",
232
+ htmlFor: "parcel-box-width",
233
+ children: "Width (cm)"
234
+ }
235
+ ),
236
+ /* @__PURE__ */ jsxRuntime.jsx(
237
+ ui.Input,
238
+ {
239
+ id: "parcel-box-width",
240
+ placeholder: "e.g. 20",
241
+ type: "number",
242
+ value: formState.width_cm,
243
+ onChange: (event) => setFormState((prev) => ({
244
+ ...prev,
245
+ width_cm: event.target.value
246
+ }))
247
+ }
248
+ )
249
+ ] }),
250
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
251
+ /* @__PURE__ */ jsxRuntime.jsx(
252
+ ui.Label,
253
+ {
254
+ className: "text-sm font-medium text-ui-fg-base",
255
+ htmlFor: "parcel-box-length",
256
+ children: "Length (cm)"
257
+ }
258
+ ),
259
+ /* @__PURE__ */ jsxRuntime.jsx(
260
+ ui.Input,
261
+ {
262
+ id: "parcel-box-length",
263
+ placeholder: "e.g. 30",
264
+ type: "number",
265
+ value: formState.length_cm,
266
+ onChange: (event) => setFormState((prev) => ({
267
+ ...prev,
268
+ length_cm: event.target.value
269
+ }))
270
+ }
271
+ )
272
+ ] }),
273
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
274
+ /* @__PURE__ */ jsxRuntime.jsx(
275
+ ui.Label,
276
+ {
277
+ className: "text-sm font-medium text-ui-fg-base",
278
+ htmlFor: "parcel-box-height",
279
+ children: "Height (cm)"
280
+ }
281
+ ),
282
+ /* @__PURE__ */ jsxRuntime.jsx(
283
+ ui.Input,
284
+ {
285
+ id: "parcel-box-height",
286
+ placeholder: "e.g. 15",
287
+ type: "number",
288
+ value: formState.height_cm,
289
+ onChange: (event) => setFormState((prev) => ({
290
+ ...prev,
291
+ height_cm: event.target.value
292
+ }))
293
+ }
294
+ )
295
+ ] }),
296
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
297
+ /* @__PURE__ */ jsxRuntime.jsx(
298
+ ui.Label,
299
+ {
300
+ className: "text-sm font-medium text-ui-fg-base",
301
+ htmlFor: "parcel-box-max-weight",
302
+ children: "Max Weight (kg)"
303
+ }
304
+ ),
305
+ /* @__PURE__ */ jsxRuntime.jsx(
306
+ ui.Input,
307
+ {
308
+ id: "parcel-box-max-weight",
309
+ placeholder: "e.g. 0.5",
310
+ type: "number",
311
+ value: formState.max_weight_kg,
312
+ onChange: (event) => setFormState((prev) => ({
313
+ ...prev,
314
+ max_weight_kg: event.target.value
315
+ }))
316
+ }
317
+ )
318
+ ] }),
319
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
320
+ /* @__PURE__ */ jsxRuntime.jsx(
321
+ ui.Label,
322
+ {
323
+ className: "text-sm font-medium text-ui-fg-base",
324
+ htmlFor: "parcel-box-price",
325
+ children: "Box Price (THB)"
326
+ }
327
+ ),
328
+ /* @__PURE__ */ jsxRuntime.jsx(
329
+ ui.Input,
330
+ {
331
+ id: "parcel-box-price",
332
+ placeholder: "e.g. 10",
333
+ type: "number",
334
+ value: formState.price_thb,
335
+ onChange: (event) => setFormState((prev) => ({
336
+ ...prev,
337
+ price_thb: event.target.value
338
+ }))
339
+ }
340
+ )
341
+ ] })
342
+ ] }),
343
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
344
+ /* @__PURE__ */ jsxRuntime.jsx(
345
+ ui.Switch,
346
+ {
347
+ checked: formState.active,
348
+ onCheckedChange: (active) => setFormState((prev) => ({ ...prev, active }))
349
+ }
350
+ ),
351
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-ui-fg-subtle", children: "Active" })
352
+ ] }),
353
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
354
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { onClick: handleSubmit, disabled: saving, children: formState.id ? "Update" : "Create" }),
355
+ formState.id && /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: resetForm, children: "Cancel" })
356
+ ] })
357
+ ] }),
358
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-md border", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
359
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
360
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Name" }),
361
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Dimensions (cm)" }),
362
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Max Weight (kg)" }),
363
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Price" }),
364
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Status" }),
365
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { className: "text-right", children: "Actions" })
366
+ ] }) }),
367
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Body, { children: tableRows })
368
+ ] }) })
369
+ ] });
370
+ }
371
+ const ParcelBoxesRoute = () => {
372
+ return /* @__PURE__ */ jsxRuntime.jsx(ParcelBoxesPage, {});
29
373
  };
374
+ const config$1 = adminSdk.defineRouteConfig({
375
+ label: "Parcel Boxes",
376
+ icon: icons.FlyingBox
377
+ });
378
+ const sdk = new Medusa__default.default({
379
+ baseUrl: typeof window !== "undefined" ? window.location.origin : "/",
380
+ auth: {
381
+ type: "session"
382
+ }
383
+ });
30
384
  const toNumber = (value) => {
31
385
  if (value.trim().length === 0) {
32
386
  return null;
@@ -35,7 +389,7 @@ const toNumber = (value) => {
35
389
  return Number.isFinite(parsed) ? parsed : null;
36
390
  };
37
391
  const getThaiAddressComponents = () => null;
38
- const ParcelShippingPage = () => {
392
+ function ParcelShippingPage() {
39
393
  const [tab, setTab] = react.useState("boxes");
40
394
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "space-y-6 p-6", children: [
41
395
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
@@ -77,7 +431,7 @@ const ParcelShippingPage = () => {
77
431
  tab === "areas" && /* @__PURE__ */ jsxRuntime.jsx(AreasSection, {})
78
432
  ] })
79
433
  ] });
80
- };
434
+ }
81
435
  const BoxesSection = () => {
82
436
  const [boxes, setBoxes] = react.useState([]);
83
437
  const [loading, setLoading] = react.useState(true);
@@ -96,9 +450,10 @@ const BoxesSection = () => {
96
450
  const refresh = react.useCallback(async () => {
97
451
  setLoading(true);
98
452
  try {
99
- const data = await requestJson(
100
- "/admin/parcel-boxes"
101
- );
453
+ const response = await sdk.client.fetch("/admin/parcel-boxes", {
454
+ method: "GET"
455
+ });
456
+ const data = await response.json();
102
457
  setBoxes(data.boxes ?? []);
103
458
  } catch (error) {
104
459
  ui.toast.error(error.message ?? "Failed to load boxes", {
@@ -145,14 +500,16 @@ const BoxesSection = () => {
145
500
  setSaving(true);
146
501
  try {
147
502
  if (formState.id) {
148
- await requestJson(
149
- `/admin/parcel-boxes/${formState.id}`,
150
- "PUT",
151
- payload
152
- );
503
+ await sdk.client.fetch(`/admin/parcel-boxes/${formState.id}`, {
504
+ method: "PUT",
505
+ body: payload
506
+ });
153
507
  ui.toast.success("Box updated", { dismissable: true });
154
508
  } else {
155
- await requestJson("/admin/parcel-boxes", "POST", payload);
509
+ await sdk.client.fetch("/admin/parcel-boxes", {
510
+ method: "POST",
511
+ body: payload
512
+ });
156
513
  ui.toast.success("Box created", { dismissable: true });
157
514
  }
158
515
  await refresh();
@@ -168,7 +525,9 @@ const BoxesSection = () => {
168
525
  const handleDelete = async (id) => {
169
526
  setDeletingId(id);
170
527
  try {
171
- await requestJson(`/admin/parcel-boxes/${id}`, "DELETE");
528
+ await sdk.client.fetch(`/admin/parcel-boxes/${id}`, {
529
+ method: "DELETE"
530
+ });
172
531
  ui.toast.success("Box removed", { dismissable: true });
173
532
  await refresh();
174
533
  } catch (error) {
@@ -181,8 +540,9 @@ const BoxesSection = () => {
181
540
  };
182
541
  const handleToggle = async (box) => {
183
542
  try {
184
- await requestJson(`/admin/parcel-boxes/${box.id}`, "PUT", {
185
- active: !box.active
543
+ await sdk.client.fetch(`/admin/parcel-boxes/${box.id}`, {
544
+ method: "PUT",
545
+ body: { active: !box.active }
186
546
  });
187
547
  await refresh();
188
548
  } catch (error) {
@@ -436,9 +796,10 @@ const RatesSection = () => {
436
796
  const refresh = react.useCallback(async () => {
437
797
  setLoading(true);
438
798
  try {
439
- const data = await requestJson(
440
- "/admin/shipping-config/rates"
441
- );
799
+ const response = await sdk.client.fetch("/admin/shipping-config/rates", {
800
+ method: "GET"
801
+ });
802
+ const data = await response.json();
442
803
  setRates(
443
804
  (data.rates ?? []).map((rate) => ({
444
805
  ...rate,
@@ -457,7 +818,10 @@ const RatesSection = () => {
457
818
  var _a, _b, _c;
458
819
  setCurrenciesLoading(true);
459
820
  try {
460
- const data = await requestJson("/admin/currencies");
821
+ const response = await sdk.client.fetch("/admin/currencies", {
822
+ method: "GET"
823
+ });
824
+ const data = await response.json();
461
825
  const supported = ((_b = (_a = data.store) == null ? void 0 : _a.supported_currencies) == null ? void 0 : _b.map(
462
826
  (item) => item.code.toUpperCase()
463
827
  )) ?? [];
@@ -536,14 +900,16 @@ const RatesSection = () => {
536
900
  setSaving(true);
537
901
  try {
538
902
  if (formState.id) {
539
- await requestJson(
540
- `/admin/shipping-config/rates/${formState.id}`,
541
- "PUT",
542
- payload
543
- );
903
+ await sdk.client.fetch(`/admin/shipping-config/rates/${formState.id}`, {
904
+ method: "PUT",
905
+ body: payload
906
+ });
544
907
  ui.toast.success("Rate updated", { dismissable: true });
545
908
  } else {
546
- await requestJson("/admin/shipping-config/rates", "POST", payload);
909
+ await sdk.client.fetch("/admin/shipping-config/rates", {
910
+ method: "POST",
911
+ body: payload
912
+ });
547
913
  ui.toast.success("Rate created", { dismissable: true });
548
914
  }
549
915
  await refresh();
@@ -559,7 +925,9 @@ const RatesSection = () => {
559
925
  const handleDelete = async (id) => {
560
926
  setDeletingId(id);
561
927
  try {
562
- await requestJson(`/admin/shipping-config/rates/${id}`, "DELETE");
928
+ await sdk.client.fetch(`/admin/shipping-config/rates/${id}`, {
929
+ method: "DELETE"
930
+ });
563
931
  ui.toast.success("Rate removed", { dismissable: true });
564
932
  await refresh();
565
933
  } catch (error) {
@@ -572,8 +940,9 @@ const RatesSection = () => {
572
940
  };
573
941
  const handleToggle = async (rate) => {
574
942
  try {
575
- await requestJson(`/admin/shipping-config/rates/${rate.id}`, "PUT", {
576
- active: !rate.active
943
+ await sdk.client.fetch(`/admin/shipping-config/rates/${rate.id}`, {
944
+ method: "PUT",
945
+ body: { active: !rate.active }
577
946
  });
578
947
  await refresh();
579
948
  } catch (error) {
@@ -816,9 +1185,10 @@ const AreasSection = () => {
816
1185
  const refresh = react.useCallback(async () => {
817
1186
  setLoading(true);
818
1187
  try {
819
- const data = await requestJson(
820
- "/admin/shipping-config/areas"
821
- );
1188
+ const response = await sdk.client.fetch("/admin/shipping-config/areas", {
1189
+ method: "GET"
1190
+ });
1191
+ const data = await response.json();
822
1192
  setAreas(data.areas ?? []);
823
1193
  } catch (error) {
824
1194
  ui.toast.error(error.message ?? "Failed to load service areas", {
@@ -858,14 +1228,16 @@ const AreasSection = () => {
858
1228
  setSaving(true);
859
1229
  try {
860
1230
  if (formState.id) {
861
- await requestJson(
862
- `/admin/shipping-config/areas/${formState.id}`,
863
- "PUT",
864
- payload
865
- );
1231
+ await sdk.client.fetch(`/admin/shipping-config/areas/${formState.id}`, {
1232
+ method: "PUT",
1233
+ body: payload
1234
+ });
866
1235
  ui.toast.success("Service area updated", { dismissable: true });
867
1236
  } else {
868
- await requestJson("/admin/shipping-config/areas", "POST", payload);
1237
+ await sdk.client.fetch("/admin/shipping-config/areas", {
1238
+ method: "POST",
1239
+ body: payload
1240
+ });
869
1241
  ui.toast.success("Service area created", { dismissable: true });
870
1242
  }
871
1243
  await refresh();
@@ -881,7 +1253,9 @@ const AreasSection = () => {
881
1253
  const handleDelete = async (id) => {
882
1254
  setDeletingId(id);
883
1255
  try {
884
- await requestJson(`/admin/shipping-config/areas/${id}`, "DELETE");
1256
+ await sdk.client.fetch(`/admin/shipping-config/areas/${id}`, {
1257
+ method: "DELETE"
1258
+ });
885
1259
  ui.toast.success("Service area removed", { dismissable: true });
886
1260
  await refresh();
887
1261
  } catch (error) {
@@ -894,8 +1268,9 @@ const AreasSection = () => {
894
1268
  };
895
1269
  const handleToggle = async (area) => {
896
1270
  try {
897
- await requestJson(`/admin/shipping-config/areas/${area.id}`, "PUT", {
898
- active: !area.active
1271
+ await sdk.client.fetch(`/admin/shipping-config/areas/${area.id}`, {
1272
+ method: "PUT",
1273
+ body: { active: !area.active }
899
1274
  });
900
1275
  await refresh();
901
1276
  } catch (error) {
@@ -1136,6 +1511,10 @@ const config = adminSdk.defineRouteConfig({
1136
1511
  const widgetModule = { widgets: [] };
1137
1512
  const routeModule = {
1138
1513
  routes: [
1514
+ {
1515
+ Component: ParcelBoxesRoute,
1516
+ path: "/parcel-boxes"
1517
+ },
1139
1518
  {
1140
1519
  Component: ParcelShippingRoute,
1141
1520
  path: "/parcel-shipping"
@@ -1144,6 +1523,12 @@ const routeModule = {
1144
1523
  };
1145
1524
  const menuItemModule = {
1146
1525
  menuItems: [
1526
+ {
1527
+ label: config$1.label,
1528
+ icon: config$1.icon,
1529
+ path: "/parcel-boxes",
1530
+ nested: void 0
1531
+ },
1147
1532
  {
1148
1533
  label: config.label,
1149
1534
  icon: config.icon,