order-management 0.0.17 → 0.0.19
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/src/admin/index.js +644 -11
- package/.medusa/server/src/admin/index.mjs +644 -11
- package/.medusa/server/src/api/admin/swaps/[id]/approve/route.js +74 -0
- package/.medusa/server/src/api/admin/swaps/[id]/process-payment/route.js +152 -0
- package/.medusa/server/src/api/admin/swaps/[id]/reject/route.js +43 -0
- package/.medusa/server/src/api/admin/swaps/[id]/route.js +70 -0
- package/.medusa/server/src/api/admin/swaps/[id]/status/route.js +45 -0
- package/.medusa/server/src/api/admin/swaps/[id]/sync/route.js +148 -0
- package/.medusa/server/src/api/admin/swaps/route.js +51 -0
- package/.medusa/server/src/api/admin/swaps/validators.js +22 -0
- package/.medusa/server/src/api/store/guest-orders/[id]/invoice/route.js +17 -5
- package/.medusa/server/src/api/store/guest-orders/[id]/returns/route.js +17 -5
- package/.medusa/server/src/api/store/guest-orders/[id]/route.js +17 -5
- package/.medusa/server/src/api/store/guest-orders/route.js +17 -5
- package/.medusa/server/src/api/store/orders/[order_id]/swaps/route.js +107 -0
- package/.medusa/server/src/api/store/otp/request/route.js +12 -5
- package/.medusa/server/src/api/store/swaps/[id]/cancel/route.js +64 -0
- package/.medusa/server/src/api/store/swaps/[id]/route.js +112 -0
- package/.medusa/server/src/api/store/swaps/route.js +117 -0
- package/.medusa/server/src/helpers/index.js +18 -0
- package/.medusa/server/src/helpers/swaps.js +88 -0
- package/.medusa/server/src/modules/swap/index.js +13 -0
- package/.medusa/server/src/modules/swap/migrations/Migration20260121164326.js +49 -0
- package/.medusa/server/src/modules/swap/models/swap.js +21 -0
- package/.medusa/server/src/modules/swap/service.js +224 -0
- package/.medusa/server/src/services/otp-service.js +16 -5
- package/.medusa/server/src/subscribers/send-order-email.js +27 -8
- package/.medusa/server/src/workflows/index.js +8 -2
- package/.medusa/server/src/workflows/steps/swap/calculate-difference-step.js +56 -0
- package/.medusa/server/src/workflows/steps/swap/create-medusa-exchange-step.js +71 -0
- package/.medusa/server/src/workflows/steps/swap/create-medusa-return-step.js +79 -0
- package/.medusa/server/src/workflows/steps/swap/create-swap-step.js +29 -0
- package/.medusa/server/src/workflows/steps/swap/handle-payment-difference-step.js +102 -0
- package/.medusa/server/src/workflows/steps/swap/index.js +26 -0
- package/.medusa/server/src/workflows/steps/swap/retrieve-swap-step.js +26 -0
- package/.medusa/server/src/workflows/steps/swap/sync-medusa-status-step.js +132 -0
- package/.medusa/server/src/workflows/steps/swap/update-swap-status-step.js +25 -0
- package/.medusa/server/src/workflows/steps/swap/validate-eligibility-step.js +25 -0
- package/.medusa/server/src/workflows/steps/swap/validate-order-step.js +69 -0
- package/.medusa/server/src/workflows/steps/swap/validate-swap-items-step.js +41 -0
- package/.medusa/server/src/workflows/swaps/approve-swap-workflow.js +22 -0
- package/.medusa/server/src/workflows/swaps/create-swap-workflow.js +52 -0
- package/.medusa/server/src/workflows/swaps/execute-swap-workflow.js +36 -0
- package/.medusa/server/src/workflows/swaps/types.js +3 -0
- package/.medusa/server/src/workflows/swaps/update-swap-status-workflow.js +23 -0
- package/README.md +208 -0
- package/package.json +1 -1
- package/.medusa/server/src/utils/resolve-options.js +0 -101
|
@@ -5,7 +5,7 @@ const adminSdk = require("@medusajs/admin-sdk");
|
|
|
5
5
|
const ui = require("@medusajs/ui");
|
|
6
6
|
const icons = require("@medusajs/icons");
|
|
7
7
|
const reactRouterDom = require("react-router-dom");
|
|
8
|
-
const useDebounce = (value, delay) => {
|
|
8
|
+
const useDebounce$1 = (value, delay) => {
|
|
9
9
|
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
10
10
|
react.useEffect(() => {
|
|
11
11
|
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
@@ -13,7 +13,7 @@ const useDebounce = (value, delay) => {
|
|
|
13
13
|
}, [value, delay]);
|
|
14
14
|
return debouncedValue;
|
|
15
15
|
};
|
|
16
|
-
const getStatusBadgeClass$
|
|
16
|
+
const getStatusBadgeClass$3 = (status) => {
|
|
17
17
|
const statusLower = status.toLowerCase();
|
|
18
18
|
if (statusLower === "requested") {
|
|
19
19
|
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
@@ -37,7 +37,7 @@ const ReturnsPage = () => {
|
|
|
37
37
|
const [items, setItems] = react.useState([]);
|
|
38
38
|
const [statusFilter, setStatusFilter] = react.useState("all");
|
|
39
39
|
const [searchQuery, setSearchQuery] = react.useState("");
|
|
40
|
-
const debouncedSearchQuery = useDebounce(searchQuery, 300);
|
|
40
|
+
const debouncedSearchQuery = useDebounce$1(searchQuery, 300);
|
|
41
41
|
const [isLoading, setIsLoading] = react.useState(true);
|
|
42
42
|
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
43
43
|
const [error, setError] = react.useState(null);
|
|
@@ -165,7 +165,7 @@ const ReturnsPage = () => {
|
|
|
165
165
|
ui.Badge,
|
|
166
166
|
{
|
|
167
167
|
size: "2xsmall",
|
|
168
|
-
className: `uppercase ${getStatusBadgeClass$
|
|
168
|
+
className: `uppercase ${getStatusBadgeClass$3(returnOrder.status)}`,
|
|
169
169
|
children: returnOrder.status.replace(/_/g, " ")
|
|
170
170
|
}
|
|
171
171
|
) }),
|
|
@@ -214,11 +214,222 @@ const ReturnsPage = () => {
|
|
|
214
214
|
) }) : null
|
|
215
215
|
] }) });
|
|
216
216
|
};
|
|
217
|
-
const config$
|
|
217
|
+
const config$3 = adminSdk.defineRouteConfig({
|
|
218
218
|
label: "Return Orders",
|
|
219
219
|
icon: icons.ArrowPath
|
|
220
220
|
});
|
|
221
|
-
const
|
|
221
|
+
const useDebounce = (value, delay) => {
|
|
222
|
+
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
223
|
+
react.useEffect(() => {
|
|
224
|
+
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
225
|
+
return () => clearTimeout(handler);
|
|
226
|
+
}, [value, delay]);
|
|
227
|
+
return debouncedValue;
|
|
228
|
+
};
|
|
229
|
+
const getStatusBadgeClass$2 = (status) => {
|
|
230
|
+
const statusLower = status.toLowerCase();
|
|
231
|
+
if (statusLower === "requested") {
|
|
232
|
+
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
233
|
+
}
|
|
234
|
+
if (statusLower === "approved") {
|
|
235
|
+
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
236
|
+
}
|
|
237
|
+
if (statusLower === "rejected") {
|
|
238
|
+
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
239
|
+
}
|
|
240
|
+
if (statusLower === "completed") {
|
|
241
|
+
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
242
|
+
}
|
|
243
|
+
if (statusLower === "cancelled") {
|
|
244
|
+
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
245
|
+
}
|
|
246
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
247
|
+
};
|
|
248
|
+
const SwapsPage = () => {
|
|
249
|
+
const navigate = reactRouterDom.useNavigate();
|
|
250
|
+
const [items, setItems] = react.useState([]);
|
|
251
|
+
const [statusFilter, setStatusFilter] = react.useState("all");
|
|
252
|
+
const [searchQuery, setSearchQuery] = react.useState("");
|
|
253
|
+
const debouncedSearchQuery = useDebounce(searchQuery, 300);
|
|
254
|
+
const [isLoading, setIsLoading] = react.useState(true);
|
|
255
|
+
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
256
|
+
const [error, setError] = react.useState(null);
|
|
257
|
+
const [offset, setOffset] = react.useState(0);
|
|
258
|
+
const [count, setCount] = react.useState(0);
|
|
259
|
+
const limit = 50;
|
|
260
|
+
const loadSwaps = react.useCallback(
|
|
261
|
+
async (nextOffset, replace = false) => {
|
|
262
|
+
var _a;
|
|
263
|
+
try {
|
|
264
|
+
if (replace) {
|
|
265
|
+
setIsLoading(true);
|
|
266
|
+
} else {
|
|
267
|
+
setIsFetchingMore(true);
|
|
268
|
+
}
|
|
269
|
+
setError(null);
|
|
270
|
+
const params = new URLSearchParams();
|
|
271
|
+
params.set("limit", String(limit));
|
|
272
|
+
params.set("offset", String(nextOffset));
|
|
273
|
+
if (statusFilter !== "all") {
|
|
274
|
+
params.set("status", statusFilter);
|
|
275
|
+
}
|
|
276
|
+
if (debouncedSearchQuery.trim()) {
|
|
277
|
+
params.set("order_id", debouncedSearchQuery.trim());
|
|
278
|
+
}
|
|
279
|
+
const response = await fetch(
|
|
280
|
+
`/admin/swaps?${params.toString()}`,
|
|
281
|
+
{ credentials: "include" }
|
|
282
|
+
);
|
|
283
|
+
if (!response.ok) {
|
|
284
|
+
const message = await response.text();
|
|
285
|
+
throw new Error(message || "Unable to load swaps");
|
|
286
|
+
}
|
|
287
|
+
const payload = await response.json();
|
|
288
|
+
setCount(payload.count ?? 0);
|
|
289
|
+
setOffset(nextOffset + (((_a = payload.swaps) == null ? void 0 : _a.length) ?? 0));
|
|
290
|
+
setItems(
|
|
291
|
+
(prev) => replace ? payload.swaps ?? [] : [...prev, ...payload.swaps ?? []]
|
|
292
|
+
);
|
|
293
|
+
} catch (loadError) {
|
|
294
|
+
const message = loadError instanceof Error ? loadError.message : "Unable to load swaps";
|
|
295
|
+
setError(message);
|
|
296
|
+
} finally {
|
|
297
|
+
setIsLoading(false);
|
|
298
|
+
setIsFetchingMore(false);
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
[statusFilter, debouncedSearchQuery]
|
|
302
|
+
);
|
|
303
|
+
react.useEffect(() => {
|
|
304
|
+
void loadSwaps(0, true);
|
|
305
|
+
}, [statusFilter, debouncedSearchQuery, loadSwaps]);
|
|
306
|
+
const hasMore = react.useMemo(() => offset < count, [offset, count]);
|
|
307
|
+
const availableStatuses = react.useMemo(() => {
|
|
308
|
+
const statuses = /* @__PURE__ */ new Set();
|
|
309
|
+
items.forEach((item) => statuses.add(item.status));
|
|
310
|
+
return Array.from(statuses).sort();
|
|
311
|
+
}, [items]);
|
|
312
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
|
|
313
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
314
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
315
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Swaps" }),
|
|
316
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "View and manage all customer swap requests" })
|
|
317
|
+
] }),
|
|
318
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => loadSwaps(0, true), children: "Refresh" })
|
|
319
|
+
] }),
|
|
320
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
321
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
322
|
+
ui.Input,
|
|
323
|
+
{
|
|
324
|
+
placeholder: "Search by swap ID or order ID",
|
|
325
|
+
value: searchQuery,
|
|
326
|
+
onChange: (event) => setSearchQuery(event.target.value),
|
|
327
|
+
className: "md:max-w-sm"
|
|
328
|
+
}
|
|
329
|
+
),
|
|
330
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
331
|
+
"select",
|
|
332
|
+
{
|
|
333
|
+
value: statusFilter,
|
|
334
|
+
onChange: (event) => setStatusFilter(event.target.value),
|
|
335
|
+
className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-xs",
|
|
336
|
+
children: [
|
|
337
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All Statuses" }),
|
|
338
|
+
availableStatuses.map((status) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
|
|
339
|
+
]
|
|
340
|
+
}
|
|
341
|
+
) })
|
|
342
|
+
] }),
|
|
343
|
+
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
344
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
345
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
346
|
+
ui.Button,
|
|
347
|
+
{
|
|
348
|
+
variant: "secondary",
|
|
349
|
+
onClick: () => loadSwaps(0, true),
|
|
350
|
+
children: "Try again"
|
|
351
|
+
}
|
|
352
|
+
) })
|
|
353
|
+
] }) : null,
|
|
354
|
+
isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading swaps..." }) }) : items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
355
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No swaps yet" }),
|
|
356
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Swap requests created by customers will appear here." })
|
|
357
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
358
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
359
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Swap ID" }),
|
|
360
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
361
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
362
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Difference Due" }),
|
|
363
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
364
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
365
|
+
] }) }),
|
|
366
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((swap) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
367
|
+
"tr",
|
|
368
|
+
{
|
|
369
|
+
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
370
|
+
onClick: () => navigate(`/swaps/${swap.id}`),
|
|
371
|
+
children: [
|
|
372
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-0.5", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: swap.id }) }) }),
|
|
373
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: swap.order_id }),
|
|
374
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
375
|
+
ui.Badge,
|
|
376
|
+
{
|
|
377
|
+
size: "2xsmall",
|
|
378
|
+
className: `uppercase ${getStatusBadgeClass$2(swap.status)}`,
|
|
379
|
+
children: swap.status.replace(/_/g, " ")
|
|
380
|
+
}
|
|
381
|
+
) }),
|
|
382
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
|
|
383
|
+
const amount = swap.difference_due;
|
|
384
|
+
if (amount == null || amount === void 0) {
|
|
385
|
+
return "—";
|
|
386
|
+
}
|
|
387
|
+
const displayAmount = Number(amount) / 100;
|
|
388
|
+
const currency = swap.currency_code || "$";
|
|
389
|
+
const sign = displayAmount >= 0 ? "+" : "";
|
|
390
|
+
return `${sign}${currency}${displayAmount.toFixed(2)}`;
|
|
391
|
+
})() }),
|
|
392
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(swap.created_at).toLocaleDateString("en-US", {
|
|
393
|
+
year: "numeric",
|
|
394
|
+
month: "short",
|
|
395
|
+
day: "numeric",
|
|
396
|
+
hour: "numeric",
|
|
397
|
+
minute: "2-digit",
|
|
398
|
+
hour12: true
|
|
399
|
+
}) }),
|
|
400
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
401
|
+
ui.Button,
|
|
402
|
+
{
|
|
403
|
+
variant: "transparent",
|
|
404
|
+
size: "small",
|
|
405
|
+
onClick: (e) => {
|
|
406
|
+
e.stopPropagation();
|
|
407
|
+
navigate(`/swaps/${swap.id}`);
|
|
408
|
+
},
|
|
409
|
+
children: "View"
|
|
410
|
+
}
|
|
411
|
+
) })
|
|
412
|
+
]
|
|
413
|
+
},
|
|
414
|
+
swap.id
|
|
415
|
+
)) })
|
|
416
|
+
] }) }),
|
|
417
|
+
hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
418
|
+
ui.Button,
|
|
419
|
+
{
|
|
420
|
+
variant: "secondary",
|
|
421
|
+
isLoading: isFetchingMore,
|
|
422
|
+
onClick: () => loadSwaps(offset, false),
|
|
423
|
+
children: "Load more"
|
|
424
|
+
}
|
|
425
|
+
) }) : null
|
|
426
|
+
] }) });
|
|
427
|
+
};
|
|
428
|
+
const config$2 = adminSdk.defineRouteConfig({
|
|
429
|
+
label: "Swaps",
|
|
430
|
+
icon: icons.ArrowPath
|
|
431
|
+
});
|
|
432
|
+
const getStatusBadgeClass$1 = (status) => {
|
|
222
433
|
const statusLower = status.toLowerCase();
|
|
223
434
|
if (statusLower === "requested") {
|
|
224
435
|
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
@@ -356,7 +567,7 @@ const ReturnDetailPage = () => {
|
|
|
356
567
|
ui.Badge,
|
|
357
568
|
{
|
|
358
569
|
size: "small",
|
|
359
|
-
className: `uppercase ${getStatusBadgeClass(returnOrder.status)}`,
|
|
570
|
+
className: `uppercase ${getStatusBadgeClass$1(returnOrder.status)}`,
|
|
360
571
|
children: returnOrder.status.replace("_", " ")
|
|
361
572
|
}
|
|
362
573
|
)
|
|
@@ -440,7 +651,7 @@ const ReturnDetailPage = () => {
|
|
|
440
651
|
ui.Badge,
|
|
441
652
|
{
|
|
442
653
|
size: "2xsmall",
|
|
443
|
-
className: `uppercase ${getStatusBadgeClass(entry.to)}`,
|
|
654
|
+
className: `uppercase ${getStatusBadgeClass$1(entry.to)}`,
|
|
444
655
|
children: entry.to.replace("_", " ")
|
|
445
656
|
}
|
|
446
657
|
),
|
|
@@ -527,10 +738,412 @@ const ReturnDetailPage = () => {
|
|
|
527
738
|
] })
|
|
528
739
|
] }) });
|
|
529
740
|
};
|
|
530
|
-
const config = adminSdk.defineRouteConfig({
|
|
741
|
+
const config$1 = adminSdk.defineRouteConfig({
|
|
531
742
|
label: "Return Order Details",
|
|
532
743
|
icon: icons.ArrowPath
|
|
533
744
|
});
|
|
745
|
+
const getStatusBadgeClass = (status) => {
|
|
746
|
+
const statusLower = status.toLowerCase();
|
|
747
|
+
if (statusLower === "requested") {
|
|
748
|
+
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
749
|
+
}
|
|
750
|
+
if (statusLower === "approved") {
|
|
751
|
+
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
752
|
+
}
|
|
753
|
+
if (statusLower === "rejected") {
|
|
754
|
+
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
755
|
+
}
|
|
756
|
+
if (statusLower === "completed") {
|
|
757
|
+
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
758
|
+
}
|
|
759
|
+
if (statusLower === "cancelled") {
|
|
760
|
+
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
761
|
+
}
|
|
762
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
763
|
+
};
|
|
764
|
+
const SwapDetailPage = () => {
|
|
765
|
+
var _a, _b;
|
|
766
|
+
const navigate = reactRouterDom.useNavigate();
|
|
767
|
+
const { id } = reactRouterDom.useParams();
|
|
768
|
+
const [swap, setSwap] = react.useState(null);
|
|
769
|
+
const [order, setOrder] = react.useState(null);
|
|
770
|
+
const [selectedStatus, setSelectedStatus] = react.useState("");
|
|
771
|
+
const [isLoading, setIsLoading] = react.useState(true);
|
|
772
|
+
const [isUpdating, setIsUpdating] = react.useState(false);
|
|
773
|
+
const [isApproving, setIsApproving] = react.useState(false);
|
|
774
|
+
const [isRejecting, setIsRejecting] = react.useState(false);
|
|
775
|
+
const [error, setError] = react.useState(null);
|
|
776
|
+
const [updateError, setUpdateError] = react.useState(null);
|
|
777
|
+
const [updateSuccess, setUpdateSuccess] = react.useState(false);
|
|
778
|
+
const availableStatuses = [
|
|
779
|
+
"requested",
|
|
780
|
+
"approved",
|
|
781
|
+
"rejected",
|
|
782
|
+
"return_started",
|
|
783
|
+
"return_shipped",
|
|
784
|
+
"return_received",
|
|
785
|
+
"new_items_shipped",
|
|
786
|
+
"completed",
|
|
787
|
+
"cancelled"
|
|
788
|
+
];
|
|
789
|
+
react.useEffect(() => {
|
|
790
|
+
if (!id) {
|
|
791
|
+
navigate("/swaps");
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
const loadSwap = async () => {
|
|
795
|
+
try {
|
|
796
|
+
setIsLoading(true);
|
|
797
|
+
setError(null);
|
|
798
|
+
const response = await fetch(`/admin/swaps/${id}`, {
|
|
799
|
+
credentials: "include"
|
|
800
|
+
});
|
|
801
|
+
if (!response.ok) {
|
|
802
|
+
const message = await response.text();
|
|
803
|
+
throw new Error(message || "Unable to load swap");
|
|
804
|
+
}
|
|
805
|
+
const payload = await response.json();
|
|
806
|
+
setSwap(payload.swap);
|
|
807
|
+
setOrder(payload.order || null);
|
|
808
|
+
setSelectedStatus("");
|
|
809
|
+
} catch (loadError) {
|
|
810
|
+
const message = loadError instanceof Error ? loadError.message : "Unable to load swap";
|
|
811
|
+
setError(message);
|
|
812
|
+
} finally {
|
|
813
|
+
setIsLoading(false);
|
|
814
|
+
}
|
|
815
|
+
};
|
|
816
|
+
void loadSwap();
|
|
817
|
+
}, [id, navigate]);
|
|
818
|
+
const handleStatusUpdate = async () => {
|
|
819
|
+
if (!id || !selectedStatus) {
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
try {
|
|
823
|
+
setIsUpdating(true);
|
|
824
|
+
setUpdateError(null);
|
|
825
|
+
setUpdateSuccess(false);
|
|
826
|
+
const response = await fetch(`/admin/swaps/${id}/status`, {
|
|
827
|
+
method: "POST",
|
|
828
|
+
headers: {
|
|
829
|
+
"Content-Type": "application/json"
|
|
830
|
+
},
|
|
831
|
+
credentials: "include",
|
|
832
|
+
body: JSON.stringify({ status: selectedStatus })
|
|
833
|
+
});
|
|
834
|
+
if (!response.ok) {
|
|
835
|
+
const message = await response.text();
|
|
836
|
+
throw new Error(message || "Unable to update status");
|
|
837
|
+
}
|
|
838
|
+
const payload = await response.json();
|
|
839
|
+
setSwap(payload.swap);
|
|
840
|
+
setSelectedStatus("");
|
|
841
|
+
setUpdateSuccess(true);
|
|
842
|
+
setTimeout(() => setUpdateSuccess(false), 3e3);
|
|
843
|
+
const detailResponse = await fetch(`/admin/swaps/${id}`, {
|
|
844
|
+
credentials: "include"
|
|
845
|
+
});
|
|
846
|
+
if (detailResponse.ok) {
|
|
847
|
+
const detailPayload = await detailResponse.json();
|
|
848
|
+
setSwap(detailPayload.swap);
|
|
849
|
+
setOrder(detailPayload.order || null);
|
|
850
|
+
}
|
|
851
|
+
} catch (updateErr) {
|
|
852
|
+
const message = updateErr instanceof Error ? updateErr.message : "Unable to update status";
|
|
853
|
+
setUpdateError(message);
|
|
854
|
+
} finally {
|
|
855
|
+
setIsUpdating(false);
|
|
856
|
+
}
|
|
857
|
+
};
|
|
858
|
+
const handleApprove = async () => {
|
|
859
|
+
if (!id) {
|
|
860
|
+
return;
|
|
861
|
+
}
|
|
862
|
+
try {
|
|
863
|
+
setIsApproving(true);
|
|
864
|
+
setUpdateError(null);
|
|
865
|
+
setUpdateSuccess(false);
|
|
866
|
+
const response = await fetch(`/admin/swaps/${id}/approve`, {
|
|
867
|
+
method: "POST",
|
|
868
|
+
headers: {
|
|
869
|
+
"Content-Type": "application/json"
|
|
870
|
+
},
|
|
871
|
+
credentials: "include"
|
|
872
|
+
});
|
|
873
|
+
if (!response.ok) {
|
|
874
|
+
const message = await response.text();
|
|
875
|
+
throw new Error(message || "Unable to approve swap");
|
|
876
|
+
}
|
|
877
|
+
const payload = await response.json();
|
|
878
|
+
setSwap(payload.swap);
|
|
879
|
+
setUpdateSuccess(true);
|
|
880
|
+
setTimeout(() => setUpdateSuccess(false), 3e3);
|
|
881
|
+
const detailResponse = await fetch(`/admin/swaps/${id}`, {
|
|
882
|
+
credentials: "include"
|
|
883
|
+
});
|
|
884
|
+
if (detailResponse.ok) {
|
|
885
|
+
const detailPayload = await response.json();
|
|
886
|
+
setSwap(detailPayload.swap);
|
|
887
|
+
setOrder(detailPayload.order || null);
|
|
888
|
+
}
|
|
889
|
+
} catch (updateErr) {
|
|
890
|
+
const message = updateErr instanceof Error ? updateErr.message : "Unable to approve swap";
|
|
891
|
+
setUpdateError(message);
|
|
892
|
+
} finally {
|
|
893
|
+
setIsApproving(false);
|
|
894
|
+
}
|
|
895
|
+
};
|
|
896
|
+
const handleReject = async () => {
|
|
897
|
+
if (!id) {
|
|
898
|
+
return;
|
|
899
|
+
}
|
|
900
|
+
try {
|
|
901
|
+
setIsRejecting(true);
|
|
902
|
+
setUpdateError(null);
|
|
903
|
+
setUpdateSuccess(false);
|
|
904
|
+
const response = await fetch(`/admin/swaps/${id}/reject`, {
|
|
905
|
+
method: "POST",
|
|
906
|
+
headers: {
|
|
907
|
+
"Content-Type": "application/json"
|
|
908
|
+
},
|
|
909
|
+
credentials: "include",
|
|
910
|
+
body: JSON.stringify({ reason: "Rejected by admin" })
|
|
911
|
+
});
|
|
912
|
+
if (!response.ok) {
|
|
913
|
+
const message = await response.text();
|
|
914
|
+
throw new Error(message || "Unable to reject swap");
|
|
915
|
+
}
|
|
916
|
+
const payload = await response.json();
|
|
917
|
+
setSwap(payload.swap);
|
|
918
|
+
setUpdateSuccess(true);
|
|
919
|
+
setTimeout(() => setUpdateSuccess(false), 3e3);
|
|
920
|
+
const detailResponse = await fetch(`/admin/swaps/${id}`, {
|
|
921
|
+
credentials: "include"
|
|
922
|
+
});
|
|
923
|
+
if (detailResponse.ok) {
|
|
924
|
+
const detailPayload = await response.json();
|
|
925
|
+
setSwap(detailPayload.swap);
|
|
926
|
+
setOrder(detailPayload.order || null);
|
|
927
|
+
}
|
|
928
|
+
} catch (updateErr) {
|
|
929
|
+
const message = updateErr instanceof Error ? updateErr.message : "Unable to reject swap";
|
|
930
|
+
setUpdateError(message);
|
|
931
|
+
} finally {
|
|
932
|
+
setIsRejecting(false);
|
|
933
|
+
}
|
|
934
|
+
};
|
|
935
|
+
if (isLoading) {
|
|
936
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading swap..." }) }) }) });
|
|
937
|
+
}
|
|
938
|
+
if (error || !swap) {
|
|
939
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
940
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error || "Swap not found" }),
|
|
941
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => navigate("/swaps"), children: "Back to list" }) })
|
|
942
|
+
] }) }) });
|
|
943
|
+
}
|
|
944
|
+
const statusHistory = ((_a = swap.metadata) == null ? void 0 : _a.status_history) || [];
|
|
945
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: [
|
|
946
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3", children: [
|
|
947
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
948
|
+
ui.Button,
|
|
949
|
+
{
|
|
950
|
+
variant: "transparent",
|
|
951
|
+
size: "small",
|
|
952
|
+
onClick: () => navigate("/swaps"),
|
|
953
|
+
className: "w-fit",
|
|
954
|
+
children: [
|
|
955
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, { className: "mr-2" }),
|
|
956
|
+
"Back to list"
|
|
957
|
+
]
|
|
958
|
+
}
|
|
959
|
+
),
|
|
960
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 md:flex-row md:items-center md:justify-between", children: [
|
|
961
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
962
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Swap Details" }),
|
|
963
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: swap.id })
|
|
964
|
+
] }),
|
|
965
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
966
|
+
ui.Badge,
|
|
967
|
+
{
|
|
968
|
+
size: "small",
|
|
969
|
+
className: `uppercase ${getStatusBadgeClass(swap.status)}`,
|
|
970
|
+
children: swap.status.replace(/_/g, " ")
|
|
971
|
+
}
|
|
972
|
+
)
|
|
973
|
+
] })
|
|
974
|
+
] }),
|
|
975
|
+
swap.status === "requested" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
|
|
976
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
977
|
+
ui.Button,
|
|
978
|
+
{
|
|
979
|
+
variant: "primary",
|
|
980
|
+
onClick: handleApprove,
|
|
981
|
+
disabled: isApproving || isRejecting,
|
|
982
|
+
isLoading: isApproving,
|
|
983
|
+
children: "Approve Swap"
|
|
984
|
+
}
|
|
985
|
+
),
|
|
986
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
987
|
+
ui.Button,
|
|
988
|
+
{
|
|
989
|
+
variant: "secondary",
|
|
990
|
+
onClick: handleReject,
|
|
991
|
+
disabled: isApproving || isRejecting,
|
|
992
|
+
isLoading: isRejecting,
|
|
993
|
+
children: "Reject Swap"
|
|
994
|
+
}
|
|
995
|
+
)
|
|
996
|
+
] }),
|
|
997
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
998
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Update Status" }),
|
|
999
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-end", children: [
|
|
1000
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
|
|
1001
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "mb-2 block text-sm font-medium text-ui-fg-base", children: "New Status" }),
|
|
1002
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1003
|
+
"select",
|
|
1004
|
+
{
|
|
1005
|
+
value: selectedStatus,
|
|
1006
|
+
onChange: (event) => setSelectedStatus(event.target.value),
|
|
1007
|
+
className: "h-9 w-full rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive",
|
|
1008
|
+
children: [
|
|
1009
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Select new status" }),
|
|
1010
|
+
availableStatuses.filter((status) => status !== swap.status).map((status) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
|
|
1011
|
+
]
|
|
1012
|
+
}
|
|
1013
|
+
)
|
|
1014
|
+
] }),
|
|
1015
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1016
|
+
ui.Button,
|
|
1017
|
+
{
|
|
1018
|
+
variant: "primary",
|
|
1019
|
+
onClick: handleStatusUpdate,
|
|
1020
|
+
disabled: !selectedStatus || isUpdating,
|
|
1021
|
+
isLoading: isUpdating,
|
|
1022
|
+
children: "Update Status"
|
|
1023
|
+
}
|
|
1024
|
+
)
|
|
1025
|
+
] }),
|
|
1026
|
+
updateError && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-error", children: updateError }),
|
|
1027
|
+
updateSuccess && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-success", children: "Status updated successfully" })
|
|
1028
|
+
] }),
|
|
1029
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-6 md:grid-cols-2", children: [
|
|
1030
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
1031
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Swap Information" }),
|
|
1032
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
1033
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1034
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Swap ID" }),
|
|
1035
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.id })
|
|
1036
|
+
] }),
|
|
1037
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1038
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Status" }),
|
|
1039
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.status })
|
|
1040
|
+
] }),
|
|
1041
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1042
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Difference Due" }),
|
|
1043
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.difference_due != null ? `${swap.currency_code || "$"}${(Number(swap.difference_due) / 100).toFixed(2)}` : "—" })
|
|
1044
|
+
] }),
|
|
1045
|
+
swap.reason && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1046
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Reason" }),
|
|
1047
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.reason })
|
|
1048
|
+
] }),
|
|
1049
|
+
swap.note && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1050
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Note" }),
|
|
1051
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.note })
|
|
1052
|
+
] }),
|
|
1053
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1054
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Created" }),
|
|
1055
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(swap.created_at).toLocaleString() })
|
|
1056
|
+
] }),
|
|
1057
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1058
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Last Updated" }),
|
|
1059
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(swap.updated_at).toLocaleString() })
|
|
1060
|
+
] })
|
|
1061
|
+
] })
|
|
1062
|
+
] }),
|
|
1063
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
1064
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Status History" }),
|
|
1065
|
+
statusHistory.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: statusHistory.map((entry, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1066
|
+
"div",
|
|
1067
|
+
{
|
|
1068
|
+
className: "flex items-center justify-between border-b border-ui-border-subtle pb-2 last:border-0",
|
|
1069
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1070
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1071
|
+
ui.Badge,
|
|
1072
|
+
{
|
|
1073
|
+
size: "2xsmall",
|
|
1074
|
+
className: `uppercase ${getStatusBadgeClass(entry.status)}`,
|
|
1075
|
+
children: entry.status.replace(/_/g, " ")
|
|
1076
|
+
}
|
|
1077
|
+
) }),
|
|
1078
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
1079
|
+
new Date(entry.timestamp).toLocaleString(),
|
|
1080
|
+
entry.admin_id && ` by ${entry.admin_id}`,
|
|
1081
|
+
entry.reason && ` - ${entry.reason}`
|
|
1082
|
+
] })
|
|
1083
|
+
] })
|
|
1084
|
+
},
|
|
1085
|
+
index
|
|
1086
|
+
)) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "No status history available" })
|
|
1087
|
+
] })
|
|
1088
|
+
] }),
|
|
1089
|
+
order && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
1090
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Related Order Information" }),
|
|
1091
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
1092
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1093
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order ID" }),
|
|
1094
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: order.id })
|
|
1095
|
+
] }),
|
|
1096
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1097
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Status" }),
|
|
1098
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: order.status || "—" })
|
|
1099
|
+
] }),
|
|
1100
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1101
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Customer" }),
|
|
1102
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: ((_b = order.customer) == null ? void 0 : _b.email) || order.email || "—" })
|
|
1103
|
+
] }),
|
|
1104
|
+
order.total && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1105
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Total" }),
|
|
1106
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "font-medium", children: [
|
|
1107
|
+
order.currency_code || "$",
|
|
1108
|
+
(Number(order.total) / 100).toFixed(2)
|
|
1109
|
+
] })
|
|
1110
|
+
] })
|
|
1111
|
+
] })
|
|
1112
|
+
] }),
|
|
1113
|
+
swap.return_items && swap.return_items.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
1114
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Items" }),
|
|
1115
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
1116
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
1117
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Item ID" }),
|
|
1118
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Quantity" }),
|
|
1119
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Reason" })
|
|
1120
|
+
] }) }),
|
|
1121
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: swap.return_items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
1122
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: item.id }),
|
|
1123
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.quantity }),
|
|
1124
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.reason || "—" })
|
|
1125
|
+
] }, item.id || index)) })
|
|
1126
|
+
] }) })
|
|
1127
|
+
] }),
|
|
1128
|
+
swap.new_items && swap.new_items.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
1129
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "New Items" }),
|
|
1130
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
1131
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
1132
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Variant ID" }),
|
|
1133
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Quantity" })
|
|
1134
|
+
] }) }),
|
|
1135
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: swap.new_items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
1136
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: item.variant_id }),
|
|
1137
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.quantity })
|
|
1138
|
+
] }, item.variant_id || index)) })
|
|
1139
|
+
] }) })
|
|
1140
|
+
] })
|
|
1141
|
+
] }) });
|
|
1142
|
+
};
|
|
1143
|
+
const config = adminSdk.defineRouteConfig({
|
|
1144
|
+
label: "Swap Details",
|
|
1145
|
+
icon: icons.ArrowPath
|
|
1146
|
+
});
|
|
534
1147
|
const i18nTranslations0 = {};
|
|
535
1148
|
const widgetModule = { widgets: [] };
|
|
536
1149
|
const routeModule = {
|
|
@@ -539,24 +1152,44 @@ const routeModule = {
|
|
|
539
1152
|
Component: ReturnsPage,
|
|
540
1153
|
path: "/returns"
|
|
541
1154
|
},
|
|
1155
|
+
{
|
|
1156
|
+
Component: SwapsPage,
|
|
1157
|
+
path: "/swaps"
|
|
1158
|
+
},
|
|
542
1159
|
{
|
|
543
1160
|
Component: ReturnDetailPage,
|
|
544
1161
|
path: "/returns/:id"
|
|
1162
|
+
},
|
|
1163
|
+
{
|
|
1164
|
+
Component: SwapDetailPage,
|
|
1165
|
+
path: "/swaps/:id"
|
|
545
1166
|
}
|
|
546
1167
|
]
|
|
547
1168
|
};
|
|
548
1169
|
const menuItemModule = {
|
|
549
1170
|
menuItems: [
|
|
1171
|
+
{
|
|
1172
|
+
label: config$3.label,
|
|
1173
|
+
icon: config$3.icon,
|
|
1174
|
+
path: "/returns",
|
|
1175
|
+
nested: void 0
|
|
1176
|
+
},
|
|
1177
|
+
{
|
|
1178
|
+
label: config$2.label,
|
|
1179
|
+
icon: config$2.icon,
|
|
1180
|
+
path: "/swaps",
|
|
1181
|
+
nested: void 0
|
|
1182
|
+
},
|
|
550
1183
|
{
|
|
551
1184
|
label: config$1.label,
|
|
552
1185
|
icon: config$1.icon,
|
|
553
|
-
path: "/returns",
|
|
1186
|
+
path: "/returns/:id",
|
|
554
1187
|
nested: void 0
|
|
555
1188
|
},
|
|
556
1189
|
{
|
|
557
1190
|
label: config.label,
|
|
558
1191
|
icon: config.icon,
|
|
559
|
-
path: "/
|
|
1192
|
+
path: "/swaps/:id",
|
|
560
1193
|
nested: void 0
|
|
561
1194
|
}
|
|
562
1195
|
]
|