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