order-management 0.0.107 → 0.0.108

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.
@@ -1,8 +1,8 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
2
  import { defineWidgetConfig, defineRouteConfig } from "@medusajs/admin-sdk";
3
- import { useState, useEffect, useRef, useCallback, useMemo } from "react";
4
- import { Text, Container, Heading, Badge, Button, Label, Select, Textarea, Input, Popover, clx, Copy, Skeleton, Tooltip, toast } from "@medusajs/ui";
5
- import { CashSolid, PencilSquareSolid, Trash, CreditCard, Receipt, ArrowPath, ChevronDownMini, Check, InformationCircle, ExclamationCircle, MagnifierAlert, ChevronRightMini, CheckCircle, ArrowLeft, ClockSolid, ShieldCheck, SquareTwoStack } from "@medusajs/icons";
3
+ import { useState, useEffect, useRef, useMemo, useCallback } from "react";
4
+ import { Text, Container, Heading, Badge, Button, Label, Select, Textarea, Popover, clx, Input, Copy, Skeleton, Tooltip, toast } from "@medusajs/ui";
5
+ import { CashSolid, PencilSquareSolid, Trash, ChevronDownMini, Check, ArrowPath, InformationCircle, ExclamationCircle, MagnifierAlert, ChevronRightMini, CreditCard, Receipt, ArrowLeft, ClockSolid, ShieldCheck, SquareTwoStack, CheckCircle } from "@medusajs/icons";
6
6
  import { useNavigate, useLocation, useSearchParams, useParams } from "react-router-dom";
7
7
  function roundRectPath(ctx, x, y, w, h, r) {
8
8
  ctx.beginPath();
@@ -605,7 +605,7 @@ const OrderRefundContextWidget = (props) => {
605
605
  const mapping = context?.refund_mapping;
606
606
  const mode = mapping?.refund_mode;
607
607
  setEditRefundMode(
608
- mode === "offline" || mode === "online" ? mode : ""
608
+ mode === "offline" || mode === "online" || mode === "wallet" ? mode : ""
609
609
  );
610
610
  setEditDetails(mapping?.details ?? "");
611
611
  setEditImageUrls(mapping?.images ?? []);
@@ -653,7 +653,7 @@ const OrderRefundContextWidget = (props) => {
653
653
  headers: { "Content-Type": "application/json" },
654
654
  credentials: "include",
655
655
  body: JSON.stringify({
656
- refund_mode: editRefundMode === "offline" || editRefundMode === "online" ? editRefundMode : null,
656
+ refund_mode: editRefundMode === "offline" || editRefundMode === "online" || editRefundMode === "wallet" ? editRefundMode : null,
657
657
  details: editDetails.trim() || null,
658
658
  images: editImageUrls
659
659
  })
@@ -713,18 +713,15 @@ const OrderRefundContextWidget = (props) => {
713
713
  ] }),
714
714
  /* @__PURE__ */ jsxs("div", { className: "mt-3 space-y-2 border-t border-ui-border-base pt-3", children: [
715
715
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
716
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", className: "text-ui-fg-subtle", children: "Payment method (refund destination)" }),
717
- context.refund_mapping?.payment_id ? /* @__PURE__ */ jsx(Badge, { color: "green", children: "Customer specified" }) : paymentDetail ? /* @__PURE__ */ jsx(Badge, { color: "orange", children: "Customer default" }) : orderPayment && !orderPayment.is_cod ? /* @__PURE__ */ jsx(Badge, { color: "blue", children: "Original payment method" }) : null
716
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", className: "text-ui-fg-subtle", children: "Refund destination" }),
717
+ context.refund_mapping?.refund_mode === "wallet" || context.refund_mapping?.is_refunded ? /* @__PURE__ */ jsx(Badge, { color: "green", children: "Customer wallet" }) : /* @__PURE__ */ jsx(Badge, { color: "blue", children: "Customer wallet" })
718
+ ] }),
719
+ /* @__PURE__ */ jsx("div", { className: "rounded-md border border-ui-border-base bg-ui-bg-subtle px-3 py-2", children: /* @__PURE__ */ jsx(Text, { size: "xsmall", className: "text-ui-fg-muted", children: "Refunds are credited to the customer's wallet when the return is received. Offline UPI/bank payout is no longer the primary path." }) }),
720
+ paymentDetail && /* @__PURE__ */ jsxs(Text, { size: "xsmall", className: "text-ui-fg-muted", children: [
721
+ "Legacy linked ",
722
+ paymentDetail.type.toUpperCase(),
723
+ " on file (optional / historical)."
718
724
  ] }),
719
- context.refund_mapping?.payment_id && !paymentDetail && /* @__PURE__ */ jsx("div", { className: "rounded-md border border-orange-200 bg-orange-50 px-3 py-2", children: /* @__PURE__ */ jsx(Text, { size: "xsmall", className: "text-ui-fg-muted", children: "The customer specified a payment method for this return, but that payment method has since been removed from their account. Ask the customer to update their refund payment method." }) }),
720
- !context.refund_mapping?.payment_id && paymentDetail?.source === "default" && /* @__PURE__ */ jsx("div", { className: "rounded-md border border-ui-border-base bg-ui-bg-subtle px-3 py-2", children: /* @__PURE__ */ jsx(Text, { size: "xsmall", className: "text-ui-fg-muted", children: "The customer did not specify a payment method for this return. Showing their default payment method." }) }),
721
- !context.refund_mapping?.payment_id && !paymentDetail && orderPayment && !orderPayment.is_cod && /* @__PURE__ */ jsx("div", { className: "rounded-md border border-ui-border-base bg-ui-bg-subtle px-3 py-2", children: /* @__PURE__ */ jsxs(Text, { size: "xsmall", className: "text-ui-fg-muted", children: [
722
- "Refund will go to the original payment method (",
723
- orderPayment.label,
724
- ")."
725
- ] }) }),
726
- !context.refund_mapping?.payment_id && !paymentDetail && (context.is_cod || orderPayment?.is_cod) && /* @__PURE__ */ jsx("div", { className: "rounded-md border border-ui-border-base bg-ui-bg-subtle px-3 py-2", children: /* @__PURE__ */ jsx(Text, { size: "xsmall", className: "text-ui-fg-muted", children: "This order was paid with Cash on Delivery. No stored bank/UPI refund destination." }) }),
727
- !context.refund_mapping?.payment_id && !paymentDetail && !orderPayment && /* @__PURE__ */ jsx("div", { className: "rounded-md border border-ui-border-base bg-ui-bg-subtle px-3 py-2", children: /* @__PURE__ */ jsx(Text, { size: "xsmall", className: "text-ui-fg-muted", children: "No payment method found for this customer." }) }),
728
725
  paymentDetails.length > 0 && /* @__PURE__ */ jsx("div", { className: "space-y-3", children: paymentDetails.map((detail) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
729
726
  /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
730
727
  /* @__PURE__ */ jsx(Badge, { children: detail.type.toUpperCase() }),
@@ -786,8 +783,9 @@ const OrderRefundContextWidget = (props) => {
786
783
  children: [
787
784
  /* @__PURE__ */ jsx(Select.Trigger, { children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "Select mode" }) }),
788
785
  /* @__PURE__ */ jsxs(Select.Content, { children: [
789
- /* @__PURE__ */ jsx(Select.Item, { value: "offline", children: "Offline" }),
790
- /* @__PURE__ */ jsx(Select.Item, { value: "online", children: "Online" })
786
+ /* @__PURE__ */ jsx(Select.Item, { value: "wallet", children: "Wallet" }),
787
+ /* @__PURE__ */ jsx(Select.Item, { value: "offline", children: "Offline (legacy)" }),
788
+ /* @__PURE__ */ jsx(Select.Item, { value: "online", children: "Online (legacy)" })
791
789
  ] })
792
790
  ]
793
791
  }
@@ -867,7 +865,7 @@ const OrderRefundContextWidget = (props) => {
867
865
  ] }) : /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
868
866
  /* @__PURE__ */ jsxs("div", { children: [
869
867
  /* @__PURE__ */ jsx(Text, { size: "xsmall", weight: "plus", className: "text-ui-fg-muted", children: "Refund mode" }),
870
- /* @__PURE__ */ jsx(Text, { size: "small", className: "block", children: context.refund_mapping.refund_mode === "offline" ? "Offline" : context.refund_mapping.refund_mode === "online" ? "Online" : context.refund_mapping.refund_mode || "—" })
868
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "block", children: context.refund_mapping.refund_mode === "wallet" ? "Wallet" : context.refund_mapping.refund_mode === "offline" ? "Offline" : context.refund_mapping.refund_mode === "online" ? "Online" : context.refund_mapping.refund_mode || "—" })
871
869
  ] }),
872
870
  /* @__PURE__ */ jsxs("div", { children: [
873
871
  /* @__PURE__ */ jsx(Text, { size: "xsmall", weight: "plus", className: "text-ui-fg-muted", children: "Details" }),
@@ -923,742 +921,6 @@ const OrderRefundContextWidget = (props) => {
923
921
  defineWidgetConfig({
924
922
  zone: "order.details.after"
925
923
  });
926
- const useDebounce$3 = (value, delay) => {
927
- const [debouncedValue, setDebouncedValue] = useState(value);
928
- useEffect(() => {
929
- const handler = setTimeout(() => setDebouncedValue(value), delay);
930
- return () => clearTimeout(handler);
931
- }, [value, delay]);
932
- return debouncedValue;
933
- };
934
- const getStatusBadgeClass$7 = (status) => {
935
- const s2 = status.toLowerCase();
936
- if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
937
- if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
938
- if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
939
- if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
940
- return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
941
- };
942
- const PaymentsPage = () => {
943
- const navigate = useNavigate();
944
- const [items, setItems] = useState([]);
945
- const [statusFilter, setStatusFilter] = useState("all");
946
- const [orderIdSearch, setOrderIdSearch] = useState("");
947
- const debouncedOrderId = useDebounce$3(orderIdSearch, 300);
948
- const [isLoading, setIsLoading] = useState(true);
949
- const [isFetchingMore, setIsFetchingMore] = useState(false);
950
- const [error, setError] = useState(null);
951
- const [offset, setOffset] = useState(0);
952
- const [count, setCount] = useState(0);
953
- const limit = 50;
954
- const loadTransactions = useCallback(
955
- async (nextOffset, replace) => {
956
- try {
957
- if (replace) setIsLoading(true);
958
- else setIsFetchingMore(true);
959
- setError(null);
960
- const params = new URLSearchParams();
961
- params.set("limit", String(limit));
962
- params.set("offset", String(nextOffset));
963
- if (statusFilter !== "all") params.set("status", statusFilter);
964
- if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
965
- const response = await fetch(
966
- `/admin/payment-transactions?${params.toString()}`,
967
- { credentials: "include" }
968
- );
969
- if (!response.ok) {
970
- const text = await response.text();
971
- throw new Error(text || "Failed to load payment transactions");
972
- }
973
- const payload = await response.json();
974
- const list = payload.transactions ?? [];
975
- setCount(payload.count ?? 0);
976
- setOffset(nextOffset + list.length);
977
- setItems((prev) => replace ? list : [...prev, ...list]);
978
- } catch (e) {
979
- setError(e instanceof Error ? e.message : "Failed to load");
980
- } finally {
981
- setIsLoading(false);
982
- setIsFetchingMore(false);
983
- }
984
- },
985
- [statusFilter, debouncedOrderId]
986
- );
987
- useEffect(() => {
988
- void loadTransactions(0, true);
989
- }, [loadTransactions]);
990
- const hasMore = useMemo(() => offset < count, [offset, count]);
991
- const displayStatus = (t) => {
992
- const s2 = t.payment_id != null && t.payment_status != null && t.payment_status !== "" ? t.payment_status : t.session_status ?? "";
993
- return s2 !== "" ? s2 : "—";
994
- };
995
- const displayAmount = (t) => {
996
- const code = (t.currency_code ?? "USD").toUpperCase();
997
- return `${code} ${Number(t.amount)}`;
998
- };
999
- return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
1000
- /* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
1001
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
1002
- /* @__PURE__ */ jsx(Heading, { level: "h1", children: "Payments" }),
1003
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "All payment attempts — completed, pending, failed, requires action" })
1004
- ] }),
1005
- /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () => loadTransactions(0, true), children: "Refresh" })
1006
- ] }),
1007
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
1008
- /* @__PURE__ */ jsx(
1009
- Input,
1010
- {
1011
- placeholder: "Search by Order ID",
1012
- value: orderIdSearch,
1013
- onChange: (e) => setOrderIdSearch(e.target.value),
1014
- className: "md:max-w-sm",
1015
- "aria-label": "Search by order ID"
1016
- }
1017
- ),
1018
- /* @__PURE__ */ jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsxs(
1019
- "select",
1020
- {
1021
- value: statusFilter,
1022
- onChange: (e) => setStatusFilter(e.target.value),
1023
- 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",
1024
- "aria-label": "Filter by status",
1025
- children: [
1026
- /* @__PURE__ */ jsx("option", { value: "all", children: "All statuses" }),
1027
- /* @__PURE__ */ jsx("option", { value: "pending", children: "Pending" }),
1028
- /* @__PURE__ */ jsx("option", { value: "requires_more", children: "Requires more" }),
1029
- /* @__PURE__ */ jsx("option", { value: "error", children: "Error" }),
1030
- /* @__PURE__ */ jsx("option", { value: "canceled", children: "Canceled" }),
1031
- /* @__PURE__ */ jsx("option", { value: "authorized", children: "Authorized" }),
1032
- /* @__PURE__ */ jsx("option", { value: "captured", children: "Captured" })
1033
- ]
1034
- }
1035
- ) })
1036
- ] }),
1037
- error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
1038
- /* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
1039
- /* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => loadTransactions(0, true), children: "Try again" }) })
1040
- ] }) : null,
1041
- isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading payments…" }) }) : items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
1042
- /* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No payment transactions yet" }),
1043
- /* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Payment attempts will appear here." })
1044
- ] }) : /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
1045
- /* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
1046
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
1047
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Amount" }),
1048
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Provider" }),
1049
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
1050
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Finalized" }),
1051
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
1052
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
1053
- ] }) }),
1054
- /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((t) => /* @__PURE__ */ jsxs(
1055
- "tr",
1056
- {
1057
- className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
1058
- onClick: () => navigate(`/payments/${t.payment_session_id}`),
1059
- children: [
1060
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: t.order_id ?? "—" }),
1061
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: displayAmount(t) }),
1062
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.provider_id }),
1063
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
1064
- Badge,
1065
- {
1066
- size: "2xsmall",
1067
- className: `uppercase ${getStatusBadgeClass$7(displayStatus(t))}`,
1068
- children: displayStatus(t) !== "—" ? displayStatus(t).replace(/_/g, " ") : "—"
1069
- }
1070
- ) }),
1071
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.payment_id != null ? "Yes" : "No" }),
1072
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(t.created_at).toLocaleDateString("en-US", {
1073
- year: "numeric",
1074
- month: "short",
1075
- day: "numeric",
1076
- hour: "numeric",
1077
- minute: "2-digit",
1078
- hour12: true
1079
- }) }),
1080
- /* @__PURE__ */ jsxs("td", { className: "px-4 py-4", children: [
1081
- /* @__PURE__ */ jsx(
1082
- Button,
1083
- {
1084
- variant: "transparent",
1085
- size: "small",
1086
- onClick: (e) => {
1087
- e.stopPropagation();
1088
- navigate(`/payments/${t.payment_session_id}`);
1089
- },
1090
- children: "View details"
1091
- }
1092
- ),
1093
- t.order_id ? /* @__PURE__ */ jsx(
1094
- Button,
1095
- {
1096
- variant: "transparent",
1097
- size: "small",
1098
- onClick: (e) => {
1099
- e.stopPropagation();
1100
- navigate(`/orders/${t.order_id}`);
1101
- },
1102
- children: "Order"
1103
- }
1104
- ) : null
1105
- ] })
1106
- ]
1107
- },
1108
- t.payment_session_id
1109
- )) })
1110
- ] }) }),
1111
- hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
1112
- Button,
1113
- {
1114
- variant: "secondary",
1115
- isLoading: isFetchingMore,
1116
- onClick: () => loadTransactions(offset, false),
1117
- children: "Load more"
1118
- }
1119
- ) }) : null
1120
- ] }) });
1121
- };
1122
- const config$9 = defineRouteConfig({
1123
- label: "Payments",
1124
- icon: CreditCard
1125
- });
1126
- const useDebounce$2 = (value, delay) => {
1127
- const [debouncedValue, setDebouncedValue] = useState(value);
1128
- useEffect(() => {
1129
- const handler = setTimeout(() => setDebouncedValue(value), delay);
1130
- return () => clearTimeout(handler);
1131
- }, [value, delay]);
1132
- return debouncedValue;
1133
- };
1134
- const getStatusBadgeClass$6 = (status) => {
1135
- const s2 = status.toLowerCase();
1136
- if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
1137
- if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
1138
- if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
1139
- if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
1140
- return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
1141
- };
1142
- const RefundsPage = () => {
1143
- const navigate = useNavigate();
1144
- const [items, setItems] = useState([]);
1145
- const [orderIdSearch, setOrderIdSearch] = useState("");
1146
- const debouncedOrderId = useDebounce$2(orderIdSearch, 300);
1147
- const [paymentStatusFilter, setPaymentStatusFilter] = useState("all");
1148
- const [providerSearch, setProviderSearch] = useState("");
1149
- const debouncedProvider = useDebounce$2(providerSearch, 300);
1150
- const [currencySearch, setCurrencySearch] = useState("");
1151
- const debouncedCurrency = useDebounce$2(currencySearch, 300);
1152
- const [dateFrom, setDateFrom] = useState("");
1153
- const [dateTo, setDateTo] = useState("");
1154
- const [amountMin, setAmountMin] = useState("");
1155
- const [amountMax, setAmountMax] = useState("");
1156
- const [isLoading, setIsLoading] = useState(true);
1157
- const [isFetchingMore, setIsFetchingMore] = useState(false);
1158
- const [error, setError] = useState(null);
1159
- const [offset, setOffset] = useState(0);
1160
- const [count, setCount] = useState(0);
1161
- const limit = 50;
1162
- const loadRefunds = useCallback(
1163
- async (nextOffset, replace) => {
1164
- try {
1165
- if (replace) setIsLoading(true);
1166
- else setIsFetchingMore(true);
1167
- setError(null);
1168
- const params = new URLSearchParams();
1169
- params.set("limit", String(limit));
1170
- params.set("offset", String(nextOffset));
1171
- if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
1172
- if (paymentStatusFilter !== "all") params.set("payment_status", paymentStatusFilter);
1173
- if (debouncedProvider.trim()) params.set("provider_id", debouncedProvider.trim());
1174
- if (debouncedCurrency.trim()) params.set("currency_code", debouncedCurrency.trim());
1175
- if (dateFrom.trim()) params.set("date_from", dateFrom.trim());
1176
- if (dateTo.trim()) params.set("date_to", dateTo.trim());
1177
- const min = amountMin.trim() ? Number(amountMin) : void 0;
1178
- const max = amountMax.trim() ? Number(amountMax) : void 0;
1179
- if (min != null && !Number.isNaN(min)) params.set("amount_min", String(min));
1180
- if (max != null && !Number.isNaN(max)) params.set("amount_max", String(max));
1181
- const response = await fetch(`/admin/refunds?${params.toString()}`, {
1182
- credentials: "include"
1183
- });
1184
- if (!response.ok) {
1185
- const text = await response.text();
1186
- throw new Error(text || "Failed to load refunds");
1187
- }
1188
- const payload = await response.json();
1189
- const list = payload.refunds ?? [];
1190
- setCount(payload.count ?? 0);
1191
- setOffset(nextOffset + list.length);
1192
- setItems((prev) => replace ? list : [...prev, ...list]);
1193
- } catch (e) {
1194
- setError(e instanceof Error ? e.message : "Failed to load");
1195
- } finally {
1196
- setIsLoading(false);
1197
- setIsFetchingMore(false);
1198
- }
1199
- },
1200
- [
1201
- debouncedOrderId,
1202
- paymentStatusFilter,
1203
- debouncedProvider,
1204
- debouncedCurrency,
1205
- dateFrom,
1206
- dateTo,
1207
- amountMin,
1208
- amountMax
1209
- ]
1210
- );
1211
- useEffect(() => {
1212
- void loadRefunds(0, true);
1213
- }, [loadRefunds]);
1214
- const hasMore = useMemo(() => offset < count, [offset, count]);
1215
- const displayAmount = (r) => {
1216
- const code = (r.currency_code ?? "USD").toUpperCase();
1217
- return `${code} ${Number(r.amount)}`;
1218
- };
1219
- const displayStatus = (r) => {
1220
- const s2 = r.payment_status ?? "";
1221
- return s2 !== "" ? s2 : "—";
1222
- };
1223
- return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
1224
- /* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
1225
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
1226
- /* @__PURE__ */ jsx(Heading, { level: "h1", children: "Refunds" }),
1227
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Refund records — amount, order, payment status" })
1228
- ] }),
1229
- /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () => loadRefunds(0, true), children: "Refresh" })
1230
- ] }),
1231
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
1232
- /* @__PURE__ */ jsx(
1233
- Input,
1234
- {
1235
- placeholder: "Order ID",
1236
- value: orderIdSearch,
1237
- onChange: (e) => setOrderIdSearch(e.target.value),
1238
- className: "md:max-w-[180px]",
1239
- "aria-label": "Filter by order ID"
1240
- }
1241
- ),
1242
- /* @__PURE__ */ jsx(
1243
- Input,
1244
- {
1245
- placeholder: "Provider",
1246
- value: providerSearch,
1247
- onChange: (e) => setProviderSearch(e.target.value),
1248
- className: "md:max-w-[140px]",
1249
- "aria-label": "Filter by provider"
1250
- }
1251
- ),
1252
- /* @__PURE__ */ jsx(
1253
- Input,
1254
- {
1255
- placeholder: "Currency",
1256
- value: currencySearch,
1257
- onChange: (e) => setCurrencySearch(e.target.value),
1258
- className: "md:max-w-[100px]",
1259
- "aria-label": "Filter by currency"
1260
- }
1261
- ),
1262
- /* @__PURE__ */ jsxs(
1263
- "select",
1264
- {
1265
- value: paymentStatusFilter,
1266
- onChange: (e) => setPaymentStatusFilter(e.target.value),
1267
- 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]",
1268
- "aria-label": "Filter by payment status",
1269
- children: [
1270
- /* @__PURE__ */ jsx("option", { value: "all", children: "All statuses" }),
1271
- /* @__PURE__ */ jsx("option", { value: "pending", children: "Pending" }),
1272
- /* @__PURE__ */ jsx("option", { value: "requires_more", children: "Requires more" }),
1273
- /* @__PURE__ */ jsx("option", { value: "error", children: "Error" }),
1274
- /* @__PURE__ */ jsx("option", { value: "canceled", children: "Canceled" }),
1275
- /* @__PURE__ */ jsx("option", { value: "authorized", children: "Authorized" }),
1276
- /* @__PURE__ */ jsx("option", { value: "captured", children: "Captured" })
1277
- ]
1278
- }
1279
- ),
1280
- /* @__PURE__ */ jsx(
1281
- Input,
1282
- {
1283
- type: "date",
1284
- placeholder: "From",
1285
- value: dateFrom,
1286
- onChange: (e) => setDateFrom(e.target.value),
1287
- className: "md:max-w-[140px]",
1288
- "aria-label": "Date from"
1289
- }
1290
- ),
1291
- /* @__PURE__ */ jsx(
1292
- Input,
1293
- {
1294
- type: "date",
1295
- placeholder: "To",
1296
- value: dateTo,
1297
- onChange: (e) => setDateTo(e.target.value),
1298
- className: "md:max-w-[140px]",
1299
- "aria-label": "Date to"
1300
- }
1301
- ),
1302
- /* @__PURE__ */ jsx(
1303
- Input,
1304
- {
1305
- placeholder: "Amount min",
1306
- value: amountMin,
1307
- onChange: (e) => setAmountMin(e.target.value),
1308
- type: "number",
1309
- min: 0,
1310
- className: "md:max-w-[100px]",
1311
- "aria-label": "Refund amount minimum"
1312
- }
1313
- ),
1314
- /* @__PURE__ */ jsx(
1315
- Input,
1316
- {
1317
- placeholder: "Amount max",
1318
- value: amountMax,
1319
- onChange: (e) => setAmountMax(e.target.value),
1320
- type: "number",
1321
- min: 0,
1322
- className: "md:max-w-[100px]",
1323
- "aria-label": "Refund amount maximum"
1324
- }
1325
- )
1326
- ] }) }),
1327
- error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
1328
- /* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
1329
- /* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => loadRefunds(0, true), children: "Try again" }) })
1330
- ] }) : null,
1331
- isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading refunds…" }) }) : items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
1332
- /* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No refunds yet" }),
1333
- /* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Refund records will appear here." })
1334
- ] }) : /* @__PURE__ */ jsx("div", { className: "w-full overflow-x-auto rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "w-full table-fixed divide-y divide-ui-border-base", style: { minWidth: 0 }, children: [
1335
- /* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
1336
- /* @__PURE__ */ jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Refund ID" }),
1337
- /* @__PURE__ */ jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
1338
- /* @__PURE__ */ jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Payment ID" }),
1339
- /* @__PURE__ */ jsx("th", { className: "w-[8%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Amount" }),
1340
- /* @__PURE__ */ jsx("th", { className: "w-[6%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Currency" }),
1341
- /* @__PURE__ */ jsx("th", { className: "w-[10%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Provider" }),
1342
- /* @__PURE__ */ jsx("th", { className: "w-[10%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Payment Status" }),
1343
- /* @__PURE__ */ jsx("th", { className: "w-[14%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Note" }),
1344
- /* @__PURE__ */ jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
1345
- /* @__PURE__ */ jsx("th", { className: "w-[8%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
1346
- ] }) }),
1347
- /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((r) => /* @__PURE__ */ jsxs(
1348
- "tr",
1349
- {
1350
- className: "cursor-pointer hover:bg-ui-bg-subtle/60",
1351
- onClick: () => navigate(`/refunds/${r.refund_id}`),
1352
- children: [
1353
- /* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 font-mono text-sm text-ui-fg-base", title: r.refund_id, children: r.refund_id }),
1354
- /* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 font-medium text-ui-fg-base", title: r.order_id ?? void 0, children: r.order_id ?? "—" }),
1355
- /* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 font-mono text-sm text-ui-fg-subtle", title: r.payment_id, children: r.payment_id }),
1356
- /* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", children: displayAmount(r) }),
1357
- /* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle uppercase", children: r.currency_code || "—" }),
1358
- /* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", title: r.provider_id || void 0, children: r.provider_id || "—" }),
1359
- /* @__PURE__ */ jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsx(
1360
- Badge,
1361
- {
1362
- size: "2xsmall",
1363
- className: `uppercase ${getStatusBadgeClass$6(displayStatus(r))}`,
1364
- children: displayStatus(r) !== "—" ? displayStatus(r).replace(/_/g, " ") : "—"
1365
- }
1366
- ) }),
1367
- /* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", title: r.note ?? void 0, children: r.note ?? "—" }),
1368
- /* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle text-xs", children: new Date(r.created_at).toLocaleDateString("en-US", {
1369
- month: "short",
1370
- day: "numeric",
1371
- hour: "numeric",
1372
- minute: "2-digit",
1373
- hour12: true
1374
- }) }),
1375
- /* @__PURE__ */ jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1", children: [
1376
- /* @__PURE__ */ jsx(
1377
- Button,
1378
- {
1379
- variant: "transparent",
1380
- size: "small",
1381
- onClick: (e) => {
1382
- e.stopPropagation();
1383
- navigate(`/refunds/${r.refund_id}`);
1384
- },
1385
- children: "Details"
1386
- }
1387
- ),
1388
- r.order_id ? /* @__PURE__ */ jsx(
1389
- Button,
1390
- {
1391
- variant: "transparent",
1392
- size: "small",
1393
- onClick: (e) => {
1394
- e.stopPropagation();
1395
- navigate(`/orders/${r.order_id}`);
1396
- },
1397
- children: "Order"
1398
- }
1399
- ) : null
1400
- ] }) })
1401
- ]
1402
- },
1403
- r.refund_id
1404
- )) })
1405
- ] }) }),
1406
- hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
1407
- Button,
1408
- {
1409
- variant: "secondary",
1410
- isLoading: isFetchingMore,
1411
- onClick: () => loadRefunds(offset, false),
1412
- children: "Load more"
1413
- }
1414
- ) }) : null
1415
- ] }) });
1416
- };
1417
- const config$8 = defineRouteConfig({
1418
- label: "Refunds",
1419
- icon: Receipt
1420
- });
1421
- const useDebounce$1 = (value, delay) => {
1422
- const [debouncedValue, setDebouncedValue] = useState(value);
1423
- useEffect(() => {
1424
- const handler = setTimeout(() => setDebouncedValue(value), delay);
1425
- return () => clearTimeout(handler);
1426
- }, [value, delay]);
1427
- return debouncedValue;
1428
- };
1429
- const getStatusBadgeClass$5 = (status) => {
1430
- const statusLower = status.toLowerCase();
1431
- if (statusLower === "requested") {
1432
- return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
1433
- }
1434
- if (statusLower === "received") {
1435
- return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
1436
- }
1437
- if (statusLower === "requires_action") {
1438
- return "bg-ui-tag-red-bg text-ui-tag-red-text";
1439
- }
1440
- if (statusLower === "completed") {
1441
- return "bg-ui-tag-green-bg text-ui-tag-green-text";
1442
- }
1443
- if (statusLower === "canceled") {
1444
- return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
1445
- }
1446
- return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
1447
- };
1448
- const ReturnsPage = () => {
1449
- const navigate = useNavigate();
1450
- const [items, setItems] = useState([]);
1451
- const [statusFilter, setStatusFilter] = useState("all");
1452
- const [createdByFilter, setCreatedByFilter] = useState("all");
1453
- const [searchQuery, setSearchQuery] = useState("");
1454
- const debouncedSearchQuery = useDebounce$1(searchQuery, 300);
1455
- const [isLoading, setIsLoading] = useState(true);
1456
- const [isFetchingMore, setIsFetchingMore] = useState(false);
1457
- const [error, setError] = useState(null);
1458
- const [offset, setOffset] = useState(0);
1459
- const [count, setCount] = useState(0);
1460
- const limit = 50;
1461
- const loadReturns = useCallback(
1462
- async (nextOffset, replace = false) => {
1463
- try {
1464
- if (replace) {
1465
- setIsLoading(true);
1466
- } else {
1467
- setIsFetchingMore(true);
1468
- }
1469
- setError(null);
1470
- const params = new URLSearchParams();
1471
- params.set("limit", String(limit));
1472
- params.set("offset", String(nextOffset));
1473
- if (statusFilter !== "all") {
1474
- params.set("status", statusFilter);
1475
- }
1476
- if (debouncedSearchQuery.trim()) {
1477
- params.set("q", debouncedSearchQuery.trim());
1478
- }
1479
- if (createdByFilter !== "all") {
1480
- params.set("created_by", createdByFilter);
1481
- }
1482
- params.set("order", "created_at");
1483
- const response = await fetch(
1484
- `/admin/return?${params.toString()}`,
1485
- { credentials: "include" }
1486
- );
1487
- if (!response.ok) {
1488
- const message = await response.text();
1489
- throw new Error(message || "Unable to load return orders");
1490
- }
1491
- const payload = await response.json();
1492
- setCount(payload.count ?? 0);
1493
- setOffset(nextOffset + (payload.returns?.length ?? 0));
1494
- setItems(
1495
- (prev) => replace ? payload.returns ?? [] : [...prev, ...payload.returns ?? []]
1496
- );
1497
- } catch (loadError) {
1498
- const message = loadError instanceof Error ? loadError.message : "Unable to load return orders";
1499
- setError(message);
1500
- } finally {
1501
- setIsLoading(false);
1502
- setIsFetchingMore(false);
1503
- }
1504
- },
1505
- [statusFilter, createdByFilter, debouncedSearchQuery]
1506
- );
1507
- useEffect(() => {
1508
- void loadReturns(0, true);
1509
- }, [statusFilter, createdByFilter, debouncedSearchQuery, loadReturns]);
1510
- const hasMore = useMemo(() => offset < count, [offset, count]);
1511
- const availableStatuses = useMemo(() => {
1512
- const statuses = /* @__PURE__ */ new Set();
1513
- items.forEach((item) => statuses.add(item.status));
1514
- return Array.from(statuses).sort();
1515
- }, [items]);
1516
- return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
1517
- /* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
1518
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
1519
- /* @__PURE__ */ jsx(Heading, { level: "h1", children: "Return Orders" }),
1520
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "View and manage all customer return orders" })
1521
- ] }),
1522
- /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () => loadReturns(0, true), children: "Refresh" })
1523
- ] }),
1524
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
1525
- /* @__PURE__ */ jsx(
1526
- Input,
1527
- {
1528
- placeholder: "Search by return ID, order ID, or customer email",
1529
- value: searchQuery,
1530
- onChange: (event) => setSearchQuery(event.target.value),
1531
- className: "md:max-w-sm"
1532
- }
1533
- ),
1534
- /* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
1535
- /* @__PURE__ */ jsxs(
1536
- "select",
1537
- {
1538
- value: createdByFilter,
1539
- onChange: (event) => setCreatedByFilter(event.target.value),
1540
- 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",
1541
- children: [
1542
- /* @__PURE__ */ jsx("option", { value: "all", children: "All (Created by)" }),
1543
- /* @__PURE__ */ jsx("option", { value: "customer", children: "Customer" }),
1544
- /* @__PURE__ */ jsx("option", { value: "admin", children: "Admin" })
1545
- ]
1546
- }
1547
- ),
1548
- /* @__PURE__ */ jsxs(
1549
- "select",
1550
- {
1551
- value: statusFilter,
1552
- onChange: (event) => setStatusFilter(event.target.value),
1553
- 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",
1554
- children: [
1555
- /* @__PURE__ */ jsx("option", { value: "all", children: "All Statuses" }),
1556
- availableStatuses.map((status) => /* @__PURE__ */ jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
1557
- ]
1558
- }
1559
- )
1560
- ] })
1561
- ] }),
1562
- error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
1563
- /* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
1564
- /* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(
1565
- Button,
1566
- {
1567
- variant: "secondary",
1568
- onClick: () => loadReturns(0, true),
1569
- children: "Try again"
1570
- }
1571
- ) })
1572
- ] }) : null,
1573
- isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading return orders..." }) }) : items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
1574
- /* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No return orders yet" }),
1575
- /* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Return orders created by customers will appear here." })
1576
- ] }) : /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
1577
- /* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
1578
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Return ID" }),
1579
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
1580
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Customer" }),
1581
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
1582
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Refund Amount" }),
1583
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
1584
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
1585
- ] }) }),
1586
- /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((returnOrder) => /* @__PURE__ */ jsxs(
1587
- "tr",
1588
- {
1589
- className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
1590
- onClick: () => navigate(`/returns/${returnOrder.id}`),
1591
- children: [
1592
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children: /* @__PURE__ */ jsx("span", { children: returnOrder.id }) }) }),
1593
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.order_id }),
1594
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.customer_email || returnOrder.order_email || "—" }),
1595
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
1596
- Badge,
1597
- {
1598
- size: "2xsmall",
1599
- className: `uppercase ${getStatusBadgeClass$5(returnOrder.status)}`,
1600
- children: returnOrder.status.replace(/_/g, " ")
1601
- }
1602
- ) }),
1603
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
1604
- const calc = returnOrder.refund;
1605
- if (calc?.is_processed && calc.final_refund_amount != null) {
1606
- return formatRefundCurrency(
1607
- calc.final_refund_amount,
1608
- calc.currency_code || returnOrder.currency_code
1609
- );
1610
- }
1611
- if (calc) {
1612
- return "Pending";
1613
- }
1614
- if (returnOrder.refund_amount == null) {
1615
- return "—";
1616
- }
1617
- return formatRefundCurrency(
1618
- Number(returnOrder.refund_amount),
1619
- returnOrder.currency_code
1620
- );
1621
- })() }),
1622
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(returnOrder.created_at).toLocaleDateString("en-US", {
1623
- year: "numeric",
1624
- month: "short",
1625
- day: "numeric",
1626
- hour: "numeric",
1627
- minute: "2-digit",
1628
- hour12: true
1629
- }) }),
1630
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
1631
- Button,
1632
- {
1633
- variant: "transparent",
1634
- size: "small",
1635
- onClick: (e) => {
1636
- e.stopPropagation();
1637
- navigate(`/app/orders/${returnOrder.order_id}`);
1638
- },
1639
- children: "Go to order"
1640
- }
1641
- ) })
1642
- ]
1643
- },
1644
- returnOrder.id
1645
- )) })
1646
- ] }) }),
1647
- hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
1648
- Button,
1649
- {
1650
- variant: "secondary",
1651
- isLoading: isFetchingMore,
1652
- onClick: () => loadReturns(offset, false),
1653
- children: "Load more"
1654
- }
1655
- ) }) : null
1656
- ] }) });
1657
- };
1658
- const config$7 = defineRouteConfig({
1659
- label: "Return Orders",
1660
- icon: ArrowPath
1661
- });
1662
924
  const AUDITED_TABLE_NAMES = [
1663
925
  "account_deletion_request",
1664
926
  "account_holder",
@@ -2944,11 +2206,211 @@ const ErrorState = ({ onRetry, detail }) => /* @__PURE__ */ jsxs("div", { classN
2944
2206
  /* @__PURE__ */ jsx(Text, { size: "xsmall", className: "max-w-md font-mono text-ui-fg-muted", children: detail }),
2945
2207
  /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "small", className: "mt-2", onClick: onRetry, children: "Try again" })
2946
2208
  ] });
2947
- const config$6 = defineRouteConfig({
2209
+ const config$9 = defineRouteConfig({
2948
2210
  label: "Deleted Records",
2949
2211
  icon: Trash
2950
2212
  });
2951
- const useDebounce = (value, delay) => {
2213
+ const useDebounce$3 = (value, delay) => {
2214
+ const [debouncedValue, setDebouncedValue] = useState(value);
2215
+ useEffect(() => {
2216
+ const handler = setTimeout(() => setDebouncedValue(value), delay);
2217
+ return () => clearTimeout(handler);
2218
+ }, [value, delay]);
2219
+ return debouncedValue;
2220
+ };
2221
+ const getStatusBadgeClass$7 = (status) => {
2222
+ const s2 = status.toLowerCase();
2223
+ if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
2224
+ if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
2225
+ if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
2226
+ if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
2227
+ return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
2228
+ };
2229
+ const PaymentsPage = () => {
2230
+ const navigate = useNavigate();
2231
+ const [items, setItems] = useState([]);
2232
+ const [statusFilter, setStatusFilter] = useState("all");
2233
+ const [orderIdSearch, setOrderIdSearch] = useState("");
2234
+ const debouncedOrderId = useDebounce$3(orderIdSearch, 300);
2235
+ const [isLoading, setIsLoading] = useState(true);
2236
+ const [isFetchingMore, setIsFetchingMore] = useState(false);
2237
+ const [error, setError] = useState(null);
2238
+ const [offset, setOffset] = useState(0);
2239
+ const [count, setCount] = useState(0);
2240
+ const limit = 50;
2241
+ const loadTransactions = useCallback(
2242
+ async (nextOffset, replace) => {
2243
+ try {
2244
+ if (replace) setIsLoading(true);
2245
+ else setIsFetchingMore(true);
2246
+ setError(null);
2247
+ const params = new URLSearchParams();
2248
+ params.set("limit", String(limit));
2249
+ params.set("offset", String(nextOffset));
2250
+ if (statusFilter !== "all") params.set("status", statusFilter);
2251
+ if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
2252
+ const response = await fetch(
2253
+ `/admin/payment-transactions?${params.toString()}`,
2254
+ { credentials: "include" }
2255
+ );
2256
+ if (!response.ok) {
2257
+ const text = await response.text();
2258
+ throw new Error(text || "Failed to load payment transactions");
2259
+ }
2260
+ const payload = await response.json();
2261
+ const list = payload.transactions ?? [];
2262
+ setCount(payload.count ?? 0);
2263
+ setOffset(nextOffset + list.length);
2264
+ setItems((prev) => replace ? list : [...prev, ...list]);
2265
+ } catch (e) {
2266
+ setError(e instanceof Error ? e.message : "Failed to load");
2267
+ } finally {
2268
+ setIsLoading(false);
2269
+ setIsFetchingMore(false);
2270
+ }
2271
+ },
2272
+ [statusFilter, debouncedOrderId]
2273
+ );
2274
+ useEffect(() => {
2275
+ void loadTransactions(0, true);
2276
+ }, [loadTransactions]);
2277
+ const hasMore = useMemo(() => offset < count, [offset, count]);
2278
+ const displayStatus = (t) => {
2279
+ const s2 = t.payment_id != null && t.payment_status != null && t.payment_status !== "" ? t.payment_status : t.session_status ?? "";
2280
+ return s2 !== "" ? s2 : "—";
2281
+ };
2282
+ const displayAmount = (t) => {
2283
+ const code = (t.currency_code ?? "USD").toUpperCase();
2284
+ return `${code} ${Number(t.amount)}`;
2285
+ };
2286
+ return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
2287
+ /* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
2288
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
2289
+ /* @__PURE__ */ jsx(Heading, { level: "h1", children: "Payments" }),
2290
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "All payment attempts — completed, pending, failed, requires action" })
2291
+ ] }),
2292
+ /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () => loadTransactions(0, true), children: "Refresh" })
2293
+ ] }),
2294
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
2295
+ /* @__PURE__ */ jsx(
2296
+ Input,
2297
+ {
2298
+ placeholder: "Search by Order ID",
2299
+ value: orderIdSearch,
2300
+ onChange: (e) => setOrderIdSearch(e.target.value),
2301
+ className: "md:max-w-sm",
2302
+ "aria-label": "Search by order ID"
2303
+ }
2304
+ ),
2305
+ /* @__PURE__ */ jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsxs(
2306
+ "select",
2307
+ {
2308
+ value: statusFilter,
2309
+ onChange: (e) => setStatusFilter(e.target.value),
2310
+ 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",
2311
+ "aria-label": "Filter by status",
2312
+ children: [
2313
+ /* @__PURE__ */ jsx("option", { value: "all", children: "All statuses" }),
2314
+ /* @__PURE__ */ jsx("option", { value: "pending", children: "Pending" }),
2315
+ /* @__PURE__ */ jsx("option", { value: "requires_more", children: "Requires more" }),
2316
+ /* @__PURE__ */ jsx("option", { value: "error", children: "Error" }),
2317
+ /* @__PURE__ */ jsx("option", { value: "canceled", children: "Canceled" }),
2318
+ /* @__PURE__ */ jsx("option", { value: "authorized", children: "Authorized" }),
2319
+ /* @__PURE__ */ jsx("option", { value: "captured", children: "Captured" })
2320
+ ]
2321
+ }
2322
+ ) })
2323
+ ] }),
2324
+ error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
2325
+ /* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
2326
+ /* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => loadTransactions(0, true), children: "Try again" }) })
2327
+ ] }) : null,
2328
+ isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading payments…" }) }) : items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
2329
+ /* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No payment transactions yet" }),
2330
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Payment attempts will appear here." })
2331
+ ] }) : /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
2332
+ /* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
2333
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
2334
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Amount" }),
2335
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Provider" }),
2336
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
2337
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Finalized" }),
2338
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
2339
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
2340
+ ] }) }),
2341
+ /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((t) => /* @__PURE__ */ jsxs(
2342
+ "tr",
2343
+ {
2344
+ className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
2345
+ onClick: () => navigate(`/payments/${t.payment_session_id}`),
2346
+ children: [
2347
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: t.order_id ?? "—" }),
2348
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: displayAmount(t) }),
2349
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.provider_id }),
2350
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
2351
+ Badge,
2352
+ {
2353
+ size: "2xsmall",
2354
+ className: `uppercase ${getStatusBadgeClass$7(displayStatus(t))}`,
2355
+ children: displayStatus(t) !== "—" ? displayStatus(t).replace(/_/g, " ") : "—"
2356
+ }
2357
+ ) }),
2358
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.payment_id != null ? "Yes" : "No" }),
2359
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(t.created_at).toLocaleDateString("en-US", {
2360
+ year: "numeric",
2361
+ month: "short",
2362
+ day: "numeric",
2363
+ hour: "numeric",
2364
+ minute: "2-digit",
2365
+ hour12: true
2366
+ }) }),
2367
+ /* @__PURE__ */ jsxs("td", { className: "px-4 py-4", children: [
2368
+ /* @__PURE__ */ jsx(
2369
+ Button,
2370
+ {
2371
+ variant: "transparent",
2372
+ size: "small",
2373
+ onClick: (e) => {
2374
+ e.stopPropagation();
2375
+ navigate(`/payments/${t.payment_session_id}`);
2376
+ },
2377
+ children: "View details"
2378
+ }
2379
+ ),
2380
+ t.order_id ? /* @__PURE__ */ jsx(
2381
+ Button,
2382
+ {
2383
+ variant: "transparent",
2384
+ size: "small",
2385
+ onClick: (e) => {
2386
+ e.stopPropagation();
2387
+ navigate(`/orders/${t.order_id}`);
2388
+ },
2389
+ children: "Order"
2390
+ }
2391
+ ) : null
2392
+ ] })
2393
+ ]
2394
+ },
2395
+ t.payment_session_id
2396
+ )) })
2397
+ ] }) }),
2398
+ hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
2399
+ Button,
2400
+ {
2401
+ variant: "secondary",
2402
+ isLoading: isFetchingMore,
2403
+ onClick: () => loadTransactions(offset, false),
2404
+ children: "Load more"
2405
+ }
2406
+ ) }) : null
2407
+ ] }) });
2408
+ };
2409
+ const config$8 = defineRouteConfig({
2410
+ label: "Payments",
2411
+ icon: CreditCard
2412
+ });
2413
+ const useDebounce$2 = (value, delay) => {
2952
2414
  const [debouncedValue, setDebouncedValue] = useState(value);
2953
2415
  useEffect(() => {
2954
2416
  const handler = setTimeout(() => setDebouncedValue(value), delay);
@@ -2956,210 +2418,276 @@ const useDebounce = (value, delay) => {
2956
2418
  }, [value, delay]);
2957
2419
  return debouncedValue;
2958
2420
  };
2959
- const getStatusBadgeClass$4 = (status) => {
2960
- const statusLower = status.toLowerCase();
2961
- if (statusLower === "requested") {
2962
- return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
2963
- }
2964
- if (statusLower === "approved") {
2965
- return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
2966
- }
2967
- if (statusLower === "rejected") {
2968
- return "bg-ui-tag-red-bg text-ui-tag-red-text";
2969
- }
2970
- if (statusLower === "completed") {
2971
- return "bg-ui-tag-green-bg text-ui-tag-green-text";
2972
- }
2973
- if (statusLower === "cancelled") {
2974
- return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
2975
- }
2421
+ const getStatusBadgeClass$6 = (status) => {
2422
+ const s2 = status.toLowerCase();
2423
+ if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
2424
+ if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
2425
+ if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
2426
+ if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
2976
2427
  return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
2977
2428
  };
2978
- const SwapsPage = () => {
2429
+ const RefundsPage = () => {
2979
2430
  const navigate = useNavigate();
2980
2431
  const [items, setItems] = useState([]);
2981
- const [statusFilter, setStatusFilter] = useState("all");
2982
- const [createdByFilter, setCreatedByFilter] = useState("all");
2983
- const [searchQuery, setSearchQuery] = useState("");
2984
- const debouncedSearchQuery = useDebounce(searchQuery, 300);
2432
+ const [orderIdSearch, setOrderIdSearch] = useState("");
2433
+ const debouncedOrderId = useDebounce$2(orderIdSearch, 300);
2434
+ const [paymentStatusFilter, setPaymentStatusFilter] = useState("all");
2435
+ const [providerSearch, setProviderSearch] = useState("");
2436
+ const debouncedProvider = useDebounce$2(providerSearch, 300);
2437
+ const [currencySearch, setCurrencySearch] = useState("");
2438
+ const debouncedCurrency = useDebounce$2(currencySearch, 300);
2439
+ const [dateFrom, setDateFrom] = useState("");
2440
+ const [dateTo, setDateTo] = useState("");
2441
+ const [amountMin, setAmountMin] = useState("");
2442
+ const [amountMax, setAmountMax] = useState("");
2985
2443
  const [isLoading, setIsLoading] = useState(true);
2986
2444
  const [isFetchingMore, setIsFetchingMore] = useState(false);
2987
2445
  const [error, setError] = useState(null);
2988
2446
  const [offset, setOffset] = useState(0);
2989
2447
  const [count, setCount] = useState(0);
2990
2448
  const limit = 50;
2991
- const loadSwaps = useCallback(
2992
- async (nextOffset, replace = false) => {
2449
+ const loadRefunds = useCallback(
2450
+ async (nextOffset, replace) => {
2993
2451
  try {
2994
- if (replace) {
2995
- setIsLoading(true);
2996
- } else {
2997
- setIsFetchingMore(true);
2998
- }
2452
+ if (replace) setIsLoading(true);
2453
+ else setIsFetchingMore(true);
2999
2454
  setError(null);
3000
2455
  const params = new URLSearchParams();
3001
2456
  params.set("limit", String(limit));
3002
2457
  params.set("offset", String(nextOffset));
3003
- if (statusFilter !== "all") {
3004
- params.set("status", statusFilter);
3005
- }
3006
- if (debouncedSearchQuery.trim()) {
3007
- params.set("order_id", debouncedSearchQuery.trim());
3008
- }
3009
- if (createdByFilter !== "all") {
3010
- params.set("created_by", createdByFilter);
3011
- }
3012
- const response = await fetch(
3013
- `/admin/swaps?${params.toString()}`,
3014
- { credentials: "include" }
3015
- );
2458
+ if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
2459
+ if (paymentStatusFilter !== "all") params.set("payment_status", paymentStatusFilter);
2460
+ if (debouncedProvider.trim()) params.set("provider_id", debouncedProvider.trim());
2461
+ if (debouncedCurrency.trim()) params.set("currency_code", debouncedCurrency.trim());
2462
+ if (dateFrom.trim()) params.set("date_from", dateFrom.trim());
2463
+ if (dateTo.trim()) params.set("date_to", dateTo.trim());
2464
+ const min = amountMin.trim() ? Number(amountMin) : void 0;
2465
+ const max = amountMax.trim() ? Number(amountMax) : void 0;
2466
+ if (min != null && !Number.isNaN(min)) params.set("amount_min", String(min));
2467
+ if (max != null && !Number.isNaN(max)) params.set("amount_max", String(max));
2468
+ const response = await fetch(`/admin/refunds?${params.toString()}`, {
2469
+ credentials: "include"
2470
+ });
3016
2471
  if (!response.ok) {
3017
- const message = await response.text();
3018
- throw new Error(message || "Unable to load swaps");
2472
+ const text = await response.text();
2473
+ throw new Error(text || "Failed to load refunds");
3019
2474
  }
3020
2475
  const payload = await response.json();
2476
+ const list = payload.refunds ?? [];
3021
2477
  setCount(payload.count ?? 0);
3022
- setOffset(nextOffset + (payload.swaps?.length ?? 0));
3023
- setItems(
3024
- (prev) => replace ? payload.swaps ?? [] : [...prev, ...payload.swaps ?? []]
3025
- );
3026
- } catch (loadError) {
3027
- const message = loadError instanceof Error ? loadError.message : "Unable to load swaps";
3028
- setError(message);
2478
+ setOffset(nextOffset + list.length);
2479
+ setItems((prev) => replace ? list : [...prev, ...list]);
2480
+ } catch (e) {
2481
+ setError(e instanceof Error ? e.message : "Failed to load");
3029
2482
  } finally {
3030
2483
  setIsLoading(false);
3031
2484
  setIsFetchingMore(false);
3032
2485
  }
3033
2486
  },
3034
- [statusFilter, createdByFilter, debouncedSearchQuery]
2487
+ [
2488
+ debouncedOrderId,
2489
+ paymentStatusFilter,
2490
+ debouncedProvider,
2491
+ debouncedCurrency,
2492
+ dateFrom,
2493
+ dateTo,
2494
+ amountMin,
2495
+ amountMax
2496
+ ]
3035
2497
  );
3036
2498
  useEffect(() => {
3037
- void loadSwaps(0, true);
3038
- }, [statusFilter, createdByFilter, debouncedSearchQuery, loadSwaps]);
2499
+ void loadRefunds(0, true);
2500
+ }, [loadRefunds]);
3039
2501
  const hasMore = useMemo(() => offset < count, [offset, count]);
3040
- const availableStatuses = useMemo(() => {
3041
- const statuses = /* @__PURE__ */ new Set();
3042
- items.forEach((item) => statuses.add(item.status));
3043
- return Array.from(statuses).sort();
3044
- }, [items]);
2502
+ const displayAmount = (r) => {
2503
+ const code = (r.currency_code ?? "USD").toUpperCase();
2504
+ return `${code} ${Number(r.amount)}`;
2505
+ };
2506
+ const displayStatus = (r) => {
2507
+ const s2 = r.payment_status ?? "";
2508
+ return s2 !== "" ? s2 : "—";
2509
+ };
3045
2510
  return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
3046
2511
  /* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
3047
2512
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
3048
- /* @__PURE__ */ jsx(Heading, { level: "h1", children: "Exchanges" }),
3049
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "View and manage all customer exchange requests" })
2513
+ /* @__PURE__ */ jsx(Heading, { level: "h1", children: "Refunds" }),
2514
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Refund records — amount, order, payment status" })
3050
2515
  ] }),
3051
- /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () => loadSwaps(0, true), children: "Refresh" })
2516
+ /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () => loadRefunds(0, true), children: "Refresh" })
3052
2517
  ] }),
3053
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
2518
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
3054
2519
  /* @__PURE__ */ jsx(
3055
2520
  Input,
3056
2521
  {
3057
- placeholder: "Search by swap ID or order ID",
3058
- value: searchQuery,
3059
- onChange: (event) => setSearchQuery(event.target.value),
3060
- className: "md:max-w-sm"
2522
+ placeholder: "Order ID",
2523
+ value: orderIdSearch,
2524
+ onChange: (e) => setOrderIdSearch(e.target.value),
2525
+ className: "md:max-w-[180px]",
2526
+ "aria-label": "Filter by order ID"
3061
2527
  }
3062
2528
  ),
3063
- /* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
3064
- /* @__PURE__ */ jsxs(
3065
- "select",
3066
- {
3067
- value: createdByFilter,
3068
- onChange: (event) => setCreatedByFilter(event.target.value),
3069
- 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",
3070
- children: [
3071
- /* @__PURE__ */ jsx("option", { value: "all", children: "All (Created by)" }),
3072
- /* @__PURE__ */ jsx("option", { value: "customer", children: "Customer" }),
3073
- /* @__PURE__ */ jsx("option", { value: "admin", children: "Admin" })
3074
- ]
3075
- }
3076
- ),
3077
- /* @__PURE__ */ jsxs(
3078
- "select",
3079
- {
3080
- value: statusFilter,
3081
- onChange: (event) => setStatusFilter(event.target.value),
3082
- 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",
3083
- children: [
3084
- /* @__PURE__ */ jsx("option", { value: "all", children: "All Statuses" }),
3085
- availableStatuses.map((status) => /* @__PURE__ */ jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
3086
- ]
3087
- }
3088
- )
3089
- ] })
3090
- ] }),
3091
- error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
3092
- /* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
3093
- /* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(
3094
- Button,
2529
+ /* @__PURE__ */ jsx(
2530
+ Input,
2531
+ {
2532
+ placeholder: "Provider",
2533
+ value: providerSearch,
2534
+ onChange: (e) => setProviderSearch(e.target.value),
2535
+ className: "md:max-w-[140px]",
2536
+ "aria-label": "Filter by provider"
2537
+ }
2538
+ ),
2539
+ /* @__PURE__ */ jsx(
2540
+ Input,
2541
+ {
2542
+ placeholder: "Currency",
2543
+ value: currencySearch,
2544
+ onChange: (e) => setCurrencySearch(e.target.value),
2545
+ className: "md:max-w-[100px]",
2546
+ "aria-label": "Filter by currency"
2547
+ }
2548
+ ),
2549
+ /* @__PURE__ */ jsxs(
2550
+ "select",
2551
+ {
2552
+ value: paymentStatusFilter,
2553
+ onChange: (e) => setPaymentStatusFilter(e.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-[160px]",
2555
+ "aria-label": "Filter by payment status",
2556
+ children: [
2557
+ /* @__PURE__ */ jsx("option", { value: "all", children: "All statuses" }),
2558
+ /* @__PURE__ */ jsx("option", { value: "pending", children: "Pending" }),
2559
+ /* @__PURE__ */ jsx("option", { value: "requires_more", children: "Requires more" }),
2560
+ /* @__PURE__ */ jsx("option", { value: "error", children: "Error" }),
2561
+ /* @__PURE__ */ jsx("option", { value: "canceled", children: "Canceled" }),
2562
+ /* @__PURE__ */ jsx("option", { value: "authorized", children: "Authorized" }),
2563
+ /* @__PURE__ */ jsx("option", { value: "captured", children: "Captured" })
2564
+ ]
2565
+ }
2566
+ ),
2567
+ /* @__PURE__ */ jsx(
2568
+ Input,
2569
+ {
2570
+ type: "date",
2571
+ placeholder: "From",
2572
+ value: dateFrom,
2573
+ onChange: (e) => setDateFrom(e.target.value),
2574
+ className: "md:max-w-[140px]",
2575
+ "aria-label": "Date from"
2576
+ }
2577
+ ),
2578
+ /* @__PURE__ */ jsx(
2579
+ Input,
2580
+ {
2581
+ type: "date",
2582
+ placeholder: "To",
2583
+ value: dateTo,
2584
+ onChange: (e) => setDateTo(e.target.value),
2585
+ className: "md:max-w-[140px]",
2586
+ "aria-label": "Date to"
2587
+ }
2588
+ ),
2589
+ /* @__PURE__ */ jsx(
2590
+ Input,
2591
+ {
2592
+ placeholder: "Amount min",
2593
+ value: amountMin,
2594
+ onChange: (e) => setAmountMin(e.target.value),
2595
+ type: "number",
2596
+ min: 0,
2597
+ className: "md:max-w-[100px]",
2598
+ "aria-label": "Refund amount minimum"
2599
+ }
2600
+ ),
2601
+ /* @__PURE__ */ jsx(
2602
+ Input,
3095
2603
  {
3096
- variant: "secondary",
3097
- onClick: () => loadSwaps(0, true),
3098
- children: "Try again"
2604
+ placeholder: "Amount max",
2605
+ value: amountMax,
2606
+ onChange: (e) => setAmountMax(e.target.value),
2607
+ type: "number",
2608
+ min: 0,
2609
+ className: "md:max-w-[100px]",
2610
+ "aria-label": "Refund amount maximum"
3099
2611
  }
3100
- ) })
2612
+ )
2613
+ ] }) }),
2614
+ error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
2615
+ /* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
2616
+ /* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => loadRefunds(0, true), children: "Try again" }) })
3101
2617
  ] }) : null,
3102
- isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading swaps..." }) }) : items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
3103
- /* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No exchanges yet" }),
3104
- /* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Exchange requests created by customers will appear here." })
3105
- ] }) : /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
2618
+ isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading refunds…" }) }) : items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
2619
+ /* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No refunds yet" }),
2620
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Refund records will appear here." })
2621
+ ] }) : /* @__PURE__ */ jsx("div", { className: "w-full overflow-x-auto rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "w-full table-fixed divide-y divide-ui-border-base", style: { minWidth: 0 }, children: [
3106
2622
  /* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
3107
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Exchange ID" }),
3108
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
3109
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
3110
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Difference Due" }),
3111
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
3112
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
2623
+ /* @__PURE__ */ jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Refund ID" }),
2624
+ /* @__PURE__ */ jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
2625
+ /* @__PURE__ */ jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Payment ID" }),
2626
+ /* @__PURE__ */ jsx("th", { className: "w-[8%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Amount" }),
2627
+ /* @__PURE__ */ jsx("th", { className: "w-[6%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Currency" }),
2628
+ /* @__PURE__ */ jsx("th", { className: "w-[10%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Provider" }),
2629
+ /* @__PURE__ */ jsx("th", { className: "w-[10%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Payment Status" }),
2630
+ /* @__PURE__ */ jsx("th", { className: "w-[14%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Note" }),
2631
+ /* @__PURE__ */ jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
2632
+ /* @__PURE__ */ jsx("th", { className: "w-[8%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
3113
2633
  ] }) }),
3114
- /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((swap) => /* @__PURE__ */ jsxs(
2634
+ /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((r) => /* @__PURE__ */ jsxs(
3115
2635
  "tr",
3116
2636
  {
3117
- className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
3118
- onClick: () => navigate(`/swaps/${swap.id}`),
2637
+ className: "cursor-pointer hover:bg-ui-bg-subtle/60",
2638
+ onClick: () => navigate(`/refunds/${r.refund_id}`),
3119
2639
  children: [
3120
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children: /* @__PURE__ */ jsx("span", { children: swap.id }) }) }),
3121
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: swap.order_id }),
3122
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
2640
+ /* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 font-mono text-sm text-ui-fg-base", title: r.refund_id, children: r.refund_id }),
2641
+ /* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 font-medium text-ui-fg-base", title: r.order_id ?? void 0, children: r.order_id ?? "—" }),
2642
+ /* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 font-mono text-sm text-ui-fg-subtle", title: r.payment_id, children: r.payment_id }),
2643
+ /* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", children: displayAmount(r) }),
2644
+ /* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle uppercase", children: r.currency_code || "—" }),
2645
+ /* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", title: r.provider_id || void 0, children: r.provider_id || "—" }),
2646
+ /* @__PURE__ */ jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsx(
3123
2647
  Badge,
3124
2648
  {
3125
2649
  size: "2xsmall",
3126
- className: `uppercase ${getStatusBadgeClass$4(swap.status)}`,
3127
- children: swap.status.replace(/_/g, " ")
2650
+ className: `uppercase ${getStatusBadgeClass$6(displayStatus(r))}`,
2651
+ children: displayStatus(r) !== "—" ? displayStatus(r).replace(/_/g, " ") : "—"
3128
2652
  }
3129
2653
  ) }),
3130
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
3131
- const amount = swap.difference_due;
3132
- if (amount == null || amount === void 0) {
3133
- return "—";
3134
- }
3135
- const displayAmount = Number(amount) / 100;
3136
- const currency = swap.currency_code || "$";
3137
- const sign = displayAmount >= 0 ? "+" : "";
3138
- return `${sign}${currency}${displayAmount.toFixed(2)}`;
3139
- })() }),
3140
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(swap.created_at).toLocaleDateString("en-US", {
3141
- year: "numeric",
2654
+ /* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", title: r.note ?? void 0, children: r.note ?? "—" }),
2655
+ /* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle text-xs", children: new Date(r.created_at).toLocaleDateString("en-US", {
3142
2656
  month: "short",
3143
2657
  day: "numeric",
3144
2658
  hour: "numeric",
3145
2659
  minute: "2-digit",
3146
2660
  hour12: true
3147
2661
  }) }),
3148
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
3149
- Button,
3150
- {
3151
- variant: "transparent",
3152
- size: "small",
3153
- onClick: (e) => {
3154
- e.stopPropagation();
3155
- navigate(`/app/orders/${swap.order_id}`);
3156
- },
3157
- children: "Go to order"
3158
- }
3159
- ) })
2662
+ /* @__PURE__ */ jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1", children: [
2663
+ /* @__PURE__ */ jsx(
2664
+ Button,
2665
+ {
2666
+ variant: "transparent",
2667
+ size: "small",
2668
+ onClick: (e) => {
2669
+ e.stopPropagation();
2670
+ navigate(`/refunds/${r.refund_id}`);
2671
+ },
2672
+ children: "Details"
2673
+ }
2674
+ ),
2675
+ r.order_id ? /* @__PURE__ */ jsx(
2676
+ Button,
2677
+ {
2678
+ variant: "transparent",
2679
+ size: "small",
2680
+ onClick: (e) => {
2681
+ e.stopPropagation();
2682
+ navigate(`/orders/${r.order_id}`);
2683
+ },
2684
+ children: "Order"
2685
+ }
2686
+ ) : null
2687
+ ] }) })
3160
2688
  ]
3161
2689
  },
3162
- swap.id
2690
+ r.refund_id
3163
2691
  )) })
3164
2692
  ] }) }),
3165
2693
  hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
@@ -3167,326 +2695,266 @@ const SwapsPage = () => {
3167
2695
  {
3168
2696
  variant: "secondary",
3169
2697
  isLoading: isFetchingMore,
3170
- onClick: () => loadSwaps(offset, false),
2698
+ onClick: () => loadRefunds(offset, false),
3171
2699
  children: "Load more"
3172
2700
  }
3173
2701
  ) }) : null
3174
2702
  ] }) });
3175
2703
  };
3176
- const config$5 = defineRouteConfig({
3177
- label: "Exchanges",
3178
- icon: ArrowPath
2704
+ const config$7 = defineRouteConfig({
2705
+ label: "Refunds",
2706
+ icon: Receipt
3179
2707
  });
3180
- const getStatusBadgeClass$3 = (status) => {
3181
- const s2 = status.toLowerCase();
3182
- if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
3183
- if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
3184
- if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
3185
- if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
3186
- return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
3187
- };
3188
- const PaymentDetailPage = () => {
3189
- const navigate = useNavigate();
3190
- const params = useParams();
3191
- const id = params?.id?.trim();
3192
- const [detail, setDetail] = useState(null);
3193
- const [loading, setLoading] = useState(!!id);
3194
- const [error, setError] = useState(null);
2708
+ const useDebounce$1 = (value, delay) => {
2709
+ const [debouncedValue, setDebouncedValue] = useState(value);
3195
2710
  useEffect(() => {
3196
- if (!id) {
3197
- setLoading(false);
3198
- return;
3199
- }
3200
- let cancelled = false;
3201
- setLoading(true);
3202
- setError(null);
3203
- fetch(`/admin/payment-transactions/${id}`, { credentials: "include" }).then((res) => {
3204
- if (!res.ok) throw new Error(res.statusText || "Failed to load");
3205
- return res.json();
3206
- }).then((data) => {
3207
- if (!cancelled) setDetail(data);
3208
- }).catch((e) => {
3209
- if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
3210
- }).finally(() => {
3211
- if (!cancelled) setLoading(false);
3212
- });
3213
- return () => {
3214
- cancelled = true;
3215
- };
3216
- }, [id]);
3217
- const displayStatus = detail ? (detail.payment_id != null && detail.payment_status != null && detail.payment_status !== "" ? detail.payment_status : detail.session_status ?? "") || "—" : "";
3218
- const sessionStatusRaw = detail?.session_status ?? "—";
3219
- const paymentStatusRaw = detail?.payment_id != null ? detail?.payment_status ?? "—" : "—";
3220
- const displayAmount = detail ? `${(detail.currency_code ?? "USD").toUpperCase()} ${Number(detail.amount)}` : "";
3221
- return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-4xl flex-col gap-6 p-6", children: [
3222
- /* @__PURE__ */ jsx("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
3223
- /* @__PURE__ */ jsx(Button, { variant: "transparent", size: "small", onClick: () => navigate("/payments"), children: "← Payments" }),
3224
- /* @__PURE__ */ jsx(Heading, { level: "h1", children: "Payment session" }),
3225
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: id ?? "—" })
3226
- ] }) }),
3227
- error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
3228
- /* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
3229
- /* @__PURE__ */ jsx(Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/payments"), children: "Back to list" })
3230
- ] }) : loading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading…" }) }) : detail ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
3231
- /* @__PURE__ */ jsx("div", { className: "rounded-xl border border-ui-border-base p-6 flex flex-col gap-4", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
3232
- /* @__PURE__ */ jsxs("div", { children: [
3233
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Order ID" }),
3234
- /* @__PURE__ */ jsx("div", { className: "mt-1", children: detail.order_id ? /* @__PURE__ */ jsx(
3235
- Button,
3236
- {
3237
- variant: "transparent",
3238
- size: "small",
3239
- onClick: () => navigate(`/orders/${detail.order_id}`),
3240
- children: detail.order_id
3241
- }
3242
- ) : /* @__PURE__ */ jsx(Text, { children: "—" }) })
3243
- ] }),
3244
- /* @__PURE__ */ jsxs("div", { children: [
3245
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
3246
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: displayAmount })
3247
- ] }),
3248
- /* @__PURE__ */ jsxs("div", { children: [
3249
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
3250
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.provider_id })
3251
- ] }),
3252
- /* @__PURE__ */ jsxs("div", { children: [
3253
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
3254
- /* @__PURE__ */ jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsx(
3255
- Badge,
3256
- {
3257
- size: "2xsmall",
3258
- className: `uppercase ${getStatusBadgeClass$3(displayStatus)}`,
3259
- children: displayStatus !== "—" ? displayStatus.replace(/_/g, " ") : "—"
3260
- }
3261
- ) })
3262
- ] }),
3263
- /* @__PURE__ */ jsxs("div", { children: [
3264
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Session status (DB)" }),
3265
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: sessionStatusRaw })
3266
- ] }),
3267
- /* @__PURE__ */ jsxs("div", { children: [
3268
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Payment status (DB)" }),
3269
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: paymentStatusRaw })
3270
- ] }),
3271
- /* @__PURE__ */ jsxs("div", { children: [
3272
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Finalized" }),
3273
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.payment_id != null ? "Yes" : "No" })
3274
- ] }),
3275
- /* @__PURE__ */ jsxs("div", { children: [
3276
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Created" }),
3277
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: new Date(detail.created_at).toLocaleDateString("en-US", {
3278
- year: "numeric",
3279
- month: "short",
3280
- day: "numeric",
3281
- hour: "numeric",
3282
- minute: "2-digit",
3283
- hour12: true
3284
- }) })
3285
- ] })
3286
- ] }) }),
3287
- Object.keys(detail.data ?? {}).length > 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
3288
- /* @__PURE__ */ jsx(Heading, { level: "h2", className: "text-lg mb-4", children: "Provider data" }),
3289
- /* @__PURE__ */ jsx("pre", { className: "text-xs bg-ui-bg-subtle p-4 rounded-lg overflow-auto max-h-96", children: JSON.stringify(detail.data, null, 2) })
3290
- ] }) : /* @__PURE__ */ jsx("div", { className: "rounded-xl border border-ui-border-base p-6", children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "No provider data for this session." }) })
3291
- ] }) : null
3292
- ] }) });
3293
- };
3294
- const config$4 = defineRouteConfig({
3295
- label: "Payment details",
3296
- icon: CreditCard
3297
- });
3298
- const getStatusBadgeClass$2 = (status) => {
3299
- const s2 = status.toLowerCase();
3300
- if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
3301
- if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
3302
- if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
3303
- if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
3304
- return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
2711
+ const handler = setTimeout(() => setDebouncedValue(value), delay);
2712
+ return () => clearTimeout(handler);
2713
+ }, [value, delay]);
2714
+ return debouncedValue;
3305
2715
  };
3306
- const formatAmount = (value) => {
3307
- return String(value);
2716
+ const getStatusBadgeClass$5 = (status) => {
2717
+ const statusLower = status.toLowerCase();
2718
+ if (statusLower === "requested") {
2719
+ return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
2720
+ }
2721
+ if (statusLower === "received") {
2722
+ return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
2723
+ }
2724
+ if (statusLower === "requires_action") {
2725
+ return "bg-ui-tag-red-bg text-ui-tag-red-text";
2726
+ }
2727
+ if (statusLower === "completed") {
2728
+ return "bg-ui-tag-green-bg text-ui-tag-green-text";
2729
+ }
2730
+ if (statusLower === "canceled") {
2731
+ return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
2732
+ }
2733
+ return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
3308
2734
  };
3309
- const RefundDetailPage = () => {
2735
+ const ReturnsPage = () => {
3310
2736
  const navigate = useNavigate();
3311
- const params = useParams();
3312
- const id = params?.id?.trim();
3313
- const [detail, setDetail] = useState(null);
3314
- const [loading, setLoading] = useState(!!id);
2737
+ const [items, setItems] = useState([]);
2738
+ const [statusFilter, setStatusFilter] = useState("all");
2739
+ const [createdByFilter, setCreatedByFilter] = useState("all");
2740
+ const [searchQuery, setSearchQuery] = useState("");
2741
+ const debouncedSearchQuery = useDebounce$1(searchQuery, 300);
2742
+ const [isLoading, setIsLoading] = useState(true);
2743
+ const [isFetchingMore, setIsFetchingMore] = useState(false);
3315
2744
  const [error, setError] = useState(null);
3316
- const [gatewayExpanded, setGatewayExpanded] = useState(false);
2745
+ const [offset, setOffset] = useState(0);
2746
+ const [count, setCount] = useState(0);
2747
+ const limit = 50;
2748
+ const loadReturns = useCallback(
2749
+ async (nextOffset, replace = false) => {
2750
+ try {
2751
+ if (replace) {
2752
+ setIsLoading(true);
2753
+ } else {
2754
+ setIsFetchingMore(true);
2755
+ }
2756
+ setError(null);
2757
+ const params = new URLSearchParams();
2758
+ params.set("limit", String(limit));
2759
+ params.set("offset", String(nextOffset));
2760
+ if (statusFilter !== "all") {
2761
+ params.set("status", statusFilter);
2762
+ }
2763
+ if (debouncedSearchQuery.trim()) {
2764
+ params.set("q", debouncedSearchQuery.trim());
2765
+ }
2766
+ if (createdByFilter !== "all") {
2767
+ params.set("created_by", createdByFilter);
2768
+ }
2769
+ params.set("order", "created_at");
2770
+ const response = await fetch(
2771
+ `/admin/return?${params.toString()}`,
2772
+ { credentials: "include" }
2773
+ );
2774
+ if (!response.ok) {
2775
+ const message = await response.text();
2776
+ throw new Error(message || "Unable to load return orders");
2777
+ }
2778
+ const payload = await response.json();
2779
+ setCount(payload.count ?? 0);
2780
+ setOffset(nextOffset + (payload.returns?.length ?? 0));
2781
+ setItems(
2782
+ (prev) => replace ? payload.returns ?? [] : [...prev, ...payload.returns ?? []]
2783
+ );
2784
+ } catch (loadError) {
2785
+ const message = loadError instanceof Error ? loadError.message : "Unable to load return orders";
2786
+ setError(message);
2787
+ } finally {
2788
+ setIsLoading(false);
2789
+ setIsFetchingMore(false);
2790
+ }
2791
+ },
2792
+ [statusFilter, createdByFilter, debouncedSearchQuery]
2793
+ );
3317
2794
  useEffect(() => {
3318
- if (!id) {
3319
- setLoading(false);
3320
- return;
3321
- }
3322
- let cancelled = false;
3323
- setLoading(true);
3324
- setError(null);
3325
- fetch(`/admin/refunds/${id}`, { credentials: "include" }).then((res) => {
3326
- if (!res.ok) throw new Error(res.statusText || "Failed to load");
3327
- return res.json();
3328
- }).then((data) => {
3329
- if (!cancelled) setDetail(data);
3330
- }).catch((e) => {
3331
- if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
3332
- }).finally(() => {
3333
- if (!cancelled) setLoading(false);
3334
- });
3335
- return () => {
3336
- cancelled = true;
3337
- };
3338
- }, [id]);
3339
- const paymentStatus = detail?.payment?.status ?? "—";
3340
- const hasGatewayData = detail?.payment?.payment_data && typeof detail.payment.payment_data === "object" && Object.keys(detail.payment.payment_data).length > 0;
3341
- return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-4xl flex-col gap-6 p-6", children: [
3342
- /* @__PURE__ */ jsx("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
3343
- /* @__PURE__ */ jsx(Button, { variant: "transparent", size: "small", onClick: () => navigate("/refunds"), children: "← Refunds" }),
3344
- /* @__PURE__ */ jsx(Heading, { level: "h1", children: "Refund details" }),
3345
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle font-mono", children: id ?? "—" })
3346
- ] }) }),
2795
+ void loadReturns(0, true);
2796
+ }, [statusFilter, createdByFilter, debouncedSearchQuery, loadReturns]);
2797
+ const hasMore = useMemo(() => offset < count, [offset, count]);
2798
+ const availableStatuses = useMemo(() => {
2799
+ const statuses = /* @__PURE__ */ new Set();
2800
+ items.forEach((item) => statuses.add(item.status));
2801
+ return Array.from(statuses).sort();
2802
+ }, [items]);
2803
+ return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
2804
+ /* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
2805
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
2806
+ /* @__PURE__ */ jsx(Heading, { level: "h1", children: "Return Orders" }),
2807
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "View and manage all customer return orders" })
2808
+ ] }),
2809
+ /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () => loadReturns(0, true), children: "Refresh" })
2810
+ ] }),
2811
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
2812
+ /* @__PURE__ */ jsx(
2813
+ Input,
2814
+ {
2815
+ placeholder: "Search by return ID, order ID, or customer email",
2816
+ value: searchQuery,
2817
+ onChange: (event) => setSearchQuery(event.target.value),
2818
+ className: "md:max-w-sm"
2819
+ }
2820
+ ),
2821
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
2822
+ /* @__PURE__ */ jsxs(
2823
+ "select",
2824
+ {
2825
+ value: createdByFilter,
2826
+ onChange: (event) => setCreatedByFilter(event.target.value),
2827
+ 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",
2828
+ children: [
2829
+ /* @__PURE__ */ jsx("option", { value: "all", children: "All (Created by)" }),
2830
+ /* @__PURE__ */ jsx("option", { value: "customer", children: "Customer" }),
2831
+ /* @__PURE__ */ jsx("option", { value: "admin", children: "Admin" })
2832
+ ]
2833
+ }
2834
+ ),
2835
+ /* @__PURE__ */ jsxs(
2836
+ "select",
2837
+ {
2838
+ value: statusFilter,
2839
+ onChange: (event) => setStatusFilter(event.target.value),
2840
+ 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",
2841
+ children: [
2842
+ /* @__PURE__ */ jsx("option", { value: "all", children: "All Statuses" }),
2843
+ availableStatuses.map((status) => /* @__PURE__ */ jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
2844
+ ]
2845
+ }
2846
+ )
2847
+ ] })
2848
+ ] }),
3347
2849
  error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
3348
2850
  /* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
3349
- /* @__PURE__ */ jsx(Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/refunds"), children: "Back to list" })
3350
- ] }) : loading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading…" }) }) : detail ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
3351
- /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
3352
- /* @__PURE__ */ jsx(Heading, { level: "h2", className: "text-lg mb-4", children: "Refund summary" }),
3353
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
3354
- /* @__PURE__ */ jsxs("div", { children: [
3355
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Refund ID" }),
3356
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.id })
3357
- ] }),
3358
- /* @__PURE__ */ jsxs("div", { children: [
3359
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
3360
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.refund.amount) })
3361
- ] }),
3362
- /* @__PURE__ */ jsxs("div", { children: [
3363
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Note" }),
3364
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.refund.note ?? "—" })
3365
- ] }),
3366
- /* @__PURE__ */ jsxs("div", { children: [
3367
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Created at" }),
3368
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: new Date(detail.refund.created_at).toLocaleDateString("en-US", {
3369
- year: "numeric",
3370
- month: "short",
3371
- day: "numeric",
3372
- hour: "numeric",
3373
- minute: "2-digit",
3374
- hour12: true
3375
- }) })
3376
- ] }),
3377
- detail.refund.created_by ? /* @__PURE__ */ jsxs("div", { children: [
3378
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Created by" }),
3379
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.created_by })
3380
- ] }) : null
3381
- ] })
3382
- ] }),
3383
- /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
3384
- /* @__PURE__ */ jsx(Heading, { level: "h2", className: "text-lg mb-4", children: "Payment summary" }),
3385
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
3386
- /* @__PURE__ */ jsxs("div", { children: [
3387
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Payment amount" }),
3388
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.payment.payment_amount) })
3389
- ] }),
3390
- /* @__PURE__ */ jsxs("div", { children: [
3391
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Captured amount" }),
3392
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.payment.captured_amount) })
3393
- ] }),
3394
- /* @__PURE__ */ jsxs("div", { children: [
3395
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Refunded amount" }),
3396
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.payment.refunded_amount) })
3397
- ] }),
3398
- /* @__PURE__ */ jsxs("div", { children: [
3399
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
3400
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.payment.provider_id || "—" })
3401
- ] }),
3402
- /* @__PURE__ */ jsxs("div", { children: [
3403
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
3404
- /* @__PURE__ */ jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsx(
2851
+ /* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(
2852
+ Button,
2853
+ {
2854
+ variant: "secondary",
2855
+ onClick: () => loadReturns(0, true),
2856
+ children: "Try again"
2857
+ }
2858
+ ) })
2859
+ ] }) : null,
2860
+ isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading return orders..." }) }) : items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
2861
+ /* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No return orders yet" }),
2862
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Return orders created by customers will appear here." })
2863
+ ] }) : /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
2864
+ /* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
2865
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Return ID" }),
2866
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
2867
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Customer" }),
2868
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
2869
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Refund Amount" }),
2870
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
2871
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
2872
+ ] }) }),
2873
+ /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((returnOrder) => /* @__PURE__ */ jsxs(
2874
+ "tr",
2875
+ {
2876
+ className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
2877
+ onClick: () => navigate(`/returns/${returnOrder.id}`),
2878
+ children: [
2879
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children: /* @__PURE__ */ jsx("span", { children: returnOrder.id }) }) }),
2880
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.order_id }),
2881
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.customer_email || returnOrder.order_email || "—" }),
2882
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
3405
2883
  Badge,
3406
2884
  {
3407
2885
  size: "2xsmall",
3408
- className: `uppercase ${getStatusBadgeClass$2(paymentStatus)}`,
3409
- children: paymentStatus !== "—" ? paymentStatus.replace(/_/g, " ") : "—"
2886
+ className: `uppercase ${getStatusBadgeClass$5(returnOrder.status)}`,
2887
+ children: returnOrder.status.replace(/_/g, " ")
3410
2888
  }
3411
- ) })
3412
- ] }),
3413
- detail.computed ? /* @__PURE__ */ jsxs(Fragment, { children: [
3414
- /* @__PURE__ */ jsxs("div", { children: [
3415
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Full refund" }),
3416
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.computed.is_full_refund ? "Yes" : "No" })
3417
- ] }),
3418
- /* @__PURE__ */ jsxs("div", { children: [
3419
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Remaining refundable" }),
3420
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.computed.remaining_refundable_amount) })
3421
- ] }),
3422
- /* @__PURE__ */ jsxs("div", { children: [
3423
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Refund %" }),
3424
- /* @__PURE__ */ jsxs(Text, { className: "mt-1 block", children: [
3425
- detail.computed.refund_percentage.toFixed(1),
3426
- "%"
3427
- ] })
3428
- ] })
3429
- ] }) : null
3430
- ] })
3431
- ] }),
3432
- /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
3433
- /* @__PURE__ */ jsx(Heading, { level: "h2", className: "text-lg mb-4", children: "Order summary" }),
3434
- detail.order ? /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
3435
- /* @__PURE__ */ jsxs("div", { children: [
3436
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Order" }),
3437
- /* @__PURE__ */ jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsx(
2889
+ ) }),
2890
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
2891
+ const calc = returnOrder.refund;
2892
+ if (calc?.is_processed && calc.final_refund_amount != null) {
2893
+ return formatRefundCurrency(
2894
+ calc.final_refund_amount,
2895
+ calc.currency_code || returnOrder.currency_code
2896
+ );
2897
+ }
2898
+ if (calc) {
2899
+ return "Pending";
2900
+ }
2901
+ if (returnOrder.refund_amount == null) {
2902
+ return "—";
2903
+ }
2904
+ return formatRefundCurrency(
2905
+ Number(returnOrder.refund_amount),
2906
+ returnOrder.currency_code
2907
+ );
2908
+ })() }),
2909
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(returnOrder.created_at).toLocaleDateString("en-US", {
2910
+ year: "numeric",
2911
+ month: "short",
2912
+ day: "numeric",
2913
+ hour: "numeric",
2914
+ minute: "2-digit",
2915
+ hour12: true
2916
+ }) }),
2917
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
3438
2918
  Button,
3439
2919
  {
3440
2920
  variant: "transparent",
3441
2921
  size: "small",
3442
- onClick: () => navigate(`/orders/${detail.order.order_id}`),
3443
- children: detail.order.order_number ?? detail.order.order_id
2922
+ onClick: (e) => {
2923
+ e.stopPropagation();
2924
+ navigate(`/app/orders/${returnOrder.order_id}`);
2925
+ },
2926
+ children: "Go to order"
3444
2927
  }
3445
2928
  ) })
3446
- ] }),
3447
- detail.order.total != null ? /* @__PURE__ */ jsxs("div", { children: [
3448
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Total" }),
3449
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.order.total) })
3450
- ] }) : null,
3451
- detail.order.customer_id ? /* @__PURE__ */ jsxs("div", { children: [
3452
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Customer ID" }),
3453
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block font-mono text-sm", children: detail.order.customer_id })
3454
- ] }) : null,
3455
- detail.order.region ? /* @__PURE__ */ jsxs("div", { children: [
3456
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Region" }),
3457
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.order.region })
3458
- ] }) : null,
3459
- detail.order.fulfillment_status ? /* @__PURE__ */ jsxs("div", { children: [
3460
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Fulfillment status" }),
3461
- /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.order.fulfillment_status })
3462
- ] }) : null
3463
- ] }) : /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "No order linked to this refund." })
3464
- ] }),
3465
- /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
3466
- /* @__PURE__ */ jsxs(
3467
- "button",
3468
- {
3469
- type: "button",
3470
- className: "flex w-full items-center justify-between text-left",
3471
- onClick: () => setGatewayExpanded((prev) => !prev),
3472
- "aria-expanded": gatewayExpanded,
3473
- "aria-label": gatewayExpanded ? "Collapse gateway data" : "Expand gateway data",
3474
- children: [
3475
- /* @__PURE__ */ jsx(Heading, { level: "h2", className: "text-lg", children: "Gateway data" }),
3476
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: gatewayExpanded ? "Collapse" : "Expand" })
3477
- ]
3478
- }
3479
- ),
3480
- gatewayExpanded && /* @__PURE__ */ jsx("div", { className: "mt-4", children: hasGatewayData ? /* @__PURE__ */ jsx("pre", { className: "text-xs bg-ui-bg-subtle p-4 rounded-lg overflow-auto max-h-96", children: JSON.stringify(detail.payment.payment_data, null, 2) }) : /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "No gateway payload for this payment." }) })
3481
- ] })
3482
- ] }) : null
2929
+ ]
2930
+ },
2931
+ returnOrder.id
2932
+ )) })
2933
+ ] }) }),
2934
+ hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
2935
+ Button,
2936
+ {
2937
+ variant: "secondary",
2938
+ isLoading: isFetchingMore,
2939
+ onClick: () => loadReturns(offset, false),
2940
+ children: "Load more"
2941
+ }
2942
+ ) }) : null
3483
2943
  ] }) });
3484
2944
  };
3485
- const config$3 = defineRouteConfig({
3486
- label: "Refund details",
3487
- icon: Receipt
2945
+ const config$6 = defineRouteConfig({
2946
+ label: "Return Orders",
2947
+ icon: ArrowPath
3488
2948
  });
3489
- const getStatusBadgeClass$1 = (status) => {
2949
+ const useDebounce = (value, delay) => {
2950
+ const [debouncedValue, setDebouncedValue] = useState(value);
2951
+ useEffect(() => {
2952
+ const handler = setTimeout(() => setDebouncedValue(value), delay);
2953
+ return () => clearTimeout(handler);
2954
+ }, [value, delay]);
2955
+ return debouncedValue;
2956
+ };
2957
+ const getStatusBadgeClass$4 = (status) => {
3490
2958
  const statusLower = status.toLowerCase();
3491
2959
  if (statusLower === "requested") {
3492
2960
  return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
@@ -3497,12 +2965,6 @@ const getStatusBadgeClass$1 = (status) => {
3497
2965
  if (statusLower === "rejected") {
3498
2966
  return "bg-ui-tag-red-bg text-ui-tag-red-text";
3499
2967
  }
3500
- if (statusLower === "received") {
3501
- return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
3502
- }
3503
- if (statusLower === "refunded") {
3504
- return "bg-ui-tag-green-bg text-ui-tag-green-text";
3505
- }
3506
2968
  if (statusLower === "completed") {
3507
2969
  return "bg-ui-tag-green-bg text-ui-tag-green-text";
3508
2970
  }
@@ -3511,262 +2973,207 @@ const getStatusBadgeClass$1 = (status) => {
3511
2973
  }
3512
2974
  return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
3513
2975
  };
3514
- const ReturnDetailPage = () => {
2976
+ const SwapsPage = () => {
3515
2977
  const navigate = useNavigate();
3516
- const { id } = useParams();
3517
- const [returnOrder, setReturnOrder] = useState(null);
2978
+ const [items, setItems] = useState([]);
2979
+ const [statusFilter, setStatusFilter] = useState("all");
2980
+ const [createdByFilter, setCreatedByFilter] = useState("all");
2981
+ const [searchQuery, setSearchQuery] = useState("");
2982
+ const debouncedSearchQuery = useDebounce(searchQuery, 300);
3518
2983
  const [isLoading, setIsLoading] = useState(true);
3519
- const [isRejecting, setIsRejecting] = useState(false);
2984
+ const [isFetchingMore, setIsFetchingMore] = useState(false);
3520
2985
  const [error, setError] = useState(null);
3521
- const [updateError, setUpdateError] = useState(null);
3522
- const [updateSuccess, setUpdateSuccess] = useState(false);
3523
- useEffect(() => {
3524
- if (!id) {
3525
- navigate("/returns");
3526
- return;
3527
- }
3528
- const loadReturn = async () => {
2986
+ const [offset, setOffset] = useState(0);
2987
+ const [count, setCount] = useState(0);
2988
+ const limit = 50;
2989
+ const loadSwaps = useCallback(
2990
+ async (nextOffset, replace = false) => {
3529
2991
  try {
3530
- setIsLoading(true);
2992
+ if (replace) {
2993
+ setIsLoading(true);
2994
+ } else {
2995
+ setIsFetchingMore(true);
2996
+ }
3531
2997
  setError(null);
3532
- const response = await fetch(`/admin/return/${id}`, {
3533
- credentials: "include"
3534
- });
3535
- if (!response.ok) {
3536
- const message = await response.text();
3537
- throw new Error(message || "Unable to load return order");
2998
+ const params = new URLSearchParams();
2999
+ params.set("limit", String(limit));
3000
+ params.set("offset", String(nextOffset));
3001
+ if (statusFilter !== "all") {
3002
+ params.set("status", statusFilter);
3538
3003
  }
3539
- const payload = await response.json();
3540
- setReturnOrder(payload.return);
3541
- } catch (loadError) {
3542
- const message = loadError instanceof Error ? loadError.message : "Unable to load return order";
3543
- setError(message);
3544
- } finally {
3545
- setIsLoading(false);
3546
- }
3547
- };
3548
- void loadReturn();
3549
- }, [id, navigate]);
3550
- const handleReject = async () => {
3551
- if (!id) {
3552
- return;
3553
- }
3554
- try {
3555
- setIsRejecting(true);
3556
- setUpdateError(null);
3557
- setUpdateSuccess(false);
3558
- const response = await fetch(`/admin/return/${id}/reject`, {
3559
- method: "POST",
3560
- headers: {
3561
- "Content-Type": "application/json"
3562
- },
3563
- credentials: "include",
3564
- body: JSON.stringify({ reason: "Rejected by admin" })
3565
- });
3566
- if (!response.ok) {
3567
- const message = await response.text();
3568
- throw new Error(message || "Unable to reject return");
3569
- }
3570
- const payload = await response.json();
3571
- setReturnOrder(payload.return);
3572
- setUpdateSuccess(true);
3573
- setTimeout(() => setUpdateSuccess(false), 3e3);
3574
- const detailResponse = await fetch(`/admin/return/${id}`, {
3575
- credentials: "include"
3576
- });
3577
- if (detailResponse.ok) {
3578
- const detailPayload = await detailResponse.json();
3579
- setReturnOrder(detailPayload.return);
3580
- }
3581
- } catch (updateErr) {
3582
- const message = updateErr instanceof Error ? updateErr.message : "Unable to reject return";
3583
- setUpdateError(message);
3584
- } finally {
3585
- setIsRejecting(false);
3586
- }
3587
- };
3588
- if (isLoading) {
3589
- return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsx(Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading return order..." }) }) }) });
3590
- }
3591
- if (error || !returnOrder) {
3592
- return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsx(Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
3593
- /* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error || "Return order not found" }),
3594
- /* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => navigate("/returns"), children: "Back to list" }) })
3595
- ] }) }) });
3596
- }
3597
- const statusHistory = returnOrder.metadata?.status_history || [];
3598
- return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: [
3599
- /* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3", children: [
3600
- /* @__PURE__ */ jsxs(
3601
- Button,
3004
+ if (debouncedSearchQuery.trim()) {
3005
+ params.set("order_id", debouncedSearchQuery.trim());
3006
+ }
3007
+ if (createdByFilter !== "all") {
3008
+ params.set("created_by", createdByFilter);
3009
+ }
3010
+ const response = await fetch(
3011
+ `/admin/swaps?${params.toString()}`,
3012
+ { credentials: "include" }
3013
+ );
3014
+ if (!response.ok) {
3015
+ const message = await response.text();
3016
+ throw new Error(message || "Unable to load swaps");
3017
+ }
3018
+ const payload = await response.json();
3019
+ setCount(payload.count ?? 0);
3020
+ setOffset(nextOffset + (payload.swaps?.length ?? 0));
3021
+ setItems(
3022
+ (prev) => replace ? payload.swaps ?? [] : [...prev, ...payload.swaps ?? []]
3023
+ );
3024
+ } catch (loadError) {
3025
+ const message = loadError instanceof Error ? loadError.message : "Unable to load swaps";
3026
+ setError(message);
3027
+ } finally {
3028
+ setIsLoading(false);
3029
+ setIsFetchingMore(false);
3030
+ }
3031
+ },
3032
+ [statusFilter, createdByFilter, debouncedSearchQuery]
3033
+ );
3034
+ useEffect(() => {
3035
+ void loadSwaps(0, true);
3036
+ }, [statusFilter, createdByFilter, debouncedSearchQuery, loadSwaps]);
3037
+ const hasMore = useMemo(() => offset < count, [offset, count]);
3038
+ const availableStatuses = useMemo(() => {
3039
+ const statuses = /* @__PURE__ */ new Set();
3040
+ items.forEach((item) => statuses.add(item.status));
3041
+ return Array.from(statuses).sort();
3042
+ }, [items]);
3043
+ return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
3044
+ /* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
3045
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
3046
+ /* @__PURE__ */ jsx(Heading, { level: "h1", children: "Exchanges" }),
3047
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "View and manage all customer exchange requests" })
3048
+ ] }),
3049
+ /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () => loadSwaps(0, true), children: "Refresh" })
3050
+ ] }),
3051
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
3052
+ /* @__PURE__ */ jsx(
3053
+ Input,
3602
3054
  {
3603
- variant: "transparent",
3604
- size: "small",
3605
- onClick: () => navigate("/returns"),
3606
- className: "w-fit",
3607
- children: [
3608
- /* @__PURE__ */ jsx(ArrowLeft, { className: "mr-2" }),
3609
- "Back to list"
3610
- ]
3055
+ placeholder: "Search by swap ID or order ID",
3056
+ value: searchQuery,
3057
+ onChange: (event) => setSearchQuery(event.target.value),
3058
+ className: "md:max-w-sm"
3611
3059
  }
3612
3060
  ),
3613
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 md:flex-row md:items-center md:justify-between", children: [
3614
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
3615
- /* @__PURE__ */ jsx(Heading, { level: "h1", children: "Return Order Details" }),
3616
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: returnOrder.id })
3617
- ] }),
3618
- /* @__PURE__ */ jsx(
3619
- Badge,
3061
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
3062
+ /* @__PURE__ */ jsxs(
3063
+ "select",
3620
3064
  {
3621
- size: "small",
3622
- className: `uppercase ${getStatusBadgeClass$1(returnOrder.status)}`,
3623
- children: returnOrder.status.replace(/_/g, " ")
3065
+ value: createdByFilter,
3066
+ onChange: (event) => setCreatedByFilter(event.target.value),
3067
+ 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",
3068
+ children: [
3069
+ /* @__PURE__ */ jsx("option", { value: "all", children: "All (Created by)" }),
3070
+ /* @__PURE__ */ jsx("option", { value: "customer", children: "Customer" }),
3071
+ /* @__PURE__ */ jsx("option", { value: "admin", children: "Admin" })
3072
+ ]
3073
+ }
3074
+ ),
3075
+ /* @__PURE__ */ jsxs(
3076
+ "select",
3077
+ {
3078
+ value: statusFilter,
3079
+ onChange: (event) => setStatusFilter(event.target.value),
3080
+ 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",
3081
+ children: [
3082
+ /* @__PURE__ */ jsx("option", { value: "all", children: "All Statuses" }),
3083
+ availableStatuses.map((status) => /* @__PURE__ */ jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
3084
+ ]
3624
3085
  }
3625
3086
  )
3626
3087
  ] })
3627
3088
  ] }),
3628
- returnOrder.status === "requested" && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
3629
- /* @__PURE__ */ jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsx(
3089
+ error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
3090
+ /* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
3091
+ /* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(
3630
3092
  Button,
3631
3093
  {
3632
- variant: "danger",
3633
- onClick: handleReject,
3634
- disabled: isRejecting,
3635
- isLoading: isRejecting,
3636
- children: "Reject (Cancel) Return"
3094
+ variant: "secondary",
3095
+ onClick: () => loadSwaps(0, true),
3096
+ children: "Try again"
3637
3097
  }
3638
- ) }),
3639
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: 'Cancel this return request. Use "Mark as received" when items are received.' })
3640
- ] }),
3641
- returnOrder.refund ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: /* @__PURE__ */ jsx(RefundCalculationBlock, { refund: returnOrder.refund }) }) : null,
3642
- /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
3643
- /* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Information" }),
3644
- /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
3645
- /* @__PURE__ */ jsxs("div", { children: [
3646
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Return ID" }),
3647
- /* @__PURE__ */ jsx(Text, { className: "font-medium", children: returnOrder.id })
3648
- ] }),
3649
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
3650
- Button,
3651
- {
3652
- variant: "secondary",
3653
- onClick: () => {
3654
- window.open(
3655
- `/app/orders/${returnOrder.order_id}`,
3656
- "_blank"
3657
- );
3658
- },
3659
- children: "View order"
3660
- }
3661
- ) })
3662
- ] })
3663
- ] }),
3664
- /* @__PURE__ */ jsxs("div", { className: "grid gap-6 md:grid-cols-2", children: [
3665
- /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
3666
- /* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Details" }),
3667
- /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
3668
- /* @__PURE__ */ jsxs("div", { children: [
3669
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Return ID" }),
3670
- /* @__PURE__ */ jsx(Text, { className: "font-medium", children: returnOrder.id })
3671
- ] }),
3672
- /* @__PURE__ */ jsxs("div", { children: [
3673
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Status" }),
3674
- /* @__PURE__ */ jsx(Text, { className: "font-medium", children: returnOrder.status })
3675
- ] }),
3676
- returnOrder.reason && /* @__PURE__ */ jsxs("div", { children: [
3677
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Reason" }),
3678
- /* @__PURE__ */ jsx(Text, { className: "font-medium", children: returnOrder.reason })
3679
- ] }),
3680
- returnOrder.note && /* @__PURE__ */ jsxs("div", { children: [
3681
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Note" }),
3682
- /* @__PURE__ */ jsx(Text, { className: "font-medium", children: returnOrder.note })
3683
- ] }),
3684
- /* @__PURE__ */ jsxs("div", { children: [
3685
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Created" }),
3686
- /* @__PURE__ */ jsx(Text, { className: "font-medium", children: new Date(returnOrder.created_at).toLocaleString() })
3687
- ] }),
3688
- /* @__PURE__ */ jsxs("div", { children: [
3689
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Last Updated" }),
3690
- /* @__PURE__ */ jsx(Text, { className: "font-medium", children: new Date(returnOrder.updated_at).toLocaleString() })
3691
- ] })
3692
- ] })
3693
- ] }),
3694
- /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
3695
- /* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Status History" }),
3696
- statusHistory.length > 0 ? /* @__PURE__ */ jsx("div", { className: "space-y-2", children: statusHistory.map((entry, index) => /* @__PURE__ */ jsx(
3697
- "div",
3698
- {
3699
- className: "flex items-center justify-between border-b border-ui-border-subtle pb-2 last:border-0",
3700
- children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
3701
- /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx(
3702
- Badge,
3703
- {
3704
- size: "2xsmall",
3705
- className: `uppercase ${getStatusBadgeClass$1(entry.status)}`,
3706
- children: entry.status.replace(/_/g, " ")
3707
- }
3708
- ) }),
3709
- /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
3710
- new Date(entry.timestamp).toLocaleString(),
3711
- entry.admin_id && ` by ${entry.admin_id}`,
3712
- entry.reason && ` - ${entry.reason}`
3713
- ] })
3714
- ] })
3715
- },
3716
- index
3717
- )) }) : /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "No status history available" })
3718
- ] })
3719
- ] }),
3720
- returnOrder.order && /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
3721
- /* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Related Order Information" }),
3722
- /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
3723
- /* @__PURE__ */ jsxs("div", { children: [
3724
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Order ID" }),
3725
- /* @__PURE__ */ jsx(Text, { className: "font-medium", children: returnOrder.order.id })
3726
- ] }),
3727
- /* @__PURE__ */ jsxs("div", { children: [
3728
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Status" }),
3729
- /* @__PURE__ */ jsx(Text, { className: "font-medium", children: returnOrder.order.status || "—" })
3730
- ] }),
3731
- /* @__PURE__ */ jsxs("div", { children: [
3732
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Customer" }),
3733
- /* @__PURE__ */ jsx(Text, { className: "font-medium", children: returnOrder.order.customer?.email || returnOrder.order.email || "—" })
3734
- ] }),
3735
- /* @__PURE__ */ jsxs("div", { children: [
3736
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Payment method" }),
3737
- /* @__PURE__ */ jsx(Text, { className: "font-medium", children: returnOrder.order.order_payment?.label || "—" })
3738
- ] }),
3739
- returnOrder.order.total && /* @__PURE__ */ jsxs("div", { children: [
3740
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Total" }),
3741
- /* @__PURE__ */ jsxs(Text, { className: "font-medium", children: [
3742
- returnOrder.order.currency_code || "$",
3743
- (Number(returnOrder.order.total) / 100).toFixed(2)
3744
- ] })
3745
- ] })
3746
- ] })
3747
- ] }),
3748
- returnOrder.return_items && returnOrder.return_items.length > 0 && /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
3749
- /* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Items" }),
3750
- /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
3751
- /* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
3752
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Item ID" }),
3753
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Quantity" }),
3754
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Reason" })
3755
- ] }) }),
3756
- /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: returnOrder.return_items.map((item, index) => /* @__PURE__ */ jsxs("tr", { children: [
3757
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: item.id }),
3758
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.quantity }),
3759
- /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.reason || "—" })
3760
- ] }, item.id || index)) })
3761
- ] }) })
3762
- ] }),
3763
- updateError && /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-ui-border-error bg-ui-bg-error-subtle p-4", children: /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-error", children: updateError }) }),
3764
- updateSuccess && /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-ui-border-success bg-ui-bg-success-subtle p-4", children: /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-success", children: "Action completed successfully" }) })
3098
+ ) })
3099
+ ] }) : null,
3100
+ isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading swaps..." }) }) : items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
3101
+ /* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No exchanges yet" }),
3102
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Exchange requests created by customers will appear here." })
3103
+ ] }) : /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
3104
+ /* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
3105
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Exchange ID" }),
3106
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
3107
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
3108
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Difference Due" }),
3109
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
3110
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
3111
+ ] }) }),
3112
+ /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((swap) => /* @__PURE__ */ jsxs(
3113
+ "tr",
3114
+ {
3115
+ className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
3116
+ onClick: () => navigate(`/swaps/${swap.id}`),
3117
+ children: [
3118
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children: /* @__PURE__ */ jsx("span", { children: swap.id }) }) }),
3119
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: swap.order_id }),
3120
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
3121
+ Badge,
3122
+ {
3123
+ size: "2xsmall",
3124
+ className: `uppercase ${getStatusBadgeClass$4(swap.status)}`,
3125
+ children: swap.status.replace(/_/g, " ")
3126
+ }
3127
+ ) }),
3128
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
3129
+ const amount = swap.difference_due;
3130
+ if (amount == null || amount === void 0) {
3131
+ return "—";
3132
+ }
3133
+ const displayAmount = Number(amount) / 100;
3134
+ const currency = swap.currency_code || "$";
3135
+ const sign = displayAmount >= 0 ? "+" : "";
3136
+ return `${sign}${currency}${displayAmount.toFixed(2)}`;
3137
+ })() }),
3138
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(swap.created_at).toLocaleDateString("en-US", {
3139
+ year: "numeric",
3140
+ month: "short",
3141
+ day: "numeric",
3142
+ hour: "numeric",
3143
+ minute: "2-digit",
3144
+ hour12: true
3145
+ }) }),
3146
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
3147
+ Button,
3148
+ {
3149
+ variant: "transparent",
3150
+ size: "small",
3151
+ onClick: (e) => {
3152
+ e.stopPropagation();
3153
+ navigate(`/app/orders/${swap.order_id}`);
3154
+ },
3155
+ children: "Go to order"
3156
+ }
3157
+ ) })
3158
+ ]
3159
+ },
3160
+ swap.id
3161
+ )) })
3162
+ ] }) }),
3163
+ hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
3164
+ Button,
3165
+ {
3166
+ variant: "secondary",
3167
+ isLoading: isFetchingMore,
3168
+ onClick: () => loadSwaps(offset, false),
3169
+ children: "Load more"
3170
+ }
3171
+ ) }) : null
3765
3172
  ] }) });
3766
3173
  };
3767
- const config$2 = defineRouteConfig({
3768
- label: "Return Order Details",
3769
- icon: CheckCircle
3174
+ const config$5 = defineRouteConfig({
3175
+ label: "Exchanges",
3176
+ icon: ArrowPath
3770
3177
  });
3771
3178
  const MASKED_VALUE = "••••••••••••";
3772
3179
  const SENSITIVE_KEY_PATTERNS = [
@@ -4196,320 +3603,911 @@ const ENTITY_FIELDS = {
4196
3603
  CREATED
4197
3604
  ]
4198
3605
  };
4199
- const GENERIC_FIELDS = [
4200
- { key: "display_id", label: "Number" },
4201
- { key: "title", label: "Title" },
4202
- { key: "name", label: "Name" },
4203
- NAME,
4204
- { key: "email", label: "Email" },
4205
- { key: "phone", label: "Phone" },
4206
- { key: "handle", label: "Handle" },
4207
- { key: "sku", label: "SKU" },
4208
- { key: "code", label: "Code" },
4209
- { key: "status", label: "Status", kind: "status" },
4210
- { key: "type", label: "Type" },
4211
- { key: "amount", label: "Amount", kind: "money" },
4212
- { key: "quantity", label: "Quantity", kind: "number" },
4213
- { key: "currency_code", label: "Currency" },
4214
- { key: "order_id", label: "Order ID", kind: "id" },
4215
- { key: "customer_id", label: "Customer ID", kind: "id" },
4216
- { key: "product_id", label: "Product ID", kind: "id" },
4217
- { key: "payment_id", label: "Payment ID", kind: "id" },
4218
- { key: "provider_id", label: "Provider" },
4219
- CREATED,
4220
- { key: "updated_at", label: "Last updated", kind: "date" }
4221
- ];
4222
- const MAX_GENERIC_FIELDS = 8;
4223
- function amountOf(value) {
4224
- if (typeof value === "number" && Number.isFinite(value)) return value;
4225
- if (typeof value === "string" && value.trim() !== "" && Number.isFinite(Number(value))) return Number(value);
4226
- if (value !== null && typeof value === "object" && "value" in value) {
4227
- return amountOf(value.value);
4228
- }
4229
- return null;
4230
- }
4231
- function formatValue(raw, kind, row) {
4232
- if (raw === null || raw === void 0 || raw === "") return null;
4233
- if (raw === MASKED_VALUE) return { value: MASKED_VALUE, kind: "masked" };
4234
- switch (kind) {
4235
- case "money": {
4236
- const amount = amountOf(raw);
4237
- if (amount === null) return null;
4238
- const currency = typeof row.currency_code === "string" ? row.currency_code : null;
4239
- return { value: formatMoney(amount, currency), kind };
4240
- }
4241
- case "date":
4242
- return typeof raw === "string" || raw instanceof Date ? { value: formatDate(raw), kind } : null;
4243
- case "boolean":
4244
- return { value: raw === true || raw === "true" ? "Yes" : "No", kind };
4245
- case "number": {
4246
- const n = amountOf(raw);
4247
- return n === null ? null : { value: formatNumber(n), kind };
3606
+ const GENERIC_FIELDS = [
3607
+ { key: "display_id", label: "Number" },
3608
+ { key: "title", label: "Title" },
3609
+ { key: "name", label: "Name" },
3610
+ NAME,
3611
+ { key: "email", label: "Email" },
3612
+ { key: "phone", label: "Phone" },
3613
+ { key: "handle", label: "Handle" },
3614
+ { key: "sku", label: "SKU" },
3615
+ { key: "code", label: "Code" },
3616
+ { key: "status", label: "Status", kind: "status" },
3617
+ { key: "type", label: "Type" },
3618
+ { key: "amount", label: "Amount", kind: "money" },
3619
+ { key: "quantity", label: "Quantity", kind: "number" },
3620
+ { key: "currency_code", label: "Currency" },
3621
+ { key: "order_id", label: "Order ID", kind: "id" },
3622
+ { key: "customer_id", label: "Customer ID", kind: "id" },
3623
+ { key: "product_id", label: "Product ID", kind: "id" },
3624
+ { key: "payment_id", label: "Payment ID", kind: "id" },
3625
+ { key: "provider_id", label: "Provider" },
3626
+ CREATED,
3627
+ { key: "updated_at", label: "Last updated", kind: "date" }
3628
+ ];
3629
+ const MAX_GENERIC_FIELDS = 8;
3630
+ function amountOf(value) {
3631
+ if (typeof value === "number" && Number.isFinite(value)) return value;
3632
+ if (typeof value === "string" && value.trim() !== "" && Number.isFinite(Number(value))) return Number(value);
3633
+ if (value !== null && typeof value === "object" && "value" in value) {
3634
+ return amountOf(value.value);
3635
+ }
3636
+ return null;
3637
+ }
3638
+ function formatValue(raw, kind, row) {
3639
+ if (raw === null || raw === void 0 || raw === "") return null;
3640
+ if (raw === MASKED_VALUE) return { value: MASKED_VALUE, kind: "masked" };
3641
+ switch (kind) {
3642
+ case "money": {
3643
+ const amount = amountOf(raw);
3644
+ if (amount === null) return null;
3645
+ const currency = typeof row.currency_code === "string" ? row.currency_code : null;
3646
+ return { value: formatMoney(amount, currency), kind };
3647
+ }
3648
+ case "date":
3649
+ return typeof raw === "string" || raw instanceof Date ? { value: formatDate(raw), kind } : null;
3650
+ case "boolean":
3651
+ return { value: raw === true || raw === "true" ? "Yes" : "No", kind };
3652
+ case "number": {
3653
+ const n = amountOf(raw);
3654
+ return n === null ? null : { value: formatNumber(n), kind };
3655
+ }
3656
+ case "status":
3657
+ return { value: String(raw).replace(/_/g, " "), kind };
3658
+ default:
3659
+ if (typeof raw === "object") return null;
3660
+ if (typeof raw === "string" && raw.length > 160) return { value: `${raw.slice(0, 157)}…`, kind };
3661
+ return { value: String(raw), kind };
3662
+ }
3663
+ }
3664
+ function summarizeOldData(tableName, oldData) {
3665
+ if (!oldData) return [];
3666
+ const { value: row } = maskSensitiveData(oldData, tableName);
3667
+ const specific = ENTITY_FIELDS[tableName];
3668
+ const specs = specific ?? GENERIC_FIELDS;
3669
+ const fields = [];
3670
+ const seenLabels = /* @__PURE__ */ new Set();
3671
+ for (const spec of specs) {
3672
+ const raw = spec.derive ? spec.derive(row) : row[spec.key];
3673
+ const formatted = formatValue(raw, spec.kind ?? "text", row);
3674
+ if (!formatted || seenLabels.has(spec.label)) continue;
3675
+ seenLabels.add(spec.label);
3676
+ const value = spec.key === "currency_code" ? formatted.value.toUpperCase() : formatted.value;
3677
+ fields.push({ key: spec.key, label: spec.label, value, kind: formatted.kind });
3678
+ if (!specific && fields.length >= MAX_GENERIC_FIELDS) break;
3679
+ }
3680
+ return fields;
3681
+ }
3682
+ function readLastListSearch() {
3683
+ try {
3684
+ return window.sessionStorage.getItem(LAST_LIST_URL_KEY) ?? "";
3685
+ } catch {
3686
+ return "";
3687
+ }
3688
+ }
3689
+ const DeletedRecordDetailPage = () => {
3690
+ const navigate = useNavigate();
3691
+ const location = useLocation();
3692
+ const { id = "" } = useParams();
3693
+ const [state, setState] = useState({ status: "loading" });
3694
+ const [reloadToken, setReloadToken] = useState(0);
3695
+ const cameFromList = location.state?.fromList === true;
3696
+ const goBack = () => {
3697
+ if (cameFromList) navigate(-1);
3698
+ else navigate(`/deleted-records-audit${readLastListSearch()}`);
3699
+ };
3700
+ useEffect(() => {
3701
+ const controller = new AbortController();
3702
+ setState({ status: "loading" });
3703
+ fetchAuditDetail(id, controller.signal).then((audit) => setState({ status: "ready", audit })).catch((e) => {
3704
+ if (controller.signal.aborted) return;
3705
+ setState({
3706
+ status: "error",
3707
+ message: e instanceof Error ? e.message : "Unknown error",
3708
+ notFound: e instanceof AuditApiError && e.status === 404
3709
+ });
3710
+ });
3711
+ return () => controller.abort();
3712
+ }, [id, reloadToken]);
3713
+ return /* @__PURE__ */ jsx("div", { className: "w-full p-3 md:p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-4 md:p-6", children: [
3714
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(Button, { variant: "transparent", size: "small", onClick: goBack, className: "-ml-2", children: [
3715
+ /* @__PURE__ */ jsx(ArrowLeft, {}),
3716
+ "Back to Deleted Records"
3717
+ ] }) }),
3718
+ state.status === "loading" ? /* @__PURE__ */ jsx(DetailSkeleton, {}) : state.status === "error" ? /* @__PURE__ */ jsx(
3719
+ DetailError,
3720
+ {
3721
+ notFound: state.notFound,
3722
+ message: state.message,
3723
+ onRetry: () => setReloadToken((t) => t + 1),
3724
+ onBack: goBack
3725
+ }
3726
+ ) : /* @__PURE__ */ jsx(DetailContent, { audit: state.audit })
3727
+ ] }) });
3728
+ };
3729
+ const DetailContent = ({ audit }) => {
3730
+ const navigate = useNavigate();
3731
+ const entity = getEntityInfo(audit.table_name);
3732
+ const source = describeSource(audit.source);
3733
+ const summary = useMemo(() => summarizeOldData(audit.table_name, audit.old_data), [audit]);
3734
+ const masked = useMemo(() => maskSensitiveData(audit.old_data, audit.table_name), [audit]);
3735
+ const guidance = getNextSteps(entity.category.id);
3736
+ const related = getRelatedLinks(audit.table_name, audit.old_data);
3737
+ const [showRaw, setShowRaw] = useState(false);
3738
+ const copyJson = async () => {
3739
+ try {
3740
+ await navigator.clipboard.writeText(JSON.stringify(masked.value, null, 2));
3741
+ toast.success("Record data copied", {
3742
+ description: masked.maskedCount ? "Sensitive values were left hidden." : void 0
3743
+ });
3744
+ } catch {
3745
+ toast.error("Couldn’t copy to clipboard");
3746
+ }
3747
+ };
3748
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3749
+ /* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3", children: [
3750
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
3751
+ /* @__PURE__ */ jsxs(Badge, { size: "small", color: "red", children: [
3752
+ /* @__PURE__ */ jsx(Trash, {}),
3753
+ "Deleted"
3754
+ ] }),
3755
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: entity.category.label })
3756
+ ] }),
3757
+ /* @__PURE__ */ jsxs(Heading, { level: "h1", children: [
3758
+ "Deleted ",
3759
+ entity.label
3760
+ ] }),
3761
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
3762
+ /* @__PURE__ */ jsx(CopyableId, { value: audit.record_id, emptyLabel: "This record type has no ID column", className: "text-sm" }),
3763
+ /* @__PURE__ */ jsxs(Text, { size: "xsmall", className: "text-ui-fg-muted", children: [
3764
+ "Database table: ",
3765
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: audit.table_name })
3766
+ ] })
3767
+ ] })
3768
+ ] }),
3769
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 rounded-lg border border-ui-tag-orange-border bg-ui-tag-orange-bg px-4 py-3", children: [
3770
+ /* @__PURE__ */ jsx(InformationCircle, { className: "mt-0.5 shrink-0 text-ui-tag-orange-icon" }),
3771
+ /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-tag-orange-text", children: [
3772
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: "This is a historical snapshot" }),
3773
+ " captured immediately before deletion. The record no longer exists in the database, so changes elsewhere in the admin are not reflected here."
3774
+ ] })
3775
+ ] }),
3776
+ /* @__PURE__ */ jsx(Section, { title: "Deletion information", children: /* @__PURE__ */ jsxs("dl", { className: "grid grid-cols-1 gap-x-6 gap-y-4 sm:grid-cols-2", children: [
3777
+ /* @__PURE__ */ jsx(Field, { label: "Deleted", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
3778
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: formatExactDateTime(audit.occurred_at) }),
3779
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 text-xs text-ui-fg-muted", children: [
3780
+ /* @__PURE__ */ jsx(ClockSolid, { className: "size-3" }),
3781
+ formatRelativeTime(audit.occurred_at)
3782
+ ] })
3783
+ ] }) }),
3784
+ /* @__PURE__ */ jsx(Field, { label: "Deleted by", children: audit.deleted_by ? /* @__PURE__ */ jsx("span", { className: "break-all text-sm text-ui-fg-base", children: audit.deleted_by }) : /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-muted", children: "Not recorded" }) }),
3785
+ /* @__PURE__ */ jsx(Field, { label: "Source", children: source.kind === "unknown" ? /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-muted", children: "Unknown" }) : /* @__PURE__ */ jsx(Badge, { size: "small", color: sourceBadgeColor(source.kind), children: source.label }) }),
3786
+ /* @__PURE__ */ jsx(Field, { label: "Action", children: /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Permanently deleted" }) })
3787
+ ] }) }),
3788
+ /* @__PURE__ */ jsx(
3789
+ Section,
3790
+ {
3791
+ title: "Record summary",
3792
+ description: `Key details of this ${entity.label.toLowerCase()} at the moment it was deleted.`,
3793
+ children: summary.length ? /* @__PURE__ */ jsx("dl", { className: "grid grid-cols-1 gap-x-6 gap-y-4 sm:grid-cols-2", children: summary.map((field) => /* @__PURE__ */ jsx(Field, { label: field.label, children: field.kind === "id" ? /* @__PURE__ */ jsx(CopyableId, { value: field.value }) : field.kind === "status" ? /* @__PURE__ */ jsx(Badge, { size: "2xsmall", color: "grey", className: "capitalize", children: field.value }) : field.kind === "masked" ? /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-muted", children: "Hidden for security" }) : /* @__PURE__ */ jsx("span", { className: "break-words text-sm text-ui-fg-base", children: field.value }) }, field.label)) }) : /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "No key details could be extracted for this record type. See the original record data below." })
3794
+ }
3795
+ ),
3796
+ /* @__PURE__ */ jsx(
3797
+ Section,
3798
+ {
3799
+ title: "Original record data",
3800
+ description: "The complete data captured before deletion.",
3801
+ actions: showRaw && audit.old_data ? /* @__PURE__ */ jsxs(Button, { variant: "secondary", size: "small", onClick: copyJson, children: [
3802
+ /* @__PURE__ */ jsx(SquareTwoStack, {}),
3803
+ "Copy JSON"
3804
+ ] }) : null,
3805
+ children: audit.old_data ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
3806
+ masked.maskedCount > 0 ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
3807
+ /* @__PURE__ */ jsx(ShieldCheck, { className: "shrink-0 text-ui-fg-muted" }),
3808
+ /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
3809
+ masked.maskedCount,
3810
+ " sensitive ",
3811
+ masked.maskedCount === 1 ? "value is" : "values are",
3812
+ " hidden for security (passwords, tokens, card or account numbers)."
3813
+ ] })
3814
+ ] }) : null,
3815
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(Button, { variant: "secondary", size: "small", onClick: () => setShowRaw((s2) => !s2), "aria-expanded": showRaw, children: [
3816
+ showRaw ? /* @__PURE__ */ jsx(ChevronDownMini, {}) : /* @__PURE__ */ jsx(ChevronRightMini, {}),
3817
+ showRaw ? "Hide full record" : "View full record"
3818
+ ] }) }),
3819
+ showRaw ? /* @__PURE__ */ jsx(JsonViewer, { data: masked.value }) : null
3820
+ ] }) : /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "No data was captured for this deletion." })
3821
+ }
3822
+ ),
3823
+ /* @__PURE__ */ jsx(Section, { title: "What you can do now", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
3824
+ /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-base", children: [
3825
+ "This record was permanently deleted. ",
3826
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Automatic restoration is not available" }),
3827
+ " ",
3828
+ "from this screen."
3829
+ ] }),
3830
+ /* @__PURE__ */ jsxs("ol", { className: "flex list-decimal flex-col gap-3 pl-5 text-sm text-ui-fg-subtle marker:text-ui-fg-muted", children: [
3831
+ /* @__PURE__ */ jsxs("li", { children: [
3832
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-ui-fg-base", children: "Check whether this was expected." }),
3833
+ " ",
3834
+ audit.deleted_by || source.kind !== "unknown" ? "Confirm with the person or system shown above." : `Who deleted it wasn’t recorded—check with your team or integrations active around ${formatExactDateTime(audit.occurred_at)}.`,
3835
+ " ",
3836
+ guidance.headline
3837
+ ] }),
3838
+ /* @__PURE__ */ jsxs("li", { children: [
3839
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-ui-fg-base", children: "If it needs to come back:" }),
3840
+ " ",
3841
+ guidance.recreate
3842
+ ] }),
3843
+ /* @__PURE__ */ jsxs("li", { children: [
3844
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-ui-fg-base", children: "Need the details?" }),
3845
+ " Use “View full record” above to see or copy everything that was stored. Sensitive values stay hidden."
3846
+ ] })
3847
+ ] }),
3848
+ guidance.adminSection || related.length ? /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
3849
+ guidance.adminSection ? /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "small", onClick: () => navigate(guidance.adminSection.path), children: guidance.adminSection.label }) : null,
3850
+ related.map((link) => /* @__PURE__ */ jsxs(
3851
+ Button,
3852
+ {
3853
+ variant: "transparent",
3854
+ size: "small",
3855
+ onClick: () => navigate(link.path),
3856
+ title: `Opens ${link.label.toLowerCase()} ${link.id} if it still exists`,
3857
+ children: [
3858
+ "Open related ",
3859
+ link.label.toLowerCase(),
3860
+ /* @__PURE__ */ jsx(ChevronRightMini, {})
3861
+ ]
3862
+ },
3863
+ link.path
3864
+ ))
3865
+ ] }) : null,
3866
+ related.length ? /* @__PURE__ */ jsx(Text, { size: "xsmall", className: "text-ui-fg-muted", children: "Related records open only if they haven’t been deleted too." }) : null
3867
+ ] }) })
3868
+ ] });
3869
+ };
3870
+ const Section = ({
3871
+ title,
3872
+ description,
3873
+ actions,
3874
+ children
3875
+ }) => /* @__PURE__ */ jsxs("section", { className: "flex flex-col gap-4 rounded-lg border border-ui-border-base p-5", children: [
3876
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-start justify-between gap-2", children: [
3877
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
3878
+ /* @__PURE__ */ jsx(Heading, { level: "h2", children: title }),
3879
+ description ? /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: description }) : null
3880
+ ] }),
3881
+ actions
3882
+ ] }),
3883
+ children
3884
+ ] });
3885
+ const Field = ({ label, children }) => /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
3886
+ /* @__PURE__ */ jsx("dt", { className: "text-xs font-medium uppercase tracking-wide text-ui-fg-muted", children: label }),
3887
+ /* @__PURE__ */ jsx("dd", { className: "min-w-0", children })
3888
+ ] });
3889
+ const DetailSkeleton = () => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", "aria-busy": "true", children: [
3890
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
3891
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-24 rounded-full" }),
3892
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-64" }),
3893
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-48" })
3894
+ ] }),
3895
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-14 w-full" }),
3896
+ Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 rounded-lg border border-ui-border-base p-5", children: [
3897
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-40" }),
3898
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: Array.from({ length: 4 }).map((__, j) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
3899
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-20" }),
3900
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-36" })
3901
+ ] }, j)) })
3902
+ ] }, i))
3903
+ ] });
3904
+ const DetailError = ({
3905
+ notFound,
3906
+ message,
3907
+ onRetry,
3908
+ onBack
3909
+ }) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2 rounded-lg border border-ui-border-base px-6 py-12 text-center", children: [
3910
+ /* @__PURE__ */ jsx(ExclamationCircle, { className: clx(notFound ? "text-ui-fg-muted" : "text-ui-fg-error") }),
3911
+ /* @__PURE__ */ jsx(Heading, { level: "h3", children: notFound ? "Audit entry not found" : "Unable to load this deleted record" }),
3912
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "max-w-md text-ui-fg-subtle", children: notFound ? "This audit entry doesn’t exist. The link may be incorrect." : "We couldn’t retrieve the audit entry right now. Check your connection and try again." }),
3913
+ !notFound ? /* @__PURE__ */ jsx(Text, { size: "xsmall", className: "max-w-md font-mono text-ui-fg-muted", children: message }) : null,
3914
+ /* @__PURE__ */ jsxs("div", { className: "mt-2 flex gap-2", children: [
3915
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "small", onClick: onBack, children: "Back to Deleted Records" }),
3916
+ !notFound ? /* @__PURE__ */ jsx(Button, { variant: "primary", size: "small", onClick: onRetry, children: "Try again" }) : null
3917
+ ] })
3918
+ ] });
3919
+ const config$4 = defineRouteConfig({});
3920
+ const getStatusBadgeClass$3 = (status) => {
3921
+ const s2 = status.toLowerCase();
3922
+ if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
3923
+ if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
3924
+ if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
3925
+ if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
3926
+ return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
3927
+ };
3928
+ const PaymentDetailPage = () => {
3929
+ const navigate = useNavigate();
3930
+ const params = useParams();
3931
+ const id = params?.id?.trim();
3932
+ const [detail, setDetail] = useState(null);
3933
+ const [loading, setLoading] = useState(!!id);
3934
+ const [error, setError] = useState(null);
3935
+ useEffect(() => {
3936
+ if (!id) {
3937
+ setLoading(false);
3938
+ return;
4248
3939
  }
4249
- case "status":
4250
- return { value: String(raw).replace(/_/g, " "), kind };
4251
- default:
4252
- if (typeof raw === "object") return null;
4253
- if (typeof raw === "string" && raw.length > 160) return { value: `${raw.slice(0, 157)}…`, kind };
4254
- return { value: String(raw), kind };
4255
- }
4256
- }
4257
- function summarizeOldData(tableName, oldData) {
4258
- if (!oldData) return [];
4259
- const { value: row } = maskSensitiveData(oldData, tableName);
4260
- const specific = ENTITY_FIELDS[tableName];
4261
- const specs = specific ?? GENERIC_FIELDS;
4262
- const fields = [];
4263
- const seenLabels = /* @__PURE__ */ new Set();
4264
- for (const spec of specs) {
4265
- const raw = spec.derive ? spec.derive(row) : row[spec.key];
4266
- const formatted = formatValue(raw, spec.kind ?? "text", row);
4267
- if (!formatted || seenLabels.has(spec.label)) continue;
4268
- seenLabels.add(spec.label);
4269
- const value = spec.key === "currency_code" ? formatted.value.toUpperCase() : formatted.value;
4270
- fields.push({ key: spec.key, label: spec.label, value, kind: formatted.kind });
4271
- if (!specific && fields.length >= MAX_GENERIC_FIELDS) break;
4272
- }
4273
- return fields;
4274
- }
4275
- function readLastListSearch() {
4276
- try {
4277
- return window.sessionStorage.getItem(LAST_LIST_URL_KEY) ?? "";
4278
- } catch {
4279
- return "";
4280
- }
4281
- }
4282
- const DeletedRecordDetailPage = () => {
3940
+ let cancelled = false;
3941
+ setLoading(true);
3942
+ setError(null);
3943
+ fetch(`/admin/payment-transactions/${id}`, { credentials: "include" }).then((res) => {
3944
+ if (!res.ok) throw new Error(res.statusText || "Failed to load");
3945
+ return res.json();
3946
+ }).then((data) => {
3947
+ if (!cancelled) setDetail(data);
3948
+ }).catch((e) => {
3949
+ if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
3950
+ }).finally(() => {
3951
+ if (!cancelled) setLoading(false);
3952
+ });
3953
+ return () => {
3954
+ cancelled = true;
3955
+ };
3956
+ }, [id]);
3957
+ const displayStatus = detail ? (detail.payment_id != null && detail.payment_status != null && detail.payment_status !== "" ? detail.payment_status : detail.session_status ?? "") || "—" : "";
3958
+ const sessionStatusRaw = detail?.session_status ?? "—";
3959
+ const paymentStatusRaw = detail?.payment_id != null ? detail?.payment_status ?? "—" : "—";
3960
+ const displayAmount = detail ? `${(detail.currency_code ?? "USD").toUpperCase()} ${Number(detail.amount)}` : "";
3961
+ return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-4xl flex-col gap-6 p-6", children: [
3962
+ /* @__PURE__ */ jsx("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
3963
+ /* @__PURE__ */ jsx(Button, { variant: "transparent", size: "small", onClick: () => navigate("/payments"), children: "← Payments" }),
3964
+ /* @__PURE__ */ jsx(Heading, { level: "h1", children: "Payment session" }),
3965
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: id ?? "—" })
3966
+ ] }) }),
3967
+ error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
3968
+ /* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
3969
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/payments"), children: "Back to list" })
3970
+ ] }) : loading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading…" }) }) : detail ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
3971
+ /* @__PURE__ */ jsx("div", { className: "rounded-xl border border-ui-border-base p-6 flex flex-col gap-4", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
3972
+ /* @__PURE__ */ jsxs("div", { children: [
3973
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Order ID" }),
3974
+ /* @__PURE__ */ jsx("div", { className: "mt-1", children: detail.order_id ? /* @__PURE__ */ jsx(
3975
+ Button,
3976
+ {
3977
+ variant: "transparent",
3978
+ size: "small",
3979
+ onClick: () => navigate(`/orders/${detail.order_id}`),
3980
+ children: detail.order_id
3981
+ }
3982
+ ) : /* @__PURE__ */ jsx(Text, { children: "—" }) })
3983
+ ] }),
3984
+ /* @__PURE__ */ jsxs("div", { children: [
3985
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
3986
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: displayAmount })
3987
+ ] }),
3988
+ /* @__PURE__ */ jsxs("div", { children: [
3989
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
3990
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.provider_id })
3991
+ ] }),
3992
+ /* @__PURE__ */ jsxs("div", { children: [
3993
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
3994
+ /* @__PURE__ */ jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsx(
3995
+ Badge,
3996
+ {
3997
+ size: "2xsmall",
3998
+ className: `uppercase ${getStatusBadgeClass$3(displayStatus)}`,
3999
+ children: displayStatus !== "—" ? displayStatus.replace(/_/g, " ") : "—"
4000
+ }
4001
+ ) })
4002
+ ] }),
4003
+ /* @__PURE__ */ jsxs("div", { children: [
4004
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Session status (DB)" }),
4005
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: sessionStatusRaw })
4006
+ ] }),
4007
+ /* @__PURE__ */ jsxs("div", { children: [
4008
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Payment status (DB)" }),
4009
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: paymentStatusRaw })
4010
+ ] }),
4011
+ /* @__PURE__ */ jsxs("div", { children: [
4012
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Finalized" }),
4013
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.payment_id != null ? "Yes" : "No" })
4014
+ ] }),
4015
+ /* @__PURE__ */ jsxs("div", { children: [
4016
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Created" }),
4017
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: new Date(detail.created_at).toLocaleDateString("en-US", {
4018
+ year: "numeric",
4019
+ month: "short",
4020
+ day: "numeric",
4021
+ hour: "numeric",
4022
+ minute: "2-digit",
4023
+ hour12: true
4024
+ }) })
4025
+ ] })
4026
+ ] }) }),
4027
+ Object.keys(detail.data ?? {}).length > 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
4028
+ /* @__PURE__ */ jsx(Heading, { level: "h2", className: "text-lg mb-4", children: "Provider data" }),
4029
+ /* @__PURE__ */ jsx("pre", { className: "text-xs bg-ui-bg-subtle p-4 rounded-lg overflow-auto max-h-96", children: JSON.stringify(detail.data, null, 2) })
4030
+ ] }) : /* @__PURE__ */ jsx("div", { className: "rounded-xl border border-ui-border-base p-6", children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "No provider data for this session." }) })
4031
+ ] }) : null
4032
+ ] }) });
4033
+ };
4034
+ const config$3 = defineRouteConfig({
4035
+ label: "Payment details",
4036
+ icon: CreditCard
4037
+ });
4038
+ const getStatusBadgeClass$2 = (status) => {
4039
+ const s2 = status.toLowerCase();
4040
+ if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
4041
+ if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
4042
+ if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
4043
+ if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
4044
+ return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
4045
+ };
4046
+ const formatAmount = (value) => {
4047
+ return String(value);
4048
+ };
4049
+ const RefundDetailPage = () => {
4283
4050
  const navigate = useNavigate();
4284
- const location = useLocation();
4285
- const { id = "" } = useParams();
4286
- const [state, setState] = useState({ status: "loading" });
4287
- const [reloadToken, setReloadToken] = useState(0);
4288
- const cameFromList = location.state?.fromList === true;
4289
- const goBack = () => {
4290
- if (cameFromList) navigate(-1);
4291
- else navigate(`/deleted-records-audit${readLastListSearch()}`);
4292
- };
4051
+ const params = useParams();
4052
+ const id = params?.id?.trim();
4053
+ const [detail, setDetail] = useState(null);
4054
+ const [loading, setLoading] = useState(!!id);
4055
+ const [error, setError] = useState(null);
4056
+ const [gatewayExpanded, setGatewayExpanded] = useState(false);
4293
4057
  useEffect(() => {
4294
- const controller = new AbortController();
4295
- setState({ status: "loading" });
4296
- fetchAuditDetail(id, controller.signal).then((audit) => setState({ status: "ready", audit })).catch((e) => {
4297
- if (controller.signal.aborted) return;
4298
- setState({
4299
- status: "error",
4300
- message: e instanceof Error ? e.message : "Unknown error",
4301
- notFound: e instanceof AuditApiError && e.status === 404
4302
- });
4058
+ if (!id) {
4059
+ setLoading(false);
4060
+ return;
4061
+ }
4062
+ let cancelled = false;
4063
+ setLoading(true);
4064
+ setError(null);
4065
+ fetch(`/admin/refunds/${id}`, { credentials: "include" }).then((res) => {
4066
+ if (!res.ok) throw new Error(res.statusText || "Failed to load");
4067
+ return res.json();
4068
+ }).then((data) => {
4069
+ if (!cancelled) setDetail(data);
4070
+ }).catch((e) => {
4071
+ if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
4072
+ }).finally(() => {
4073
+ if (!cancelled) setLoading(false);
4303
4074
  });
4304
- return () => controller.abort();
4305
- }, [id, reloadToken]);
4306
- return /* @__PURE__ */ jsx("div", { className: "w-full p-3 md:p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-4 md:p-6", children: [
4307
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(Button, { variant: "transparent", size: "small", onClick: goBack, className: "-ml-2", children: [
4308
- /* @__PURE__ */ jsx(ArrowLeft, {}),
4309
- "Back to Deleted Records"
4075
+ return () => {
4076
+ cancelled = true;
4077
+ };
4078
+ }, [id]);
4079
+ const paymentStatus = detail?.payment?.status ?? "—";
4080
+ const hasGatewayData = detail?.payment?.payment_data && typeof detail.payment.payment_data === "object" && Object.keys(detail.payment.payment_data).length > 0;
4081
+ return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-4xl flex-col gap-6 p-6", children: [
4082
+ /* @__PURE__ */ jsx("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
4083
+ /* @__PURE__ */ jsx(Button, { variant: "transparent", size: "small", onClick: () => navigate("/refunds"), children: "← Refunds" }),
4084
+ /* @__PURE__ */ jsx(Heading, { level: "h1", children: "Refund details" }),
4085
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle font-mono", children: id ?? "—" })
4310
4086
  ] }) }),
4311
- state.status === "loading" ? /* @__PURE__ */ jsx(DetailSkeleton, {}) : state.status === "error" ? /* @__PURE__ */ jsx(
4312
- DetailError,
4313
- {
4314
- notFound: state.notFound,
4315
- message: state.message,
4316
- onRetry: () => setReloadToken((t) => t + 1),
4317
- onBack: goBack
4318
- }
4319
- ) : /* @__PURE__ */ jsx(DetailContent, { audit: state.audit })
4087
+ error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
4088
+ /* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
4089
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/refunds"), children: "Back to list" })
4090
+ ] }) : loading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading…" }) }) : detail ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
4091
+ /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
4092
+ /* @__PURE__ */ jsx(Heading, { level: "h2", className: "text-lg mb-4", children: "Refund summary" }),
4093
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
4094
+ /* @__PURE__ */ jsxs("div", { children: [
4095
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Refund ID" }),
4096
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.id })
4097
+ ] }),
4098
+ /* @__PURE__ */ jsxs("div", { children: [
4099
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
4100
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.refund.amount) })
4101
+ ] }),
4102
+ /* @__PURE__ */ jsxs("div", { children: [
4103
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Note" }),
4104
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.refund.note ?? "—" })
4105
+ ] }),
4106
+ /* @__PURE__ */ jsxs("div", { children: [
4107
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Created at" }),
4108
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: new Date(detail.refund.created_at).toLocaleDateString("en-US", {
4109
+ year: "numeric",
4110
+ month: "short",
4111
+ day: "numeric",
4112
+ hour: "numeric",
4113
+ minute: "2-digit",
4114
+ hour12: true
4115
+ }) })
4116
+ ] }),
4117
+ detail.refund.created_by ? /* @__PURE__ */ jsxs("div", { children: [
4118
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Created by" }),
4119
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.created_by })
4120
+ ] }) : null
4121
+ ] })
4122
+ ] }),
4123
+ /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
4124
+ /* @__PURE__ */ jsx(Heading, { level: "h2", className: "text-lg mb-4", children: "Payment summary" }),
4125
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
4126
+ /* @__PURE__ */ jsxs("div", { children: [
4127
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Payment amount" }),
4128
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.payment.payment_amount) })
4129
+ ] }),
4130
+ /* @__PURE__ */ jsxs("div", { children: [
4131
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Captured amount" }),
4132
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.payment.captured_amount) })
4133
+ ] }),
4134
+ /* @__PURE__ */ jsxs("div", { children: [
4135
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Refunded amount" }),
4136
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.payment.refunded_amount) })
4137
+ ] }),
4138
+ /* @__PURE__ */ jsxs("div", { children: [
4139
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
4140
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.payment.provider_id || "—" })
4141
+ ] }),
4142
+ /* @__PURE__ */ jsxs("div", { children: [
4143
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
4144
+ /* @__PURE__ */ jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsx(
4145
+ Badge,
4146
+ {
4147
+ size: "2xsmall",
4148
+ className: `uppercase ${getStatusBadgeClass$2(paymentStatus)}`,
4149
+ children: paymentStatus !== "—" ? paymentStatus.replace(/_/g, " ") : "—"
4150
+ }
4151
+ ) })
4152
+ ] }),
4153
+ detail.computed ? /* @__PURE__ */ jsxs(Fragment, { children: [
4154
+ /* @__PURE__ */ jsxs("div", { children: [
4155
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Full refund" }),
4156
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.computed.is_full_refund ? "Yes" : "No" })
4157
+ ] }),
4158
+ /* @__PURE__ */ jsxs("div", { children: [
4159
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Remaining refundable" }),
4160
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.computed.remaining_refundable_amount) })
4161
+ ] }),
4162
+ /* @__PURE__ */ jsxs("div", { children: [
4163
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Refund %" }),
4164
+ /* @__PURE__ */ jsxs(Text, { className: "mt-1 block", children: [
4165
+ detail.computed.refund_percentage.toFixed(1),
4166
+ "%"
4167
+ ] })
4168
+ ] })
4169
+ ] }) : null
4170
+ ] })
4171
+ ] }),
4172
+ /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
4173
+ /* @__PURE__ */ jsx(Heading, { level: "h2", className: "text-lg mb-4", children: "Order summary" }),
4174
+ detail.order ? /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
4175
+ /* @__PURE__ */ jsxs("div", { children: [
4176
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Order" }),
4177
+ /* @__PURE__ */ jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsx(
4178
+ Button,
4179
+ {
4180
+ variant: "transparent",
4181
+ size: "small",
4182
+ onClick: () => navigate(`/orders/${detail.order.order_id}`),
4183
+ children: detail.order.order_number ?? detail.order.order_id
4184
+ }
4185
+ ) })
4186
+ ] }),
4187
+ detail.order.total != null ? /* @__PURE__ */ jsxs("div", { children: [
4188
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Total" }),
4189
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.order.total) })
4190
+ ] }) : null,
4191
+ detail.order.customer_id ? /* @__PURE__ */ jsxs("div", { children: [
4192
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Customer ID" }),
4193
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block font-mono text-sm", children: detail.order.customer_id })
4194
+ ] }) : null,
4195
+ detail.order.region ? /* @__PURE__ */ jsxs("div", { children: [
4196
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Region" }),
4197
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.order.region })
4198
+ ] }) : null,
4199
+ detail.order.fulfillment_status ? /* @__PURE__ */ jsxs("div", { children: [
4200
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Fulfillment status" }),
4201
+ /* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.order.fulfillment_status })
4202
+ ] }) : null
4203
+ ] }) : /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "No order linked to this refund." })
4204
+ ] }),
4205
+ /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
4206
+ /* @__PURE__ */ jsxs(
4207
+ "button",
4208
+ {
4209
+ type: "button",
4210
+ className: "flex w-full items-center justify-between text-left",
4211
+ onClick: () => setGatewayExpanded((prev) => !prev),
4212
+ "aria-expanded": gatewayExpanded,
4213
+ "aria-label": gatewayExpanded ? "Collapse gateway data" : "Expand gateway data",
4214
+ children: [
4215
+ /* @__PURE__ */ jsx(Heading, { level: "h2", className: "text-lg", children: "Gateway data" }),
4216
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: gatewayExpanded ? "Collapse" : "Expand" })
4217
+ ]
4218
+ }
4219
+ ),
4220
+ gatewayExpanded && /* @__PURE__ */ jsx("div", { className: "mt-4", children: hasGatewayData ? /* @__PURE__ */ jsx("pre", { className: "text-xs bg-ui-bg-subtle p-4 rounded-lg overflow-auto max-h-96", children: JSON.stringify(detail.payment.payment_data, null, 2) }) : /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "No gateway payload for this payment." }) })
4221
+ ] })
4222
+ ] }) : null
4320
4223
  ] }) });
4321
4224
  };
4322
- const DetailContent = ({ audit }) => {
4225
+ const config$2 = defineRouteConfig({
4226
+ label: "Refund details",
4227
+ icon: Receipt
4228
+ });
4229
+ const getStatusBadgeClass$1 = (status) => {
4230
+ const statusLower = status.toLowerCase();
4231
+ if (statusLower === "requested") {
4232
+ return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
4233
+ }
4234
+ if (statusLower === "approved") {
4235
+ return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
4236
+ }
4237
+ if (statusLower === "rejected") {
4238
+ return "bg-ui-tag-red-bg text-ui-tag-red-text";
4239
+ }
4240
+ if (statusLower === "received") {
4241
+ return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
4242
+ }
4243
+ if (statusLower === "refunded") {
4244
+ return "bg-ui-tag-green-bg text-ui-tag-green-text";
4245
+ }
4246
+ if (statusLower === "completed") {
4247
+ return "bg-ui-tag-green-bg text-ui-tag-green-text";
4248
+ }
4249
+ if (statusLower === "cancelled") {
4250
+ return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
4251
+ }
4252
+ return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
4253
+ };
4254
+ const ReturnDetailPage = () => {
4323
4255
  const navigate = useNavigate();
4324
- const entity = getEntityInfo(audit.table_name);
4325
- const source = describeSource(audit.source);
4326
- const summary = useMemo(() => summarizeOldData(audit.table_name, audit.old_data), [audit]);
4327
- const masked = useMemo(() => maskSensitiveData(audit.old_data, audit.table_name), [audit]);
4328
- const guidance = getNextSteps(entity.category.id);
4329
- const related = getRelatedLinks(audit.table_name, audit.old_data);
4330
- const [showRaw, setShowRaw] = useState(false);
4331
- const copyJson = async () => {
4256
+ const { id } = useParams();
4257
+ const [returnOrder, setReturnOrder] = useState(null);
4258
+ const [isLoading, setIsLoading] = useState(true);
4259
+ const [isRejecting, setIsRejecting] = useState(false);
4260
+ const [error, setError] = useState(null);
4261
+ const [updateError, setUpdateError] = useState(null);
4262
+ const [updateSuccess, setUpdateSuccess] = useState(false);
4263
+ useEffect(() => {
4264
+ if (!id) {
4265
+ navigate("/returns");
4266
+ return;
4267
+ }
4268
+ const loadReturn = async () => {
4269
+ try {
4270
+ setIsLoading(true);
4271
+ setError(null);
4272
+ const response = await fetch(`/admin/return/${id}`, {
4273
+ credentials: "include"
4274
+ });
4275
+ if (!response.ok) {
4276
+ const message = await response.text();
4277
+ throw new Error(message || "Unable to load return order");
4278
+ }
4279
+ const payload = await response.json();
4280
+ setReturnOrder(payload.return);
4281
+ } catch (loadError) {
4282
+ const message = loadError instanceof Error ? loadError.message : "Unable to load return order";
4283
+ setError(message);
4284
+ } finally {
4285
+ setIsLoading(false);
4286
+ }
4287
+ };
4288
+ void loadReturn();
4289
+ }, [id, navigate]);
4290
+ const handleReject = async () => {
4291
+ if (!id) {
4292
+ return;
4293
+ }
4332
4294
  try {
4333
- await navigator.clipboard.writeText(JSON.stringify(masked.value, null, 2));
4334
- toast.success("Record data copied", {
4335
- description: masked.maskedCount ? "Sensitive values were left hidden." : void 0
4295
+ setIsRejecting(true);
4296
+ setUpdateError(null);
4297
+ setUpdateSuccess(false);
4298
+ const response = await fetch(`/admin/return/${id}/reject`, {
4299
+ method: "POST",
4300
+ headers: {
4301
+ "Content-Type": "application/json"
4302
+ },
4303
+ credentials: "include",
4304
+ body: JSON.stringify({ reason: "Rejected by admin" })
4336
4305
  });
4337
- } catch {
4338
- toast.error("Couldn’t copy to clipboard");
4306
+ if (!response.ok) {
4307
+ const message = await response.text();
4308
+ throw new Error(message || "Unable to reject return");
4309
+ }
4310
+ const payload = await response.json();
4311
+ setReturnOrder(payload.return);
4312
+ setUpdateSuccess(true);
4313
+ setTimeout(() => setUpdateSuccess(false), 3e3);
4314
+ const detailResponse = await fetch(`/admin/return/${id}`, {
4315
+ credentials: "include"
4316
+ });
4317
+ if (detailResponse.ok) {
4318
+ const detailPayload = await detailResponse.json();
4319
+ setReturnOrder(detailPayload.return);
4320
+ }
4321
+ } catch (updateErr) {
4322
+ const message = updateErr instanceof Error ? updateErr.message : "Unable to reject return";
4323
+ setUpdateError(message);
4324
+ } finally {
4325
+ setIsRejecting(false);
4339
4326
  }
4340
4327
  };
4341
- return /* @__PURE__ */ jsxs(Fragment, { children: [
4328
+ if (isLoading) {
4329
+ return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsx(Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading return order..." }) }) }) });
4330
+ }
4331
+ if (error || !returnOrder) {
4332
+ return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsx(Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
4333
+ /* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error || "Return order not found" }),
4334
+ /* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => navigate("/returns"), children: "Back to list" }) })
4335
+ ] }) }) });
4336
+ }
4337
+ const statusHistory = returnOrder.metadata?.status_history || [];
4338
+ return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: [
4342
4339
  /* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3", children: [
4343
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
4344
- /* @__PURE__ */ jsxs(Badge, { size: "small", color: "red", children: [
4345
- /* @__PURE__ */ jsx(Trash, {}),
4346
- "Deleted"
4340
+ /* @__PURE__ */ jsxs(
4341
+ Button,
4342
+ {
4343
+ variant: "transparent",
4344
+ size: "small",
4345
+ onClick: () => navigate("/returns"),
4346
+ className: "w-fit",
4347
+ children: [
4348
+ /* @__PURE__ */ jsx(ArrowLeft, { className: "mr-2" }),
4349
+ "Back to list"
4350
+ ]
4351
+ }
4352
+ ),
4353
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 md:flex-row md:items-center md:justify-between", children: [
4354
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
4355
+ /* @__PURE__ */ jsx(Heading, { level: "h1", children: "Return Order Details" }),
4356
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: returnOrder.id })
4347
4357
  ] }),
4348
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: entity.category.label })
4349
- ] }),
4350
- /* @__PURE__ */ jsxs(Heading, { level: "h1", children: [
4351
- "Deleted ",
4352
- entity.label
4353
- ] }),
4354
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
4355
- /* @__PURE__ */ jsx(CopyableId, { value: audit.record_id, emptyLabel: "This record type has no ID column", className: "text-sm" }),
4356
- /* @__PURE__ */ jsxs(Text, { size: "xsmall", className: "text-ui-fg-muted", children: [
4357
- "Database table: ",
4358
- /* @__PURE__ */ jsx("span", { className: "font-mono", children: audit.table_name })
4359
- ] })
4358
+ /* @__PURE__ */ jsx(
4359
+ Badge,
4360
+ {
4361
+ size: "small",
4362
+ className: `uppercase ${getStatusBadgeClass$1(returnOrder.status)}`,
4363
+ children: returnOrder.status.replace(/_/g, " ")
4364
+ }
4365
+ )
4360
4366
  ] })
4361
4367
  ] }),
4362
- /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 rounded-lg border border-ui-tag-orange-border bg-ui-tag-orange-bg px-4 py-3", children: [
4363
- /* @__PURE__ */ jsx(InformationCircle, { className: "mt-0.5 shrink-0 text-ui-tag-orange-icon" }),
4364
- /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-tag-orange-text", children: [
4365
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: "This is a historical snapshot" }),
4366
- " captured immediately before deletion. The record no longer exists in the database, so changes elsewhere in the admin are not reflected here."
4367
- ] })
4368
+ returnOrder.status === "requested" && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
4369
+ /* @__PURE__ */ jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsx(
4370
+ Button,
4371
+ {
4372
+ variant: "danger",
4373
+ onClick: handleReject,
4374
+ disabled: isRejecting,
4375
+ isLoading: isRejecting,
4376
+ children: "Reject (Cancel) Return"
4377
+ }
4378
+ ) }),
4379
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: 'Cancel this return request. Use "Mark as received" when items are received.' })
4368
4380
  ] }),
4369
- /* @__PURE__ */ jsx(Section, { title: "Deletion information", children: /* @__PURE__ */ jsxs("dl", { className: "grid grid-cols-1 gap-x-6 gap-y-4 sm:grid-cols-2", children: [
4370
- /* @__PURE__ */ jsx(Field, { label: "Deleted", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
4371
- /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: formatExactDateTime(audit.occurred_at) }),
4372
- /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 text-xs text-ui-fg-muted", children: [
4373
- /* @__PURE__ */ jsx(ClockSolid, { className: "size-3" }),
4374
- formatRelativeTime(audit.occurred_at)
4375
- ] })
4376
- ] }) }),
4377
- /* @__PURE__ */ jsx(Field, { label: "Deleted by", children: audit.deleted_by ? /* @__PURE__ */ jsx("span", { className: "break-all text-sm text-ui-fg-base", children: audit.deleted_by }) : /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-muted", children: "Not recorded" }) }),
4378
- /* @__PURE__ */ jsx(Field, { label: "Source", children: source.kind === "unknown" ? /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-muted", children: "Unknown" }) : /* @__PURE__ */ jsx(Badge, { size: "small", color: sourceBadgeColor(source.kind), children: source.label }) }),
4379
- /* @__PURE__ */ jsx(Field, { label: "Action", children: /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Permanently deleted" }) })
4380
- ] }) }),
4381
- /* @__PURE__ */ jsx(
4382
- Section,
4383
- {
4384
- title: "Record summary",
4385
- description: `Key details of this ${entity.label.toLowerCase()} at the moment it was deleted.`,
4386
- children: summary.length ? /* @__PURE__ */ jsx("dl", { className: "grid grid-cols-1 gap-x-6 gap-y-4 sm:grid-cols-2", children: summary.map((field) => /* @__PURE__ */ jsx(Field, { label: field.label, children: field.kind === "id" ? /* @__PURE__ */ jsx(CopyableId, { value: field.value }) : field.kind === "status" ? /* @__PURE__ */ jsx(Badge, { size: "2xsmall", color: "grey", className: "capitalize", children: field.value }) : field.kind === "masked" ? /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-muted", children: "Hidden for security" }) : /* @__PURE__ */ jsx("span", { className: "break-words text-sm text-ui-fg-base", children: field.value }) }, field.label)) }) : /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "No key details could be extracted for this record type. See the original record data below." })
4387
- }
4388
- ),
4389
- /* @__PURE__ */ jsx(
4390
- Section,
4391
- {
4392
- title: "Original record data",
4393
- description: "The complete data captured before deletion.",
4394
- actions: showRaw && audit.old_data ? /* @__PURE__ */ jsxs(Button, { variant: "secondary", size: "small", onClick: copyJson, children: [
4395
- /* @__PURE__ */ jsx(SquareTwoStack, {}),
4396
- "Copy JSON"
4397
- ] }) : null,
4398
- children: audit.old_data ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
4399
- masked.maskedCount > 0 ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
4400
- /* @__PURE__ */ jsx(ShieldCheck, { className: "shrink-0 text-ui-fg-muted" }),
4401
- /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
4402
- masked.maskedCount,
4403
- " sensitive ",
4404
- masked.maskedCount === 1 ? "value is" : "values are",
4405
- " hidden for security (passwords, tokens, card or account numbers)."
4406
- ] })
4407
- ] }) : null,
4408
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(Button, { variant: "secondary", size: "small", onClick: () => setShowRaw((s2) => !s2), "aria-expanded": showRaw, children: [
4409
- showRaw ? /* @__PURE__ */ jsx(ChevronDownMini, {}) : /* @__PURE__ */ jsx(ChevronRightMini, {}),
4410
- showRaw ? "Hide full record" : "View full record"
4411
- ] }) }),
4412
- showRaw ? /* @__PURE__ */ jsx(JsonViewer, { data: masked.value }) : null
4413
- ] }) : /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "No data was captured for this deletion." })
4414
- }
4415
- ),
4416
- /* @__PURE__ */ jsx(Section, { title: "What you can do now", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
4417
- /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-base", children: [
4418
- "This record was permanently deleted. ",
4419
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Automatic restoration is not available" }),
4420
- " ",
4421
- "from this screen."
4422
- ] }),
4423
- /* @__PURE__ */ jsxs("ol", { className: "flex list-decimal flex-col gap-3 pl-5 text-sm text-ui-fg-subtle marker:text-ui-fg-muted", children: [
4424
- /* @__PURE__ */ jsxs("li", { children: [
4425
- /* @__PURE__ */ jsx("span", { className: "font-medium text-ui-fg-base", children: "Check whether this was expected." }),
4426
- " ",
4427
- audit.deleted_by || source.kind !== "unknown" ? "Confirm with the person or system shown above." : `Who deleted it wasn’t recorded—check with your team or integrations active around ${formatExactDateTime(audit.occurred_at)}.`,
4428
- " ",
4429
- guidance.headline
4430
- ] }),
4431
- /* @__PURE__ */ jsxs("li", { children: [
4432
- /* @__PURE__ */ jsx("span", { className: "font-medium text-ui-fg-base", children: "If it needs to come back:" }),
4433
- " ",
4434
- guidance.recreate
4381
+ returnOrder.refund ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: /* @__PURE__ */ jsx(RefundCalculationBlock, { refund: returnOrder.refund }) }) : null,
4382
+ /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
4383
+ /* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Information" }),
4384
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
4385
+ /* @__PURE__ */ jsxs("div", { children: [
4386
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Return ID" }),
4387
+ /* @__PURE__ */ jsx(Text, { className: "font-medium", children: returnOrder.id })
4435
4388
  ] }),
4436
- /* @__PURE__ */ jsxs("li", { children: [
4437
- /* @__PURE__ */ jsx("span", { className: "font-medium text-ui-fg-base", children: "Need the details?" }),
4438
- " Use “View full record” above to see or copy everything that was stored. Sensitive values stay hidden."
4389
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
4390
+ Button,
4391
+ {
4392
+ variant: "secondary",
4393
+ onClick: () => {
4394
+ window.open(
4395
+ `/app/orders/${returnOrder.order_id}`,
4396
+ "_blank"
4397
+ );
4398
+ },
4399
+ children: "View order"
4400
+ }
4401
+ ) })
4402
+ ] })
4403
+ ] }),
4404
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-6 md:grid-cols-2", children: [
4405
+ /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
4406
+ /* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Details" }),
4407
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
4408
+ /* @__PURE__ */ jsxs("div", { children: [
4409
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Return ID" }),
4410
+ /* @__PURE__ */ jsx(Text, { className: "font-medium", children: returnOrder.id })
4411
+ ] }),
4412
+ /* @__PURE__ */ jsxs("div", { children: [
4413
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Status" }),
4414
+ /* @__PURE__ */ jsx(Text, { className: "font-medium", children: returnOrder.status })
4415
+ ] }),
4416
+ returnOrder.reason && /* @__PURE__ */ jsxs("div", { children: [
4417
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Reason" }),
4418
+ /* @__PURE__ */ jsx(Text, { className: "font-medium", children: returnOrder.reason })
4419
+ ] }),
4420
+ returnOrder.note && /* @__PURE__ */ jsxs("div", { children: [
4421
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Note" }),
4422
+ /* @__PURE__ */ jsx(Text, { className: "font-medium", children: returnOrder.note })
4423
+ ] }),
4424
+ /* @__PURE__ */ jsxs("div", { children: [
4425
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Created" }),
4426
+ /* @__PURE__ */ jsx(Text, { className: "font-medium", children: new Date(returnOrder.created_at).toLocaleString() })
4427
+ ] }),
4428
+ /* @__PURE__ */ jsxs("div", { children: [
4429
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Last Updated" }),
4430
+ /* @__PURE__ */ jsx(Text, { className: "font-medium", children: new Date(returnOrder.updated_at).toLocaleString() })
4431
+ ] })
4439
4432
  ] })
4440
4433
  ] }),
4441
- guidance.adminSection || related.length ? /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
4442
- guidance.adminSection ? /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "small", onClick: () => navigate(guidance.adminSection.path), children: guidance.adminSection.label }) : null,
4443
- related.map((link) => /* @__PURE__ */ jsxs(
4444
- Button,
4434
+ /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
4435
+ /* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Status History" }),
4436
+ statusHistory.length > 0 ? /* @__PURE__ */ jsx("div", { className: "space-y-2", children: statusHistory.map((entry, index) => /* @__PURE__ */ jsx(
4437
+ "div",
4445
4438
  {
4446
- variant: "transparent",
4447
- size: "small",
4448
- onClick: () => navigate(link.path),
4449
- title: `Opens ${link.label.toLowerCase()} ${link.id} if it still exists`,
4450
- children: [
4451
- "Open related ",
4452
- link.label.toLowerCase(),
4453
- /* @__PURE__ */ jsx(ChevronRightMini, {})
4454
- ]
4439
+ className: "flex items-center justify-between border-b border-ui-border-subtle pb-2 last:border-0",
4440
+ children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
4441
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx(
4442
+ Badge,
4443
+ {
4444
+ size: "2xsmall",
4445
+ className: `uppercase ${getStatusBadgeClass$1(entry.status)}`,
4446
+ children: entry.status.replace(/_/g, " ")
4447
+ }
4448
+ ) }),
4449
+ /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
4450
+ new Date(entry.timestamp).toLocaleString(),
4451
+ entry.admin_id && ` by ${entry.admin_id}`,
4452
+ entry.reason && ` - ${entry.reason}`
4453
+ ] })
4454
+ ] })
4455
4455
  },
4456
- link.path
4457
- ))
4458
- ] }) : null,
4459
- related.length ? /* @__PURE__ */ jsx(Text, { size: "xsmall", className: "text-ui-fg-muted", children: "Related records open only if they haven’t been deleted too." }) : null
4460
- ] }) })
4461
- ] });
4462
- };
4463
- const Section = ({
4464
- title,
4465
- description,
4466
- actions,
4467
- children
4468
- }) => /* @__PURE__ */ jsxs("section", { className: "flex flex-col gap-4 rounded-lg border border-ui-border-base p-5", children: [
4469
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-start justify-between gap-2", children: [
4470
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
4471
- /* @__PURE__ */ jsx(Heading, { level: "h2", children: title }),
4472
- description ? /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: description }) : null
4456
+ index
4457
+ )) }) : /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "No status history available" })
4458
+ ] })
4473
4459
  ] }),
4474
- actions
4475
- ] }),
4476
- children
4477
- ] });
4478
- const Field = ({ label, children }) => /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
4479
- /* @__PURE__ */ jsx("dt", { className: "text-xs font-medium uppercase tracking-wide text-ui-fg-muted", children: label }),
4480
- /* @__PURE__ */ jsx("dd", { className: "min-w-0", children })
4481
- ] });
4482
- const DetailSkeleton = () => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", "aria-busy": "true", children: [
4483
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
4484
- /* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-24 rounded-full" }),
4485
- /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-64" }),
4486
- /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-48" })
4487
- ] }),
4488
- /* @__PURE__ */ jsx(Skeleton, { className: "h-14 w-full" }),
4489
- Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 rounded-lg border border-ui-border-base p-5", children: [
4490
- /* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-40" }),
4491
- /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: Array.from({ length: 4 }).map((__, j) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
4492
- /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-20" }),
4493
- /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-36" })
4494
- ] }, j)) })
4495
- ] }, i))
4496
- ] });
4497
- const DetailError = ({
4498
- notFound,
4499
- message,
4500
- onRetry,
4501
- onBack
4502
- }) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2 rounded-lg border border-ui-border-base px-6 py-12 text-center", children: [
4503
- /* @__PURE__ */ jsx(ExclamationCircle, { className: clx(notFound ? "text-ui-fg-muted" : "text-ui-fg-error") }),
4504
- /* @__PURE__ */ jsx(Heading, { level: "h3", children: notFound ? "Audit entry not found" : "Unable to load this deleted record" }),
4505
- /* @__PURE__ */ jsx(Text, { size: "small", className: "max-w-md text-ui-fg-subtle", children: notFound ? "This audit entry doesn’t exist. The link may be incorrect." : "We couldn’t retrieve the audit entry right now. Check your connection and try again." }),
4506
- !notFound ? /* @__PURE__ */ jsx(Text, { size: "xsmall", className: "max-w-md font-mono text-ui-fg-muted", children: message }) : null,
4507
- /* @__PURE__ */ jsxs("div", { className: "mt-2 flex gap-2", children: [
4508
- /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "small", onClick: onBack, children: "Back to Deleted Records" }),
4509
- !notFound ? /* @__PURE__ */ jsx(Button, { variant: "primary", size: "small", onClick: onRetry, children: "Try again" }) : null
4510
- ] })
4511
- ] });
4512
- const config$1 = defineRouteConfig({});
4460
+ returnOrder.order && /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
4461
+ /* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Related Order Information" }),
4462
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
4463
+ /* @__PURE__ */ jsxs("div", { children: [
4464
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Order ID" }),
4465
+ /* @__PURE__ */ jsx(Text, { className: "font-medium", children: returnOrder.order.id })
4466
+ ] }),
4467
+ /* @__PURE__ */ jsxs("div", { children: [
4468
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Status" }),
4469
+ /* @__PURE__ */ jsx(Text, { className: "font-medium", children: returnOrder.order.status || "—" })
4470
+ ] }),
4471
+ /* @__PURE__ */ jsxs("div", { children: [
4472
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Customer" }),
4473
+ /* @__PURE__ */ jsx(Text, { className: "font-medium", children: returnOrder.order.customer?.email || returnOrder.order.email || "—" })
4474
+ ] }),
4475
+ /* @__PURE__ */ jsxs("div", { children: [
4476
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Payment method" }),
4477
+ /* @__PURE__ */ jsx(Text, { className: "font-medium", children: returnOrder.order.order_payment?.label || "—" })
4478
+ ] }),
4479
+ returnOrder.order.total && /* @__PURE__ */ jsxs("div", { children: [
4480
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Total" }),
4481
+ /* @__PURE__ */ jsxs(Text, { className: "font-medium", children: [
4482
+ returnOrder.order.currency_code || "$",
4483
+ (Number(returnOrder.order.total) / 100).toFixed(2)
4484
+ ] })
4485
+ ] })
4486
+ ] })
4487
+ ] }),
4488
+ returnOrder.return_items && returnOrder.return_items.length > 0 && /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
4489
+ /* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Items" }),
4490
+ /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
4491
+ /* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
4492
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Item ID" }),
4493
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Quantity" }),
4494
+ /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Reason" })
4495
+ ] }) }),
4496
+ /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: returnOrder.return_items.map((item, index) => /* @__PURE__ */ jsxs("tr", { children: [
4497
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: item.id }),
4498
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.quantity }),
4499
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.reason || "—" })
4500
+ ] }, item.id || index)) })
4501
+ ] }) })
4502
+ ] }),
4503
+ updateError && /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-ui-border-error bg-ui-bg-error-subtle p-4", children: /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-error", children: updateError }) }),
4504
+ updateSuccess && /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-ui-border-success bg-ui-bg-success-subtle p-4", children: /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-success", children: "Action completed successfully" }) })
4505
+ ] }) });
4506
+ };
4507
+ const config$1 = defineRouteConfig({
4508
+ label: "Return Order Details",
4509
+ icon: CheckCircle
4510
+ });
4513
4511
  const getStatusBadgeClass = (status) => {
4514
4512
  const statusLower = status.toLowerCase();
4515
4513
  if (statusLower === "requested") {
@@ -4803,24 +4801,24 @@ const widgetModule = { widgets: [
4803
4801
  ] };
4804
4802
  const routeModule = {
4805
4803
  routes: [
4804
+ {
4805
+ Component: DeletedRecordsPage,
4806
+ path: "/deleted-records-audit",
4807
+ handle: { label: config$9.label, translationNs: config$9.translationNs }
4808
+ },
4806
4809
  {
4807
4810
  Component: PaymentsPage,
4808
4811
  path: "/payments",
4809
- handle: { label: config$9.label, translationNs: config$9.translationNs }
4812
+ handle: { label: config$8.label, translationNs: config$8.translationNs }
4810
4813
  },
4811
4814
  {
4812
4815
  Component: RefundsPage,
4813
4816
  path: "/refunds",
4814
- handle: { label: config$8.label, translationNs: config$8.translationNs }
4817
+ handle: { label: config$7.label, translationNs: config$7.translationNs }
4815
4818
  },
4816
4819
  {
4817
4820
  Component: ReturnsPage,
4818
4821
  path: "/returns",
4819
- handle: { label: config$7.label, translationNs: config$7.translationNs }
4820
- },
4821
- {
4822
- Component: DeletedRecordsPage,
4823
- path: "/deleted-records-audit",
4824
4822
  handle: { label: config$6.label, translationNs: config$6.translationNs }
4825
4823
  },
4826
4824
  {
@@ -4828,24 +4826,24 @@ const routeModule = {
4828
4826
  path: "/swaps",
4829
4827
  handle: { label: config$5.label, translationNs: config$5.translationNs }
4830
4828
  },
4829
+ {
4830
+ Component: DeletedRecordDetailPage,
4831
+ path: "/deleted-records-audit/:id",
4832
+ handle: { label: config$4.label, translationNs: config$4.translationNs }
4833
+ },
4831
4834
  {
4832
4835
  Component: PaymentDetailPage,
4833
4836
  path: "/payments/:id",
4834
- handle: { label: config$4.label, translationNs: config$4.translationNs }
4837
+ handle: { label: config$3.label, translationNs: config$3.translationNs }
4835
4838
  },
4836
4839
  {
4837
4840
  Component: RefundDetailPage,
4838
4841
  path: "/refunds/:id",
4839
- handle: { label: config$3.label, translationNs: config$3.translationNs }
4842
+ handle: { label: config$2.label, translationNs: config$2.translationNs }
4840
4843
  },
4841
4844
  {
4842
4845
  Component: ReturnDetailPage,
4843
4846
  path: "/returns/:id",
4844
- handle: { label: config$2.label, translationNs: config$2.translationNs }
4845
- },
4846
- {
4847
- Component: DeletedRecordDetailPage,
4848
- path: "/deleted-records-audit/:id",
4849
4847
  handle: { label: config$1.label, translationNs: config$1.translationNs }
4850
4848
  },
4851
4849
  {
@@ -4857,18 +4855,10 @@ const routeModule = {
4857
4855
  };
4858
4856
  const menuItemModule = {
4859
4857
  menuItems: [
4860
- {
4861
- label: config$6.label,
4862
- icon: config$6.icon,
4863
- path: "/deleted-records-audit",
4864
- nested: void 0,
4865
- rank: void 0,
4866
- translationNs: void 0
4867
- },
4868
4858
  {
4869
4859
  label: config$9.label,
4870
4860
  icon: config$9.icon,
4871
- path: "/payments",
4861
+ path: "/deleted-records-audit",
4872
4862
  nested: void 0,
4873
4863
  rank: void 0,
4874
4864
  translationNs: void 0
@@ -4876,7 +4866,7 @@ const menuItemModule = {
4876
4866
  {
4877
4867
  label: config$7.label,
4878
4868
  icon: config$7.icon,
4879
- path: "/returns",
4869
+ path: "/refunds",
4880
4870
  nested: void 0,
4881
4871
  rank: void 0,
4882
4872
  translationNs: void 0
@@ -4884,23 +4874,23 @@ const menuItemModule = {
4884
4874
  {
4885
4875
  label: config$8.label,
4886
4876
  icon: config$8.icon,
4887
- path: "/refunds",
4877
+ path: "/payments",
4888
4878
  nested: void 0,
4889
4879
  rank: void 0,
4890
4880
  translationNs: void 0
4891
4881
  },
4892
4882
  {
4893
- label: config$5.label,
4894
- icon: config$5.icon,
4895
- path: "/swaps",
4883
+ label: config$6.label,
4884
+ icon: config$6.icon,
4885
+ path: "/returns",
4896
4886
  nested: void 0,
4897
4887
  rank: void 0,
4898
4888
  translationNs: void 0
4899
4889
  },
4900
4890
  {
4901
- label: config$4.label,
4902
- icon: config$4.icon,
4903
- path: "/payments/:id",
4891
+ label: config$5.label,
4892
+ icon: config$5.icon,
4893
+ path: "/swaps",
4904
4894
  nested: void 0,
4905
4895
  rank: void 0,
4906
4896
  translationNs: void 0
@@ -4908,7 +4898,7 @@ const menuItemModule = {
4908
4898
  {
4909
4899
  label: config$2.label,
4910
4900
  icon: config$2.icon,
4911
- path: "/returns/:id",
4901
+ path: "/refunds/:id",
4912
4902
  nested: void 0,
4913
4903
  rank: void 0,
4914
4904
  translationNs: void 0
@@ -4916,7 +4906,15 @@ const menuItemModule = {
4916
4906
  {
4917
4907
  label: config$3.label,
4918
4908
  icon: config$3.icon,
4919
- path: "/refunds/:id",
4909
+ path: "/payments/:id",
4910
+ nested: void 0,
4911
+ rank: void 0,
4912
+ translationNs: void 0
4913
+ },
4914
+ {
4915
+ label: config$1.label,
4916
+ icon: config$1.icon,
4917
+ path: "/returns/:id",
4920
4918
  nested: void 0,
4921
4919
  rank: void 0,
4922
4920
  translationNs: void 0