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