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