order-management 0.0.99 → 0.0.101
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 +1328 -1328
- package/.medusa/server/src/admin/index.mjs +1329 -1329
- package/.medusa/server/src/utils/notification-handler.js +44 -23
- package/.medusa/server/src/utils/template.js +28 -23
- package/README.md +1 -1
- package/package.json +1 -1
|
@@ -2440,275 +2440,222 @@ const useDebounce$2 = (value, delay) => {
|
|
|
2440
2440
|
return debouncedValue;
|
|
2441
2441
|
};
|
|
2442
2442
|
const getStatusBadgeClass$6 = (status) => {
|
|
2443
|
-
const
|
|
2444
|
-
if (
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
if (
|
|
2443
|
+
const statusLower = status.toLowerCase();
|
|
2444
|
+
if (statusLower === "requested") {
|
|
2445
|
+
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
2446
|
+
}
|
|
2447
|
+
if (statusLower === "received") {
|
|
2448
|
+
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
2449
|
+
}
|
|
2450
|
+
if (statusLower === "requires_action") {
|
|
2451
|
+
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
2452
|
+
}
|
|
2453
|
+
if (statusLower === "completed") {
|
|
2454
|
+
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
2455
|
+
}
|
|
2456
|
+
if (statusLower === "canceled") {
|
|
2457
|
+
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
2458
|
+
}
|
|
2448
2459
|
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
2449
2460
|
};
|
|
2450
|
-
const
|
|
2461
|
+
const ReturnsPage = () => {
|
|
2451
2462
|
const navigate = reactRouterDom.useNavigate();
|
|
2452
2463
|
const [items, setItems] = react.useState([]);
|
|
2453
|
-
const [
|
|
2454
|
-
const
|
|
2455
|
-
const [
|
|
2456
|
-
const
|
|
2457
|
-
const debouncedProvider = useDebounce$2(providerSearch, 300);
|
|
2458
|
-
const [currencySearch, setCurrencySearch] = react.useState("");
|
|
2459
|
-
const debouncedCurrency = useDebounce$2(currencySearch, 300);
|
|
2460
|
-
const [dateFrom, setDateFrom] = react.useState("");
|
|
2461
|
-
const [dateTo, setDateTo] = react.useState("");
|
|
2462
|
-
const [amountMin, setAmountMin] = react.useState("");
|
|
2463
|
-
const [amountMax, setAmountMax] = react.useState("");
|
|
2464
|
+
const [statusFilter, setStatusFilter] = react.useState("all");
|
|
2465
|
+
const [createdByFilter, setCreatedByFilter] = react.useState("all");
|
|
2466
|
+
const [searchQuery, setSearchQuery] = react.useState("");
|
|
2467
|
+
const debouncedSearchQuery = useDebounce$2(searchQuery, 300);
|
|
2464
2468
|
const [isLoading, setIsLoading] = react.useState(true);
|
|
2465
2469
|
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
2466
2470
|
const [error, setError] = react.useState(null);
|
|
2467
2471
|
const [offset, setOffset] = react.useState(0);
|
|
2468
2472
|
const [count, setCount] = react.useState(0);
|
|
2469
2473
|
const limit = 50;
|
|
2470
|
-
const
|
|
2471
|
-
async (nextOffset, replace) => {
|
|
2474
|
+
const loadReturns = react.useCallback(
|
|
2475
|
+
async (nextOffset, replace = false) => {
|
|
2476
|
+
var _a;
|
|
2472
2477
|
try {
|
|
2473
|
-
if (replace)
|
|
2474
|
-
|
|
2478
|
+
if (replace) {
|
|
2479
|
+
setIsLoading(true);
|
|
2480
|
+
} else {
|
|
2481
|
+
setIsFetchingMore(true);
|
|
2482
|
+
}
|
|
2475
2483
|
setError(null);
|
|
2476
2484
|
const params = new URLSearchParams();
|
|
2477
2485
|
params.set("limit", String(limit));
|
|
2478
2486
|
params.set("offset", String(nextOffset));
|
|
2479
|
-
if (
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
if (
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
const response = await fetch(
|
|
2490
|
-
|
|
2491
|
-
|
|
2487
|
+
if (statusFilter !== "all") {
|
|
2488
|
+
params.set("status", statusFilter);
|
|
2489
|
+
}
|
|
2490
|
+
if (debouncedSearchQuery.trim()) {
|
|
2491
|
+
params.set("q", debouncedSearchQuery.trim());
|
|
2492
|
+
}
|
|
2493
|
+
if (createdByFilter !== "all") {
|
|
2494
|
+
params.set("created_by", createdByFilter);
|
|
2495
|
+
}
|
|
2496
|
+
params.set("order", "created_at");
|
|
2497
|
+
const response = await fetch(
|
|
2498
|
+
`/admin/return?${params.toString()}`,
|
|
2499
|
+
{ credentials: "include" }
|
|
2500
|
+
);
|
|
2492
2501
|
if (!response.ok) {
|
|
2493
|
-
const
|
|
2494
|
-
throw new Error(
|
|
2502
|
+
const message = await response.text();
|
|
2503
|
+
throw new Error(message || "Unable to load return orders");
|
|
2495
2504
|
}
|
|
2496
2505
|
const payload = await response.json();
|
|
2497
|
-
const list = payload.refunds ?? [];
|
|
2498
2506
|
setCount(payload.count ?? 0);
|
|
2499
|
-
setOffset(nextOffset +
|
|
2500
|
-
setItems(
|
|
2501
|
-
|
|
2502
|
-
|
|
2507
|
+
setOffset(nextOffset + (((_a = payload.returns) == null ? void 0 : _a.length) ?? 0));
|
|
2508
|
+
setItems(
|
|
2509
|
+
(prev) => replace ? payload.returns ?? [] : [...prev, ...payload.returns ?? []]
|
|
2510
|
+
);
|
|
2511
|
+
} catch (loadError) {
|
|
2512
|
+
const message = loadError instanceof Error ? loadError.message : "Unable to load return orders";
|
|
2513
|
+
setError(message);
|
|
2503
2514
|
} finally {
|
|
2504
2515
|
setIsLoading(false);
|
|
2505
2516
|
setIsFetchingMore(false);
|
|
2506
2517
|
}
|
|
2507
2518
|
},
|
|
2508
|
-
[
|
|
2509
|
-
debouncedOrderId,
|
|
2510
|
-
paymentStatusFilter,
|
|
2511
|
-
debouncedProvider,
|
|
2512
|
-
debouncedCurrency,
|
|
2513
|
-
dateFrom,
|
|
2514
|
-
dateTo,
|
|
2515
|
-
amountMin,
|
|
2516
|
-
amountMax
|
|
2517
|
-
]
|
|
2519
|
+
[statusFilter, createdByFilter, debouncedSearchQuery]
|
|
2518
2520
|
);
|
|
2519
2521
|
react.useEffect(() => {
|
|
2520
|
-
void
|
|
2521
|
-
}, [
|
|
2522
|
+
void loadReturns(0, true);
|
|
2523
|
+
}, [statusFilter, createdByFilter, debouncedSearchQuery, loadReturns]);
|
|
2522
2524
|
const hasMore = react.useMemo(() => offset < count, [offset, count]);
|
|
2523
|
-
const
|
|
2524
|
-
const
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
const s2 = r.payment_status ?? "";
|
|
2529
|
-
return s2 !== "" ? s2 : "—";
|
|
2530
|
-
};
|
|
2525
|
+
const availableStatuses = react.useMemo(() => {
|
|
2526
|
+
const statuses = /* @__PURE__ */ new Set();
|
|
2527
|
+
items.forEach((item) => statuses.add(item.status));
|
|
2528
|
+
return Array.from(statuses).sort();
|
|
2529
|
+
}, [items]);
|
|
2531
2530
|
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: [
|
|
2532
2531
|
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
2533
2532
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
2534
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "
|
|
2535
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "
|
|
2533
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Return Orders" }),
|
|
2534
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "View and manage all customer return orders" })
|
|
2536
2535
|
] }),
|
|
2537
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () =>
|
|
2536
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => loadReturns(0, true), children: "Refresh" })
|
|
2538
2537
|
] }),
|
|
2539
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2540
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2541
|
-
ui.Input,
|
|
2542
|
-
{
|
|
2543
|
-
placeholder: "Order ID",
|
|
2544
|
-
value: orderIdSearch,
|
|
2545
|
-
onChange: (e) => setOrderIdSearch(e.target.value),
|
|
2546
|
-
className: "md:max-w-[180px]",
|
|
2547
|
-
"aria-label": "Filter by order ID"
|
|
2548
|
-
}
|
|
2549
|
-
),
|
|
2538
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
2550
2539
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2551
2540
|
ui.Input,
|
|
2552
2541
|
{
|
|
2553
|
-
placeholder: "
|
|
2554
|
-
value:
|
|
2555
|
-
onChange: (
|
|
2556
|
-
className: "md:max-w-
|
|
2557
|
-
"aria-label": "Filter by provider"
|
|
2542
|
+
placeholder: "Search by return ID, order ID, or customer email",
|
|
2543
|
+
value: searchQuery,
|
|
2544
|
+
onChange: (event) => setSearchQuery(event.target.value),
|
|
2545
|
+
className: "md:max-w-sm"
|
|
2558
2546
|
}
|
|
2559
2547
|
),
|
|
2560
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2561
|
-
|
|
2548
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
|
|
2549
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2550
|
+
"select",
|
|
2551
|
+
{
|
|
2552
|
+
value: createdByFilter,
|
|
2553
|
+
onChange: (event) => setCreatedByFilter(event.target.value),
|
|
2554
|
+
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",
|
|
2555
|
+
children: [
|
|
2556
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All (Created by)" }),
|
|
2557
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "customer", children: "Customer" }),
|
|
2558
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "admin", children: "Admin" })
|
|
2559
|
+
]
|
|
2560
|
+
}
|
|
2561
|
+
),
|
|
2562
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2563
|
+
"select",
|
|
2564
|
+
{
|
|
2565
|
+
value: statusFilter,
|
|
2566
|
+
onChange: (event) => setStatusFilter(event.target.value),
|
|
2567
|
+
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",
|
|
2568
|
+
children: [
|
|
2569
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All Statuses" }),
|
|
2570
|
+
availableStatuses.map((status) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
|
|
2571
|
+
]
|
|
2572
|
+
}
|
|
2573
|
+
)
|
|
2574
|
+
] })
|
|
2575
|
+
] }),
|
|
2576
|
+
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
2577
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
2578
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2579
|
+
ui.Button,
|
|
2562
2580
|
{
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
className: "md:max-w-[100px]",
|
|
2567
|
-
"aria-label": "Filter by currency"
|
|
2581
|
+
variant: "secondary",
|
|
2582
|
+
onClick: () => loadReturns(0, true),
|
|
2583
|
+
children: "Try again"
|
|
2568
2584
|
}
|
|
2569
|
-
)
|
|
2570
|
-
|
|
2571
|
-
|
|
2585
|
+
) })
|
|
2586
|
+
] }) : null,
|
|
2587
|
+
isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading return orders..." }) }) : items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
2588
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No return orders yet" }),
|
|
2589
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Return orders created by customers will appear here." })
|
|
2590
|
+
] }) : /* @__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: [
|
|
2591
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
2592
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Return ID" }),
|
|
2593
|
+
/* @__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" }),
|
|
2594
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Customer" }),
|
|
2595
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
2596
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Refund Amount" }),
|
|
2597
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
2598
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
2599
|
+
] }) }),
|
|
2600
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((returnOrder) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2601
|
+
"tr",
|
|
2572
2602
|
{
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
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-[160px]",
|
|
2576
|
-
"aria-label": "Filter by payment status",
|
|
2603
|
+
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
2604
|
+
onClick: () => navigate(`/returns/${returnOrder.id}`),
|
|
2577
2605
|
children: [
|
|
2578
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
2579
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
2580
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
2581
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
2582
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "canceled", children: "Canceled" }),
|
|
2583
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "authorized", children: "Authorized" }),
|
|
2584
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "captured", children: "Captured" })
|
|
2585
|
-
]
|
|
2586
|
-
}
|
|
2587
|
-
),
|
|
2588
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2589
|
-
ui.Input,
|
|
2590
|
-
{
|
|
2591
|
-
type: "date",
|
|
2592
|
-
placeholder: "From",
|
|
2593
|
-
value: dateFrom,
|
|
2594
|
-
onChange: (e) => setDateFrom(e.target.value),
|
|
2595
|
-
className: "md:max-w-[140px]",
|
|
2596
|
-
"aria-label": "Date from"
|
|
2597
|
-
}
|
|
2598
|
-
),
|
|
2599
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2600
|
-
ui.Input,
|
|
2601
|
-
{
|
|
2602
|
-
type: "date",
|
|
2603
|
-
placeholder: "To",
|
|
2604
|
-
value: dateTo,
|
|
2605
|
-
onChange: (e) => setDateTo(e.target.value),
|
|
2606
|
-
className: "md:max-w-[140px]",
|
|
2607
|
-
"aria-label": "Date to"
|
|
2608
|
-
}
|
|
2609
|
-
),
|
|
2610
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2611
|
-
ui.Input,
|
|
2612
|
-
{
|
|
2613
|
-
placeholder: "Amount min",
|
|
2614
|
-
value: amountMin,
|
|
2615
|
-
onChange: (e) => setAmountMin(e.target.value),
|
|
2616
|
-
type: "number",
|
|
2617
|
-
min: 0,
|
|
2618
|
-
className: "md:max-w-[100px]",
|
|
2619
|
-
"aria-label": "Refund amount minimum"
|
|
2620
|
-
}
|
|
2621
|
-
),
|
|
2622
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2623
|
-
ui.Input,
|
|
2624
|
-
{
|
|
2625
|
-
placeholder: "Amount max",
|
|
2626
|
-
value: amountMax,
|
|
2627
|
-
onChange: (e) => setAmountMax(e.target.value),
|
|
2628
|
-
type: "number",
|
|
2629
|
-
min: 0,
|
|
2630
|
-
className: "md:max-w-[100px]",
|
|
2631
|
-
"aria-label": "Refund amount maximum"
|
|
2632
|
-
}
|
|
2633
|
-
)
|
|
2634
|
-
] }) }),
|
|
2635
|
-
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
2636
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
2637
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => loadRefunds(0, true), children: "Try again" }) })
|
|
2638
|
-
] }) : null,
|
|
2639
|
-
isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading refunds…" }) }) : items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
2640
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No refunds yet" }),
|
|
2641
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Refund records will appear here." })
|
|
2642
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full overflow-x-auto rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full table-fixed divide-y divide-ui-border-base", style: { minWidth: 0 }, children: [
|
|
2643
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
2644
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Refund ID" }),
|
|
2645
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
2646
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Payment ID" }),
|
|
2647
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[8%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Amount" }),
|
|
2648
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[6%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Currency" }),
|
|
2649
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[10%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Provider" }),
|
|
2650
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[10%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Payment Status" }),
|
|
2651
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[14%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Note" }),
|
|
2652
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
2653
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[8%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
2654
|
-
] }) }),
|
|
2655
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((r) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2656
|
-
"tr",
|
|
2657
|
-
{
|
|
2658
|
-
className: "cursor-pointer hover:bg-ui-bg-subtle/60",
|
|
2659
|
-
onClick: () => navigate(`/refunds/${r.refund_id}`),
|
|
2660
|
-
children: [
|
|
2661
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 font-mono text-sm text-ui-fg-base", title: r.refund_id, children: r.refund_id }),
|
|
2662
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 font-medium text-ui-fg-base", title: r.order_id ?? void 0, children: r.order_id ?? "—" }),
|
|
2663
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 font-mono text-sm text-ui-fg-subtle", title: r.payment_id, children: r.payment_id }),
|
|
2664
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", children: displayAmount(r) }),
|
|
2665
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle uppercase", children: r.currency_code || "—" }),
|
|
2666
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", title: r.provider_id || void 0, children: r.provider_id || "—" }),
|
|
2667
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2606
|
+
/* @__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: returnOrder.id }) }) }),
|
|
2607
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.order_id }),
|
|
2608
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.customer_email || returnOrder.order_email || "—" }),
|
|
2609
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2668
2610
|
ui.Badge,
|
|
2669
2611
|
{
|
|
2670
2612
|
size: "2xsmall",
|
|
2671
|
-
className: `uppercase ${getStatusBadgeClass$6(
|
|
2672
|
-
children:
|
|
2613
|
+
className: `uppercase ${getStatusBadgeClass$6(returnOrder.status)}`,
|
|
2614
|
+
children: returnOrder.status.replace(/_/g, " ")
|
|
2673
2615
|
}
|
|
2674
2616
|
) }),
|
|
2675
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "
|
|
2676
|
-
|
|
2617
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
|
|
2618
|
+
const calc = returnOrder.refund;
|
|
2619
|
+
if ((calc == null ? void 0 : calc.is_processed) && calc.final_refund_amount != null) {
|
|
2620
|
+
return formatRefundCurrency(
|
|
2621
|
+
calc.final_refund_amount,
|
|
2622
|
+
calc.currency_code || returnOrder.currency_code
|
|
2623
|
+
);
|
|
2624
|
+
}
|
|
2625
|
+
if (calc) {
|
|
2626
|
+
return "Pending";
|
|
2627
|
+
}
|
|
2628
|
+
if (returnOrder.refund_amount == null) {
|
|
2629
|
+
return "—";
|
|
2630
|
+
}
|
|
2631
|
+
return formatRefundCurrency(
|
|
2632
|
+
Number(returnOrder.refund_amount),
|
|
2633
|
+
returnOrder.currency_code
|
|
2634
|
+
);
|
|
2635
|
+
})() }),
|
|
2636
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(returnOrder.created_at).toLocaleDateString("en-US", {
|
|
2637
|
+
year: "numeric",
|
|
2677
2638
|
month: "short",
|
|
2678
2639
|
day: "numeric",
|
|
2679
2640
|
hour: "numeric",
|
|
2680
2641
|
minute: "2-digit",
|
|
2681
2642
|
hour12: true
|
|
2682
2643
|
}) }),
|
|
2683
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
),
|
|
2696
|
-
r.order_id ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2697
|
-
ui.Button,
|
|
2698
|
-
{
|
|
2699
|
-
variant: "transparent",
|
|
2700
|
-
size: "small",
|
|
2701
|
-
onClick: (e) => {
|
|
2702
|
-
e.stopPropagation();
|
|
2703
|
-
navigate(`/orders/${r.order_id}`);
|
|
2704
|
-
},
|
|
2705
|
-
children: "Order"
|
|
2706
|
-
}
|
|
2707
|
-
) : null
|
|
2708
|
-
] }) })
|
|
2644
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2645
|
+
ui.Button,
|
|
2646
|
+
{
|
|
2647
|
+
variant: "transparent",
|
|
2648
|
+
size: "small",
|
|
2649
|
+
onClick: (e) => {
|
|
2650
|
+
e.stopPropagation();
|
|
2651
|
+
navigate(`/app/orders/${returnOrder.order_id}`);
|
|
2652
|
+
},
|
|
2653
|
+
children: "Go to order"
|
|
2654
|
+
}
|
|
2655
|
+
) })
|
|
2709
2656
|
]
|
|
2710
2657
|
},
|
|
2711
|
-
|
|
2658
|
+
returnOrder.id
|
|
2712
2659
|
)) })
|
|
2713
2660
|
] }) }),
|
|
2714
2661
|
hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2716,643 +2663,171 @@ const RefundsPage = () => {
|
|
|
2716
2663
|
{
|
|
2717
2664
|
variant: "secondary",
|
|
2718
2665
|
isLoading: isFetchingMore,
|
|
2719
|
-
onClick: () =>
|
|
2666
|
+
onClick: () => loadReturns(offset, false),
|
|
2720
2667
|
children: "Load more"
|
|
2721
2668
|
}
|
|
2722
2669
|
) }) : null
|
|
2723
2670
|
] }) });
|
|
2724
2671
|
};
|
|
2725
2672
|
const config$6 = adminSdk.defineRouteConfig({
|
|
2726
|
-
label: "
|
|
2727
|
-
icon: icons.
|
|
2673
|
+
label: "Return Orders",
|
|
2674
|
+
icon: icons.ArrowPath
|
|
2728
2675
|
});
|
|
2729
|
-
const
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2676
|
+
const MASKED_VALUE = "••••••••••••";
|
|
2677
|
+
const SENSITIVE_KEY_PATTERNS = [
|
|
2678
|
+
/password|passwd|passphrase/i,
|
|
2679
|
+
/secret/i,
|
|
2680
|
+
/token/i,
|
|
2681
|
+
/api_?key$/i,
|
|
2682
|
+
/private_?key/i,
|
|
2683
|
+
/access_?key/i,
|
|
2684
|
+
/(^|_)hash(ed)?($|_)/i,
|
|
2685
|
+
/(^|_)salt$/i,
|
|
2686
|
+
/^cvv$|^cvc$|security_code/i,
|
|
2687
|
+
/card_?number/i,
|
|
2688
|
+
/account_?number/i,
|
|
2689
|
+
/credential/i,
|
|
2690
|
+
/authorization/i,
|
|
2691
|
+
/recovery_?code/i,
|
|
2692
|
+
/(^|_)otp($|_)/i,
|
|
2693
|
+
/verification_?code/i,
|
|
2694
|
+
/^code_hash$/i,
|
|
2695
|
+
/webhook_?signature/i
|
|
2696
|
+
];
|
|
2697
|
+
const TABLE_SENSITIVE_KEYS = {
|
|
2698
|
+
otp_verification: /* @__PURE__ */ new Set(["code", "value"]),
|
|
2699
|
+
auth_verification: /* @__PURE__ */ new Set(["code", "value"]),
|
|
2700
|
+
auth_mfa_factor: /* @__PURE__ */ new Set(["value", "config"])
|
|
2736
2701
|
};
|
|
2737
|
-
const
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2702
|
+
const SAFE_KEYS = /* @__PURE__ */ new Set([
|
|
2703
|
+
"token_type",
|
|
2704
|
+
"redacted",
|
|
2705
|
+
"api_key_id",
|
|
2706
|
+
"token_id",
|
|
2707
|
+
"notification_token_id"
|
|
2708
|
+
]);
|
|
2709
|
+
function isSensitiveKey(key) {
|
|
2710
|
+
const normalized = key.trim().toLowerCase();
|
|
2711
|
+
if (SAFE_KEYS.has(normalized)) return false;
|
|
2712
|
+
return SENSITIVE_KEY_PATTERNS.some((pattern) => pattern.test(normalized));
|
|
2713
|
+
}
|
|
2714
|
+
const FULLY_SECRET_TABLES = /* @__PURE__ */ new Set(["auth_mfa_recovery_code", "auth_password_reset_token"]);
|
|
2715
|
+
const ALWAYS_VISIBLE_KEYS = /* @__PURE__ */ new Set(["id", "created_at", "updated_at", "deleted_at", "expires_at", "used_at"]);
|
|
2716
|
+
function maskValue(value, ctx, depth) {
|
|
2717
|
+
var _a;
|
|
2718
|
+
if (Array.isArray(value)) return value.map((item) => maskValue(item, ctx, depth + 1));
|
|
2719
|
+
if (value !== null && typeof value === "object") {
|
|
2720
|
+
const out = {};
|
|
2721
|
+
for (const [key, inner] of Object.entries(value)) {
|
|
2722
|
+
const topLevel = depth === 0;
|
|
2723
|
+
const secret = inner !== null && inner !== void 0 && inner !== "" && (isSensitiveKey(key) || topLevel && ((_a = ctx.tableKeys) == null ? void 0 : _a.has(key.toLowerCase())) === true || topLevel && ctx.maskAll && !ALWAYS_VISIBLE_KEYS.has(key) && !key.endsWith("_id"));
|
|
2724
|
+
if (secret) {
|
|
2725
|
+
ctx.count += 1;
|
|
2726
|
+
out[key] = MASKED_VALUE;
|
|
2727
|
+
} else {
|
|
2728
|
+
out[key] = maskValue(inner, ctx, depth + 1);
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
return out;
|
|
2753
2732
|
}
|
|
2754
|
-
return
|
|
2733
|
+
return value;
|
|
2734
|
+
}
|
|
2735
|
+
function maskSensitiveData(data, tableName) {
|
|
2736
|
+
const ctx = {
|
|
2737
|
+
count: 0,
|
|
2738
|
+
maskAll: tableName ? FULLY_SECRET_TABLES.has(tableName) : false,
|
|
2739
|
+
tableKeys: tableName ? TABLE_SENSITIVE_KEYS[tableName] : void 0
|
|
2740
|
+
};
|
|
2741
|
+
const value = maskValue(data, ctx, 0);
|
|
2742
|
+
return { value, maskedCount: ctx.count };
|
|
2743
|
+
}
|
|
2744
|
+
const AUTO_EXPAND_DEPTH = 1;
|
|
2745
|
+
const LONG_STRING = 200;
|
|
2746
|
+
const JsonViewer = ({ data }) => {
|
|
2747
|
+
const [generation, setGeneration] = react.useState(0);
|
|
2748
|
+
const [expandAll, setExpandAll] = react.useState(null);
|
|
2749
|
+
const setAll = (value) => {
|
|
2750
|
+
setExpandAll(value);
|
|
2751
|
+
setGeneration((g) => g + 1);
|
|
2752
|
+
};
|
|
2753
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
2754
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
2755
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => setAll(true), children: "Expand all" }),
|
|
2756
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => setAll(false), children: "Collapse all" })
|
|
2757
|
+
] }),
|
|
2758
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-[560px] overflow-auto rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 font-mono text-xs leading-5", children: /* @__PURE__ */ jsxRuntime.jsx(JsonNode, { value: data, depth: 0, forceExpand: expandAll }, generation) })
|
|
2759
|
+
] });
|
|
2755
2760
|
};
|
|
2756
|
-
const
|
|
2757
|
-
const
|
|
2758
|
-
const [
|
|
2759
|
-
const
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
const loadReturns = react.useCallback(
|
|
2770
|
-
async (nextOffset, replace = false) => {
|
|
2771
|
-
var _a;
|
|
2772
|
-
try {
|
|
2773
|
-
if (replace) {
|
|
2774
|
-
setIsLoading(true);
|
|
2775
|
-
} else {
|
|
2776
|
-
setIsFetchingMore(true);
|
|
2777
|
-
}
|
|
2778
|
-
setError(null);
|
|
2779
|
-
const params = new URLSearchParams();
|
|
2780
|
-
params.set("limit", String(limit));
|
|
2781
|
-
params.set("offset", String(nextOffset));
|
|
2782
|
-
if (statusFilter !== "all") {
|
|
2783
|
-
params.set("status", statusFilter);
|
|
2784
|
-
}
|
|
2785
|
-
if (debouncedSearchQuery.trim()) {
|
|
2786
|
-
params.set("q", debouncedSearchQuery.trim());
|
|
2787
|
-
}
|
|
2788
|
-
if (createdByFilter !== "all") {
|
|
2789
|
-
params.set("created_by", createdByFilter);
|
|
2790
|
-
}
|
|
2791
|
-
params.set("order", "created_at");
|
|
2792
|
-
const response = await fetch(
|
|
2793
|
-
`/admin/return?${params.toString()}`,
|
|
2794
|
-
{ credentials: "include" }
|
|
2795
|
-
);
|
|
2796
|
-
if (!response.ok) {
|
|
2797
|
-
const message = await response.text();
|
|
2798
|
-
throw new Error(message || "Unable to load return orders");
|
|
2799
|
-
}
|
|
2800
|
-
const payload = await response.json();
|
|
2801
|
-
setCount(payload.count ?? 0);
|
|
2802
|
-
setOffset(nextOffset + (((_a = payload.returns) == null ? void 0 : _a.length) ?? 0));
|
|
2803
|
-
setItems(
|
|
2804
|
-
(prev) => replace ? payload.returns ?? [] : [...prev, ...payload.returns ?? []]
|
|
2805
|
-
);
|
|
2806
|
-
} catch (loadError) {
|
|
2807
|
-
const message = loadError instanceof Error ? loadError.message : "Unable to load return orders";
|
|
2808
|
-
setError(message);
|
|
2809
|
-
} finally {
|
|
2810
|
-
setIsLoading(false);
|
|
2811
|
-
setIsFetchingMore(false);
|
|
2812
|
-
}
|
|
2813
|
-
},
|
|
2814
|
-
[statusFilter, createdByFilter, debouncedSearchQuery]
|
|
2815
|
-
);
|
|
2816
|
-
react.useEffect(() => {
|
|
2817
|
-
void loadReturns(0, true);
|
|
2818
|
-
}, [statusFilter, createdByFilter, debouncedSearchQuery, loadReturns]);
|
|
2819
|
-
const hasMore = react.useMemo(() => offset < count, [offset, count]);
|
|
2820
|
-
const availableStatuses = react.useMemo(() => {
|
|
2821
|
-
const statuses = /* @__PURE__ */ new Set();
|
|
2822
|
-
items.forEach((item) => statuses.add(item.status));
|
|
2823
|
-
return Array.from(statuses).sort();
|
|
2824
|
-
}, [items]);
|
|
2825
|
-
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: [
|
|
2826
|
-
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
2827
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
2828
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Return Orders" }),
|
|
2829
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "View and manage all customer return orders" })
|
|
2830
|
-
] }),
|
|
2831
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => loadReturns(0, true), children: "Refresh" })
|
|
2832
|
-
] }),
|
|
2833
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
2834
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2835
|
-
ui.Input,
|
|
2836
|
-
{
|
|
2837
|
-
placeholder: "Search by return ID, order ID, or customer email",
|
|
2838
|
-
value: searchQuery,
|
|
2839
|
-
onChange: (event) => setSearchQuery(event.target.value),
|
|
2840
|
-
className: "md:max-w-sm"
|
|
2841
|
-
}
|
|
2842
|
-
),
|
|
2843
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
|
|
2844
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2845
|
-
"select",
|
|
2846
|
-
{
|
|
2847
|
-
value: createdByFilter,
|
|
2848
|
-
onChange: (event) => setCreatedByFilter(event.target.value),
|
|
2849
|
-
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",
|
|
2850
|
-
children: [
|
|
2851
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All (Created by)" }),
|
|
2852
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "customer", children: "Customer" }),
|
|
2853
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "admin", children: "Admin" })
|
|
2854
|
-
]
|
|
2855
|
-
}
|
|
2856
|
-
),
|
|
2857
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2858
|
-
"select",
|
|
2859
|
-
{
|
|
2860
|
-
value: statusFilter,
|
|
2861
|
-
onChange: (event) => setStatusFilter(event.target.value),
|
|
2862
|
-
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",
|
|
2863
|
-
children: [
|
|
2864
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All Statuses" }),
|
|
2865
|
-
availableStatuses.map((status) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
|
|
2866
|
-
]
|
|
2867
|
-
}
|
|
2868
|
-
)
|
|
2761
|
+
const JsonNode = ({ name, value, depth, forceExpand }) => {
|
|
2762
|
+
const isContainer = value !== null && typeof value === "object";
|
|
2763
|
+
const [open, setOpen] = react.useState(forceExpand ?? depth < AUTO_EXPAND_DEPTH);
|
|
2764
|
+
const label = name !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-fg-subtle", children: [
|
|
2765
|
+
name,
|
|
2766
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: ": " })
|
|
2767
|
+
] }) : null;
|
|
2768
|
+
if (!isContainer) {
|
|
2769
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-start", style: { paddingLeft: depth ? 16 : 0 }, children: [
|
|
2770
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-4 shrink-0" }),
|
|
2771
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 break-words [overflow-wrap:anywhere]", children: [
|
|
2772
|
+
label,
|
|
2773
|
+
/* @__PURE__ */ jsxRuntime.jsx(Primitive, { value })
|
|
2869
2774
|
] })
|
|
2870
|
-
] })
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
children: "Try again"
|
|
2879
|
-
}
|
|
2880
|
-
) })
|
|
2881
|
-
] }) : null,
|
|
2882
|
-
isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading return orders..." }) }) : items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
2883
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No return orders yet" }),
|
|
2884
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Return orders created by customers will appear here." })
|
|
2885
|
-
] }) : /* @__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: [
|
|
2886
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
2887
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Return ID" }),
|
|
2888
|
-
/* @__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" }),
|
|
2889
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Customer" }),
|
|
2890
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
2891
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Refund Amount" }),
|
|
2892
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
2893
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
2894
|
-
] }) }),
|
|
2895
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((returnOrder) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2896
|
-
"tr",
|
|
2897
|
-
{
|
|
2898
|
-
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
2899
|
-
onClick: () => navigate(`/returns/${returnOrder.id}`),
|
|
2900
|
-
children: [
|
|
2901
|
-
/* @__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: returnOrder.id }) }) }),
|
|
2902
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.order_id }),
|
|
2903
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.customer_email || returnOrder.order_email || "—" }),
|
|
2904
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2905
|
-
ui.Badge,
|
|
2906
|
-
{
|
|
2907
|
-
size: "2xsmall",
|
|
2908
|
-
className: `uppercase ${getStatusBadgeClass$5(returnOrder.status)}`,
|
|
2909
|
-
children: returnOrder.status.replace(/_/g, " ")
|
|
2910
|
-
}
|
|
2911
|
-
) }),
|
|
2912
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
|
|
2913
|
-
const calc = returnOrder.refund;
|
|
2914
|
-
if ((calc == null ? void 0 : calc.is_processed) && calc.final_refund_amount != null) {
|
|
2915
|
-
return formatRefundCurrency(
|
|
2916
|
-
calc.final_refund_amount,
|
|
2917
|
-
calc.currency_code || returnOrder.currency_code
|
|
2918
|
-
);
|
|
2919
|
-
}
|
|
2920
|
-
if (calc) {
|
|
2921
|
-
return "Pending";
|
|
2922
|
-
}
|
|
2923
|
-
if (returnOrder.refund_amount == null) {
|
|
2924
|
-
return "—";
|
|
2925
|
-
}
|
|
2926
|
-
return formatRefundCurrency(
|
|
2927
|
-
Number(returnOrder.refund_amount),
|
|
2928
|
-
returnOrder.currency_code
|
|
2929
|
-
);
|
|
2930
|
-
})() }),
|
|
2931
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(returnOrder.created_at).toLocaleDateString("en-US", {
|
|
2932
|
-
year: "numeric",
|
|
2933
|
-
month: "short",
|
|
2934
|
-
day: "numeric",
|
|
2935
|
-
hour: "numeric",
|
|
2936
|
-
minute: "2-digit",
|
|
2937
|
-
hour12: true
|
|
2938
|
-
}) }),
|
|
2939
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2940
|
-
ui.Button,
|
|
2941
|
-
{
|
|
2942
|
-
variant: "transparent",
|
|
2943
|
-
size: "small",
|
|
2944
|
-
onClick: (e) => {
|
|
2945
|
-
e.stopPropagation();
|
|
2946
|
-
navigate(`/app/orders/${returnOrder.order_id}`);
|
|
2947
|
-
},
|
|
2948
|
-
children: "Go to order"
|
|
2949
|
-
}
|
|
2950
|
-
) })
|
|
2951
|
-
]
|
|
2952
|
-
},
|
|
2953
|
-
returnOrder.id
|
|
2954
|
-
)) })
|
|
2955
|
-
] }) }),
|
|
2956
|
-
hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2957
|
-
ui.Button,
|
|
2775
|
+
] });
|
|
2776
|
+
}
|
|
2777
|
+
const entries = Array.isArray(value) ? value.map((v, i) => [String(i), v]) : Object.entries(value);
|
|
2778
|
+
const [openBracket, closeBracket] = Array.isArray(value) ? ["[", "]"] : ["{", "}"];
|
|
2779
|
+
const summary = Array.isArray(value) ? `${entries.length} items` : `${entries.length} keys`;
|
|
2780
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { paddingLeft: depth ? 16 : 0 }, children: [
|
|
2781
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2782
|
+
"button",
|
|
2958
2783
|
{
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2784
|
+
type: "button",
|
|
2785
|
+
onClick: () => setOpen((o) => !o),
|
|
2786
|
+
className: "flex items-start text-left hover:bg-ui-bg-base-hover",
|
|
2787
|
+
"aria-expanded": open,
|
|
2788
|
+
children: [
|
|
2789
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex w-4 shrink-0 items-center pt-0.5 text-ui-fg-muted", children: entries.length ? open ? /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDownMini, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRightMini, {}) : null }),
|
|
2790
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
2791
|
+
label,
|
|
2792
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: openBracket }),
|
|
2793
|
+
!open || entries.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2794
|
+
entries.length ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-1 italic text-ui-fg-muted", children: summary }) : null,
|
|
2795
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: closeBracket })
|
|
2796
|
+
] }) : null
|
|
2797
|
+
] })
|
|
2798
|
+
]
|
|
2963
2799
|
}
|
|
2964
|
-
)
|
|
2965
|
-
|
|
2966
|
-
}
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
});
|
|
2971
|
-
const useDebounce = (value, delay) => {
|
|
2972
|
-
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
2973
|
-
react.useEffect(() => {
|
|
2974
|
-
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
2975
|
-
return () => clearTimeout(handler);
|
|
2976
|
-
}, [value, delay]);
|
|
2977
|
-
return debouncedValue;
|
|
2800
|
+
),
|
|
2801
|
+
open && entries.length ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2802
|
+
entries.map(([key, child]) => /* @__PURE__ */ jsxRuntime.jsx(JsonNode, { name: key, value: child, depth: depth + 1, forceExpand }, key)),
|
|
2803
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { paddingLeft: 16 }, className: "text-ui-fg-muted", children: closeBracket })
|
|
2804
|
+
] }) : null
|
|
2805
|
+
] });
|
|
2978
2806
|
};
|
|
2979
|
-
const
|
|
2980
|
-
const
|
|
2981
|
-
if (
|
|
2982
|
-
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
2983
|
-
}
|
|
2984
|
-
if (statusLower === "approved") {
|
|
2985
|
-
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
2986
|
-
}
|
|
2987
|
-
if (statusLower === "rejected") {
|
|
2988
|
-
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
2989
|
-
}
|
|
2990
|
-
if (statusLower === "completed") {
|
|
2991
|
-
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
2992
|
-
}
|
|
2993
|
-
if (statusLower === "cancelled") {
|
|
2994
|
-
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
2807
|
+
const Primitive = ({ value }) => {
|
|
2808
|
+
const [showFull, setShowFull] = react.useState(false);
|
|
2809
|
+
if (value === MASKED_VALUE) {
|
|
2810
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded bg-ui-tag-orange-bg px-1 text-ui-tag-orange-text", title: "Hidden for security", children: MASKED_VALUE });
|
|
2995
2811
|
}
|
|
2996
|
-
return "
|
|
2997
|
-
};
|
|
2998
|
-
|
|
2999
|
-
const
|
|
3000
|
-
const
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
const [error, setError] = react.useState(null);
|
|
3008
|
-
const [offset, setOffset] = react.useState(0);
|
|
3009
|
-
const [count, setCount] = react.useState(0);
|
|
3010
|
-
const limit = 50;
|
|
3011
|
-
const loadSwaps = react.useCallback(
|
|
3012
|
-
async (nextOffset, replace = false) => {
|
|
3013
|
-
var _a;
|
|
3014
|
-
try {
|
|
3015
|
-
if (replace) {
|
|
3016
|
-
setIsLoading(true);
|
|
3017
|
-
} else {
|
|
3018
|
-
setIsFetchingMore(true);
|
|
3019
|
-
}
|
|
3020
|
-
setError(null);
|
|
3021
|
-
const params = new URLSearchParams();
|
|
3022
|
-
params.set("limit", String(limit));
|
|
3023
|
-
params.set("offset", String(nextOffset));
|
|
3024
|
-
if (statusFilter !== "all") {
|
|
3025
|
-
params.set("status", statusFilter);
|
|
3026
|
-
}
|
|
3027
|
-
if (debouncedSearchQuery.trim()) {
|
|
3028
|
-
params.set("order_id", debouncedSearchQuery.trim());
|
|
3029
|
-
}
|
|
3030
|
-
if (createdByFilter !== "all") {
|
|
3031
|
-
params.set("created_by", createdByFilter);
|
|
3032
|
-
}
|
|
3033
|
-
const response = await fetch(
|
|
3034
|
-
`/admin/swaps?${params.toString()}`,
|
|
3035
|
-
{ credentials: "include" }
|
|
3036
|
-
);
|
|
3037
|
-
if (!response.ok) {
|
|
3038
|
-
const message = await response.text();
|
|
3039
|
-
throw new Error(message || "Unable to load swaps");
|
|
3040
|
-
}
|
|
3041
|
-
const payload = await response.json();
|
|
3042
|
-
setCount(payload.count ?? 0);
|
|
3043
|
-
setOffset(nextOffset + (((_a = payload.swaps) == null ? void 0 : _a.length) ?? 0));
|
|
3044
|
-
setItems(
|
|
3045
|
-
(prev) => replace ? payload.swaps ?? [] : [...prev, ...payload.swaps ?? []]
|
|
3046
|
-
);
|
|
3047
|
-
} catch (loadError) {
|
|
3048
|
-
const message = loadError instanceof Error ? loadError.message : "Unable to load swaps";
|
|
3049
|
-
setError(message);
|
|
3050
|
-
} finally {
|
|
3051
|
-
setIsLoading(false);
|
|
3052
|
-
setIsFetchingMore(false);
|
|
3053
|
-
}
|
|
3054
|
-
},
|
|
3055
|
-
[statusFilter, createdByFilter, debouncedSearchQuery]
|
|
3056
|
-
);
|
|
3057
|
-
react.useEffect(() => {
|
|
3058
|
-
void loadSwaps(0, true);
|
|
3059
|
-
}, [statusFilter, createdByFilter, debouncedSearchQuery, loadSwaps]);
|
|
3060
|
-
const hasMore = react.useMemo(() => offset < count, [offset, count]);
|
|
3061
|
-
const availableStatuses = react.useMemo(() => {
|
|
3062
|
-
const statuses = /* @__PURE__ */ new Set();
|
|
3063
|
-
items.forEach((item) => statuses.add(item.status));
|
|
3064
|
-
return Array.from(statuses).sort();
|
|
3065
|
-
}, [items]);
|
|
3066
|
-
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: [
|
|
3067
|
-
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
3068
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3069
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Exchanges" }),
|
|
3070
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "View and manage all customer exchange requests" })
|
|
3071
|
-
] }),
|
|
3072
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => loadSwaps(0, true), children: "Refresh" })
|
|
3073
|
-
] }),
|
|
3074
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
3075
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3076
|
-
ui.Input,
|
|
3077
|
-
{
|
|
3078
|
-
placeholder: "Search by swap ID or order ID",
|
|
3079
|
-
value: searchQuery,
|
|
3080
|
-
onChange: (event) => setSearchQuery(event.target.value),
|
|
3081
|
-
className: "md:max-w-sm"
|
|
3082
|
-
}
|
|
3083
|
-
),
|
|
3084
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
|
|
3085
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3086
|
-
"select",
|
|
3087
|
-
{
|
|
3088
|
-
value: createdByFilter,
|
|
3089
|
-
onChange: (event) => setCreatedByFilter(event.target.value),
|
|
3090
|
-
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",
|
|
3091
|
-
children: [
|
|
3092
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All (Created by)" }),
|
|
3093
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "customer", children: "Customer" }),
|
|
3094
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "admin", children: "Admin" })
|
|
3095
|
-
]
|
|
3096
|
-
}
|
|
3097
|
-
),
|
|
3098
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3099
|
-
"select",
|
|
3100
|
-
{
|
|
3101
|
-
value: statusFilter,
|
|
3102
|
-
onChange: (event) => setStatusFilter(event.target.value),
|
|
3103
|
-
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",
|
|
3104
|
-
children: [
|
|
3105
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All Statuses" }),
|
|
3106
|
-
availableStatuses.map((status) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
|
|
3107
|
-
]
|
|
3108
|
-
}
|
|
3109
|
-
)
|
|
3110
|
-
] })
|
|
3111
|
-
] }),
|
|
3112
|
-
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
3113
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
3114
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3115
|
-
ui.Button,
|
|
3116
|
-
{
|
|
3117
|
-
variant: "secondary",
|
|
3118
|
-
onClick: () => loadSwaps(0, true),
|
|
3119
|
-
children: "Try again"
|
|
3120
|
-
}
|
|
3121
|
-
) })
|
|
3122
|
-
] }) : null,
|
|
3123
|
-
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: [
|
|
3124
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No exchanges yet" }),
|
|
3125
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Exchange requests created by customers will appear here." })
|
|
3126
|
-
] }) : /* @__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: [
|
|
3127
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
3128
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Exchange ID" }),
|
|
3129
|
-
/* @__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" }),
|
|
3130
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
3131
|
-
/* @__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" }),
|
|
3132
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
3133
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
3134
|
-
] }) }),
|
|
3135
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((swap) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3136
|
-
"tr",
|
|
3137
|
-
{
|
|
3138
|
-
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
3139
|
-
onClick: () => navigate(`/swaps/${swap.id}`),
|
|
3140
|
-
children: [
|
|
3141
|
-
/* @__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 }) }) }),
|
|
3142
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: swap.order_id }),
|
|
3143
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3144
|
-
ui.Badge,
|
|
3145
|
-
{
|
|
3146
|
-
size: "2xsmall",
|
|
3147
|
-
className: `uppercase ${getStatusBadgeClass$4(swap.status)}`,
|
|
3148
|
-
children: swap.status.replace(/_/g, " ")
|
|
3149
|
-
}
|
|
3150
|
-
) }),
|
|
3151
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
|
|
3152
|
-
const amount = swap.difference_due;
|
|
3153
|
-
if (amount == null || amount === void 0) {
|
|
3154
|
-
return "—";
|
|
3155
|
-
}
|
|
3156
|
-
const displayAmount = Number(amount) / 100;
|
|
3157
|
-
const currency = swap.currency_code || "$";
|
|
3158
|
-
const sign = displayAmount >= 0 ? "+" : "";
|
|
3159
|
-
return `${sign}${currency}${displayAmount.toFixed(2)}`;
|
|
3160
|
-
})() }),
|
|
3161
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(swap.created_at).toLocaleDateString("en-US", {
|
|
3162
|
-
year: "numeric",
|
|
3163
|
-
month: "short",
|
|
3164
|
-
day: "numeric",
|
|
3165
|
-
hour: "numeric",
|
|
3166
|
-
minute: "2-digit",
|
|
3167
|
-
hour12: true
|
|
3168
|
-
}) }),
|
|
3169
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3170
|
-
ui.Button,
|
|
3171
|
-
{
|
|
3172
|
-
variant: "transparent",
|
|
3173
|
-
size: "small",
|
|
3174
|
-
onClick: (e) => {
|
|
3175
|
-
e.stopPropagation();
|
|
3176
|
-
navigate(`/app/orders/${swap.order_id}`);
|
|
3177
|
-
},
|
|
3178
|
-
children: "Go to order"
|
|
3179
|
-
}
|
|
3180
|
-
) })
|
|
3181
|
-
]
|
|
3182
|
-
},
|
|
3183
|
-
swap.id
|
|
3184
|
-
)) })
|
|
3185
|
-
] }) }),
|
|
3186
|
-
hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3187
|
-
ui.Button,
|
|
2812
|
+
if (value === null || value === void 0) return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: "null" });
|
|
2813
|
+
if (typeof value === "boolean") return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-tag-purple-text", children: String(value) });
|
|
2814
|
+
if (typeof value === "number") return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-tag-blue-text", children: value });
|
|
2815
|
+
const text = String(value);
|
|
2816
|
+
const truncated = !showFull && text.length > LONG_STRING;
|
|
2817
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: ui.clx("text-ui-tag-green-text"), children: [
|
|
2818
|
+
'"',
|
|
2819
|
+
truncated ? `${text.slice(0, LONG_STRING)}…` : text,
|
|
2820
|
+
'"',
|
|
2821
|
+
text.length > LONG_STRING ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2822
|
+
"button",
|
|
3188
2823
|
{
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
children: "
|
|
2824
|
+
type: "button",
|
|
2825
|
+
onClick: () => setShowFull((s2) => !s2),
|
|
2826
|
+
className: "ml-1 font-sans text-ui-fg-interactive hover:underline",
|
|
2827
|
+
children: showFull ? "show less" : `show all (${text.length} chars)`
|
|
3193
2828
|
}
|
|
3194
|
-
)
|
|
3195
|
-
] })
|
|
3196
|
-
};
|
|
3197
|
-
const config$4 = adminSdk.defineRouteConfig({
|
|
3198
|
-
label: "Exchanges",
|
|
3199
|
-
icon: icons.ArrowPath
|
|
3200
|
-
});
|
|
3201
|
-
const MASKED_VALUE = "••••••••••••";
|
|
3202
|
-
const SENSITIVE_KEY_PATTERNS = [
|
|
3203
|
-
/password|passwd|passphrase/i,
|
|
3204
|
-
/secret/i,
|
|
3205
|
-
/token/i,
|
|
3206
|
-
/api_?key$/i,
|
|
3207
|
-
/private_?key/i,
|
|
3208
|
-
/access_?key/i,
|
|
3209
|
-
/(^|_)hash(ed)?($|_)/i,
|
|
3210
|
-
/(^|_)salt$/i,
|
|
3211
|
-
/^cvv$|^cvc$|security_code/i,
|
|
3212
|
-
/card_?number/i,
|
|
3213
|
-
/account_?number/i,
|
|
3214
|
-
/credential/i,
|
|
3215
|
-
/authorization/i,
|
|
3216
|
-
/recovery_?code/i,
|
|
3217
|
-
/(^|_)otp($|_)/i,
|
|
3218
|
-
/verification_?code/i,
|
|
3219
|
-
/^code_hash$/i,
|
|
3220
|
-
/webhook_?signature/i
|
|
3221
|
-
];
|
|
3222
|
-
const TABLE_SENSITIVE_KEYS = {
|
|
3223
|
-
otp_verification: /* @__PURE__ */ new Set(["code", "value"]),
|
|
3224
|
-
auth_verification: /* @__PURE__ */ new Set(["code", "value"]),
|
|
3225
|
-
auth_mfa_factor: /* @__PURE__ */ new Set(["value", "config"])
|
|
3226
|
-
};
|
|
3227
|
-
const SAFE_KEYS = /* @__PURE__ */ new Set([
|
|
3228
|
-
"token_type",
|
|
3229
|
-
"redacted",
|
|
3230
|
-
"api_key_id",
|
|
3231
|
-
"token_id",
|
|
3232
|
-
"notification_token_id"
|
|
3233
|
-
]);
|
|
3234
|
-
function isSensitiveKey(key) {
|
|
3235
|
-
const normalized = key.trim().toLowerCase();
|
|
3236
|
-
if (SAFE_KEYS.has(normalized)) return false;
|
|
3237
|
-
return SENSITIVE_KEY_PATTERNS.some((pattern) => pattern.test(normalized));
|
|
3238
|
-
}
|
|
3239
|
-
const FULLY_SECRET_TABLES = /* @__PURE__ */ new Set(["auth_mfa_recovery_code", "auth_password_reset_token"]);
|
|
3240
|
-
const ALWAYS_VISIBLE_KEYS = /* @__PURE__ */ new Set(["id", "created_at", "updated_at", "deleted_at", "expires_at", "used_at"]);
|
|
3241
|
-
function maskValue(value, ctx, depth) {
|
|
3242
|
-
var _a;
|
|
3243
|
-
if (Array.isArray(value)) return value.map((item) => maskValue(item, ctx, depth + 1));
|
|
3244
|
-
if (value !== null && typeof value === "object") {
|
|
3245
|
-
const out = {};
|
|
3246
|
-
for (const [key, inner] of Object.entries(value)) {
|
|
3247
|
-
const topLevel = depth === 0;
|
|
3248
|
-
const secret = inner !== null && inner !== void 0 && inner !== "" && (isSensitiveKey(key) || topLevel && ((_a = ctx.tableKeys) == null ? void 0 : _a.has(key.toLowerCase())) === true || topLevel && ctx.maskAll && !ALWAYS_VISIBLE_KEYS.has(key) && !key.endsWith("_id"));
|
|
3249
|
-
if (secret) {
|
|
3250
|
-
ctx.count += 1;
|
|
3251
|
-
out[key] = MASKED_VALUE;
|
|
3252
|
-
} else {
|
|
3253
|
-
out[key] = maskValue(inner, ctx, depth + 1);
|
|
3254
|
-
}
|
|
3255
|
-
}
|
|
3256
|
-
return out;
|
|
3257
|
-
}
|
|
3258
|
-
return value;
|
|
3259
|
-
}
|
|
3260
|
-
function maskSensitiveData(data, tableName) {
|
|
3261
|
-
const ctx = {
|
|
3262
|
-
count: 0,
|
|
3263
|
-
maskAll: tableName ? FULLY_SECRET_TABLES.has(tableName) : false,
|
|
3264
|
-
tableKeys: tableName ? TABLE_SENSITIVE_KEYS[tableName] : void 0
|
|
3265
|
-
};
|
|
3266
|
-
const value = maskValue(data, ctx, 0);
|
|
3267
|
-
return { value, maskedCount: ctx.count };
|
|
3268
|
-
}
|
|
3269
|
-
const AUTO_EXPAND_DEPTH = 1;
|
|
3270
|
-
const LONG_STRING = 200;
|
|
3271
|
-
const JsonViewer = ({ data }) => {
|
|
3272
|
-
const [generation, setGeneration] = react.useState(0);
|
|
3273
|
-
const [expandAll, setExpandAll] = react.useState(null);
|
|
3274
|
-
const setAll = (value) => {
|
|
3275
|
-
setExpandAll(value);
|
|
3276
|
-
setGeneration((g) => g + 1);
|
|
3277
|
-
};
|
|
3278
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
3279
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
3280
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => setAll(true), children: "Expand all" }),
|
|
3281
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => setAll(false), children: "Collapse all" })
|
|
3282
|
-
] }),
|
|
3283
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-[560px] overflow-auto rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 font-mono text-xs leading-5", children: /* @__PURE__ */ jsxRuntime.jsx(JsonNode, { value: data, depth: 0, forceExpand: expandAll }, generation) })
|
|
3284
|
-
] });
|
|
3285
|
-
};
|
|
3286
|
-
const JsonNode = ({ name, value, depth, forceExpand }) => {
|
|
3287
|
-
const isContainer = value !== null && typeof value === "object";
|
|
3288
|
-
const [open, setOpen] = react.useState(forceExpand ?? depth < AUTO_EXPAND_DEPTH);
|
|
3289
|
-
const label = name !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-fg-subtle", children: [
|
|
3290
|
-
name,
|
|
3291
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: ": " })
|
|
3292
|
-
] }) : null;
|
|
3293
|
-
if (!isContainer) {
|
|
3294
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-start", style: { paddingLeft: depth ? 16 : 0 }, children: [
|
|
3295
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-4 shrink-0" }),
|
|
3296
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 break-words [overflow-wrap:anywhere]", children: [
|
|
3297
|
-
label,
|
|
3298
|
-
/* @__PURE__ */ jsxRuntime.jsx(Primitive, { value })
|
|
3299
|
-
] })
|
|
3300
|
-
] });
|
|
3301
|
-
}
|
|
3302
|
-
const entries = Array.isArray(value) ? value.map((v, i) => [String(i), v]) : Object.entries(value);
|
|
3303
|
-
const [openBracket, closeBracket] = Array.isArray(value) ? ["[", "]"] : ["{", "}"];
|
|
3304
|
-
const summary = Array.isArray(value) ? `${entries.length} items` : `${entries.length} keys`;
|
|
3305
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { paddingLeft: depth ? 16 : 0 }, children: [
|
|
3306
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3307
|
-
"button",
|
|
3308
|
-
{
|
|
3309
|
-
type: "button",
|
|
3310
|
-
onClick: () => setOpen((o) => !o),
|
|
3311
|
-
className: "flex items-start text-left hover:bg-ui-bg-base-hover",
|
|
3312
|
-
"aria-expanded": open,
|
|
3313
|
-
children: [
|
|
3314
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex w-4 shrink-0 items-center pt-0.5 text-ui-fg-muted", children: entries.length ? open ? /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDownMini, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRightMini, {}) : null }),
|
|
3315
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
3316
|
-
label,
|
|
3317
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: openBracket }),
|
|
3318
|
-
!open || entries.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3319
|
-
entries.length ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-1 italic text-ui-fg-muted", children: summary }) : null,
|
|
3320
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: closeBracket })
|
|
3321
|
-
] }) : null
|
|
3322
|
-
] })
|
|
3323
|
-
]
|
|
3324
|
-
}
|
|
3325
|
-
),
|
|
3326
|
-
open && entries.length ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3327
|
-
entries.map(([key, child]) => /* @__PURE__ */ jsxRuntime.jsx(JsonNode, { name: key, value: child, depth: depth + 1, forceExpand }, key)),
|
|
3328
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { paddingLeft: 16 }, className: "text-ui-fg-muted", children: closeBracket })
|
|
3329
|
-
] }) : null
|
|
3330
|
-
] });
|
|
3331
|
-
};
|
|
3332
|
-
const Primitive = ({ value }) => {
|
|
3333
|
-
const [showFull, setShowFull] = react.useState(false);
|
|
3334
|
-
if (value === MASKED_VALUE) {
|
|
3335
|
-
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded bg-ui-tag-orange-bg px-1 text-ui-tag-orange-text", title: "Hidden for security", children: MASKED_VALUE });
|
|
3336
|
-
}
|
|
3337
|
-
if (value === null || value === void 0) return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: "null" });
|
|
3338
|
-
if (typeof value === "boolean") return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-tag-purple-text", children: String(value) });
|
|
3339
|
-
if (typeof value === "number") return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-tag-blue-text", children: value });
|
|
3340
|
-
const text = String(value);
|
|
3341
|
-
const truncated = !showFull && text.length > LONG_STRING;
|
|
3342
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: ui.clx("text-ui-tag-green-text"), children: [
|
|
3343
|
-
'"',
|
|
3344
|
-
truncated ? `${text.slice(0, LONG_STRING)}…` : text,
|
|
3345
|
-
'"',
|
|
3346
|
-
text.length > LONG_STRING ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3347
|
-
"button",
|
|
3348
|
-
{
|
|
3349
|
-
type: "button",
|
|
3350
|
-
onClick: () => setShowFull((s2) => !s2),
|
|
3351
|
-
className: "ml-1 font-sans text-ui-fg-interactive hover:underline",
|
|
3352
|
-
children: showFull ? "show less" : `show all (${text.length} chars)`
|
|
3353
|
-
}
|
|
3354
|
-
) : null
|
|
3355
|
-
] });
|
|
2829
|
+
) : null
|
|
2830
|
+
] });
|
|
3356
2831
|
};
|
|
3357
2832
|
const GUIDANCE = {
|
|
3358
2833
|
orders: {
|
|
@@ -3942,6 +3417,531 @@ const DetailError = ({
|
|
|
3942
3417
|
] })
|
|
3943
3418
|
] });
|
|
3944
3419
|
adminSdk.defineRouteConfig({});
|
|
3420
|
+
const useDebounce$1 = (value, delay) => {
|
|
3421
|
+
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
3422
|
+
react.useEffect(() => {
|
|
3423
|
+
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
3424
|
+
return () => clearTimeout(handler);
|
|
3425
|
+
}, [value, delay]);
|
|
3426
|
+
return debouncedValue;
|
|
3427
|
+
};
|
|
3428
|
+
const getStatusBadgeClass$5 = (status) => {
|
|
3429
|
+
const statusLower = status.toLowerCase();
|
|
3430
|
+
if (statusLower === "requested") {
|
|
3431
|
+
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
3432
|
+
}
|
|
3433
|
+
if (statusLower === "approved") {
|
|
3434
|
+
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
3435
|
+
}
|
|
3436
|
+
if (statusLower === "rejected") {
|
|
3437
|
+
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
3438
|
+
}
|
|
3439
|
+
if (statusLower === "completed") {
|
|
3440
|
+
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
3441
|
+
}
|
|
3442
|
+
if (statusLower === "cancelled") {
|
|
3443
|
+
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
3444
|
+
}
|
|
3445
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
3446
|
+
};
|
|
3447
|
+
const SwapsPage = () => {
|
|
3448
|
+
const navigate = reactRouterDom.useNavigate();
|
|
3449
|
+
const [items, setItems] = react.useState([]);
|
|
3450
|
+
const [statusFilter, setStatusFilter] = react.useState("all");
|
|
3451
|
+
const [createdByFilter, setCreatedByFilter] = react.useState("all");
|
|
3452
|
+
const [searchQuery, setSearchQuery] = react.useState("");
|
|
3453
|
+
const debouncedSearchQuery = useDebounce$1(searchQuery, 300);
|
|
3454
|
+
const [isLoading, setIsLoading] = react.useState(true);
|
|
3455
|
+
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
3456
|
+
const [error, setError] = react.useState(null);
|
|
3457
|
+
const [offset, setOffset] = react.useState(0);
|
|
3458
|
+
const [count, setCount] = react.useState(0);
|
|
3459
|
+
const limit = 50;
|
|
3460
|
+
const loadSwaps = react.useCallback(
|
|
3461
|
+
async (nextOffset, replace = false) => {
|
|
3462
|
+
var _a;
|
|
3463
|
+
try {
|
|
3464
|
+
if (replace) {
|
|
3465
|
+
setIsLoading(true);
|
|
3466
|
+
} else {
|
|
3467
|
+
setIsFetchingMore(true);
|
|
3468
|
+
}
|
|
3469
|
+
setError(null);
|
|
3470
|
+
const params = new URLSearchParams();
|
|
3471
|
+
params.set("limit", String(limit));
|
|
3472
|
+
params.set("offset", String(nextOffset));
|
|
3473
|
+
if (statusFilter !== "all") {
|
|
3474
|
+
params.set("status", statusFilter);
|
|
3475
|
+
}
|
|
3476
|
+
if (debouncedSearchQuery.trim()) {
|
|
3477
|
+
params.set("order_id", debouncedSearchQuery.trim());
|
|
3478
|
+
}
|
|
3479
|
+
if (createdByFilter !== "all") {
|
|
3480
|
+
params.set("created_by", createdByFilter);
|
|
3481
|
+
}
|
|
3482
|
+
const response = await fetch(
|
|
3483
|
+
`/admin/swaps?${params.toString()}`,
|
|
3484
|
+
{ credentials: "include" }
|
|
3485
|
+
);
|
|
3486
|
+
if (!response.ok) {
|
|
3487
|
+
const message = await response.text();
|
|
3488
|
+
throw new Error(message || "Unable to load swaps");
|
|
3489
|
+
}
|
|
3490
|
+
const payload = await response.json();
|
|
3491
|
+
setCount(payload.count ?? 0);
|
|
3492
|
+
setOffset(nextOffset + (((_a = payload.swaps) == null ? void 0 : _a.length) ?? 0));
|
|
3493
|
+
setItems(
|
|
3494
|
+
(prev) => replace ? payload.swaps ?? [] : [...prev, ...payload.swaps ?? []]
|
|
3495
|
+
);
|
|
3496
|
+
} catch (loadError) {
|
|
3497
|
+
const message = loadError instanceof Error ? loadError.message : "Unable to load swaps";
|
|
3498
|
+
setError(message);
|
|
3499
|
+
} finally {
|
|
3500
|
+
setIsLoading(false);
|
|
3501
|
+
setIsFetchingMore(false);
|
|
3502
|
+
}
|
|
3503
|
+
},
|
|
3504
|
+
[statusFilter, createdByFilter, debouncedSearchQuery]
|
|
3505
|
+
);
|
|
3506
|
+
react.useEffect(() => {
|
|
3507
|
+
void loadSwaps(0, true);
|
|
3508
|
+
}, [statusFilter, createdByFilter, debouncedSearchQuery, loadSwaps]);
|
|
3509
|
+
const hasMore = react.useMemo(() => offset < count, [offset, count]);
|
|
3510
|
+
const availableStatuses = react.useMemo(() => {
|
|
3511
|
+
const statuses = /* @__PURE__ */ new Set();
|
|
3512
|
+
items.forEach((item) => statuses.add(item.status));
|
|
3513
|
+
return Array.from(statuses).sort();
|
|
3514
|
+
}, [items]);
|
|
3515
|
+
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: [
|
|
3516
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
3517
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3518
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Exchanges" }),
|
|
3519
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "View and manage all customer exchange requests" })
|
|
3520
|
+
] }),
|
|
3521
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => loadSwaps(0, true), children: "Refresh" })
|
|
3522
|
+
] }),
|
|
3523
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
3524
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3525
|
+
ui.Input,
|
|
3526
|
+
{
|
|
3527
|
+
placeholder: "Search by swap ID or order ID",
|
|
3528
|
+
value: searchQuery,
|
|
3529
|
+
onChange: (event) => setSearchQuery(event.target.value),
|
|
3530
|
+
className: "md:max-w-sm"
|
|
3531
|
+
}
|
|
3532
|
+
),
|
|
3533
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
|
|
3534
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3535
|
+
"select",
|
|
3536
|
+
{
|
|
3537
|
+
value: createdByFilter,
|
|
3538
|
+
onChange: (event) => setCreatedByFilter(event.target.value),
|
|
3539
|
+
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",
|
|
3540
|
+
children: [
|
|
3541
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All (Created by)" }),
|
|
3542
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "customer", children: "Customer" }),
|
|
3543
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "admin", children: "Admin" })
|
|
3544
|
+
]
|
|
3545
|
+
}
|
|
3546
|
+
),
|
|
3547
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3548
|
+
"select",
|
|
3549
|
+
{
|
|
3550
|
+
value: statusFilter,
|
|
3551
|
+
onChange: (event) => setStatusFilter(event.target.value),
|
|
3552
|
+
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",
|
|
3553
|
+
children: [
|
|
3554
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All Statuses" }),
|
|
3555
|
+
availableStatuses.map((status) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
|
|
3556
|
+
]
|
|
3557
|
+
}
|
|
3558
|
+
)
|
|
3559
|
+
] })
|
|
3560
|
+
] }),
|
|
3561
|
+
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
3562
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
3563
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3564
|
+
ui.Button,
|
|
3565
|
+
{
|
|
3566
|
+
variant: "secondary",
|
|
3567
|
+
onClick: () => loadSwaps(0, true),
|
|
3568
|
+
children: "Try again"
|
|
3569
|
+
}
|
|
3570
|
+
) })
|
|
3571
|
+
] }) : null,
|
|
3572
|
+
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: [
|
|
3573
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No exchanges yet" }),
|
|
3574
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Exchange requests created by customers will appear here." })
|
|
3575
|
+
] }) : /* @__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: [
|
|
3576
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
3577
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Exchange ID" }),
|
|
3578
|
+
/* @__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" }),
|
|
3579
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
3580
|
+
/* @__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" }),
|
|
3581
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
3582
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
3583
|
+
] }) }),
|
|
3584
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((swap) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3585
|
+
"tr",
|
|
3586
|
+
{
|
|
3587
|
+
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
3588
|
+
onClick: () => navigate(`/swaps/${swap.id}`),
|
|
3589
|
+
children: [
|
|
3590
|
+
/* @__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 }) }) }),
|
|
3591
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: swap.order_id }),
|
|
3592
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3593
|
+
ui.Badge,
|
|
3594
|
+
{
|
|
3595
|
+
size: "2xsmall",
|
|
3596
|
+
className: `uppercase ${getStatusBadgeClass$5(swap.status)}`,
|
|
3597
|
+
children: swap.status.replace(/_/g, " ")
|
|
3598
|
+
}
|
|
3599
|
+
) }),
|
|
3600
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
|
|
3601
|
+
const amount = swap.difference_due;
|
|
3602
|
+
if (amount == null || amount === void 0) {
|
|
3603
|
+
return "—";
|
|
3604
|
+
}
|
|
3605
|
+
const displayAmount = Number(amount) / 100;
|
|
3606
|
+
const currency = swap.currency_code || "$";
|
|
3607
|
+
const sign = displayAmount >= 0 ? "+" : "";
|
|
3608
|
+
return `${sign}${currency}${displayAmount.toFixed(2)}`;
|
|
3609
|
+
})() }),
|
|
3610
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(swap.created_at).toLocaleDateString("en-US", {
|
|
3611
|
+
year: "numeric",
|
|
3612
|
+
month: "short",
|
|
3613
|
+
day: "numeric",
|
|
3614
|
+
hour: "numeric",
|
|
3615
|
+
minute: "2-digit",
|
|
3616
|
+
hour12: true
|
|
3617
|
+
}) }),
|
|
3618
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3619
|
+
ui.Button,
|
|
3620
|
+
{
|
|
3621
|
+
variant: "transparent",
|
|
3622
|
+
size: "small",
|
|
3623
|
+
onClick: (e) => {
|
|
3624
|
+
e.stopPropagation();
|
|
3625
|
+
navigate(`/app/orders/${swap.order_id}`);
|
|
3626
|
+
},
|
|
3627
|
+
children: "Go to order"
|
|
3628
|
+
}
|
|
3629
|
+
) })
|
|
3630
|
+
]
|
|
3631
|
+
},
|
|
3632
|
+
swap.id
|
|
3633
|
+
)) })
|
|
3634
|
+
] }) }),
|
|
3635
|
+
hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3636
|
+
ui.Button,
|
|
3637
|
+
{
|
|
3638
|
+
variant: "secondary",
|
|
3639
|
+
isLoading: isFetchingMore,
|
|
3640
|
+
onClick: () => loadSwaps(offset, false),
|
|
3641
|
+
children: "Load more"
|
|
3642
|
+
}
|
|
3643
|
+
) }) : null
|
|
3644
|
+
] }) });
|
|
3645
|
+
};
|
|
3646
|
+
const config$5 = adminSdk.defineRouteConfig({
|
|
3647
|
+
label: "Exchanges",
|
|
3648
|
+
icon: icons.ArrowPath
|
|
3649
|
+
});
|
|
3650
|
+
const useDebounce = (value, delay) => {
|
|
3651
|
+
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
3652
|
+
react.useEffect(() => {
|
|
3653
|
+
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
3654
|
+
return () => clearTimeout(handler);
|
|
3655
|
+
}, [value, delay]);
|
|
3656
|
+
return debouncedValue;
|
|
3657
|
+
};
|
|
3658
|
+
const getStatusBadgeClass$4 = (status) => {
|
|
3659
|
+
const s2 = status.toLowerCase();
|
|
3660
|
+
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
3661
|
+
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
3662
|
+
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
3663
|
+
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
3664
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
3665
|
+
};
|
|
3666
|
+
const RefundsPage = () => {
|
|
3667
|
+
const navigate = reactRouterDom.useNavigate();
|
|
3668
|
+
const [items, setItems] = react.useState([]);
|
|
3669
|
+
const [orderIdSearch, setOrderIdSearch] = react.useState("");
|
|
3670
|
+
const debouncedOrderId = useDebounce(orderIdSearch, 300);
|
|
3671
|
+
const [paymentStatusFilter, setPaymentStatusFilter] = react.useState("all");
|
|
3672
|
+
const [providerSearch, setProviderSearch] = react.useState("");
|
|
3673
|
+
const debouncedProvider = useDebounce(providerSearch, 300);
|
|
3674
|
+
const [currencySearch, setCurrencySearch] = react.useState("");
|
|
3675
|
+
const debouncedCurrency = useDebounce(currencySearch, 300);
|
|
3676
|
+
const [dateFrom, setDateFrom] = react.useState("");
|
|
3677
|
+
const [dateTo, setDateTo] = react.useState("");
|
|
3678
|
+
const [amountMin, setAmountMin] = react.useState("");
|
|
3679
|
+
const [amountMax, setAmountMax] = react.useState("");
|
|
3680
|
+
const [isLoading, setIsLoading] = react.useState(true);
|
|
3681
|
+
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
3682
|
+
const [error, setError] = react.useState(null);
|
|
3683
|
+
const [offset, setOffset] = react.useState(0);
|
|
3684
|
+
const [count, setCount] = react.useState(0);
|
|
3685
|
+
const limit = 50;
|
|
3686
|
+
const loadRefunds = react.useCallback(
|
|
3687
|
+
async (nextOffset, replace) => {
|
|
3688
|
+
try {
|
|
3689
|
+
if (replace) setIsLoading(true);
|
|
3690
|
+
else setIsFetchingMore(true);
|
|
3691
|
+
setError(null);
|
|
3692
|
+
const params = new URLSearchParams();
|
|
3693
|
+
params.set("limit", String(limit));
|
|
3694
|
+
params.set("offset", String(nextOffset));
|
|
3695
|
+
if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
|
|
3696
|
+
if (paymentStatusFilter !== "all") params.set("payment_status", paymentStatusFilter);
|
|
3697
|
+
if (debouncedProvider.trim()) params.set("provider_id", debouncedProvider.trim());
|
|
3698
|
+
if (debouncedCurrency.trim()) params.set("currency_code", debouncedCurrency.trim());
|
|
3699
|
+
if (dateFrom.trim()) params.set("date_from", dateFrom.trim());
|
|
3700
|
+
if (dateTo.trim()) params.set("date_to", dateTo.trim());
|
|
3701
|
+
const min = amountMin.trim() ? Number(amountMin) : void 0;
|
|
3702
|
+
const max = amountMax.trim() ? Number(amountMax) : void 0;
|
|
3703
|
+
if (min != null && !Number.isNaN(min)) params.set("amount_min", String(min));
|
|
3704
|
+
if (max != null && !Number.isNaN(max)) params.set("amount_max", String(max));
|
|
3705
|
+
const response = await fetch(`/admin/refunds?${params.toString()}`, {
|
|
3706
|
+
credentials: "include"
|
|
3707
|
+
});
|
|
3708
|
+
if (!response.ok) {
|
|
3709
|
+
const text = await response.text();
|
|
3710
|
+
throw new Error(text || "Failed to load refunds");
|
|
3711
|
+
}
|
|
3712
|
+
const payload = await response.json();
|
|
3713
|
+
const list = payload.refunds ?? [];
|
|
3714
|
+
setCount(payload.count ?? 0);
|
|
3715
|
+
setOffset(nextOffset + list.length);
|
|
3716
|
+
setItems((prev) => replace ? list : [...prev, ...list]);
|
|
3717
|
+
} catch (e) {
|
|
3718
|
+
setError(e instanceof Error ? e.message : "Failed to load");
|
|
3719
|
+
} finally {
|
|
3720
|
+
setIsLoading(false);
|
|
3721
|
+
setIsFetchingMore(false);
|
|
3722
|
+
}
|
|
3723
|
+
},
|
|
3724
|
+
[
|
|
3725
|
+
debouncedOrderId,
|
|
3726
|
+
paymentStatusFilter,
|
|
3727
|
+
debouncedProvider,
|
|
3728
|
+
debouncedCurrency,
|
|
3729
|
+
dateFrom,
|
|
3730
|
+
dateTo,
|
|
3731
|
+
amountMin,
|
|
3732
|
+
amountMax
|
|
3733
|
+
]
|
|
3734
|
+
);
|
|
3735
|
+
react.useEffect(() => {
|
|
3736
|
+
void loadRefunds(0, true);
|
|
3737
|
+
}, [loadRefunds]);
|
|
3738
|
+
const hasMore = react.useMemo(() => offset < count, [offset, count]);
|
|
3739
|
+
const displayAmount = (r) => {
|
|
3740
|
+
const code = (r.currency_code ?? "USD").toUpperCase();
|
|
3741
|
+
return `${code} ${Number(r.amount)}`;
|
|
3742
|
+
};
|
|
3743
|
+
const displayStatus = (r) => {
|
|
3744
|
+
const s2 = r.payment_status ?? "";
|
|
3745
|
+
return s2 !== "" ? s2 : "—";
|
|
3746
|
+
};
|
|
3747
|
+
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: [
|
|
3748
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
3749
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3750
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Refunds" }),
|
|
3751
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Refund records — amount, order, payment status" })
|
|
3752
|
+
] }),
|
|
3753
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => loadRefunds(0, true), children: "Refresh" })
|
|
3754
|
+
] }),
|
|
3755
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
3756
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3757
|
+
ui.Input,
|
|
3758
|
+
{
|
|
3759
|
+
placeholder: "Order ID",
|
|
3760
|
+
value: orderIdSearch,
|
|
3761
|
+
onChange: (e) => setOrderIdSearch(e.target.value),
|
|
3762
|
+
className: "md:max-w-[180px]",
|
|
3763
|
+
"aria-label": "Filter by order ID"
|
|
3764
|
+
}
|
|
3765
|
+
),
|
|
3766
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3767
|
+
ui.Input,
|
|
3768
|
+
{
|
|
3769
|
+
placeholder: "Provider",
|
|
3770
|
+
value: providerSearch,
|
|
3771
|
+
onChange: (e) => setProviderSearch(e.target.value),
|
|
3772
|
+
className: "md:max-w-[140px]",
|
|
3773
|
+
"aria-label": "Filter by provider"
|
|
3774
|
+
}
|
|
3775
|
+
),
|
|
3776
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3777
|
+
ui.Input,
|
|
3778
|
+
{
|
|
3779
|
+
placeholder: "Currency",
|
|
3780
|
+
value: currencySearch,
|
|
3781
|
+
onChange: (e) => setCurrencySearch(e.target.value),
|
|
3782
|
+
className: "md:max-w-[100px]",
|
|
3783
|
+
"aria-label": "Filter by currency"
|
|
3784
|
+
}
|
|
3785
|
+
),
|
|
3786
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3787
|
+
"select",
|
|
3788
|
+
{
|
|
3789
|
+
value: paymentStatusFilter,
|
|
3790
|
+
onChange: (e) => setPaymentStatusFilter(e.target.value),
|
|
3791
|
+
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-[160px]",
|
|
3792
|
+
"aria-label": "Filter by payment status",
|
|
3793
|
+
children: [
|
|
3794
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All statuses" }),
|
|
3795
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "pending", children: "Pending" }),
|
|
3796
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "requires_more", children: "Requires more" }),
|
|
3797
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "error", children: "Error" }),
|
|
3798
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "canceled", children: "Canceled" }),
|
|
3799
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "authorized", children: "Authorized" }),
|
|
3800
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "captured", children: "Captured" })
|
|
3801
|
+
]
|
|
3802
|
+
}
|
|
3803
|
+
),
|
|
3804
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3805
|
+
ui.Input,
|
|
3806
|
+
{
|
|
3807
|
+
type: "date",
|
|
3808
|
+
placeholder: "From",
|
|
3809
|
+
value: dateFrom,
|
|
3810
|
+
onChange: (e) => setDateFrom(e.target.value),
|
|
3811
|
+
className: "md:max-w-[140px]",
|
|
3812
|
+
"aria-label": "Date from"
|
|
3813
|
+
}
|
|
3814
|
+
),
|
|
3815
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3816
|
+
ui.Input,
|
|
3817
|
+
{
|
|
3818
|
+
type: "date",
|
|
3819
|
+
placeholder: "To",
|
|
3820
|
+
value: dateTo,
|
|
3821
|
+
onChange: (e) => setDateTo(e.target.value),
|
|
3822
|
+
className: "md:max-w-[140px]",
|
|
3823
|
+
"aria-label": "Date to"
|
|
3824
|
+
}
|
|
3825
|
+
),
|
|
3826
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3827
|
+
ui.Input,
|
|
3828
|
+
{
|
|
3829
|
+
placeholder: "Amount min",
|
|
3830
|
+
value: amountMin,
|
|
3831
|
+
onChange: (e) => setAmountMin(e.target.value),
|
|
3832
|
+
type: "number",
|
|
3833
|
+
min: 0,
|
|
3834
|
+
className: "md:max-w-[100px]",
|
|
3835
|
+
"aria-label": "Refund amount minimum"
|
|
3836
|
+
}
|
|
3837
|
+
),
|
|
3838
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3839
|
+
ui.Input,
|
|
3840
|
+
{
|
|
3841
|
+
placeholder: "Amount max",
|
|
3842
|
+
value: amountMax,
|
|
3843
|
+
onChange: (e) => setAmountMax(e.target.value),
|
|
3844
|
+
type: "number",
|
|
3845
|
+
min: 0,
|
|
3846
|
+
className: "md:max-w-[100px]",
|
|
3847
|
+
"aria-label": "Refund amount maximum"
|
|
3848
|
+
}
|
|
3849
|
+
)
|
|
3850
|
+
] }) }),
|
|
3851
|
+
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
3852
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
3853
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => loadRefunds(0, true), children: "Try again" }) })
|
|
3854
|
+
] }) : null,
|
|
3855
|
+
isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading refunds…" }) }) : items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
3856
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No refunds yet" }),
|
|
3857
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Refund records will appear here." })
|
|
3858
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full overflow-x-auto rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full table-fixed divide-y divide-ui-border-base", style: { minWidth: 0 }, children: [
|
|
3859
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
3860
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Refund ID" }),
|
|
3861
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
3862
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Payment ID" }),
|
|
3863
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[8%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Amount" }),
|
|
3864
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[6%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Currency" }),
|
|
3865
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[10%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Provider" }),
|
|
3866
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[10%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Payment Status" }),
|
|
3867
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[14%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Note" }),
|
|
3868
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
3869
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[8%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
3870
|
+
] }) }),
|
|
3871
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((r) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3872
|
+
"tr",
|
|
3873
|
+
{
|
|
3874
|
+
className: "cursor-pointer hover:bg-ui-bg-subtle/60",
|
|
3875
|
+
onClick: () => navigate(`/refunds/${r.refund_id}`),
|
|
3876
|
+
children: [
|
|
3877
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 font-mono text-sm text-ui-fg-base", title: r.refund_id, children: r.refund_id }),
|
|
3878
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 font-medium text-ui-fg-base", title: r.order_id ?? void 0, children: r.order_id ?? "—" }),
|
|
3879
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 font-mono text-sm text-ui-fg-subtle", title: r.payment_id, children: r.payment_id }),
|
|
3880
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", children: displayAmount(r) }),
|
|
3881
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle uppercase", children: r.currency_code || "—" }),
|
|
3882
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", title: r.provider_id || void 0, children: r.provider_id || "—" }),
|
|
3883
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3884
|
+
ui.Badge,
|
|
3885
|
+
{
|
|
3886
|
+
size: "2xsmall",
|
|
3887
|
+
className: `uppercase ${getStatusBadgeClass$4(displayStatus(r))}`,
|
|
3888
|
+
children: displayStatus(r) !== "—" ? displayStatus(r).replace(/_/g, " ") : "—"
|
|
3889
|
+
}
|
|
3890
|
+
) }),
|
|
3891
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", title: r.note ?? void 0, children: r.note ?? "—" }),
|
|
3892
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle text-xs", children: new Date(r.created_at).toLocaleDateString("en-US", {
|
|
3893
|
+
month: "short",
|
|
3894
|
+
day: "numeric",
|
|
3895
|
+
hour: "numeric",
|
|
3896
|
+
minute: "2-digit",
|
|
3897
|
+
hour12: true
|
|
3898
|
+
}) }),
|
|
3899
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-1", children: [
|
|
3900
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3901
|
+
ui.Button,
|
|
3902
|
+
{
|
|
3903
|
+
variant: "transparent",
|
|
3904
|
+
size: "small",
|
|
3905
|
+
onClick: (e) => {
|
|
3906
|
+
e.stopPropagation();
|
|
3907
|
+
navigate(`/refunds/${r.refund_id}`);
|
|
3908
|
+
},
|
|
3909
|
+
children: "Details"
|
|
3910
|
+
}
|
|
3911
|
+
),
|
|
3912
|
+
r.order_id ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3913
|
+
ui.Button,
|
|
3914
|
+
{
|
|
3915
|
+
variant: "transparent",
|
|
3916
|
+
size: "small",
|
|
3917
|
+
onClick: (e) => {
|
|
3918
|
+
e.stopPropagation();
|
|
3919
|
+
navigate(`/orders/${r.order_id}`);
|
|
3920
|
+
},
|
|
3921
|
+
children: "Order"
|
|
3922
|
+
}
|
|
3923
|
+
) : null
|
|
3924
|
+
] }) })
|
|
3925
|
+
]
|
|
3926
|
+
},
|
|
3927
|
+
r.refund_id
|
|
3928
|
+
)) })
|
|
3929
|
+
] }) }),
|
|
3930
|
+
hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3931
|
+
ui.Button,
|
|
3932
|
+
{
|
|
3933
|
+
variant: "secondary",
|
|
3934
|
+
isLoading: isFetchingMore,
|
|
3935
|
+
onClick: () => loadRefunds(offset, false),
|
|
3936
|
+
children: "Load more"
|
|
3937
|
+
}
|
|
3938
|
+
) }) : null
|
|
3939
|
+
] }) });
|
|
3940
|
+
};
|
|
3941
|
+
const config$4 = adminSdk.defineRouteConfig({
|
|
3942
|
+
label: "Refunds",
|
|
3943
|
+
icon: icons.Receipt
|
|
3944
|
+
});
|
|
3945
3945
|
const getStatusBadgeClass$3 = (status) => {
|
|
3946
3946
|
const s2 = status.toLowerCase();
|
|
3947
3947
|
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
@@ -4072,471 +4072,275 @@ const getStatusBadgeClass$2 = (status) => {
|
|
|
4072
4072
|
if (statusLower === "rejected") {
|
|
4073
4073
|
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
4074
4074
|
}
|
|
4075
|
-
if (statusLower === "received") {
|
|
4076
|
-
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
4077
|
-
}
|
|
4078
|
-
if (statusLower === "refunded") {
|
|
4079
|
-
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
4080
|
-
}
|
|
4081
4075
|
if (statusLower === "completed") {
|
|
4082
4076
|
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
4083
4077
|
}
|
|
4084
|
-
if (statusLower === "cancelled") {
|
|
4078
|
+
if (statusLower === "cancelled" || statusLower === "canceled") {
|
|
4085
4079
|
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
4086
4080
|
}
|
|
4081
|
+
if (statusLower === "pending") {
|
|
4082
|
+
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
4083
|
+
}
|
|
4087
4084
|
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
4088
4085
|
};
|
|
4089
|
-
const
|
|
4086
|
+
const SwapDetailPage = () => {
|
|
4090
4087
|
var _a, _b, _c;
|
|
4091
4088
|
const navigate = reactRouterDom.useNavigate();
|
|
4092
4089
|
const { id } = reactRouterDom.useParams();
|
|
4093
|
-
const [
|
|
4090
|
+
const [swap, setSwap] = react.useState(null);
|
|
4091
|
+
const [order, setOrder] = react.useState(null);
|
|
4094
4092
|
const [isLoading, setIsLoading] = react.useState(true);
|
|
4095
|
-
|
|
4093
|
+
react.useState(false);
|
|
4094
|
+
const [isCancelling, setIsCancelling] = react.useState(false);
|
|
4096
4095
|
const [error, setError] = react.useState(null);
|
|
4097
4096
|
const [updateError, setUpdateError] = react.useState(null);
|
|
4098
4097
|
const [updateSuccess, setUpdateSuccess] = react.useState(false);
|
|
4099
4098
|
react.useEffect(() => {
|
|
4100
4099
|
if (!id) {
|
|
4101
|
-
navigate("/
|
|
4100
|
+
navigate("/swaps");
|
|
4102
4101
|
return;
|
|
4103
4102
|
}
|
|
4104
|
-
const
|
|
4103
|
+
const loadSwap = async () => {
|
|
4105
4104
|
try {
|
|
4106
4105
|
setIsLoading(true);
|
|
4107
4106
|
setError(null);
|
|
4108
|
-
const response = await fetch(`/admin/
|
|
4107
|
+
const response = await fetch(`/admin/swaps/${id}`, {
|
|
4109
4108
|
credentials: "include"
|
|
4110
4109
|
});
|
|
4111
4110
|
if (!response.ok) {
|
|
4112
4111
|
const message = await response.text();
|
|
4113
|
-
throw new Error(message || "Unable to load
|
|
4112
|
+
throw new Error(message || "Unable to load swap");
|
|
4114
4113
|
}
|
|
4115
4114
|
const payload = await response.json();
|
|
4116
|
-
|
|
4115
|
+
setSwap(payload.swap);
|
|
4116
|
+
setOrder(payload.order || null);
|
|
4117
4117
|
} catch (loadError) {
|
|
4118
|
-
const message = loadError instanceof Error ? loadError.message : "Unable to load
|
|
4118
|
+
const message = loadError instanceof Error ? loadError.message : "Unable to load swap";
|
|
4119
4119
|
setError(message);
|
|
4120
4120
|
} finally {
|
|
4121
4121
|
setIsLoading(false);
|
|
4122
4122
|
}
|
|
4123
4123
|
};
|
|
4124
|
-
void
|
|
4124
|
+
void loadSwap();
|
|
4125
4125
|
}, [id, navigate]);
|
|
4126
|
-
const
|
|
4126
|
+
const handleCancelExchange = async () => {
|
|
4127
4127
|
if (!id) {
|
|
4128
4128
|
return;
|
|
4129
4129
|
}
|
|
4130
4130
|
try {
|
|
4131
|
-
|
|
4131
|
+
setIsCancelling(true);
|
|
4132
4132
|
setUpdateError(null);
|
|
4133
4133
|
setUpdateSuccess(false);
|
|
4134
|
-
const response = await fetch(`/admin/
|
|
4134
|
+
const response = await fetch(`/admin/swaps/${id}/cancel`, {
|
|
4135
4135
|
method: "POST",
|
|
4136
4136
|
headers: {
|
|
4137
4137
|
"Content-Type": "application/json"
|
|
4138
4138
|
},
|
|
4139
|
-
credentials: "include"
|
|
4140
|
-
body: JSON.stringify({ reason: "Rejected by admin" })
|
|
4139
|
+
credentials: "include"
|
|
4141
4140
|
});
|
|
4142
4141
|
if (!response.ok) {
|
|
4143
4142
|
const message = await response.text();
|
|
4144
|
-
throw new Error(message || "Unable to
|
|
4143
|
+
throw new Error(message || "Unable to cancel exchange");
|
|
4145
4144
|
}
|
|
4146
4145
|
const payload = await response.json();
|
|
4147
|
-
|
|
4146
|
+
setSwap(payload.swap);
|
|
4148
4147
|
setUpdateSuccess(true);
|
|
4149
4148
|
setTimeout(() => setUpdateSuccess(false), 3e3);
|
|
4150
|
-
const detailResponse = await fetch(`/admin/
|
|
4149
|
+
const detailResponse = await fetch(`/admin/swaps/${id}`, {
|
|
4151
4150
|
credentials: "include"
|
|
4152
4151
|
});
|
|
4153
4152
|
if (detailResponse.ok) {
|
|
4154
4153
|
const detailPayload = await detailResponse.json();
|
|
4155
|
-
|
|
4154
|
+
setSwap(detailPayload.swap);
|
|
4155
|
+
setOrder(detailPayload.order || null);
|
|
4156
4156
|
}
|
|
4157
|
-
} catch (
|
|
4158
|
-
const message =
|
|
4157
|
+
} catch (cancelErr) {
|
|
4158
|
+
const message = cancelErr instanceof Error ? cancelErr.message : "Unable to cancel exchange";
|
|
4159
4159
|
setUpdateError(message);
|
|
4160
4160
|
} finally {
|
|
4161
|
-
|
|
4161
|
+
setIsCancelling(false);
|
|
4162
4162
|
}
|
|
4163
4163
|
};
|
|
4164
|
+
const isOrderExchange = Boolean(swap == null ? void 0 : swap.exchange_id);
|
|
4165
|
+
const canCancelExchange = isOrderExchange && swap && !["cancelled", "canceled", "completed", "declined"].includes(
|
|
4166
|
+
((_a = swap.status) == null ? void 0 : _a.toLowerCase()) ?? ""
|
|
4167
|
+
);
|
|
4164
4168
|
if (isLoading) {
|
|
4165
|
-
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
|
|
4166
|
-
}
|
|
4167
|
-
if (error || !returnOrder) {
|
|
4168
|
-
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: [
|
|
4169
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error || "Return order not found" }),
|
|
4170
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => navigate("/returns"), children: "Back to list" }) })
|
|
4171
|
-
] }) }) });
|
|
4169
|
+
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..." }) }) }) });
|
|
4172
4170
|
}
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
children: returnOrder.status.replace(/_/g, " ")
|
|
4200
|
-
}
|
|
4201
|
-
)
|
|
4202
|
-
] })
|
|
4203
|
-
] }),
|
|
4204
|
-
returnOrder.status === "requested" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
4205
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4206
|
-
ui.Button,
|
|
4207
|
-
{
|
|
4208
|
-
variant: "danger",
|
|
4209
|
-
onClick: handleReject,
|
|
4210
|
-
disabled: isRejecting,
|
|
4211
|
-
isLoading: isRejecting,
|
|
4212
|
-
children: "Reject (Cancel) Return"
|
|
4213
|
-
}
|
|
4214
|
-
) }),
|
|
4215
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: 'Cancel this return request. Use "Mark as received" when items are received.' })
|
|
4216
|
-
] }),
|
|
4217
|
-
returnOrder.refund ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: /* @__PURE__ */ jsxRuntime.jsx(RefundCalculationBlock, { refund: returnOrder.refund }) }) : null,
|
|
4218
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4219
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Information" }),
|
|
4220
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
4221
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4222
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Return ID" }),
|
|
4223
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.id })
|
|
4224
|
-
] }),
|
|
4225
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4226
|
-
ui.Button,
|
|
4227
|
-
{
|
|
4228
|
-
variant: "secondary",
|
|
4229
|
-
onClick: () => {
|
|
4230
|
-
window.open(
|
|
4231
|
-
`/app/orders/${returnOrder.order_id}`,
|
|
4232
|
-
"_blank"
|
|
4233
|
-
);
|
|
4234
|
-
},
|
|
4235
|
-
children: "View order"
|
|
4236
|
-
}
|
|
4237
|
-
) })
|
|
4238
|
-
] })
|
|
4239
|
-
] }),
|
|
4240
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-6 md:grid-cols-2", children: [
|
|
4241
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4242
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Details" }),
|
|
4243
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
4244
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4245
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Return ID" }),
|
|
4246
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.id })
|
|
4247
|
-
] }),
|
|
4248
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4249
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Status" }),
|
|
4250
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.status })
|
|
4251
|
-
] }),
|
|
4252
|
-
returnOrder.reason && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4253
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Reason" }),
|
|
4254
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.reason })
|
|
4255
|
-
] }),
|
|
4256
|
-
returnOrder.note && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4257
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Note" }),
|
|
4258
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.note })
|
|
4259
|
-
] }),
|
|
4260
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4261
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Created" }),
|
|
4262
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(returnOrder.created_at).toLocaleString() })
|
|
4263
|
-
] }),
|
|
4264
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4265
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Last Updated" }),
|
|
4266
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(returnOrder.updated_at).toLocaleString() })
|
|
4267
|
-
] })
|
|
4268
|
-
] })
|
|
4269
|
-
] }),
|
|
4270
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4271
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Status History" }),
|
|
4272
|
-
statusHistory.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: statusHistory.map((entry, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
4273
|
-
"div",
|
|
4274
|
-
{
|
|
4275
|
-
className: "flex items-center justify-between border-b border-ui-border-subtle pb-2 last:border-0",
|
|
4276
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
4277
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4278
|
-
ui.Badge,
|
|
4279
|
-
{
|
|
4280
|
-
size: "2xsmall",
|
|
4281
|
-
className: `uppercase ${getStatusBadgeClass$2(entry.status)}`,
|
|
4282
|
-
children: entry.status.replace(/_/g, " ")
|
|
4283
|
-
}
|
|
4284
|
-
) }),
|
|
4285
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
4286
|
-
new Date(entry.timestamp).toLocaleString(),
|
|
4287
|
-
entry.admin_id && ` by ${entry.admin_id}`,
|
|
4288
|
-
entry.reason && ` - ${entry.reason}`
|
|
4289
|
-
] })
|
|
4290
|
-
] })
|
|
4291
|
-
},
|
|
4292
|
-
index
|
|
4293
|
-
)) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "No status history available" })
|
|
4294
|
-
] })
|
|
4295
|
-
] }),
|
|
4296
|
-
returnOrder.order && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4297
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Related Order Information" }),
|
|
4298
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
4299
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4300
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order ID" }),
|
|
4301
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.order.id })
|
|
4302
|
-
] }),
|
|
4303
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4304
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Status" }),
|
|
4305
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.order.status || "—" })
|
|
4306
|
-
] }),
|
|
4307
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4308
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Customer" }),
|
|
4309
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: ((_b = returnOrder.order.customer) == null ? void 0 : _b.email) || returnOrder.order.email || "—" })
|
|
4310
|
-
] }),
|
|
4311
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4312
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Payment method" }),
|
|
4313
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: ((_c = returnOrder.order.order_payment) == null ? void 0 : _c.label) || "—" })
|
|
4171
|
+
if (error || !swap) {
|
|
4172
|
+
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: [
|
|
4173
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error || "Swap not found" }),
|
|
4174
|
+
/* @__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" }) })
|
|
4175
|
+
] }) }) });
|
|
4176
|
+
}
|
|
4177
|
+
const statusHistory = ((_b = swap.metadata) == null ? void 0 : _b.status_history) || [];
|
|
4178
|
+
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: [
|
|
4179
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3", children: [
|
|
4180
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4181
|
+
ui.Button,
|
|
4182
|
+
{
|
|
4183
|
+
variant: "transparent",
|
|
4184
|
+
size: "small",
|
|
4185
|
+
onClick: () => navigate("/swaps"),
|
|
4186
|
+
className: "w-fit",
|
|
4187
|
+
children: [
|
|
4188
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, { className: "mr-2" }),
|
|
4189
|
+
"Back to list"
|
|
4190
|
+
]
|
|
4191
|
+
}
|
|
4192
|
+
),
|
|
4193
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 md:flex-row md:items-center md:justify-between", children: [
|
|
4194
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
4195
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Exchange Details" }),
|
|
4196
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: swap.id })
|
|
4314
4197
|
] }),
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4198
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4199
|
+
ui.Badge,
|
|
4200
|
+
{
|
|
4201
|
+
size: "small",
|
|
4202
|
+
className: `uppercase ${getStatusBadgeClass$2(swap.status)}`,
|
|
4203
|
+
children: swap.status.replace(/_/g, " ")
|
|
4204
|
+
}
|
|
4205
|
+
)
|
|
4322
4206
|
] })
|
|
4323
4207
|
] }),
|
|
4324
|
-
|
|
4325
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
] }, item.id || index)) })
|
|
4337
|
-
] }) })
|
|
4208
|
+
canCancelExchange && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
4209
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4210
|
+
ui.Button,
|
|
4211
|
+
{
|
|
4212
|
+
variant: "danger",
|
|
4213
|
+
onClick: handleCancelExchange,
|
|
4214
|
+
disabled: isCancelling,
|
|
4215
|
+
isLoading: isCancelling,
|
|
4216
|
+
children: "Cancel Exchange"
|
|
4217
|
+
}
|
|
4218
|
+
) }),
|
|
4219
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "This will cancel the exchange request. The order will remain unchanged." })
|
|
4338
4220
|
] }),
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
const config$2 = adminSdk.defineRouteConfig({
|
|
4344
|
-
label: "Return Order Details",
|
|
4345
|
-
icon: icons.CheckCircle
|
|
4346
|
-
});
|
|
4347
|
-
const getStatusBadgeClass$1 = (status) => {
|
|
4348
|
-
const s2 = status.toLowerCase();
|
|
4349
|
-
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
4350
|
-
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
4351
|
-
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
4352
|
-
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
4353
|
-
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
4354
|
-
};
|
|
4355
|
-
const formatAmount = (value) => {
|
|
4356
|
-
return String(value);
|
|
4357
|
-
};
|
|
4358
|
-
const RefundDetailPage = () => {
|
|
4359
|
-
var _a, _b, _c;
|
|
4360
|
-
const navigate = reactRouterDom.useNavigate();
|
|
4361
|
-
const params = reactRouterDom.useParams();
|
|
4362
|
-
const id = (_a = params == null ? void 0 : params.id) == null ? void 0 : _a.trim();
|
|
4363
|
-
const [detail, setDetail] = react.useState(null);
|
|
4364
|
-
const [loading, setLoading] = react.useState(!!id);
|
|
4365
|
-
const [error, setError] = react.useState(null);
|
|
4366
|
-
const [gatewayExpanded, setGatewayExpanded] = react.useState(false);
|
|
4367
|
-
react.useEffect(() => {
|
|
4368
|
-
if (!id) {
|
|
4369
|
-
setLoading(false);
|
|
4370
|
-
return;
|
|
4371
|
-
}
|
|
4372
|
-
let cancelled = false;
|
|
4373
|
-
setLoading(true);
|
|
4374
|
-
setError(null);
|
|
4375
|
-
fetch(`/admin/refunds/${id}`, { credentials: "include" }).then((res) => {
|
|
4376
|
-
if (!res.ok) throw new Error(res.statusText || "Failed to load");
|
|
4377
|
-
return res.json();
|
|
4378
|
-
}).then((data) => {
|
|
4379
|
-
if (!cancelled) setDetail(data);
|
|
4380
|
-
}).catch((e) => {
|
|
4381
|
-
if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
|
|
4382
|
-
}).finally(() => {
|
|
4383
|
-
if (!cancelled) setLoading(false);
|
|
4384
|
-
});
|
|
4385
|
-
return () => {
|
|
4386
|
-
cancelled = true;
|
|
4387
|
-
};
|
|
4388
|
-
}, [id]);
|
|
4389
|
-
const paymentStatus = ((_b = detail == null ? void 0 : detail.payment) == null ? void 0 : _b.status) ?? "—";
|
|
4390
|
-
const hasGatewayData = ((_c = detail == null ? void 0 : detail.payment) == null ? void 0 : _c.payment_data) && typeof detail.payment.payment_data === "object" && Object.keys(detail.payment.payment_data).length > 0;
|
|
4391
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-4xl flex-col gap-6 p-6", children: [
|
|
4392
|
-
/* @__PURE__ */ jsxRuntime.jsx("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
4393
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => navigate("/refunds"), children: "← Refunds" }),
|
|
4394
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Refund details" }),
|
|
4395
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle font-mono", children: id ?? "—" })
|
|
4396
|
-
] }) }),
|
|
4397
|
-
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
4398
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
4399
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/refunds"), children: "Back to list" })
|
|
4400
|
-
] }) : loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading…" }) }) : detail ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
4401
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4402
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Refund summary" }),
|
|
4403
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
4404
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4405
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund ID" }),
|
|
4406
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.id })
|
|
4407
|
-
] }),
|
|
4408
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4409
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
|
|
4410
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.refund.amount) })
|
|
4411
|
-
] }),
|
|
4221
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-6 md:grid-cols-2", children: [
|
|
4222
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4223
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Exchange Information" }),
|
|
4224
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
4412
4225
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4413
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-
|
|
4414
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "
|
|
4226
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Exchange ID" }),
|
|
4227
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.id })
|
|
4415
4228
|
] }),
|
|
4416
4229
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4417
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-
|
|
4418
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "
|
|
4419
|
-
year: "numeric",
|
|
4420
|
-
month: "short",
|
|
4421
|
-
day: "numeric",
|
|
4422
|
-
hour: "numeric",
|
|
4423
|
-
minute: "2-digit",
|
|
4424
|
-
hour12: true
|
|
4425
|
-
}) })
|
|
4230
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Status" }),
|
|
4231
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.status })
|
|
4426
4232
|
] }),
|
|
4427
|
-
detail.refund.created_by ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4428
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created by" }),
|
|
4429
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.created_by })
|
|
4430
|
-
] }) : null
|
|
4431
|
-
] })
|
|
4432
|
-
] }),
|
|
4433
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4434
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Payment summary" }),
|
|
4435
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
4436
4233
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4437
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-
|
|
4438
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "
|
|
4234
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Difference Due" }),
|
|
4235
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.difference_due != null ? `${swap.currency_code || "$"}${(Number(swap.difference_due) / 100).toFixed(2)}` : "—" })
|
|
4439
4236
|
] }),
|
|
4440
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4441
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-
|
|
4442
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "
|
|
4237
|
+
swap.reason && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4238
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Reason" }),
|
|
4239
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.reason })
|
|
4443
4240
|
] }),
|
|
4444
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4445
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-
|
|
4446
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "
|
|
4241
|
+
swap.note && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4242
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Note" }),
|
|
4243
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.note })
|
|
4447
4244
|
] }),
|
|
4448
4245
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4449
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-
|
|
4450
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "
|
|
4246
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Created" }),
|
|
4247
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(swap.created_at).toLocaleString() })
|
|
4451
4248
|
] }),
|
|
4452
4249
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4453
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-
|
|
4454
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4455
|
-
ui.Badge,
|
|
4456
|
-
{
|
|
4457
|
-
size: "2xsmall",
|
|
4458
|
-
className: `uppercase ${getStatusBadgeClass$1(paymentStatus)}`,
|
|
4459
|
-
children: paymentStatus !== "—" ? paymentStatus.replace(/_/g, " ") : "—"
|
|
4460
|
-
}
|
|
4461
|
-
) })
|
|
4250
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Last Updated" }),
|
|
4251
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(swap.updated_at).toLocaleString() })
|
|
4462
4252
|
] }),
|
|
4463
|
-
|
|
4464
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
] }),
|
|
4468
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4469
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Remaining refundable" }),
|
|
4470
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.computed.remaining_refundable_amount) })
|
|
4471
|
-
] }),
|
|
4472
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4473
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund %" }),
|
|
4474
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "mt-1 block", children: [
|
|
4475
|
-
detail.computed.refund_percentage.toFixed(1),
|
|
4476
|
-
"%"
|
|
4477
|
-
] })
|
|
4478
|
-
] })
|
|
4479
|
-
] }) : null
|
|
4253
|
+
swap.exchange_id && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4254
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Exchange ID" }),
|
|
4255
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.exchange_id })
|
|
4256
|
+
] })
|
|
4480
4257
|
] })
|
|
4481
4258
|
] }),
|
|
4482
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-
|
|
4483
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Order" }),
|
|
4487
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4488
|
-
ui.Button,
|
|
4489
|
-
{
|
|
4490
|
-
variant: "transparent",
|
|
4491
|
-
size: "small",
|
|
4492
|
-
onClick: () => navigate(`/orders/${detail.order.order_id}`),
|
|
4493
|
-
children: detail.order.order_number ?? detail.order.order_id
|
|
4494
|
-
}
|
|
4495
|
-
) })
|
|
4496
|
-
] }),
|
|
4497
|
-
detail.order.total != null ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4498
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Total" }),
|
|
4499
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.order.total) })
|
|
4500
|
-
] }) : null,
|
|
4501
|
-
detail.order.customer_id ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4502
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Customer ID" }),
|
|
4503
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.order.customer_id })
|
|
4504
|
-
] }) : null,
|
|
4505
|
-
detail.order.region ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4506
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Region" }),
|
|
4507
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.region })
|
|
4508
|
-
] }) : null,
|
|
4509
|
-
detail.order.fulfillment_status ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4510
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Fulfillment status" }),
|
|
4511
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.fulfillment_status })
|
|
4512
|
-
] }) : null
|
|
4513
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No order linked to this refund." })
|
|
4514
|
-
] }),
|
|
4515
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4516
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4517
|
-
"button",
|
|
4259
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4260
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Status History" }),
|
|
4261
|
+
statusHistory.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: statusHistory.map((entry, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
4262
|
+
"div",
|
|
4518
4263
|
{
|
|
4519
|
-
|
|
4520
|
-
className: "flex
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4264
|
+
className: "flex items-center justify-between border-b border-ui-border-subtle pb-2 last:border-0",
|
|
4265
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
4266
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4267
|
+
ui.Badge,
|
|
4268
|
+
{
|
|
4269
|
+
size: "2xsmall",
|
|
4270
|
+
className: `uppercase ${getStatusBadgeClass$2(entry.status)}`,
|
|
4271
|
+
children: entry.status.replace(/_/g, " ")
|
|
4272
|
+
}
|
|
4273
|
+
) }),
|
|
4274
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
4275
|
+
new Date(entry.timestamp).toLocaleString(),
|
|
4276
|
+
entry.admin_id && ` by ${entry.admin_id}`,
|
|
4277
|
+
entry.reason && ` - ${entry.reason}`
|
|
4278
|
+
] })
|
|
4279
|
+
] })
|
|
4280
|
+
},
|
|
4281
|
+
index
|
|
4282
|
+
)) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "No status history available" })
|
|
4531
4283
|
] })
|
|
4532
|
-
] })
|
|
4284
|
+
] }),
|
|
4285
|
+
order && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4286
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Related Order Information" }),
|
|
4287
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
4288
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4289
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order ID" }),
|
|
4290
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: order.id })
|
|
4291
|
+
] }),
|
|
4292
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4293
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Status" }),
|
|
4294
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: order.status || "—" })
|
|
4295
|
+
] }),
|
|
4296
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4297
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Customer" }),
|
|
4298
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: ((_c = order.customer) == null ? void 0 : _c.email) || order.email || "—" })
|
|
4299
|
+
] }),
|
|
4300
|
+
order.total && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4301
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Total" }),
|
|
4302
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "font-medium", children: [
|
|
4303
|
+
order.currency_code || "$",
|
|
4304
|
+
(Number(order.total) / 100).toFixed(2)
|
|
4305
|
+
] })
|
|
4306
|
+
] })
|
|
4307
|
+
] })
|
|
4308
|
+
] }),
|
|
4309
|
+
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: [
|
|
4310
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Items" }),
|
|
4311
|
+
/* @__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: [
|
|
4312
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
4313
|
+
/* @__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" }),
|
|
4314
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Quantity" }),
|
|
4315
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Reason" })
|
|
4316
|
+
] }) }),
|
|
4317
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: swap.return_items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
4318
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: item.id }),
|
|
4319
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.quantity }),
|
|
4320
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.reason || "—" })
|
|
4321
|
+
] }, item.id || index)) })
|
|
4322
|
+
] }) })
|
|
4323
|
+
] }),
|
|
4324
|
+
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: [
|
|
4325
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "New Items" }),
|
|
4326
|
+
/* @__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: [
|
|
4327
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
4328
|
+
/* @__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" }),
|
|
4329
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Quantity" })
|
|
4330
|
+
] }) }),
|
|
4331
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: swap.new_items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
4332
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: item.variant_id }),
|
|
4333
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.quantity })
|
|
4334
|
+
] }, item.variant_id || index)) })
|
|
4335
|
+
] }) })
|
|
4336
|
+
] })
|
|
4533
4337
|
] }) });
|
|
4534
4338
|
};
|
|
4535
|
-
const config$
|
|
4536
|
-
label: "
|
|
4537
|
-
icon: icons.
|
|
4339
|
+
const config$2 = adminSdk.defineRouteConfig({
|
|
4340
|
+
label: "Swap Details",
|
|
4341
|
+
icon: icons.ArrowPath
|
|
4538
4342
|
});
|
|
4539
|
-
const getStatusBadgeClass = (status) => {
|
|
4343
|
+
const getStatusBadgeClass$1 = (status) => {
|
|
4540
4344
|
const statusLower = status.toLowerCase();
|
|
4541
4345
|
if (statusLower === "requested") {
|
|
4542
4346
|
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
@@ -4547,109 +4351,105 @@ const getStatusBadgeClass = (status) => {
|
|
|
4547
4351
|
if (statusLower === "rejected") {
|
|
4548
4352
|
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
4549
4353
|
}
|
|
4354
|
+
if (statusLower === "received") {
|
|
4355
|
+
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
4356
|
+
}
|
|
4357
|
+
if (statusLower === "refunded") {
|
|
4358
|
+
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
4359
|
+
}
|
|
4550
4360
|
if (statusLower === "completed") {
|
|
4551
4361
|
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
4552
4362
|
}
|
|
4553
|
-
if (statusLower === "cancelled"
|
|
4363
|
+
if (statusLower === "cancelled") {
|
|
4554
4364
|
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
4555
4365
|
}
|
|
4556
|
-
if (statusLower === "pending") {
|
|
4557
|
-
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
4558
|
-
}
|
|
4559
4366
|
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
4560
4367
|
};
|
|
4561
|
-
const
|
|
4368
|
+
const ReturnDetailPage = () => {
|
|
4562
4369
|
var _a, _b, _c;
|
|
4563
4370
|
const navigate = reactRouterDom.useNavigate();
|
|
4564
4371
|
const { id } = reactRouterDom.useParams();
|
|
4565
|
-
const [
|
|
4566
|
-
const [order, setOrder] = react.useState(null);
|
|
4372
|
+
const [returnOrder, setReturnOrder] = react.useState(null);
|
|
4567
4373
|
const [isLoading, setIsLoading] = react.useState(true);
|
|
4568
|
-
react.useState(false);
|
|
4569
|
-
const [isCancelling, setIsCancelling] = react.useState(false);
|
|
4374
|
+
const [isRejecting, setIsRejecting] = react.useState(false);
|
|
4570
4375
|
const [error, setError] = react.useState(null);
|
|
4571
4376
|
const [updateError, setUpdateError] = react.useState(null);
|
|
4572
4377
|
const [updateSuccess, setUpdateSuccess] = react.useState(false);
|
|
4573
4378
|
react.useEffect(() => {
|
|
4574
4379
|
if (!id) {
|
|
4575
|
-
navigate("/
|
|
4380
|
+
navigate("/returns");
|
|
4576
4381
|
return;
|
|
4577
4382
|
}
|
|
4578
|
-
const
|
|
4383
|
+
const loadReturn = async () => {
|
|
4579
4384
|
try {
|
|
4580
4385
|
setIsLoading(true);
|
|
4581
4386
|
setError(null);
|
|
4582
|
-
const response = await fetch(`/admin/
|
|
4387
|
+
const response = await fetch(`/admin/return/${id}`, {
|
|
4583
4388
|
credentials: "include"
|
|
4584
4389
|
});
|
|
4585
4390
|
if (!response.ok) {
|
|
4586
4391
|
const message = await response.text();
|
|
4587
|
-
throw new Error(message || "Unable to load
|
|
4392
|
+
throw new Error(message || "Unable to load return order");
|
|
4588
4393
|
}
|
|
4589
4394
|
const payload = await response.json();
|
|
4590
|
-
|
|
4591
|
-
setOrder(payload.order || null);
|
|
4395
|
+
setReturnOrder(payload.return);
|
|
4592
4396
|
} catch (loadError) {
|
|
4593
|
-
const message = loadError instanceof Error ? loadError.message : "Unable to load
|
|
4397
|
+
const message = loadError instanceof Error ? loadError.message : "Unable to load return order";
|
|
4594
4398
|
setError(message);
|
|
4595
4399
|
} finally {
|
|
4596
4400
|
setIsLoading(false);
|
|
4597
4401
|
}
|
|
4598
4402
|
};
|
|
4599
|
-
void
|
|
4403
|
+
void loadReturn();
|
|
4600
4404
|
}, [id, navigate]);
|
|
4601
|
-
const
|
|
4405
|
+
const handleReject = async () => {
|
|
4602
4406
|
if (!id) {
|
|
4603
4407
|
return;
|
|
4604
4408
|
}
|
|
4605
4409
|
try {
|
|
4606
|
-
|
|
4410
|
+
setIsRejecting(true);
|
|
4607
4411
|
setUpdateError(null);
|
|
4608
4412
|
setUpdateSuccess(false);
|
|
4609
|
-
const response = await fetch(`/admin/
|
|
4413
|
+
const response = await fetch(`/admin/return/${id}/reject`, {
|
|
4610
4414
|
method: "POST",
|
|
4611
4415
|
headers: {
|
|
4612
4416
|
"Content-Type": "application/json"
|
|
4613
4417
|
},
|
|
4614
|
-
credentials: "include"
|
|
4418
|
+
credentials: "include",
|
|
4419
|
+
body: JSON.stringify({ reason: "Rejected by admin" })
|
|
4615
4420
|
});
|
|
4616
4421
|
if (!response.ok) {
|
|
4617
4422
|
const message = await response.text();
|
|
4618
|
-
throw new Error(message || "Unable to
|
|
4423
|
+
throw new Error(message || "Unable to reject return");
|
|
4619
4424
|
}
|
|
4620
4425
|
const payload = await response.json();
|
|
4621
|
-
|
|
4426
|
+
setReturnOrder(payload.return);
|
|
4622
4427
|
setUpdateSuccess(true);
|
|
4623
4428
|
setTimeout(() => setUpdateSuccess(false), 3e3);
|
|
4624
|
-
const detailResponse = await fetch(`/admin/
|
|
4429
|
+
const detailResponse = await fetch(`/admin/return/${id}`, {
|
|
4625
4430
|
credentials: "include"
|
|
4626
4431
|
});
|
|
4627
4432
|
if (detailResponse.ok) {
|
|
4628
4433
|
const detailPayload = await detailResponse.json();
|
|
4629
|
-
|
|
4630
|
-
setOrder(detailPayload.order || null);
|
|
4434
|
+
setReturnOrder(detailPayload.return);
|
|
4631
4435
|
}
|
|
4632
|
-
} catch (
|
|
4633
|
-
const message =
|
|
4436
|
+
} catch (updateErr) {
|
|
4437
|
+
const message = updateErr instanceof Error ? updateErr.message : "Unable to reject return";
|
|
4634
4438
|
setUpdateError(message);
|
|
4635
4439
|
} finally {
|
|
4636
|
-
|
|
4440
|
+
setIsRejecting(false);
|
|
4637
4441
|
}
|
|
4638
4442
|
};
|
|
4639
|
-
const isOrderExchange = Boolean(swap == null ? void 0 : swap.exchange_id);
|
|
4640
|
-
const canCancelExchange = isOrderExchange && swap && !["cancelled", "canceled", "completed", "declined"].includes(
|
|
4641
|
-
((_a = swap.status) == null ? void 0 : _a.toLowerCase()) ?? ""
|
|
4642
|
-
);
|
|
4643
4443
|
if (isLoading) {
|
|
4644
|
-
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
|
|
4444
|
+
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 return order..." }) }) }) });
|
|
4645
4445
|
}
|
|
4646
|
-
if (error || !
|
|
4446
|
+
if (error || !returnOrder) {
|
|
4647
4447
|
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: [
|
|
4648
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error || "
|
|
4649
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => navigate("/
|
|
4448
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error || "Return order not found" }),
|
|
4449
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => navigate("/returns"), children: "Back to list" }) })
|
|
4650
4450
|
] }) }) });
|
|
4651
4451
|
}
|
|
4652
|
-
const statusHistory = ((
|
|
4452
|
+
const statusHistory = ((_a = returnOrder.metadata) == null ? void 0 : _a.status_history) || [];
|
|
4653
4453
|
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: [
|
|
4654
4454
|
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3", children: [
|
|
4655
4455
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -4657,7 +4457,7 @@ const SwapDetailPage = () => {
|
|
|
4657
4457
|
{
|
|
4658
4458
|
variant: "transparent",
|
|
4659
4459
|
size: "small",
|
|
4660
|
-
onClick: () => navigate("/
|
|
4460
|
+
onClick: () => navigate("/returns"),
|
|
4661
4461
|
className: "w-fit",
|
|
4662
4462
|
children: [
|
|
4663
4463
|
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, { className: "mr-2" }),
|
|
@@ -4667,67 +4467,82 @@ const SwapDetailPage = () => {
|
|
|
4667
4467
|
),
|
|
4668
4468
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 md:flex-row md:items-center md:justify-between", children: [
|
|
4669
4469
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
4670
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "
|
|
4671
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children:
|
|
4470
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Return Order Details" }),
|
|
4471
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: returnOrder.id })
|
|
4672
4472
|
] }),
|
|
4673
4473
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4674
4474
|
ui.Badge,
|
|
4675
4475
|
{
|
|
4676
4476
|
size: "small",
|
|
4677
|
-
className: `uppercase ${getStatusBadgeClass(
|
|
4678
|
-
children:
|
|
4477
|
+
className: `uppercase ${getStatusBadgeClass$1(returnOrder.status)}`,
|
|
4478
|
+
children: returnOrder.status.replace(/_/g, " ")
|
|
4679
4479
|
}
|
|
4680
4480
|
)
|
|
4681
4481
|
] })
|
|
4682
4482
|
] }),
|
|
4683
|
-
|
|
4483
|
+
returnOrder.status === "requested" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
4684
4484
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4685
4485
|
ui.Button,
|
|
4686
4486
|
{
|
|
4687
4487
|
variant: "danger",
|
|
4688
|
-
onClick:
|
|
4689
|
-
disabled:
|
|
4690
|
-
isLoading:
|
|
4691
|
-
children: "Cancel
|
|
4488
|
+
onClick: handleReject,
|
|
4489
|
+
disabled: isRejecting,
|
|
4490
|
+
isLoading: isRejecting,
|
|
4491
|
+
children: "Reject (Cancel) Return"
|
|
4692
4492
|
}
|
|
4693
4493
|
) }),
|
|
4694
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children:
|
|
4494
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: 'Cancel this return request. Use "Mark as received" when items are received.' })
|
|
4495
|
+
] }),
|
|
4496
|
+
returnOrder.refund ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: /* @__PURE__ */ jsxRuntime.jsx(RefundCalculationBlock, { refund: returnOrder.refund }) }) : null,
|
|
4497
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4498
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Information" }),
|
|
4499
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
4500
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4501
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Return ID" }),
|
|
4502
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.id })
|
|
4503
|
+
] }),
|
|
4504
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4505
|
+
ui.Button,
|
|
4506
|
+
{
|
|
4507
|
+
variant: "secondary",
|
|
4508
|
+
onClick: () => {
|
|
4509
|
+
window.open(
|
|
4510
|
+
`/app/orders/${returnOrder.order_id}`,
|
|
4511
|
+
"_blank"
|
|
4512
|
+
);
|
|
4513
|
+
},
|
|
4514
|
+
children: "View order"
|
|
4515
|
+
}
|
|
4516
|
+
) })
|
|
4517
|
+
] })
|
|
4695
4518
|
] }),
|
|
4696
4519
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-6 md:grid-cols-2", children: [
|
|
4697
4520
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4698
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "
|
|
4521
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Details" }),
|
|
4699
4522
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
4700
4523
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4701
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "
|
|
4702
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children:
|
|
4524
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Return ID" }),
|
|
4525
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.id })
|
|
4703
4526
|
] }),
|
|
4704
4527
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4705
4528
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Status" }),
|
|
4706
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children:
|
|
4707
|
-
] }),
|
|
4708
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4709
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Difference Due" }),
|
|
4710
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.difference_due != null ? `${swap.currency_code || "$"}${(Number(swap.difference_due) / 100).toFixed(2)}` : "—" })
|
|
4529
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.status })
|
|
4711
4530
|
] }),
|
|
4712
|
-
|
|
4531
|
+
returnOrder.reason && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4713
4532
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Reason" }),
|
|
4714
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children:
|
|
4533
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.reason })
|
|
4715
4534
|
] }),
|
|
4716
|
-
|
|
4535
|
+
returnOrder.note && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4717
4536
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Note" }),
|
|
4718
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children:
|
|
4537
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.note })
|
|
4719
4538
|
] }),
|
|
4720
4539
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4721
4540
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Created" }),
|
|
4722
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(
|
|
4541
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(returnOrder.created_at).toLocaleString() })
|
|
4723
4542
|
] }),
|
|
4724
4543
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4725
4544
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Last Updated" }),
|
|
4726
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(
|
|
4727
|
-
] }),
|
|
4728
|
-
swap.exchange_id && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4729
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Exchange ID" }),
|
|
4730
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.exchange_id })
|
|
4545
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(returnOrder.updated_at).toLocaleString() })
|
|
4731
4546
|
] })
|
|
4732
4547
|
] })
|
|
4733
4548
|
] }),
|
|
@@ -4742,7 +4557,7 @@ const SwapDetailPage = () => {
|
|
|
4742
4557
|
ui.Badge,
|
|
4743
4558
|
{
|
|
4744
4559
|
size: "2xsmall",
|
|
4745
|
-
className: `uppercase ${getStatusBadgeClass(entry.status)}`,
|
|
4560
|
+
className: `uppercase ${getStatusBadgeClass$1(entry.status)}`,
|
|
4746
4561
|
children: entry.status.replace(/_/g, " ")
|
|
4747
4562
|
}
|
|
4748
4563
|
) }),
|
|
@@ -4757,31 +4572,35 @@ const SwapDetailPage = () => {
|
|
|
4757
4572
|
)) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "No status history available" })
|
|
4758
4573
|
] })
|
|
4759
4574
|
] }),
|
|
4760
|
-
order && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4575
|
+
returnOrder.order && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4761
4576
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Related Order Information" }),
|
|
4762
4577
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
4763
4578
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4764
4579
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order ID" }),
|
|
4765
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: order.id })
|
|
4580
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.order.id })
|
|
4766
4581
|
] }),
|
|
4767
4582
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4768
4583
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Status" }),
|
|
4769
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: order.status || "—" })
|
|
4584
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.order.status || "—" })
|
|
4770
4585
|
] }),
|
|
4771
4586
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4772
4587
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Customer" }),
|
|
4773
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: ((
|
|
4588
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: ((_b = returnOrder.order.customer) == null ? void 0 : _b.email) || returnOrder.order.email || "—" })
|
|
4774
4589
|
] }),
|
|
4775
|
-
|
|
4590
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4591
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Payment method" }),
|
|
4592
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: ((_c = returnOrder.order.order_payment) == null ? void 0 : _c.label) || "—" })
|
|
4593
|
+
] }),
|
|
4594
|
+
returnOrder.order.total && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4776
4595
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Total" }),
|
|
4777
4596
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "font-medium", children: [
|
|
4778
|
-
order.currency_code || "$",
|
|
4779
|
-
(Number(order.total) / 100).toFixed(2)
|
|
4597
|
+
returnOrder.order.currency_code || "$",
|
|
4598
|
+
(Number(returnOrder.order.total) / 100).toFixed(2)
|
|
4780
4599
|
] })
|
|
4781
4600
|
] })
|
|
4782
4601
|
] })
|
|
4783
4602
|
] }),
|
|
4784
|
-
|
|
4603
|
+
returnOrder.return_items && returnOrder.return_items.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4785
4604
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Items" }),
|
|
4786
4605
|
/* @__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: [
|
|
4787
4606
|
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
@@ -4789,31 +4608,212 @@ const SwapDetailPage = () => {
|
|
|
4789
4608
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Quantity" }),
|
|
4790
4609
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Reason" })
|
|
4791
4610
|
] }) }),
|
|
4792
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children:
|
|
4611
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: returnOrder.return_items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
4793
4612
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: item.id }),
|
|
4794
4613
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.quantity }),
|
|
4795
4614
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.reason || "—" })
|
|
4796
4615
|
] }, item.id || index)) })
|
|
4797
4616
|
] }) })
|
|
4798
4617
|
] }),
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4618
|
+
updateError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-ui-border-error bg-ui-bg-error-subtle p-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-error", children: updateError }) }),
|
|
4619
|
+
updateSuccess && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-ui-border-success bg-ui-bg-success-subtle p-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-success", children: "Action completed successfully" }) })
|
|
4620
|
+
] }) });
|
|
4621
|
+
};
|
|
4622
|
+
const config$1 = adminSdk.defineRouteConfig({
|
|
4623
|
+
label: "Return Order Details",
|
|
4624
|
+
icon: icons.CheckCircle
|
|
4625
|
+
});
|
|
4626
|
+
const getStatusBadgeClass = (status) => {
|
|
4627
|
+
const s2 = status.toLowerCase();
|
|
4628
|
+
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
4629
|
+
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
4630
|
+
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
4631
|
+
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
4632
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
4633
|
+
};
|
|
4634
|
+
const formatAmount = (value) => {
|
|
4635
|
+
return String(value);
|
|
4636
|
+
};
|
|
4637
|
+
const RefundDetailPage = () => {
|
|
4638
|
+
var _a, _b, _c;
|
|
4639
|
+
const navigate = reactRouterDom.useNavigate();
|
|
4640
|
+
const params = reactRouterDom.useParams();
|
|
4641
|
+
const id = (_a = params == null ? void 0 : params.id) == null ? void 0 : _a.trim();
|
|
4642
|
+
const [detail, setDetail] = react.useState(null);
|
|
4643
|
+
const [loading, setLoading] = react.useState(!!id);
|
|
4644
|
+
const [error, setError] = react.useState(null);
|
|
4645
|
+
const [gatewayExpanded, setGatewayExpanded] = react.useState(false);
|
|
4646
|
+
react.useEffect(() => {
|
|
4647
|
+
if (!id) {
|
|
4648
|
+
setLoading(false);
|
|
4649
|
+
return;
|
|
4650
|
+
}
|
|
4651
|
+
let cancelled = false;
|
|
4652
|
+
setLoading(true);
|
|
4653
|
+
setError(null);
|
|
4654
|
+
fetch(`/admin/refunds/${id}`, { credentials: "include" }).then((res) => {
|
|
4655
|
+
if (!res.ok) throw new Error(res.statusText || "Failed to load");
|
|
4656
|
+
return res.json();
|
|
4657
|
+
}).then((data) => {
|
|
4658
|
+
if (!cancelled) setDetail(data);
|
|
4659
|
+
}).catch((e) => {
|
|
4660
|
+
if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
|
|
4661
|
+
}).finally(() => {
|
|
4662
|
+
if (!cancelled) setLoading(false);
|
|
4663
|
+
});
|
|
4664
|
+
return () => {
|
|
4665
|
+
cancelled = true;
|
|
4666
|
+
};
|
|
4667
|
+
}, [id]);
|
|
4668
|
+
const paymentStatus = ((_b = detail == null ? void 0 : detail.payment) == null ? void 0 : _b.status) ?? "—";
|
|
4669
|
+
const hasGatewayData = ((_c = detail == null ? void 0 : detail.payment) == null ? void 0 : _c.payment_data) && typeof detail.payment.payment_data === "object" && Object.keys(detail.payment.payment_data).length > 0;
|
|
4670
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-4xl flex-col gap-6 p-6", children: [
|
|
4671
|
+
/* @__PURE__ */ jsxRuntime.jsx("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
4672
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => navigate("/refunds"), children: "← Refunds" }),
|
|
4673
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Refund details" }),
|
|
4674
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle font-mono", children: id ?? "—" })
|
|
4675
|
+
] }) }),
|
|
4676
|
+
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
4677
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
4678
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/refunds"), children: "Back to list" })
|
|
4679
|
+
] }) : loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading…" }) }) : detail ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
4680
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4681
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Refund summary" }),
|
|
4682
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
4683
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4684
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund ID" }),
|
|
4685
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.id })
|
|
4686
|
+
] }),
|
|
4687
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4688
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
|
|
4689
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.refund.amount) })
|
|
4690
|
+
] }),
|
|
4691
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4692
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Note" }),
|
|
4693
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.refund.note ?? "—" })
|
|
4694
|
+
] }),
|
|
4695
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4696
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created at" }),
|
|
4697
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: new Date(detail.refund.created_at).toLocaleDateString("en-US", {
|
|
4698
|
+
year: "numeric",
|
|
4699
|
+
month: "short",
|
|
4700
|
+
day: "numeric",
|
|
4701
|
+
hour: "numeric",
|
|
4702
|
+
minute: "2-digit",
|
|
4703
|
+
hour12: true
|
|
4704
|
+
}) })
|
|
4705
|
+
] }),
|
|
4706
|
+
detail.refund.created_by ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4707
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created by" }),
|
|
4708
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.created_by })
|
|
4709
|
+
] }) : null
|
|
4710
|
+
] })
|
|
4711
|
+
] }),
|
|
4712
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4713
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Payment summary" }),
|
|
4714
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
4715
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4716
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Payment amount" }),
|
|
4717
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.payment_amount) })
|
|
4718
|
+
] }),
|
|
4719
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4720
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Captured amount" }),
|
|
4721
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.captured_amount) })
|
|
4722
|
+
] }),
|
|
4723
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4724
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refunded amount" }),
|
|
4725
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.refunded_amount) })
|
|
4726
|
+
] }),
|
|
4727
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4728
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
|
|
4729
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.payment.provider_id || "—" })
|
|
4730
|
+
] }),
|
|
4731
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4732
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
|
|
4733
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4734
|
+
ui.Badge,
|
|
4735
|
+
{
|
|
4736
|
+
size: "2xsmall",
|
|
4737
|
+
className: `uppercase ${getStatusBadgeClass(paymentStatus)}`,
|
|
4738
|
+
children: paymentStatus !== "—" ? paymentStatus.replace(/_/g, " ") : "—"
|
|
4739
|
+
}
|
|
4740
|
+
) })
|
|
4741
|
+
] }),
|
|
4742
|
+
detail.computed ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4743
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4744
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Full refund" }),
|
|
4745
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.computed.is_full_refund ? "Yes" : "No" })
|
|
4746
|
+
] }),
|
|
4747
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4748
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Remaining refundable" }),
|
|
4749
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.computed.remaining_refundable_amount) })
|
|
4750
|
+
] }),
|
|
4751
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4752
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund %" }),
|
|
4753
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "mt-1 block", children: [
|
|
4754
|
+
detail.computed.refund_percentage.toFixed(1),
|
|
4755
|
+
"%"
|
|
4756
|
+
] })
|
|
4757
|
+
] })
|
|
4758
|
+
] }) : null
|
|
4759
|
+
] })
|
|
4760
|
+
] }),
|
|
4761
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4762
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Order summary" }),
|
|
4763
|
+
detail.order ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
4764
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4765
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Order" }),
|
|
4766
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4767
|
+
ui.Button,
|
|
4768
|
+
{
|
|
4769
|
+
variant: "transparent",
|
|
4770
|
+
size: "small",
|
|
4771
|
+
onClick: () => navigate(`/orders/${detail.order.order_id}`),
|
|
4772
|
+
children: detail.order.order_number ?? detail.order.order_id
|
|
4773
|
+
}
|
|
4774
|
+
) })
|
|
4775
|
+
] }),
|
|
4776
|
+
detail.order.total != null ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4777
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Total" }),
|
|
4778
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.order.total) })
|
|
4779
|
+
] }) : null,
|
|
4780
|
+
detail.order.customer_id ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4781
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Customer ID" }),
|
|
4782
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.order.customer_id })
|
|
4783
|
+
] }) : null,
|
|
4784
|
+
detail.order.region ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4785
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Region" }),
|
|
4786
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.region })
|
|
4787
|
+
] }) : null,
|
|
4788
|
+
detail.order.fulfillment_status ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4789
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Fulfillment status" }),
|
|
4790
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.fulfillment_status })
|
|
4791
|
+
] }) : null
|
|
4792
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No order linked to this refund." })
|
|
4793
|
+
] }),
|
|
4794
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4795
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4796
|
+
"button",
|
|
4797
|
+
{
|
|
4798
|
+
type: "button",
|
|
4799
|
+
className: "flex w-full items-center justify-between text-left",
|
|
4800
|
+
onClick: () => setGatewayExpanded((prev) => !prev),
|
|
4801
|
+
"aria-expanded": gatewayExpanded,
|
|
4802
|
+
"aria-label": gatewayExpanded ? "Collapse gateway data" : "Expand gateway data",
|
|
4803
|
+
children: [
|
|
4804
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg", children: "Gateway data" }),
|
|
4805
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: gatewayExpanded ? "Collapse" : "Expand" })
|
|
4806
|
+
]
|
|
4807
|
+
}
|
|
4808
|
+
),
|
|
4809
|
+
gatewayExpanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4", children: hasGatewayData ? /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-xs bg-ui-bg-subtle p-4 rounded-lg overflow-auto max-h-96", children: JSON.stringify(detail.payment.payment_data, null, 2) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No gateway payload for this payment." }) })
|
|
4810
|
+
] })
|
|
4811
|
+
] }) : null
|
|
4812
4812
|
] }) });
|
|
4813
4813
|
};
|
|
4814
4814
|
const config = adminSdk.defineRouteConfig({
|
|
4815
|
-
label: "
|
|
4816
|
-
icon: icons.
|
|
4815
|
+
label: "Refund details",
|
|
4816
|
+
icon: icons.Receipt
|
|
4817
4817
|
});
|
|
4818
4818
|
const i18nTranslations0 = {};
|
|
4819
4819
|
const widgetModule = { widgets: [
|
|
@@ -4836,26 +4836,30 @@ const routeModule = {
|
|
|
4836
4836
|
Component: PaymentsPage,
|
|
4837
4837
|
path: "/payments"
|
|
4838
4838
|
},
|
|
4839
|
-
{
|
|
4840
|
-
Component: RefundsPage,
|
|
4841
|
-
path: "/refunds"
|
|
4842
|
-
},
|
|
4843
4839
|
{
|
|
4844
4840
|
Component: ReturnsPage,
|
|
4845
4841
|
path: "/returns"
|
|
4846
4842
|
},
|
|
4843
|
+
{
|
|
4844
|
+
Component: DeletedRecordDetailPage,
|
|
4845
|
+
path: "/deleted-records-audit/:id"
|
|
4846
|
+
},
|
|
4847
4847
|
{
|
|
4848
4848
|
Component: SwapsPage,
|
|
4849
4849
|
path: "/swaps"
|
|
4850
4850
|
},
|
|
4851
4851
|
{
|
|
4852
|
-
Component:
|
|
4853
|
-
path: "/
|
|
4852
|
+
Component: RefundsPage,
|
|
4853
|
+
path: "/refunds"
|
|
4854
4854
|
},
|
|
4855
4855
|
{
|
|
4856
4856
|
Component: PaymentDetailPage,
|
|
4857
4857
|
path: "/payments/:id"
|
|
4858
4858
|
},
|
|
4859
|
+
{
|
|
4860
|
+
Component: SwapDetailPage,
|
|
4861
|
+
path: "/swaps/:id"
|
|
4862
|
+
},
|
|
4859
4863
|
{
|
|
4860
4864
|
Component: ReturnDetailPage,
|
|
4861
4865
|
path: "/returns/:id"
|
|
@@ -4863,10 +4867,6 @@ const routeModule = {
|
|
|
4863
4867
|
{
|
|
4864
4868
|
Component: RefundDetailPage,
|
|
4865
4869
|
path: "/refunds/:id"
|
|
4866
|
-
},
|
|
4867
|
-
{
|
|
4868
|
-
Component: SwapDetailPage,
|
|
4869
|
-
path: "/swaps/:id"
|
|
4870
4870
|
}
|
|
4871
4871
|
]
|
|
4872
4872
|
};
|
|
@@ -4887,25 +4887,19 @@ const menuItemModule = {
|
|
|
4887
4887
|
{
|
|
4888
4888
|
label: config$6.label,
|
|
4889
4889
|
icon: config$6.icon,
|
|
4890
|
-
path: "/
|
|
4890
|
+
path: "/returns",
|
|
4891
4891
|
nested: void 0
|
|
4892
4892
|
},
|
|
4893
4893
|
{
|
|
4894
4894
|
label: config$5.label,
|
|
4895
4895
|
icon: config$5.icon,
|
|
4896
|
-
path: "/
|
|
4896
|
+
path: "/swaps",
|
|
4897
4897
|
nested: void 0
|
|
4898
4898
|
},
|
|
4899
4899
|
{
|
|
4900
4900
|
label: config$4.label,
|
|
4901
4901
|
icon: config$4.icon,
|
|
4902
|
-
path: "/
|
|
4903
|
-
nested: void 0
|
|
4904
|
-
},
|
|
4905
|
-
{
|
|
4906
|
-
label: config$1.label,
|
|
4907
|
-
icon: config$1.icon,
|
|
4908
|
-
path: "/refunds/:id",
|
|
4902
|
+
path: "/refunds",
|
|
4909
4903
|
nested: void 0
|
|
4910
4904
|
},
|
|
4911
4905
|
{
|
|
@@ -4914,16 +4908,22 @@ const menuItemModule = {
|
|
|
4914
4908
|
path: "/payments/:id",
|
|
4915
4909
|
nested: void 0
|
|
4916
4910
|
},
|
|
4911
|
+
{
|
|
4912
|
+
label: config$1.label,
|
|
4913
|
+
icon: config$1.icon,
|
|
4914
|
+
path: "/returns/:id",
|
|
4915
|
+
nested: void 0
|
|
4916
|
+
},
|
|
4917
4917
|
{
|
|
4918
4918
|
label: config$2.label,
|
|
4919
4919
|
icon: config$2.icon,
|
|
4920
|
-
path: "/
|
|
4920
|
+
path: "/swaps/:id",
|
|
4921
4921
|
nested: void 0
|
|
4922
4922
|
},
|
|
4923
4923
|
{
|
|
4924
4924
|
label: config.label,
|
|
4925
4925
|
icon: config.icon,
|
|
4926
|
-
path: "/
|
|
4926
|
+
path: "/refunds/:id",
|
|
4927
4927
|
nested: void 0
|
|
4928
4928
|
}
|
|
4929
4929
|
]
|