order-management 0.0.100 → 0.0.101
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.medusa/server/src/admin/index.js +2121 -2121
- package/.medusa/server/src/admin/index.mjs +2124 -2124
- package/package.json +1 -1
|
@@ -3,9 +3,9 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
|
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
5
5
|
import { defineWidgetConfig, defineRouteConfig } from "@medusajs/admin-sdk";
|
|
6
|
-
import { useState, useEffect, useRef,
|
|
7
|
-
import { Text, Container, Heading, Badge, Button, Label, Select, Textarea,
|
|
8
|
-
import { CashSolid, PencilSquareSolid, Trash,
|
|
6
|
+
import { useState, useEffect, useRef, useMemo, useCallback } from "react";
|
|
7
|
+
import { Text, Container, Heading, Badge, Button, Label, Select, Textarea, Popover, clx, Input, Copy, Skeleton, Tooltip, toast } from "@medusajs/ui";
|
|
8
|
+
import { CashSolid, PencilSquareSolid, Trash, ChevronDownMini, Check, ArrowPath, InformationCircle, ChevronRightMini, MagnifierAlert, ExclamationCircle, CreditCard, ArrowLeft, ClockSolid, SquareTwoStack, ShieldCheck, Receipt, CheckCircle } from "@medusajs/icons";
|
|
9
9
|
import { useNavigate, useLocation, useSearchParams, useParams } from "react-router-dom";
|
|
10
10
|
function roundRectPath(ctx, x, y, w, h, r) {
|
|
11
11
|
ctx.beginPath();
|
|
@@ -935,501 +935,6 @@ const OrderRefundContextWidget = (props) => {
|
|
|
935
935
|
defineWidgetConfig({
|
|
936
936
|
zone: "order.details.after"
|
|
937
937
|
});
|
|
938
|
-
const useDebounce$3 = (value, delay) => {
|
|
939
|
-
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
940
|
-
useEffect(() => {
|
|
941
|
-
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
942
|
-
return () => clearTimeout(handler);
|
|
943
|
-
}, [value, delay]);
|
|
944
|
-
return debouncedValue;
|
|
945
|
-
};
|
|
946
|
-
const getStatusBadgeClass$7 = (status) => {
|
|
947
|
-
const s2 = status.toLowerCase();
|
|
948
|
-
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
949
|
-
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
950
|
-
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
951
|
-
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
952
|
-
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
953
|
-
};
|
|
954
|
-
const PaymentsPage = () => {
|
|
955
|
-
const navigate = useNavigate();
|
|
956
|
-
const [items, setItems] = useState([]);
|
|
957
|
-
const [statusFilter, setStatusFilter] = useState("all");
|
|
958
|
-
const [orderIdSearch, setOrderIdSearch] = useState("");
|
|
959
|
-
const debouncedOrderId = useDebounce$3(orderIdSearch, 300);
|
|
960
|
-
const [isLoading, setIsLoading] = useState(true);
|
|
961
|
-
const [isFetchingMore, setIsFetchingMore] = useState(false);
|
|
962
|
-
const [error, setError] = useState(null);
|
|
963
|
-
const [offset, setOffset] = useState(0);
|
|
964
|
-
const [count, setCount] = useState(0);
|
|
965
|
-
const limit = 50;
|
|
966
|
-
const loadTransactions = useCallback(
|
|
967
|
-
async (nextOffset, replace) => {
|
|
968
|
-
try {
|
|
969
|
-
if (replace) setIsLoading(true);
|
|
970
|
-
else setIsFetchingMore(true);
|
|
971
|
-
setError(null);
|
|
972
|
-
const params = new URLSearchParams();
|
|
973
|
-
params.set("limit", String(limit));
|
|
974
|
-
params.set("offset", String(nextOffset));
|
|
975
|
-
if (statusFilter !== "all") params.set("status", statusFilter);
|
|
976
|
-
if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
|
|
977
|
-
const response = await fetch(
|
|
978
|
-
`/admin/payment-transactions?${params.toString()}`,
|
|
979
|
-
{ credentials: "include" }
|
|
980
|
-
);
|
|
981
|
-
if (!response.ok) {
|
|
982
|
-
const text = await response.text();
|
|
983
|
-
throw new Error(text || "Failed to load payment transactions");
|
|
984
|
-
}
|
|
985
|
-
const payload = await response.json();
|
|
986
|
-
const list = payload.transactions ?? [];
|
|
987
|
-
setCount(payload.count ?? 0);
|
|
988
|
-
setOffset(nextOffset + list.length);
|
|
989
|
-
setItems((prev) => replace ? list : [...prev, ...list]);
|
|
990
|
-
} catch (e) {
|
|
991
|
-
setError(e instanceof Error ? e.message : "Failed to load");
|
|
992
|
-
} finally {
|
|
993
|
-
setIsLoading(false);
|
|
994
|
-
setIsFetchingMore(false);
|
|
995
|
-
}
|
|
996
|
-
},
|
|
997
|
-
[statusFilter, debouncedOrderId]
|
|
998
|
-
);
|
|
999
|
-
useEffect(() => {
|
|
1000
|
-
void loadTransactions(0, true);
|
|
1001
|
-
}, [loadTransactions]);
|
|
1002
|
-
const hasMore = useMemo(() => offset < count, [offset, count]);
|
|
1003
|
-
const displayStatus = (t) => {
|
|
1004
|
-
const s2 = t.payment_id != null && t.payment_status != null && t.payment_status !== "" ? t.payment_status : t.session_status ?? "";
|
|
1005
|
-
return s2 !== "" ? s2 : "—";
|
|
1006
|
-
};
|
|
1007
|
-
const displayAmount = (t) => {
|
|
1008
|
-
const code = (t.currency_code ?? "USD").toUpperCase();
|
|
1009
|
-
return `${code} ${Number(t.amount)}`;
|
|
1010
|
-
};
|
|
1011
|
-
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: [
|
|
1012
|
-
/* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
1013
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1014
|
-
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Payments" }),
|
|
1015
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "All payment attempts — completed, pending, failed, requires action" })
|
|
1016
|
-
] }),
|
|
1017
|
-
/* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () => loadTransactions(0, true), children: "Refresh" })
|
|
1018
|
-
] }),
|
|
1019
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
1020
|
-
/* @__PURE__ */ jsx(
|
|
1021
|
-
Input,
|
|
1022
|
-
{
|
|
1023
|
-
placeholder: "Search by Order ID",
|
|
1024
|
-
value: orderIdSearch,
|
|
1025
|
-
onChange: (e) => setOrderIdSearch(e.target.value),
|
|
1026
|
-
className: "md:max-w-sm",
|
|
1027
|
-
"aria-label": "Search by order ID"
|
|
1028
|
-
}
|
|
1029
|
-
),
|
|
1030
|
-
/* @__PURE__ */ jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsxs(
|
|
1031
|
-
"select",
|
|
1032
|
-
{
|
|
1033
|
-
value: statusFilter,
|
|
1034
|
-
onChange: (e) => setStatusFilter(e.target.value),
|
|
1035
|
-
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",
|
|
1036
|
-
"aria-label": "Filter by status",
|
|
1037
|
-
children: [
|
|
1038
|
-
/* @__PURE__ */ jsx("option", { value: "all", children: "All statuses" }),
|
|
1039
|
-
/* @__PURE__ */ jsx("option", { value: "pending", children: "Pending" }),
|
|
1040
|
-
/* @__PURE__ */ jsx("option", { value: "requires_more", children: "Requires more" }),
|
|
1041
|
-
/* @__PURE__ */ jsx("option", { value: "error", children: "Error" }),
|
|
1042
|
-
/* @__PURE__ */ jsx("option", { value: "canceled", children: "Canceled" }),
|
|
1043
|
-
/* @__PURE__ */ jsx("option", { value: "authorized", children: "Authorized" }),
|
|
1044
|
-
/* @__PURE__ */ jsx("option", { value: "captured", children: "Captured" })
|
|
1045
|
-
]
|
|
1046
|
-
}
|
|
1047
|
-
) })
|
|
1048
|
-
] }),
|
|
1049
|
-
error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
1050
|
-
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
1051
|
-
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => loadTransactions(0, true), children: "Try again" }) })
|
|
1052
|
-
] }) : null,
|
|
1053
|
-
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: [
|
|
1054
|
-
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No payment transactions yet" }),
|
|
1055
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Payment attempts will appear here." })
|
|
1056
|
-
] }) : /* @__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: [
|
|
1057
|
-
/* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
1058
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
1059
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Amount" }),
|
|
1060
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Provider" }),
|
|
1061
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
1062
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Finalized" }),
|
|
1063
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
1064
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
1065
|
-
] }) }),
|
|
1066
|
-
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((t) => /* @__PURE__ */ jsxs(
|
|
1067
|
-
"tr",
|
|
1068
|
-
{
|
|
1069
|
-
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
1070
|
-
onClick: () => navigate(`/payments/${t.payment_session_id}`),
|
|
1071
|
-
children: [
|
|
1072
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: t.order_id ?? "—" }),
|
|
1073
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: displayAmount(t) }),
|
|
1074
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.provider_id }),
|
|
1075
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
|
|
1076
|
-
Badge,
|
|
1077
|
-
{
|
|
1078
|
-
size: "2xsmall",
|
|
1079
|
-
className: `uppercase ${getStatusBadgeClass$7(displayStatus(t))}`,
|
|
1080
|
-
children: displayStatus(t) !== "—" ? displayStatus(t).replace(/_/g, " ") : "—"
|
|
1081
|
-
}
|
|
1082
|
-
) }),
|
|
1083
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.payment_id != null ? "Yes" : "No" }),
|
|
1084
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(t.created_at).toLocaleDateString("en-US", {
|
|
1085
|
-
year: "numeric",
|
|
1086
|
-
month: "short",
|
|
1087
|
-
day: "numeric",
|
|
1088
|
-
hour: "numeric",
|
|
1089
|
-
minute: "2-digit",
|
|
1090
|
-
hour12: true
|
|
1091
|
-
}) }),
|
|
1092
|
-
/* @__PURE__ */ jsxs("td", { className: "px-4 py-4", children: [
|
|
1093
|
-
/* @__PURE__ */ jsx(
|
|
1094
|
-
Button,
|
|
1095
|
-
{
|
|
1096
|
-
variant: "transparent",
|
|
1097
|
-
size: "small",
|
|
1098
|
-
onClick: (e) => {
|
|
1099
|
-
e.stopPropagation();
|
|
1100
|
-
navigate(`/payments/${t.payment_session_id}`);
|
|
1101
|
-
},
|
|
1102
|
-
children: "View details"
|
|
1103
|
-
}
|
|
1104
|
-
),
|
|
1105
|
-
t.order_id ? /* @__PURE__ */ jsx(
|
|
1106
|
-
Button,
|
|
1107
|
-
{
|
|
1108
|
-
variant: "transparent",
|
|
1109
|
-
size: "small",
|
|
1110
|
-
onClick: (e) => {
|
|
1111
|
-
e.stopPropagation();
|
|
1112
|
-
navigate(`/orders/${t.order_id}`);
|
|
1113
|
-
},
|
|
1114
|
-
children: "Order"
|
|
1115
|
-
}
|
|
1116
|
-
) : null
|
|
1117
|
-
] })
|
|
1118
|
-
]
|
|
1119
|
-
},
|
|
1120
|
-
t.payment_session_id
|
|
1121
|
-
)) })
|
|
1122
|
-
] }) }),
|
|
1123
|
-
hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
|
|
1124
|
-
Button,
|
|
1125
|
-
{
|
|
1126
|
-
variant: "secondary",
|
|
1127
|
-
isLoading: isFetchingMore,
|
|
1128
|
-
onClick: () => loadTransactions(offset, false),
|
|
1129
|
-
children: "Load more"
|
|
1130
|
-
}
|
|
1131
|
-
) }) : null
|
|
1132
|
-
] }) });
|
|
1133
|
-
};
|
|
1134
|
-
const config$8 = defineRouteConfig({
|
|
1135
|
-
label: "Payments",
|
|
1136
|
-
icon: CreditCard
|
|
1137
|
-
});
|
|
1138
|
-
const useDebounce$2 = (value, delay) => {
|
|
1139
|
-
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
1140
|
-
useEffect(() => {
|
|
1141
|
-
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
1142
|
-
return () => clearTimeout(handler);
|
|
1143
|
-
}, [value, delay]);
|
|
1144
|
-
return debouncedValue;
|
|
1145
|
-
};
|
|
1146
|
-
const getStatusBadgeClass$6 = (status) => {
|
|
1147
|
-
const s2 = status.toLowerCase();
|
|
1148
|
-
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
1149
|
-
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
1150
|
-
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
1151
|
-
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
1152
|
-
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
1153
|
-
};
|
|
1154
|
-
const RefundsPage = () => {
|
|
1155
|
-
const navigate = useNavigate();
|
|
1156
|
-
const [items, setItems] = useState([]);
|
|
1157
|
-
const [orderIdSearch, setOrderIdSearch] = useState("");
|
|
1158
|
-
const debouncedOrderId = useDebounce$2(orderIdSearch, 300);
|
|
1159
|
-
const [paymentStatusFilter, setPaymentStatusFilter] = useState("all");
|
|
1160
|
-
const [providerSearch, setProviderSearch] = useState("");
|
|
1161
|
-
const debouncedProvider = useDebounce$2(providerSearch, 300);
|
|
1162
|
-
const [currencySearch, setCurrencySearch] = useState("");
|
|
1163
|
-
const debouncedCurrency = useDebounce$2(currencySearch, 300);
|
|
1164
|
-
const [dateFrom, setDateFrom] = useState("");
|
|
1165
|
-
const [dateTo, setDateTo] = useState("");
|
|
1166
|
-
const [amountMin, setAmountMin] = useState("");
|
|
1167
|
-
const [amountMax, setAmountMax] = useState("");
|
|
1168
|
-
const [isLoading, setIsLoading] = useState(true);
|
|
1169
|
-
const [isFetchingMore, setIsFetchingMore] = useState(false);
|
|
1170
|
-
const [error, setError] = useState(null);
|
|
1171
|
-
const [offset, setOffset] = useState(0);
|
|
1172
|
-
const [count, setCount] = useState(0);
|
|
1173
|
-
const limit = 50;
|
|
1174
|
-
const loadRefunds = useCallback(
|
|
1175
|
-
async (nextOffset, replace) => {
|
|
1176
|
-
try {
|
|
1177
|
-
if (replace) setIsLoading(true);
|
|
1178
|
-
else setIsFetchingMore(true);
|
|
1179
|
-
setError(null);
|
|
1180
|
-
const params = new URLSearchParams();
|
|
1181
|
-
params.set("limit", String(limit));
|
|
1182
|
-
params.set("offset", String(nextOffset));
|
|
1183
|
-
if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
|
|
1184
|
-
if (paymentStatusFilter !== "all") params.set("payment_status", paymentStatusFilter);
|
|
1185
|
-
if (debouncedProvider.trim()) params.set("provider_id", debouncedProvider.trim());
|
|
1186
|
-
if (debouncedCurrency.trim()) params.set("currency_code", debouncedCurrency.trim());
|
|
1187
|
-
if (dateFrom.trim()) params.set("date_from", dateFrom.trim());
|
|
1188
|
-
if (dateTo.trim()) params.set("date_to", dateTo.trim());
|
|
1189
|
-
const min = amountMin.trim() ? Number(amountMin) : void 0;
|
|
1190
|
-
const max = amountMax.trim() ? Number(amountMax) : void 0;
|
|
1191
|
-
if (min != null && !Number.isNaN(min)) params.set("amount_min", String(min));
|
|
1192
|
-
if (max != null && !Number.isNaN(max)) params.set("amount_max", String(max));
|
|
1193
|
-
const response = await fetch(`/admin/refunds?${params.toString()}`, {
|
|
1194
|
-
credentials: "include"
|
|
1195
|
-
});
|
|
1196
|
-
if (!response.ok) {
|
|
1197
|
-
const text = await response.text();
|
|
1198
|
-
throw new Error(text || "Failed to load refunds");
|
|
1199
|
-
}
|
|
1200
|
-
const payload = await response.json();
|
|
1201
|
-
const list = payload.refunds ?? [];
|
|
1202
|
-
setCount(payload.count ?? 0);
|
|
1203
|
-
setOffset(nextOffset + list.length);
|
|
1204
|
-
setItems((prev) => replace ? list : [...prev, ...list]);
|
|
1205
|
-
} catch (e) {
|
|
1206
|
-
setError(e instanceof Error ? e.message : "Failed to load");
|
|
1207
|
-
} finally {
|
|
1208
|
-
setIsLoading(false);
|
|
1209
|
-
setIsFetchingMore(false);
|
|
1210
|
-
}
|
|
1211
|
-
},
|
|
1212
|
-
[
|
|
1213
|
-
debouncedOrderId,
|
|
1214
|
-
paymentStatusFilter,
|
|
1215
|
-
debouncedProvider,
|
|
1216
|
-
debouncedCurrency,
|
|
1217
|
-
dateFrom,
|
|
1218
|
-
dateTo,
|
|
1219
|
-
amountMin,
|
|
1220
|
-
amountMax
|
|
1221
|
-
]
|
|
1222
|
-
);
|
|
1223
|
-
useEffect(() => {
|
|
1224
|
-
void loadRefunds(0, true);
|
|
1225
|
-
}, [loadRefunds]);
|
|
1226
|
-
const hasMore = useMemo(() => offset < count, [offset, count]);
|
|
1227
|
-
const displayAmount = (r) => {
|
|
1228
|
-
const code = (r.currency_code ?? "USD").toUpperCase();
|
|
1229
|
-
return `${code} ${Number(r.amount)}`;
|
|
1230
|
-
};
|
|
1231
|
-
const displayStatus = (r) => {
|
|
1232
|
-
const s2 = r.payment_status ?? "";
|
|
1233
|
-
return s2 !== "" ? s2 : "—";
|
|
1234
|
-
};
|
|
1235
|
-
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: [
|
|
1236
|
-
/* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
1237
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1238
|
-
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Refunds" }),
|
|
1239
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Refund records — amount, order, payment status" })
|
|
1240
|
-
] }),
|
|
1241
|
-
/* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () => loadRefunds(0, true), children: "Refresh" })
|
|
1242
|
-
] }),
|
|
1243
|
-
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
1244
|
-
/* @__PURE__ */ jsx(
|
|
1245
|
-
Input,
|
|
1246
|
-
{
|
|
1247
|
-
placeholder: "Order ID",
|
|
1248
|
-
value: orderIdSearch,
|
|
1249
|
-
onChange: (e) => setOrderIdSearch(e.target.value),
|
|
1250
|
-
className: "md:max-w-[180px]",
|
|
1251
|
-
"aria-label": "Filter by order ID"
|
|
1252
|
-
}
|
|
1253
|
-
),
|
|
1254
|
-
/* @__PURE__ */ jsx(
|
|
1255
|
-
Input,
|
|
1256
|
-
{
|
|
1257
|
-
placeholder: "Provider",
|
|
1258
|
-
value: providerSearch,
|
|
1259
|
-
onChange: (e) => setProviderSearch(e.target.value),
|
|
1260
|
-
className: "md:max-w-[140px]",
|
|
1261
|
-
"aria-label": "Filter by provider"
|
|
1262
|
-
}
|
|
1263
|
-
),
|
|
1264
|
-
/* @__PURE__ */ jsx(
|
|
1265
|
-
Input,
|
|
1266
|
-
{
|
|
1267
|
-
placeholder: "Currency",
|
|
1268
|
-
value: currencySearch,
|
|
1269
|
-
onChange: (e) => setCurrencySearch(e.target.value),
|
|
1270
|
-
className: "md:max-w-[100px]",
|
|
1271
|
-
"aria-label": "Filter by currency"
|
|
1272
|
-
}
|
|
1273
|
-
),
|
|
1274
|
-
/* @__PURE__ */ jsxs(
|
|
1275
|
-
"select",
|
|
1276
|
-
{
|
|
1277
|
-
value: paymentStatusFilter,
|
|
1278
|
-
onChange: (e) => setPaymentStatusFilter(e.target.value),
|
|
1279
|
-
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]",
|
|
1280
|
-
"aria-label": "Filter by payment status",
|
|
1281
|
-
children: [
|
|
1282
|
-
/* @__PURE__ */ jsx("option", { value: "all", children: "All statuses" }),
|
|
1283
|
-
/* @__PURE__ */ jsx("option", { value: "pending", children: "Pending" }),
|
|
1284
|
-
/* @__PURE__ */ jsx("option", { value: "requires_more", children: "Requires more" }),
|
|
1285
|
-
/* @__PURE__ */ jsx("option", { value: "error", children: "Error" }),
|
|
1286
|
-
/* @__PURE__ */ jsx("option", { value: "canceled", children: "Canceled" }),
|
|
1287
|
-
/* @__PURE__ */ jsx("option", { value: "authorized", children: "Authorized" }),
|
|
1288
|
-
/* @__PURE__ */ jsx("option", { value: "captured", children: "Captured" })
|
|
1289
|
-
]
|
|
1290
|
-
}
|
|
1291
|
-
),
|
|
1292
|
-
/* @__PURE__ */ jsx(
|
|
1293
|
-
Input,
|
|
1294
|
-
{
|
|
1295
|
-
type: "date",
|
|
1296
|
-
placeholder: "From",
|
|
1297
|
-
value: dateFrom,
|
|
1298
|
-
onChange: (e) => setDateFrom(e.target.value),
|
|
1299
|
-
className: "md:max-w-[140px]",
|
|
1300
|
-
"aria-label": "Date from"
|
|
1301
|
-
}
|
|
1302
|
-
),
|
|
1303
|
-
/* @__PURE__ */ jsx(
|
|
1304
|
-
Input,
|
|
1305
|
-
{
|
|
1306
|
-
type: "date",
|
|
1307
|
-
placeholder: "To",
|
|
1308
|
-
value: dateTo,
|
|
1309
|
-
onChange: (e) => setDateTo(e.target.value),
|
|
1310
|
-
className: "md:max-w-[140px]",
|
|
1311
|
-
"aria-label": "Date to"
|
|
1312
|
-
}
|
|
1313
|
-
),
|
|
1314
|
-
/* @__PURE__ */ jsx(
|
|
1315
|
-
Input,
|
|
1316
|
-
{
|
|
1317
|
-
placeholder: "Amount min",
|
|
1318
|
-
value: amountMin,
|
|
1319
|
-
onChange: (e) => setAmountMin(e.target.value),
|
|
1320
|
-
type: "number",
|
|
1321
|
-
min: 0,
|
|
1322
|
-
className: "md:max-w-[100px]",
|
|
1323
|
-
"aria-label": "Refund amount minimum"
|
|
1324
|
-
}
|
|
1325
|
-
),
|
|
1326
|
-
/* @__PURE__ */ jsx(
|
|
1327
|
-
Input,
|
|
1328
|
-
{
|
|
1329
|
-
placeholder: "Amount max",
|
|
1330
|
-
value: amountMax,
|
|
1331
|
-
onChange: (e) => setAmountMax(e.target.value),
|
|
1332
|
-
type: "number",
|
|
1333
|
-
min: 0,
|
|
1334
|
-
className: "md:max-w-[100px]",
|
|
1335
|
-
"aria-label": "Refund amount maximum"
|
|
1336
|
-
}
|
|
1337
|
-
)
|
|
1338
|
-
] }) }),
|
|
1339
|
-
error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
1340
|
-
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
1341
|
-
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => loadRefunds(0, true), children: "Try again" }) })
|
|
1342
|
-
] }) : null,
|
|
1343
|
-
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: [
|
|
1344
|
-
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No refunds yet" }),
|
|
1345
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Refund records will appear here." })
|
|
1346
|
-
] }) : /* @__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: [
|
|
1347
|
-
/* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
1348
|
-
/* @__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" }),
|
|
1349
|
-
/* @__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" }),
|
|
1350
|
-
/* @__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" }),
|
|
1351
|
-
/* @__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" }),
|
|
1352
|
-
/* @__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" }),
|
|
1353
|
-
/* @__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" }),
|
|
1354
|
-
/* @__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" }),
|
|
1355
|
-
/* @__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" }),
|
|
1356
|
-
/* @__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" }),
|
|
1357
|
-
/* @__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" })
|
|
1358
|
-
] }) }),
|
|
1359
|
-
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((r) => /* @__PURE__ */ jsxs(
|
|
1360
|
-
"tr",
|
|
1361
|
-
{
|
|
1362
|
-
className: "cursor-pointer hover:bg-ui-bg-subtle/60",
|
|
1363
|
-
onClick: () => navigate(`/refunds/${r.refund_id}`),
|
|
1364
|
-
children: [
|
|
1365
|
-
/* @__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 }),
|
|
1366
|
-
/* @__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 ?? "—" }),
|
|
1367
|
-
/* @__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 }),
|
|
1368
|
-
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", children: displayAmount(r) }),
|
|
1369
|
-
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle uppercase", children: r.currency_code || "—" }),
|
|
1370
|
-
/* @__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 || "—" }),
|
|
1371
|
-
/* @__PURE__ */ jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsx(
|
|
1372
|
-
Badge,
|
|
1373
|
-
{
|
|
1374
|
-
size: "2xsmall",
|
|
1375
|
-
className: `uppercase ${getStatusBadgeClass$6(displayStatus(r))}`,
|
|
1376
|
-
children: displayStatus(r) !== "—" ? displayStatus(r).replace(/_/g, " ") : "—"
|
|
1377
|
-
}
|
|
1378
|
-
) }),
|
|
1379
|
-
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", title: r.note ?? void 0, children: r.note ?? "—" }),
|
|
1380
|
-
/* @__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", {
|
|
1381
|
-
month: "short",
|
|
1382
|
-
day: "numeric",
|
|
1383
|
-
hour: "numeric",
|
|
1384
|
-
minute: "2-digit",
|
|
1385
|
-
hour12: true
|
|
1386
|
-
}) }),
|
|
1387
|
-
/* @__PURE__ */ jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1", children: [
|
|
1388
|
-
/* @__PURE__ */ jsx(
|
|
1389
|
-
Button,
|
|
1390
|
-
{
|
|
1391
|
-
variant: "transparent",
|
|
1392
|
-
size: "small",
|
|
1393
|
-
onClick: (e) => {
|
|
1394
|
-
e.stopPropagation();
|
|
1395
|
-
navigate(`/refunds/${r.refund_id}`);
|
|
1396
|
-
},
|
|
1397
|
-
children: "Details"
|
|
1398
|
-
}
|
|
1399
|
-
),
|
|
1400
|
-
r.order_id ? /* @__PURE__ */ jsx(
|
|
1401
|
-
Button,
|
|
1402
|
-
{
|
|
1403
|
-
variant: "transparent",
|
|
1404
|
-
size: "small",
|
|
1405
|
-
onClick: (e) => {
|
|
1406
|
-
e.stopPropagation();
|
|
1407
|
-
navigate(`/orders/${r.order_id}`);
|
|
1408
|
-
},
|
|
1409
|
-
children: "Order"
|
|
1410
|
-
}
|
|
1411
|
-
) : null
|
|
1412
|
-
] }) })
|
|
1413
|
-
]
|
|
1414
|
-
},
|
|
1415
|
-
r.refund_id
|
|
1416
|
-
)) })
|
|
1417
|
-
] }) }),
|
|
1418
|
-
hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
|
|
1419
|
-
Button,
|
|
1420
|
-
{
|
|
1421
|
-
variant: "secondary",
|
|
1422
|
-
isLoading: isFetchingMore,
|
|
1423
|
-
onClick: () => loadRefunds(offset, false),
|
|
1424
|
-
children: "Load more"
|
|
1425
|
-
}
|
|
1426
|
-
) }) : null
|
|
1427
|
-
] }) });
|
|
1428
|
-
};
|
|
1429
|
-
const config$7 = defineRouteConfig({
|
|
1430
|
-
label: "Refunds",
|
|
1431
|
-
icon: Receipt
|
|
1432
|
-
});
|
|
1433
938
|
const AUDITED_TABLE_NAMES = [
|
|
1434
939
|
"account_deletion_request",
|
|
1435
940
|
"account_holder",
|
|
@@ -2721,11 +2226,211 @@ const ErrorState = ({ onRetry, detail }) => /* @__PURE__ */ jsxs("div", { classN
|
|
|
2721
2226
|
/* @__PURE__ */ jsx(Text, { size: "xsmall", className: "max-w-md font-mono text-ui-fg-muted", children: detail }),
|
|
2722
2227
|
/* @__PURE__ */ jsx(Button, { variant: "secondary", size: "small", className: "mt-2", onClick: onRetry, children: "Try again" })
|
|
2723
2228
|
] });
|
|
2724
|
-
const config$
|
|
2229
|
+
const config$8 = defineRouteConfig({
|
|
2725
2230
|
label: "Deleted Records",
|
|
2726
2231
|
icon: Trash
|
|
2727
2232
|
});
|
|
2728
|
-
const useDebounce$
|
|
2233
|
+
const useDebounce$3 = (value, delay) => {
|
|
2234
|
+
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
2235
|
+
useEffect(() => {
|
|
2236
|
+
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
2237
|
+
return () => clearTimeout(handler);
|
|
2238
|
+
}, [value, delay]);
|
|
2239
|
+
return debouncedValue;
|
|
2240
|
+
};
|
|
2241
|
+
const getStatusBadgeClass$7 = (status) => {
|
|
2242
|
+
const s2 = status.toLowerCase();
|
|
2243
|
+
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
2244
|
+
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
2245
|
+
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
2246
|
+
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
2247
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
2248
|
+
};
|
|
2249
|
+
const PaymentsPage = () => {
|
|
2250
|
+
const navigate = useNavigate();
|
|
2251
|
+
const [items, setItems] = useState([]);
|
|
2252
|
+
const [statusFilter, setStatusFilter] = useState("all");
|
|
2253
|
+
const [orderIdSearch, setOrderIdSearch] = useState("");
|
|
2254
|
+
const debouncedOrderId = useDebounce$3(orderIdSearch, 300);
|
|
2255
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
2256
|
+
const [isFetchingMore, setIsFetchingMore] = useState(false);
|
|
2257
|
+
const [error, setError] = useState(null);
|
|
2258
|
+
const [offset, setOffset] = useState(0);
|
|
2259
|
+
const [count, setCount] = useState(0);
|
|
2260
|
+
const limit = 50;
|
|
2261
|
+
const loadTransactions = useCallback(
|
|
2262
|
+
async (nextOffset, replace) => {
|
|
2263
|
+
try {
|
|
2264
|
+
if (replace) setIsLoading(true);
|
|
2265
|
+
else setIsFetchingMore(true);
|
|
2266
|
+
setError(null);
|
|
2267
|
+
const params = new URLSearchParams();
|
|
2268
|
+
params.set("limit", String(limit));
|
|
2269
|
+
params.set("offset", String(nextOffset));
|
|
2270
|
+
if (statusFilter !== "all") params.set("status", statusFilter);
|
|
2271
|
+
if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
|
|
2272
|
+
const response = await fetch(
|
|
2273
|
+
`/admin/payment-transactions?${params.toString()}`,
|
|
2274
|
+
{ credentials: "include" }
|
|
2275
|
+
);
|
|
2276
|
+
if (!response.ok) {
|
|
2277
|
+
const text = await response.text();
|
|
2278
|
+
throw new Error(text || "Failed to load payment transactions");
|
|
2279
|
+
}
|
|
2280
|
+
const payload = await response.json();
|
|
2281
|
+
const list = payload.transactions ?? [];
|
|
2282
|
+
setCount(payload.count ?? 0);
|
|
2283
|
+
setOffset(nextOffset + list.length);
|
|
2284
|
+
setItems((prev) => replace ? list : [...prev, ...list]);
|
|
2285
|
+
} catch (e) {
|
|
2286
|
+
setError(e instanceof Error ? e.message : "Failed to load");
|
|
2287
|
+
} finally {
|
|
2288
|
+
setIsLoading(false);
|
|
2289
|
+
setIsFetchingMore(false);
|
|
2290
|
+
}
|
|
2291
|
+
},
|
|
2292
|
+
[statusFilter, debouncedOrderId]
|
|
2293
|
+
);
|
|
2294
|
+
useEffect(() => {
|
|
2295
|
+
void loadTransactions(0, true);
|
|
2296
|
+
}, [loadTransactions]);
|
|
2297
|
+
const hasMore = useMemo(() => offset < count, [offset, count]);
|
|
2298
|
+
const displayStatus = (t) => {
|
|
2299
|
+
const s2 = t.payment_id != null && t.payment_status != null && t.payment_status !== "" ? t.payment_status : t.session_status ?? "";
|
|
2300
|
+
return s2 !== "" ? s2 : "—";
|
|
2301
|
+
};
|
|
2302
|
+
const displayAmount = (t) => {
|
|
2303
|
+
const code = (t.currency_code ?? "USD").toUpperCase();
|
|
2304
|
+
return `${code} ${Number(t.amount)}`;
|
|
2305
|
+
};
|
|
2306
|
+
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: [
|
|
2307
|
+
/* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
2308
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
2309
|
+
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Payments" }),
|
|
2310
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "All payment attempts — completed, pending, failed, requires action" })
|
|
2311
|
+
] }),
|
|
2312
|
+
/* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () => loadTransactions(0, true), children: "Refresh" })
|
|
2313
|
+
] }),
|
|
2314
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
2315
|
+
/* @__PURE__ */ jsx(
|
|
2316
|
+
Input,
|
|
2317
|
+
{
|
|
2318
|
+
placeholder: "Search by Order ID",
|
|
2319
|
+
value: orderIdSearch,
|
|
2320
|
+
onChange: (e) => setOrderIdSearch(e.target.value),
|
|
2321
|
+
className: "md:max-w-sm",
|
|
2322
|
+
"aria-label": "Search by order ID"
|
|
2323
|
+
}
|
|
2324
|
+
),
|
|
2325
|
+
/* @__PURE__ */ jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsxs(
|
|
2326
|
+
"select",
|
|
2327
|
+
{
|
|
2328
|
+
value: statusFilter,
|
|
2329
|
+
onChange: (e) => setStatusFilter(e.target.value),
|
|
2330
|
+
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",
|
|
2331
|
+
"aria-label": "Filter by status",
|
|
2332
|
+
children: [
|
|
2333
|
+
/* @__PURE__ */ jsx("option", { value: "all", children: "All statuses" }),
|
|
2334
|
+
/* @__PURE__ */ jsx("option", { value: "pending", children: "Pending" }),
|
|
2335
|
+
/* @__PURE__ */ jsx("option", { value: "requires_more", children: "Requires more" }),
|
|
2336
|
+
/* @__PURE__ */ jsx("option", { value: "error", children: "Error" }),
|
|
2337
|
+
/* @__PURE__ */ jsx("option", { value: "canceled", children: "Canceled" }),
|
|
2338
|
+
/* @__PURE__ */ jsx("option", { value: "authorized", children: "Authorized" }),
|
|
2339
|
+
/* @__PURE__ */ jsx("option", { value: "captured", children: "Captured" })
|
|
2340
|
+
]
|
|
2341
|
+
}
|
|
2342
|
+
) })
|
|
2343
|
+
] }),
|
|
2344
|
+
error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
2345
|
+
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
2346
|
+
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => loadTransactions(0, true), children: "Try again" }) })
|
|
2347
|
+
] }) : null,
|
|
2348
|
+
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: [
|
|
2349
|
+
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No payment transactions yet" }),
|
|
2350
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Payment attempts will appear here." })
|
|
2351
|
+
] }) : /* @__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: [
|
|
2352
|
+
/* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
2353
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
2354
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Amount" }),
|
|
2355
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Provider" }),
|
|
2356
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
2357
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Finalized" }),
|
|
2358
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
2359
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
2360
|
+
] }) }),
|
|
2361
|
+
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((t) => /* @__PURE__ */ jsxs(
|
|
2362
|
+
"tr",
|
|
2363
|
+
{
|
|
2364
|
+
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
2365
|
+
onClick: () => navigate(`/payments/${t.payment_session_id}`),
|
|
2366
|
+
children: [
|
|
2367
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: t.order_id ?? "—" }),
|
|
2368
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: displayAmount(t) }),
|
|
2369
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.provider_id }),
|
|
2370
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
|
|
2371
|
+
Badge,
|
|
2372
|
+
{
|
|
2373
|
+
size: "2xsmall",
|
|
2374
|
+
className: `uppercase ${getStatusBadgeClass$7(displayStatus(t))}`,
|
|
2375
|
+
children: displayStatus(t) !== "—" ? displayStatus(t).replace(/_/g, " ") : "—"
|
|
2376
|
+
}
|
|
2377
|
+
) }),
|
|
2378
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.payment_id != null ? "Yes" : "No" }),
|
|
2379
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(t.created_at).toLocaleDateString("en-US", {
|
|
2380
|
+
year: "numeric",
|
|
2381
|
+
month: "short",
|
|
2382
|
+
day: "numeric",
|
|
2383
|
+
hour: "numeric",
|
|
2384
|
+
minute: "2-digit",
|
|
2385
|
+
hour12: true
|
|
2386
|
+
}) }),
|
|
2387
|
+
/* @__PURE__ */ jsxs("td", { className: "px-4 py-4", children: [
|
|
2388
|
+
/* @__PURE__ */ jsx(
|
|
2389
|
+
Button,
|
|
2390
|
+
{
|
|
2391
|
+
variant: "transparent",
|
|
2392
|
+
size: "small",
|
|
2393
|
+
onClick: (e) => {
|
|
2394
|
+
e.stopPropagation();
|
|
2395
|
+
navigate(`/payments/${t.payment_session_id}`);
|
|
2396
|
+
},
|
|
2397
|
+
children: "View details"
|
|
2398
|
+
}
|
|
2399
|
+
),
|
|
2400
|
+
t.order_id ? /* @__PURE__ */ jsx(
|
|
2401
|
+
Button,
|
|
2402
|
+
{
|
|
2403
|
+
variant: "transparent",
|
|
2404
|
+
size: "small",
|
|
2405
|
+
onClick: (e) => {
|
|
2406
|
+
e.stopPropagation();
|
|
2407
|
+
navigate(`/orders/${t.order_id}`);
|
|
2408
|
+
},
|
|
2409
|
+
children: "Order"
|
|
2410
|
+
}
|
|
2411
|
+
) : null
|
|
2412
|
+
] })
|
|
2413
|
+
]
|
|
2414
|
+
},
|
|
2415
|
+
t.payment_session_id
|
|
2416
|
+
)) })
|
|
2417
|
+
] }) }),
|
|
2418
|
+
hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
|
|
2419
|
+
Button,
|
|
2420
|
+
{
|
|
2421
|
+
variant: "secondary",
|
|
2422
|
+
isLoading: isFetchingMore,
|
|
2423
|
+
onClick: () => loadTransactions(offset, false),
|
|
2424
|
+
children: "Load more"
|
|
2425
|
+
}
|
|
2426
|
+
) }) : null
|
|
2427
|
+
] }) });
|
|
2428
|
+
};
|
|
2429
|
+
const config$7 = defineRouteConfig({
|
|
2430
|
+
label: "Payments",
|
|
2431
|
+
icon: CreditCard
|
|
2432
|
+
});
|
|
2433
|
+
const useDebounce$2 = (value, delay) => {
|
|
2729
2434
|
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
2730
2435
|
useEffect(() => {
|
|
2731
2436
|
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
@@ -2733,7 +2438,7 @@ const useDebounce$1 = (value, delay) => {
|
|
|
2733
2438
|
}, [value, delay]);
|
|
2734
2439
|
return debouncedValue;
|
|
2735
2440
|
};
|
|
2736
|
-
const getStatusBadgeClass$
|
|
2441
|
+
const getStatusBadgeClass$6 = (status) => {
|
|
2737
2442
|
const statusLower = status.toLowerCase();
|
|
2738
2443
|
if (statusLower === "requested") {
|
|
2739
2444
|
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
@@ -2758,7 +2463,7 @@ const ReturnsPage = () => {
|
|
|
2758
2463
|
const [statusFilter, setStatusFilter] = useState("all");
|
|
2759
2464
|
const [createdByFilter, setCreatedByFilter] = useState("all");
|
|
2760
2465
|
const [searchQuery, setSearchQuery] = useState("");
|
|
2761
|
-
const debouncedSearchQuery = useDebounce$
|
|
2466
|
+
const debouncedSearchQuery = useDebounce$2(searchQuery, 300);
|
|
2762
2467
|
const [isLoading, setIsLoading] = useState(true);
|
|
2763
2468
|
const [isFetchingMore, setIsFetchingMore] = useState(false);
|
|
2764
2469
|
const [error, setError] = useState(null);
|
|
@@ -2866,1392 +2571,1774 @@ const ReturnsPage = () => {
|
|
|
2866
2571
|
}
|
|
2867
2572
|
)
|
|
2868
2573
|
] })
|
|
2869
|
-
] }),
|
|
2870
|
-
error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
2871
|
-
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
2872
|
-
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(
|
|
2873
|
-
Button,
|
|
2874
|
-
{
|
|
2875
|
-
variant: "secondary",
|
|
2876
|
-
onClick: () => loadReturns(0, true),
|
|
2877
|
-
children: "Try again"
|
|
2878
|
-
}
|
|
2879
|
-
) })
|
|
2880
|
-
] }) : null,
|
|
2881
|
-
isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading return orders..." }) }) : items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
2882
|
-
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No return orders yet" }),
|
|
2883
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Return orders created by customers will appear here." })
|
|
2884
|
-
] }) : /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
2885
|
-
/* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
2886
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Return ID" }),
|
|
2887
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
2888
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Customer" }),
|
|
2889
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
2890
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Refund Amount" }),
|
|
2891
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
2892
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
2893
|
-
] }) }),
|
|
2894
|
-
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((returnOrder) => /* @__PURE__ */ jsxs(
|
|
2895
|
-
"tr",
|
|
2896
|
-
{
|
|
2897
|
-
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
2898
|
-
onClick: () => navigate(`/returns/${returnOrder.id}`),
|
|
2899
|
-
children: [
|
|
2900
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children: /* @__PURE__ */ jsx("span", { children: returnOrder.id }) }) }),
|
|
2901
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.order_id }),
|
|
2902
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.customer_email || returnOrder.order_email || "—" }),
|
|
2903
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
|
|
2904
|
-
Badge,
|
|
2905
|
-
{
|
|
2906
|
-
size: "2xsmall",
|
|
2907
|
-
className: `uppercase ${getStatusBadgeClass$
|
|
2908
|
-
children: returnOrder.status.replace(/_/g, " ")
|
|
2909
|
-
}
|
|
2910
|
-
) }),
|
|
2911
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
|
|
2912
|
-
const calc = returnOrder.refund;
|
|
2913
|
-
if ((calc == null ? void 0 : calc.is_processed) && calc.final_refund_amount != null) {
|
|
2914
|
-
return formatRefundCurrency(
|
|
2915
|
-
calc.final_refund_amount,
|
|
2916
|
-
calc.currency_code || returnOrder.currency_code
|
|
2917
|
-
);
|
|
2918
|
-
}
|
|
2919
|
-
if (calc) {
|
|
2920
|
-
return "Pending";
|
|
2921
|
-
}
|
|
2922
|
-
if (returnOrder.refund_amount == null) {
|
|
2923
|
-
return "—";
|
|
2924
|
-
}
|
|
2925
|
-
return formatRefundCurrency(
|
|
2926
|
-
Number(returnOrder.refund_amount),
|
|
2927
|
-
returnOrder.currency_code
|
|
2928
|
-
);
|
|
2929
|
-
})() }),
|
|
2930
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(returnOrder.created_at).toLocaleDateString("en-US", {
|
|
2931
|
-
year: "numeric",
|
|
2932
|
-
month: "short",
|
|
2933
|
-
day: "numeric",
|
|
2934
|
-
hour: "numeric",
|
|
2935
|
-
minute: "2-digit",
|
|
2936
|
-
hour12: true
|
|
2937
|
-
}) }),
|
|
2938
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
|
|
2939
|
-
Button,
|
|
2940
|
-
{
|
|
2941
|
-
variant: "transparent",
|
|
2942
|
-
size: "small",
|
|
2943
|
-
onClick: (e) => {
|
|
2944
|
-
e.stopPropagation();
|
|
2945
|
-
navigate(`/app/orders/${returnOrder.order_id}`);
|
|
2946
|
-
},
|
|
2947
|
-
children: "Go to order"
|
|
2948
|
-
}
|
|
2949
|
-
) })
|
|
2950
|
-
]
|
|
2951
|
-
},
|
|
2952
|
-
returnOrder.id
|
|
2953
|
-
)) })
|
|
2954
|
-
] }) }),
|
|
2955
|
-
hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
|
|
2956
|
-
Button,
|
|
2574
|
+
] }),
|
|
2575
|
+
error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
2576
|
+
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
2577
|
+
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(
|
|
2578
|
+
Button,
|
|
2579
|
+
{
|
|
2580
|
+
variant: "secondary",
|
|
2581
|
+
onClick: () => loadReturns(0, true),
|
|
2582
|
+
children: "Try again"
|
|
2583
|
+
}
|
|
2584
|
+
) })
|
|
2585
|
+
] }) : null,
|
|
2586
|
+
isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading return orders..." }) }) : items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
2587
|
+
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No return orders yet" }),
|
|
2588
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Return orders created by customers will appear here." })
|
|
2589
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
2590
|
+
/* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
2591
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Return ID" }),
|
|
2592
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
2593
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Customer" }),
|
|
2594
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
2595
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Refund Amount" }),
|
|
2596
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
2597
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
2598
|
+
] }) }),
|
|
2599
|
+
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((returnOrder) => /* @__PURE__ */ jsxs(
|
|
2600
|
+
"tr",
|
|
2601
|
+
{
|
|
2602
|
+
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
2603
|
+
onClick: () => navigate(`/returns/${returnOrder.id}`),
|
|
2604
|
+
children: [
|
|
2605
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children: /* @__PURE__ */ jsx("span", { children: returnOrder.id }) }) }),
|
|
2606
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.order_id }),
|
|
2607
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.customer_email || returnOrder.order_email || "—" }),
|
|
2608
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
|
|
2609
|
+
Badge,
|
|
2610
|
+
{
|
|
2611
|
+
size: "2xsmall",
|
|
2612
|
+
className: `uppercase ${getStatusBadgeClass$6(returnOrder.status)}`,
|
|
2613
|
+
children: returnOrder.status.replace(/_/g, " ")
|
|
2614
|
+
}
|
|
2615
|
+
) }),
|
|
2616
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
|
|
2617
|
+
const calc = returnOrder.refund;
|
|
2618
|
+
if ((calc == null ? void 0 : calc.is_processed) && calc.final_refund_amount != null) {
|
|
2619
|
+
return formatRefundCurrency(
|
|
2620
|
+
calc.final_refund_amount,
|
|
2621
|
+
calc.currency_code || returnOrder.currency_code
|
|
2622
|
+
);
|
|
2623
|
+
}
|
|
2624
|
+
if (calc) {
|
|
2625
|
+
return "Pending";
|
|
2626
|
+
}
|
|
2627
|
+
if (returnOrder.refund_amount == null) {
|
|
2628
|
+
return "—";
|
|
2629
|
+
}
|
|
2630
|
+
return formatRefundCurrency(
|
|
2631
|
+
Number(returnOrder.refund_amount),
|
|
2632
|
+
returnOrder.currency_code
|
|
2633
|
+
);
|
|
2634
|
+
})() }),
|
|
2635
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(returnOrder.created_at).toLocaleDateString("en-US", {
|
|
2636
|
+
year: "numeric",
|
|
2637
|
+
month: "short",
|
|
2638
|
+
day: "numeric",
|
|
2639
|
+
hour: "numeric",
|
|
2640
|
+
minute: "2-digit",
|
|
2641
|
+
hour12: true
|
|
2642
|
+
}) }),
|
|
2643
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
|
|
2644
|
+
Button,
|
|
2645
|
+
{
|
|
2646
|
+
variant: "transparent",
|
|
2647
|
+
size: "small",
|
|
2648
|
+
onClick: (e) => {
|
|
2649
|
+
e.stopPropagation();
|
|
2650
|
+
navigate(`/app/orders/${returnOrder.order_id}`);
|
|
2651
|
+
},
|
|
2652
|
+
children: "Go to order"
|
|
2653
|
+
}
|
|
2654
|
+
) })
|
|
2655
|
+
]
|
|
2656
|
+
},
|
|
2657
|
+
returnOrder.id
|
|
2658
|
+
)) })
|
|
2659
|
+
] }) }),
|
|
2660
|
+
hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
|
|
2661
|
+
Button,
|
|
2662
|
+
{
|
|
2663
|
+
variant: "secondary",
|
|
2664
|
+
isLoading: isFetchingMore,
|
|
2665
|
+
onClick: () => loadReturns(offset, false),
|
|
2666
|
+
children: "Load more"
|
|
2667
|
+
}
|
|
2668
|
+
) }) : null
|
|
2669
|
+
] }) });
|
|
2670
|
+
};
|
|
2671
|
+
const config$6 = defineRouteConfig({
|
|
2672
|
+
label: "Return Orders",
|
|
2673
|
+
icon: ArrowPath
|
|
2674
|
+
});
|
|
2675
|
+
const MASKED_VALUE = "••••••••••••";
|
|
2676
|
+
const SENSITIVE_KEY_PATTERNS = [
|
|
2677
|
+
/password|passwd|passphrase/i,
|
|
2678
|
+
/secret/i,
|
|
2679
|
+
/token/i,
|
|
2680
|
+
/api_?key$/i,
|
|
2681
|
+
/private_?key/i,
|
|
2682
|
+
/access_?key/i,
|
|
2683
|
+
/(^|_)hash(ed)?($|_)/i,
|
|
2684
|
+
/(^|_)salt$/i,
|
|
2685
|
+
/^cvv$|^cvc$|security_code/i,
|
|
2686
|
+
/card_?number/i,
|
|
2687
|
+
/account_?number/i,
|
|
2688
|
+
/credential/i,
|
|
2689
|
+
/authorization/i,
|
|
2690
|
+
/recovery_?code/i,
|
|
2691
|
+
/(^|_)otp($|_)/i,
|
|
2692
|
+
/verification_?code/i,
|
|
2693
|
+
/^code_hash$/i,
|
|
2694
|
+
/webhook_?signature/i
|
|
2695
|
+
];
|
|
2696
|
+
const TABLE_SENSITIVE_KEYS = {
|
|
2697
|
+
otp_verification: /* @__PURE__ */ new Set(["code", "value"]),
|
|
2698
|
+
auth_verification: /* @__PURE__ */ new Set(["code", "value"]),
|
|
2699
|
+
auth_mfa_factor: /* @__PURE__ */ new Set(["value", "config"])
|
|
2700
|
+
};
|
|
2701
|
+
const SAFE_KEYS = /* @__PURE__ */ new Set([
|
|
2702
|
+
"token_type",
|
|
2703
|
+
"redacted",
|
|
2704
|
+
"api_key_id",
|
|
2705
|
+
"token_id",
|
|
2706
|
+
"notification_token_id"
|
|
2707
|
+
]);
|
|
2708
|
+
function isSensitiveKey(key) {
|
|
2709
|
+
const normalized = key.trim().toLowerCase();
|
|
2710
|
+
if (SAFE_KEYS.has(normalized)) return false;
|
|
2711
|
+
return SENSITIVE_KEY_PATTERNS.some((pattern) => pattern.test(normalized));
|
|
2712
|
+
}
|
|
2713
|
+
const FULLY_SECRET_TABLES = /* @__PURE__ */ new Set(["auth_mfa_recovery_code", "auth_password_reset_token"]);
|
|
2714
|
+
const ALWAYS_VISIBLE_KEYS = /* @__PURE__ */ new Set(["id", "created_at", "updated_at", "deleted_at", "expires_at", "used_at"]);
|
|
2715
|
+
function maskValue(value, ctx, depth) {
|
|
2716
|
+
var _a;
|
|
2717
|
+
if (Array.isArray(value)) return value.map((item) => maskValue(item, ctx, depth + 1));
|
|
2718
|
+
if (value !== null && typeof value === "object") {
|
|
2719
|
+
const out = {};
|
|
2720
|
+
for (const [key, inner] of Object.entries(value)) {
|
|
2721
|
+
const topLevel = depth === 0;
|
|
2722
|
+
const secret = inner !== null && inner !== void 0 && inner !== "" && (isSensitiveKey(key) || topLevel && ((_a = ctx.tableKeys) == null ? void 0 : _a.has(key.toLowerCase())) === true || topLevel && ctx.maskAll && !ALWAYS_VISIBLE_KEYS.has(key) && !key.endsWith("_id"));
|
|
2723
|
+
if (secret) {
|
|
2724
|
+
ctx.count += 1;
|
|
2725
|
+
out[key] = MASKED_VALUE;
|
|
2726
|
+
} else {
|
|
2727
|
+
out[key] = maskValue(inner, ctx, depth + 1);
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2730
|
+
return out;
|
|
2731
|
+
}
|
|
2732
|
+
return value;
|
|
2733
|
+
}
|
|
2734
|
+
function maskSensitiveData(data, tableName) {
|
|
2735
|
+
const ctx = {
|
|
2736
|
+
count: 0,
|
|
2737
|
+
maskAll: tableName ? FULLY_SECRET_TABLES.has(tableName) : false,
|
|
2738
|
+
tableKeys: tableName ? TABLE_SENSITIVE_KEYS[tableName] : void 0
|
|
2739
|
+
};
|
|
2740
|
+
const value = maskValue(data, ctx, 0);
|
|
2741
|
+
return { value, maskedCount: ctx.count };
|
|
2742
|
+
}
|
|
2743
|
+
const AUTO_EXPAND_DEPTH = 1;
|
|
2744
|
+
const LONG_STRING = 200;
|
|
2745
|
+
const JsonViewer = ({ data }) => {
|
|
2746
|
+
const [generation, setGeneration] = useState(0);
|
|
2747
|
+
const [expandAll, setExpandAll] = useState(null);
|
|
2748
|
+
const setAll = (value) => {
|
|
2749
|
+
setExpandAll(value);
|
|
2750
|
+
setGeneration((g) => g + 1);
|
|
2751
|
+
};
|
|
2752
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
2753
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
2754
|
+
/* @__PURE__ */ jsx(Button, { variant: "transparent", size: "small", onClick: () => setAll(true), children: "Expand all" }),
|
|
2755
|
+
/* @__PURE__ */ jsx(Button, { variant: "transparent", size: "small", onClick: () => setAll(false), children: "Collapse all" })
|
|
2756
|
+
] }),
|
|
2757
|
+
/* @__PURE__ */ jsx("div", { className: "max-h-[560px] overflow-auto rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 font-mono text-xs leading-5", children: /* @__PURE__ */ jsx(JsonNode, { value: data, depth: 0, forceExpand: expandAll }, generation) })
|
|
2758
|
+
] });
|
|
2759
|
+
};
|
|
2760
|
+
const JsonNode = ({ name, value, depth, forceExpand }) => {
|
|
2761
|
+
const isContainer = value !== null && typeof value === "object";
|
|
2762
|
+
const [open, setOpen] = useState(forceExpand ?? depth < AUTO_EXPAND_DEPTH);
|
|
2763
|
+
const label = name !== void 0 ? /* @__PURE__ */ jsxs("span", { className: "text-ui-fg-subtle", children: [
|
|
2764
|
+
name,
|
|
2765
|
+
/* @__PURE__ */ jsx("span", { className: "text-ui-fg-muted", children: ": " })
|
|
2766
|
+
] }) : null;
|
|
2767
|
+
if (!isContainer) {
|
|
2768
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-start", style: { paddingLeft: depth ? 16 : 0 }, children: [
|
|
2769
|
+
/* @__PURE__ */ jsx("span", { className: "w-4 shrink-0" }),
|
|
2770
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 break-words [overflow-wrap:anywhere]", children: [
|
|
2771
|
+
label,
|
|
2772
|
+
/* @__PURE__ */ jsx(Primitive, { value })
|
|
2773
|
+
] })
|
|
2774
|
+
] });
|
|
2775
|
+
}
|
|
2776
|
+
const entries = Array.isArray(value) ? value.map((v, i) => [String(i), v]) : Object.entries(value);
|
|
2777
|
+
const [openBracket, closeBracket] = Array.isArray(value) ? ["[", "]"] : ["{", "}"];
|
|
2778
|
+
const summary = Array.isArray(value) ? `${entries.length} items` : `${entries.length} keys`;
|
|
2779
|
+
return /* @__PURE__ */ jsxs("div", { style: { paddingLeft: depth ? 16 : 0 }, children: [
|
|
2780
|
+
/* @__PURE__ */ jsxs(
|
|
2781
|
+
"button",
|
|
2957
2782
|
{
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2783
|
+
type: "button",
|
|
2784
|
+
onClick: () => setOpen((o) => !o),
|
|
2785
|
+
className: "flex items-start text-left hover:bg-ui-bg-base-hover",
|
|
2786
|
+
"aria-expanded": open,
|
|
2787
|
+
children: [
|
|
2788
|
+
/* @__PURE__ */ jsx("span", { className: "flex w-4 shrink-0 items-center pt-0.5 text-ui-fg-muted", children: entries.length ? open ? /* @__PURE__ */ jsx(ChevronDownMini, {}) : /* @__PURE__ */ jsx(ChevronRightMini, {}) : null }),
|
|
2789
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
2790
|
+
label,
|
|
2791
|
+
/* @__PURE__ */ jsx("span", { className: "text-ui-fg-muted", children: openBracket }),
|
|
2792
|
+
!open || entries.length === 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2793
|
+
entries.length ? /* @__PURE__ */ jsx("span", { className: "px-1 italic text-ui-fg-muted", children: summary }) : null,
|
|
2794
|
+
/* @__PURE__ */ jsx("span", { className: "text-ui-fg-muted", children: closeBracket })
|
|
2795
|
+
] }) : null
|
|
2796
|
+
] })
|
|
2797
|
+
]
|
|
2962
2798
|
}
|
|
2963
|
-
)
|
|
2964
|
-
|
|
2799
|
+
),
|
|
2800
|
+
open && entries.length ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2801
|
+
entries.map(([key, child]) => /* @__PURE__ */ jsx(JsonNode, { name: key, value: child, depth: depth + 1, forceExpand }, key)),
|
|
2802
|
+
/* @__PURE__ */ jsx("div", { style: { paddingLeft: 16 }, className: "text-ui-fg-muted", children: closeBracket })
|
|
2803
|
+
] }) : null
|
|
2804
|
+
] });
|
|
2965
2805
|
};
|
|
2966
|
-
const
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
});
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
return
|
|
2806
|
+
const Primitive = ({ value }) => {
|
|
2807
|
+
const [showFull, setShowFull] = useState(false);
|
|
2808
|
+
if (value === MASKED_VALUE) {
|
|
2809
|
+
return /* @__PURE__ */ jsx("span", { className: "rounded bg-ui-tag-orange-bg px-1 text-ui-tag-orange-text", title: "Hidden for security", children: MASKED_VALUE });
|
|
2810
|
+
}
|
|
2811
|
+
if (value === null || value === void 0) return /* @__PURE__ */ jsx("span", { className: "text-ui-fg-muted", children: "null" });
|
|
2812
|
+
if (typeof value === "boolean") return /* @__PURE__ */ jsx("span", { className: "text-ui-tag-purple-text", children: String(value) });
|
|
2813
|
+
if (typeof value === "number") return /* @__PURE__ */ jsx("span", { className: "text-ui-tag-blue-text", children: value });
|
|
2814
|
+
const text = String(value);
|
|
2815
|
+
const truncated = !showFull && text.length > LONG_STRING;
|
|
2816
|
+
return /* @__PURE__ */ jsxs("span", { className: clx("text-ui-tag-green-text"), children: [
|
|
2817
|
+
'"',
|
|
2818
|
+
truncated ? `${text.slice(0, LONG_STRING)}…` : text,
|
|
2819
|
+
'"',
|
|
2820
|
+
text.length > LONG_STRING ? /* @__PURE__ */ jsx(
|
|
2821
|
+
"button",
|
|
2822
|
+
{
|
|
2823
|
+
type: "button",
|
|
2824
|
+
onClick: () => setShowFull((s2) => !s2),
|
|
2825
|
+
className: "ml-1 font-sans text-ui-fg-interactive hover:underline",
|
|
2826
|
+
children: showFull ? "show less" : `show all (${text.length} chars)`
|
|
2827
|
+
}
|
|
2828
|
+
) : null
|
|
2829
|
+
] });
|
|
2830
|
+
};
|
|
2831
|
+
const GUIDANCE = {
|
|
2832
|
+
orders: {
|
|
2833
|
+
headline: "Order data affects customers, payments and reports.",
|
|
2834
|
+
recreate: "Orders can’t be recreated identically from the admin. If this deletion was not intended, ask a developer to restore it from a database backup using the snapshot on this page.",
|
|
2835
|
+
adminSection: { label: "Go to Orders", path: "/orders" }
|
|
2836
|
+
},
|
|
2837
|
+
carts: {
|
|
2838
|
+
headline: "Carts are usually cleaned up automatically.",
|
|
2839
|
+
recreate: "No action is normally needed. Customers can simply add items to a new cart."
|
|
2840
|
+
},
|
|
2841
|
+
customers: {
|
|
2842
|
+
headline: "Customer data may be needed for orders, support and compliance.",
|
|
2843
|
+
recreate: "If it was deleted by mistake, recreate it from Customers using the values shown above. A recreated customer gets a new ID and must reset their password.",
|
|
2844
|
+
adminSection: { label: "Go to Customers", path: "/customers" }
|
|
2845
|
+
},
|
|
2846
|
+
catalog: {
|
|
2847
|
+
headline: "Catalog changes affect what customers can see and buy.",
|
|
2848
|
+
recreate: "If it was deleted by mistake, recreate it from Products using the values shown above. It will get a new ID.",
|
|
2849
|
+
adminSection: { label: "Go to Products", path: "/products" }
|
|
2850
|
+
},
|
|
2851
|
+
pricing: {
|
|
2852
|
+
headline: "Pricing and promotions affect what customers pay.",
|
|
2853
|
+
recreate: "If it was deleted by mistake, recreate it from Promotions or Price Lists using the values shown above.",
|
|
2854
|
+
adminSection: { label: "Go to Promotions", path: "/promotions" }
|
|
2855
|
+
},
|
|
2856
|
+
payments: {
|
|
2857
|
+
headline: "Payment records are financial data.",
|
|
2858
|
+
recreate: "Do not recreate payment records by hand—this can make balances inconsistent. If this deletion was not expected, escalate to a developer or your finance team."
|
|
2859
|
+
},
|
|
2860
|
+
fulfillment: {
|
|
2861
|
+
headline: "Shipping and fulfillment settings affect checkout and delivery.",
|
|
2862
|
+
recreate: "If it was deleted by mistake, recreate it from Settings → Locations & Shipping using the values shown above.",
|
|
2863
|
+
adminSection: { label: "Go to Settings", path: "/settings" }
|
|
2864
|
+
},
|
|
2865
|
+
inventory: {
|
|
2866
|
+
headline: "Inventory changes can affect stock levels and availability.",
|
|
2867
|
+
recreate: "If it was deleted by mistake, recreate it from Inventory using the values shown above and re-check stock quantities.",
|
|
2868
|
+
adminSection: { label: "Go to Inventory", path: "/inventory" }
|
|
2869
|
+
},
|
|
2870
|
+
wallet: {
|
|
2871
|
+
headline: "Wallet and credit records are financial data.",
|
|
2872
|
+
recreate: "Do not recreate balances by hand. If this deletion was not expected, escalate to a developer or your finance team so balances can be verified."
|
|
2873
|
+
},
|
|
2874
|
+
access: {
|
|
2875
|
+
headline: "Access records control who can sign in.",
|
|
2876
|
+
recreate: "Secrets such as passwords and keys can’t be restored. Re-invite the user or create a new API key if access is still needed.",
|
|
2877
|
+
adminSection: { label: "Go to Settings", path: "/settings" }
|
|
2878
|
+
},
|
|
2879
|
+
store: {
|
|
2880
|
+
headline: "Store settings affect regions, currencies and taxes.",
|
|
2881
|
+
recreate: "If it was deleted by mistake, recreate it from Settings using the values shown above.",
|
|
2882
|
+
adminSection: { label: "Go to Settings", path: "/settings" }
|
|
2883
|
+
},
|
|
2884
|
+
engagement: {
|
|
2885
|
+
headline: "Customer-generated content.",
|
|
2886
|
+
recreate: "These usually can’t be recreated on the customer’s behalf. Keep the snapshot on this page if you need a record of it."
|
|
2887
|
+
},
|
|
2888
|
+
notifications: {
|
|
2889
|
+
headline: "Notification records are usually cleaned up automatically.",
|
|
2890
|
+
recreate: "No action is normally needed."
|
|
2891
|
+
},
|
|
2892
|
+
system: {
|
|
2893
|
+
headline: "Internal system data, usually removed automatically by the platform.",
|
|
2894
|
+
recreate: "No action is normally needed. If you suspect a problem, share this page with a developer."
|
|
2895
|
+
}
|
|
2896
|
+
};
|
|
2897
|
+
function getNextSteps(category) {
|
|
2898
|
+
return GUIDANCE[category];
|
|
2899
|
+
}
|
|
2900
|
+
const RELATED_LINKS = [
|
|
2901
|
+
{ key: "order_id", label: "Order", path: (id) => `/orders/${id}`, selfTables: ["order"] },
|
|
2902
|
+
{ key: "customer_id", label: "Customer", path: (id) => `/customers/${id}`, selfTables: ["customer"] },
|
|
2903
|
+
{ key: "product_id", label: "Product", path: (id) => `/products/${id}`, selfTables: ["product"] }
|
|
2904
|
+
];
|
|
2905
|
+
function getRelatedLinks(tableName, oldData) {
|
|
2906
|
+
if (!oldData) return [];
|
|
2907
|
+
return RELATED_LINKS.flatMap((link) => {
|
|
2908
|
+
const id = oldData[link.key];
|
|
2909
|
+
if (link.selfTables.includes(tableName) || typeof id !== "string" || !id.trim()) return [];
|
|
2910
|
+
return [{ label: link.label, id, path: link.path(id) }];
|
|
2911
|
+
});
|
|
2912
|
+
}
|
|
2913
|
+
const fullName = (row) => {
|
|
2914
|
+
const parts = [row.first_name, row.last_name].filter(
|
|
2915
|
+
(part) => typeof part === "string" && part.trim() !== ""
|
|
2916
|
+
);
|
|
2917
|
+
return parts.length ? parts.join(" ") : void 0;
|
|
2918
|
+
};
|
|
2919
|
+
const addressLine = (row) => {
|
|
2920
|
+
const parts = [row.address_1, row.address_2, row.city, row.province, row.postal_code, row.country_code].filter((part) => typeof part === "string" && part.trim() !== "").map((part) => part.trim());
|
|
2921
|
+
return parts.length ? parts.join(", ") : void 0;
|
|
2922
|
+
};
|
|
2923
|
+
const NAME = { key: "name", label: "Name", derive: fullName };
|
|
2924
|
+
const ADDRESS = { key: "address", label: "Address", derive: addressLine };
|
|
2925
|
+
const CREATED = { key: "created_at", label: "Created", kind: "date" };
|
|
2926
|
+
const ENTITY_FIELDS = {
|
|
2927
|
+
order: [
|
|
2928
|
+
{ key: "display_id", label: "Order number" },
|
|
2929
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
2930
|
+
{ key: "email", label: "Customer email" },
|
|
2931
|
+
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
2932
|
+
{ key: "currency_code", label: "Currency" },
|
|
2933
|
+
{ key: "region_id", label: "Region ID", kind: "id" },
|
|
2934
|
+
{ key: "sales_channel_id", label: "Sales channel ID", kind: "id" },
|
|
2935
|
+
{ key: "canceled_at", label: "Canceled", kind: "date" },
|
|
2936
|
+
CREATED
|
|
2937
|
+
],
|
|
2938
|
+
order_line_item: [
|
|
2939
|
+
{ key: "title", label: "Item" },
|
|
2940
|
+
{ key: "variant_title", label: "Variant" },
|
|
2941
|
+
{ key: "variant_sku", label: "SKU" },
|
|
2942
|
+
{ key: "unit_price", label: "Unit price", kind: "money" },
|
|
2943
|
+
{ key: "product_id", label: "Product ID", kind: "id" },
|
|
2944
|
+
{ key: "variant_id", label: "Variant ID", kind: "id" },
|
|
2945
|
+
CREATED
|
|
2946
|
+
],
|
|
2947
|
+
cart_line_item: [
|
|
2948
|
+
{ key: "title", label: "Item" },
|
|
2949
|
+
{ key: "variant_sku", label: "SKU" },
|
|
2950
|
+
{ key: "quantity", label: "Quantity", kind: "number" },
|
|
2951
|
+
{ key: "unit_price", label: "Unit price", kind: "money" },
|
|
2952
|
+
{ key: "cart_id", label: "Cart ID", kind: "id" },
|
|
2953
|
+
{ key: "variant_id", label: "Variant ID", kind: "id" },
|
|
2954
|
+
CREATED
|
|
2955
|
+
],
|
|
2956
|
+
cart: [
|
|
2957
|
+
{ key: "email", label: "Email" },
|
|
2958
|
+
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
2959
|
+
{ key: "currency_code", label: "Currency" },
|
|
2960
|
+
{ key: "region_id", label: "Region ID", kind: "id" },
|
|
2961
|
+
{ key: "completed_at", label: "Completed", kind: "date" },
|
|
2962
|
+
CREATED
|
|
2963
|
+
],
|
|
2964
|
+
customer: [
|
|
2965
|
+
NAME,
|
|
2966
|
+
{ key: "email", label: "Email" },
|
|
2967
|
+
{ key: "phone", label: "Phone" },
|
|
2968
|
+
{ key: "company_name", label: "Company" },
|
|
2969
|
+
{ key: "has_account", label: "Registered account", kind: "boolean" },
|
|
2970
|
+
CREATED
|
|
2971
|
+
],
|
|
2972
|
+
customer_address: [
|
|
2973
|
+
{ key: "address_name", label: "Label" },
|
|
2974
|
+
NAME,
|
|
2975
|
+
ADDRESS,
|
|
2976
|
+
{ key: "phone", label: "Phone" },
|
|
2977
|
+
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
2978
|
+
{ key: "is_default_shipping", label: "Default shipping", kind: "boolean" },
|
|
2979
|
+
CREATED
|
|
2980
|
+
],
|
|
2981
|
+
order_address: [NAME, ADDRESS, { key: "phone", label: "Phone" }, CREATED],
|
|
2982
|
+
cart_address: [NAME, ADDRESS, { key: "phone", label: "Phone" }, CREATED],
|
|
2983
|
+
product: [
|
|
2984
|
+
{ key: "title", label: "Title" },
|
|
2985
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
2986
|
+
{ key: "handle", label: "Handle" },
|
|
2987
|
+
{ key: "subtitle", label: "Subtitle" },
|
|
2988
|
+
{ key: "collection_id", label: "Collection ID", kind: "id" },
|
|
2989
|
+
{ key: "is_giftcard", label: "Gift card", kind: "boolean" },
|
|
2990
|
+
CREATED
|
|
2991
|
+
],
|
|
2992
|
+
product_variant: [
|
|
2993
|
+
{ key: "title", label: "Title" },
|
|
2994
|
+
{ key: "sku", label: "SKU" },
|
|
2995
|
+
{ key: "barcode", label: "Barcode" },
|
|
2996
|
+
{ key: "product_id", label: "Product ID", kind: "id" },
|
|
2997
|
+
{ key: "manage_inventory", label: "Manages inventory", kind: "boolean" },
|
|
2998
|
+
CREATED
|
|
2999
|
+
],
|
|
3000
|
+
product_category: [
|
|
3001
|
+
{ key: "name", label: "Name" },
|
|
3002
|
+
{ key: "handle", label: "Handle" },
|
|
3003
|
+
{ key: "is_active", label: "Active", kind: "boolean" },
|
|
3004
|
+
{ key: "parent_category_id", label: "Parent category ID", kind: "id" },
|
|
3005
|
+
CREATED
|
|
3006
|
+
],
|
|
3007
|
+
product_collection: [{ key: "title", label: "Title" }, { key: "handle", label: "Handle" }, CREATED],
|
|
3008
|
+
payment: [
|
|
3009
|
+
{ key: "amount", label: "Amount", kind: "money" },
|
|
3010
|
+
{ key: "currency_code", label: "Currency" },
|
|
3011
|
+
{ key: "provider_id", label: "Provider" },
|
|
3012
|
+
{ key: "captured_at", label: "Captured", kind: "date" },
|
|
3013
|
+
{ key: "canceled_at", label: "Canceled", kind: "date" },
|
|
3014
|
+
{ key: "payment_collection_id", label: "Payment collection ID", kind: "id" },
|
|
3015
|
+
CREATED
|
|
3016
|
+
],
|
|
3017
|
+
payment_session: [
|
|
3018
|
+
{ key: "amount", label: "Amount", kind: "money" },
|
|
3019
|
+
{ key: "currency_code", label: "Currency" },
|
|
3020
|
+
{ key: "provider_id", label: "Provider" },
|
|
3021
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
3022
|
+
{ key: "payment_collection_id", label: "Payment collection ID", kind: "id" },
|
|
3023
|
+
CREATED
|
|
3024
|
+
],
|
|
3025
|
+
payment_collection: [
|
|
3026
|
+
{ key: "amount", label: "Amount", kind: "money" },
|
|
3027
|
+
{ key: "currency_code", label: "Currency" },
|
|
3028
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
3029
|
+
CREATED
|
|
3030
|
+
],
|
|
3031
|
+
refund: [
|
|
3032
|
+
{ key: "amount", label: "Amount", kind: "money" },
|
|
3033
|
+
{ key: "payment_id", label: "Payment ID", kind: "id" },
|
|
3034
|
+
{ key: "refund_reason_id", label: "Refund reason ID", kind: "id" },
|
|
3035
|
+
{ key: "note", label: "Note" },
|
|
3036
|
+
{ key: "created_by", label: "Created by" },
|
|
3037
|
+
CREATED
|
|
3038
|
+
],
|
|
3039
|
+
return: [
|
|
3040
|
+
{ key: "display_id", label: "Return number" },
|
|
3041
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
3042
|
+
{ key: "order_id", label: "Order ID", kind: "id" },
|
|
3043
|
+
{ key: "refund_amount", label: "Refund amount", kind: "money" },
|
|
3044
|
+
{ key: "received_at", label: "Received", kind: "date" },
|
|
3045
|
+
CREATED
|
|
3046
|
+
],
|
|
3047
|
+
payment_detail: [
|
|
3048
|
+
{ key: "type", label: "Method type" },
|
|
3049
|
+
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
3050
|
+
{ key: "is_default", label: "Default method", kind: "boolean" },
|
|
3051
|
+
CREATED
|
|
3052
|
+
],
|
|
3053
|
+
user: [NAME, { key: "email", label: "Email" }, CREATED],
|
|
3054
|
+
invite: [
|
|
3055
|
+
{ key: "email", label: "Email" },
|
|
3056
|
+
{ key: "accepted", label: "Accepted", kind: "boolean" },
|
|
3057
|
+
{ key: "expires_at", label: "Expires", kind: "date" },
|
|
3058
|
+
CREATED
|
|
3059
|
+
],
|
|
3060
|
+
api_key: [
|
|
3061
|
+
{ key: "title", label: "Title" },
|
|
3062
|
+
{ key: "type", label: "Type" },
|
|
3063
|
+
{ key: "redacted", label: "Key (redacted)" },
|
|
3064
|
+
{ key: "revoked_at", label: "Revoked", kind: "date" },
|
|
3065
|
+
CREATED
|
|
3066
|
+
],
|
|
3067
|
+
promotion: [
|
|
3068
|
+
{ key: "code", label: "Promotion code" },
|
|
3069
|
+
{ key: "type", label: "Type" },
|
|
3070
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
3071
|
+
{ key: "is_automatic", label: "Automatic", kind: "boolean" },
|
|
3072
|
+
CREATED
|
|
3073
|
+
],
|
|
3074
|
+
fulfillment: [
|
|
3075
|
+
{ key: "provider_id", label: "Provider" },
|
|
3076
|
+
{ key: "location_id", label: "Location ID", kind: "id" },
|
|
3077
|
+
{ key: "shipped_at", label: "Shipped", kind: "date" },
|
|
3078
|
+
{ key: "delivered_at", label: "Delivered", kind: "date" },
|
|
3079
|
+
{ key: "canceled_at", label: "Canceled", kind: "date" },
|
|
3080
|
+
CREATED
|
|
3081
|
+
],
|
|
3082
|
+
inventory_item: [
|
|
3083
|
+
{ key: "sku", label: "SKU" },
|
|
3084
|
+
{ key: "title", label: "Title" },
|
|
3085
|
+
{ key: "requires_shipping", label: "Requires shipping", kind: "boolean" },
|
|
3086
|
+
CREATED
|
|
3087
|
+
],
|
|
3088
|
+
inventory_level: [
|
|
3089
|
+
{ key: "inventory_item_id", label: "Inventory item ID", kind: "id" },
|
|
3090
|
+
{ key: "location_id", label: "Location ID", kind: "id" },
|
|
3091
|
+
{ key: "stocked_quantity", label: "Stocked", kind: "number" },
|
|
3092
|
+
{ key: "reserved_quantity", label: "Reserved", kind: "number" },
|
|
3093
|
+
CREATED
|
|
3094
|
+
],
|
|
3095
|
+
review: [
|
|
3096
|
+
{ key: "title", label: "Title" },
|
|
3097
|
+
{ key: "rating", label: "Rating", kind: "number" },
|
|
3098
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
3099
|
+
{ key: "product_id", label: "Product ID", kind: "id" },
|
|
3100
|
+
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
3101
|
+
CREATED
|
|
3102
|
+
]
|
|
2977
3103
|
};
|
|
2978
|
-
const
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
3104
|
+
const GENERIC_FIELDS = [
|
|
3105
|
+
{ key: "display_id", label: "Number" },
|
|
3106
|
+
{ key: "title", label: "Title" },
|
|
3107
|
+
{ key: "name", label: "Name" },
|
|
3108
|
+
NAME,
|
|
3109
|
+
{ key: "email", label: "Email" },
|
|
3110
|
+
{ key: "phone", label: "Phone" },
|
|
3111
|
+
{ key: "handle", label: "Handle" },
|
|
3112
|
+
{ key: "sku", label: "SKU" },
|
|
3113
|
+
{ key: "code", label: "Code" },
|
|
3114
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
3115
|
+
{ key: "type", label: "Type" },
|
|
3116
|
+
{ key: "amount", label: "Amount", kind: "money" },
|
|
3117
|
+
{ key: "quantity", label: "Quantity", kind: "number" },
|
|
3118
|
+
{ key: "currency_code", label: "Currency" },
|
|
3119
|
+
{ key: "order_id", label: "Order ID", kind: "id" },
|
|
3120
|
+
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
3121
|
+
{ key: "product_id", label: "Product ID", kind: "id" },
|
|
3122
|
+
{ key: "payment_id", label: "Payment ID", kind: "id" },
|
|
3123
|
+
{ key: "provider_id", label: "Provider" },
|
|
3124
|
+
CREATED,
|
|
3125
|
+
{ key: "updated_at", label: "Last updated", kind: "date" }
|
|
3126
|
+
];
|
|
3127
|
+
const MAX_GENERIC_FIELDS = 8;
|
|
3128
|
+
function amountOf(value) {
|
|
3129
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
3130
|
+
if (typeof value === "string" && value.trim() !== "" && Number.isFinite(Number(value))) return Number(value);
|
|
3131
|
+
if (value !== null && typeof value === "object" && "value" in value) {
|
|
3132
|
+
return amountOf(value.value);
|
|
2985
3133
|
}
|
|
2986
|
-
|
|
2987
|
-
|
|
3134
|
+
return null;
|
|
3135
|
+
}
|
|
3136
|
+
function formatValue(raw, kind, row) {
|
|
3137
|
+
if (raw === null || raw === void 0 || raw === "") return null;
|
|
3138
|
+
if (raw === MASKED_VALUE) return { value: MASKED_VALUE, kind: "masked" };
|
|
3139
|
+
switch (kind) {
|
|
3140
|
+
case "money": {
|
|
3141
|
+
const amount = amountOf(raw);
|
|
3142
|
+
if (amount === null) return null;
|
|
3143
|
+
const currency = typeof row.currency_code === "string" ? row.currency_code : null;
|
|
3144
|
+
return { value: formatMoney(amount, currency), kind };
|
|
3145
|
+
}
|
|
3146
|
+
case "date":
|
|
3147
|
+
return typeof raw === "string" || raw instanceof Date ? { value: formatDate(raw), kind } : null;
|
|
3148
|
+
case "boolean":
|
|
3149
|
+
return { value: raw === true || raw === "true" ? "Yes" : "No", kind };
|
|
3150
|
+
case "number": {
|
|
3151
|
+
const n = amountOf(raw);
|
|
3152
|
+
return n === null ? null : { value: formatNumber(n), kind };
|
|
3153
|
+
}
|
|
3154
|
+
case "status":
|
|
3155
|
+
return { value: String(raw).replace(/_/g, " "), kind };
|
|
3156
|
+
default:
|
|
3157
|
+
if (typeof raw === "object") return null;
|
|
3158
|
+
if (typeof raw === "string" && raw.length > 160) return { value: `${raw.slice(0, 157)}…`, kind };
|
|
3159
|
+
return { value: String(raw), kind };
|
|
2988
3160
|
}
|
|
2989
|
-
|
|
2990
|
-
|
|
3161
|
+
}
|
|
3162
|
+
function summarizeOldData(tableName, oldData) {
|
|
3163
|
+
if (!oldData) return [];
|
|
3164
|
+
const { value: row } = maskSensitiveData(oldData, tableName);
|
|
3165
|
+
const specific = ENTITY_FIELDS[tableName];
|
|
3166
|
+
const specs = specific ?? GENERIC_FIELDS;
|
|
3167
|
+
const fields = [];
|
|
3168
|
+
const seenLabels = /* @__PURE__ */ new Set();
|
|
3169
|
+
for (const spec of specs) {
|
|
3170
|
+
const raw = spec.derive ? spec.derive(row) : row[spec.key];
|
|
3171
|
+
const formatted = formatValue(raw, spec.kind ?? "text", row);
|
|
3172
|
+
if (!formatted || seenLabels.has(spec.label)) continue;
|
|
3173
|
+
seenLabels.add(spec.label);
|
|
3174
|
+
const value = spec.key === "currency_code" ? formatted.value.toUpperCase() : formatted.value;
|
|
3175
|
+
fields.push({ key: spec.key, label: spec.label, value, kind: formatted.kind });
|
|
3176
|
+
if (!specific && fields.length >= MAX_GENERIC_FIELDS) break;
|
|
2991
3177
|
}
|
|
2992
|
-
|
|
2993
|
-
|
|
3178
|
+
return fields;
|
|
3179
|
+
}
|
|
3180
|
+
function readLastListSearch() {
|
|
3181
|
+
try {
|
|
3182
|
+
return window.sessionStorage.getItem(LAST_LIST_URL_KEY) ?? "";
|
|
3183
|
+
} catch {
|
|
3184
|
+
return "";
|
|
2994
3185
|
}
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
const SwapsPage = () => {
|
|
2998
|
-
const navigate = useNavigate();
|
|
2999
|
-
const [items, setItems] = useState([]);
|
|
3000
|
-
const [statusFilter, setStatusFilter] = useState("all");
|
|
3001
|
-
const [createdByFilter, setCreatedByFilter] = useState("all");
|
|
3002
|
-
const [searchQuery, setSearchQuery] = useState("");
|
|
3003
|
-
const debouncedSearchQuery = useDebounce(searchQuery, 300);
|
|
3004
|
-
const [isLoading, setIsLoading] = useState(true);
|
|
3005
|
-
const [isFetchingMore, setIsFetchingMore] = useState(false);
|
|
3006
|
-
const [error, setError] = useState(null);
|
|
3007
|
-
const [offset, setOffset] = useState(0);
|
|
3008
|
-
const [count, setCount] = useState(0);
|
|
3009
|
-
const limit = 50;
|
|
3010
|
-
const loadSwaps = useCallback(
|
|
3011
|
-
async (nextOffset, replace = false) => {
|
|
3012
|
-
var _a;
|
|
3013
|
-
try {
|
|
3014
|
-
if (replace) {
|
|
3015
|
-
setIsLoading(true);
|
|
3016
|
-
} else {
|
|
3017
|
-
setIsFetchingMore(true);
|
|
3018
|
-
}
|
|
3019
|
-
setError(null);
|
|
3020
|
-
const params = new URLSearchParams();
|
|
3021
|
-
params.set("limit", String(limit));
|
|
3022
|
-
params.set("offset", String(nextOffset));
|
|
3023
|
-
if (statusFilter !== "all") {
|
|
3024
|
-
params.set("status", statusFilter);
|
|
3025
|
-
}
|
|
3026
|
-
if (debouncedSearchQuery.trim()) {
|
|
3027
|
-
params.set("order_id", debouncedSearchQuery.trim());
|
|
3028
|
-
}
|
|
3029
|
-
if (createdByFilter !== "all") {
|
|
3030
|
-
params.set("created_by", createdByFilter);
|
|
3031
|
-
}
|
|
3032
|
-
const response = await fetch(
|
|
3033
|
-
`/admin/swaps?${params.toString()}`,
|
|
3034
|
-
{ credentials: "include" }
|
|
3035
|
-
);
|
|
3036
|
-
if (!response.ok) {
|
|
3037
|
-
const message = await response.text();
|
|
3038
|
-
throw new Error(message || "Unable to load swaps");
|
|
3039
|
-
}
|
|
3040
|
-
const payload = await response.json();
|
|
3041
|
-
setCount(payload.count ?? 0);
|
|
3042
|
-
setOffset(nextOffset + (((_a = payload.swaps) == null ? void 0 : _a.length) ?? 0));
|
|
3043
|
-
setItems(
|
|
3044
|
-
(prev) => replace ? payload.swaps ?? [] : [...prev, ...payload.swaps ?? []]
|
|
3045
|
-
);
|
|
3046
|
-
} catch (loadError) {
|
|
3047
|
-
const message = loadError instanceof Error ? loadError.message : "Unable to load swaps";
|
|
3048
|
-
setError(message);
|
|
3049
|
-
} finally {
|
|
3050
|
-
setIsLoading(false);
|
|
3051
|
-
setIsFetchingMore(false);
|
|
3052
|
-
}
|
|
3053
|
-
},
|
|
3054
|
-
[statusFilter, createdByFilter, debouncedSearchQuery]
|
|
3055
|
-
);
|
|
3056
|
-
useEffect(() => {
|
|
3057
|
-
void loadSwaps(0, true);
|
|
3058
|
-
}, [statusFilter, createdByFilter, debouncedSearchQuery, loadSwaps]);
|
|
3059
|
-
const hasMore = useMemo(() => offset < count, [offset, count]);
|
|
3060
|
-
const availableStatuses = useMemo(() => {
|
|
3061
|
-
const statuses = /* @__PURE__ */ new Set();
|
|
3062
|
-
items.forEach((item) => statuses.add(item.status));
|
|
3063
|
-
return Array.from(statuses).sort();
|
|
3064
|
-
}, [items]);
|
|
3065
|
-
return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
|
|
3066
|
-
/* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
3067
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3068
|
-
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Exchanges" }),
|
|
3069
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "View and manage all customer exchange requests" })
|
|
3070
|
-
] }),
|
|
3071
|
-
/* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () => loadSwaps(0, true), children: "Refresh" })
|
|
3072
|
-
] }),
|
|
3073
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
3074
|
-
/* @__PURE__ */ jsx(
|
|
3075
|
-
Input,
|
|
3076
|
-
{
|
|
3077
|
-
placeholder: "Search by swap ID or order ID",
|
|
3078
|
-
value: searchQuery,
|
|
3079
|
-
onChange: (event) => setSearchQuery(event.target.value),
|
|
3080
|
-
className: "md:max-w-sm"
|
|
3081
|
-
}
|
|
3082
|
-
),
|
|
3083
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
|
|
3084
|
-
/* @__PURE__ */ jsxs(
|
|
3085
|
-
"select",
|
|
3086
|
-
{
|
|
3087
|
-
value: createdByFilter,
|
|
3088
|
-
onChange: (event) => setCreatedByFilter(event.target.value),
|
|
3089
|
-
className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-xs",
|
|
3090
|
-
children: [
|
|
3091
|
-
/* @__PURE__ */ jsx("option", { value: "all", children: "All (Created by)" }),
|
|
3092
|
-
/* @__PURE__ */ jsx("option", { value: "customer", children: "Customer" }),
|
|
3093
|
-
/* @__PURE__ */ jsx("option", { value: "admin", children: "Admin" })
|
|
3094
|
-
]
|
|
3095
|
-
}
|
|
3096
|
-
),
|
|
3097
|
-
/* @__PURE__ */ jsxs(
|
|
3098
|
-
"select",
|
|
3099
|
-
{
|
|
3100
|
-
value: statusFilter,
|
|
3101
|
-
onChange: (event) => setStatusFilter(event.target.value),
|
|
3102
|
-
className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-xs",
|
|
3103
|
-
children: [
|
|
3104
|
-
/* @__PURE__ */ jsx("option", { value: "all", children: "All Statuses" }),
|
|
3105
|
-
availableStatuses.map((status) => /* @__PURE__ */ jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
|
|
3106
|
-
]
|
|
3107
|
-
}
|
|
3108
|
-
)
|
|
3109
|
-
] })
|
|
3110
|
-
] }),
|
|
3111
|
-
error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
3112
|
-
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
3113
|
-
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(
|
|
3114
|
-
Button,
|
|
3115
|
-
{
|
|
3116
|
-
variant: "secondary",
|
|
3117
|
-
onClick: () => loadSwaps(0, true),
|
|
3118
|
-
children: "Try again"
|
|
3119
|
-
}
|
|
3120
|
-
) })
|
|
3121
|
-
] }) : null,
|
|
3122
|
-
isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading swaps..." }) }) : items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
3123
|
-
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No exchanges yet" }),
|
|
3124
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Exchange requests created by customers will appear here." })
|
|
3125
|
-
] }) : /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
3126
|
-
/* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
3127
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Exchange ID" }),
|
|
3128
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
3129
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
3130
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Difference Due" }),
|
|
3131
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
3132
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
3133
|
-
] }) }),
|
|
3134
|
-
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((swap) => /* @__PURE__ */ jsxs(
|
|
3135
|
-
"tr",
|
|
3136
|
-
{
|
|
3137
|
-
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
3138
|
-
onClick: () => navigate(`/swaps/${swap.id}`),
|
|
3139
|
-
children: [
|
|
3140
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children: /* @__PURE__ */ jsx("span", { children: swap.id }) }) }),
|
|
3141
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: swap.order_id }),
|
|
3142
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
|
|
3143
|
-
Badge,
|
|
3144
|
-
{
|
|
3145
|
-
size: "2xsmall",
|
|
3146
|
-
className: `uppercase ${getStatusBadgeClass$4(swap.status)}`,
|
|
3147
|
-
children: swap.status.replace(/_/g, " ")
|
|
3148
|
-
}
|
|
3149
|
-
) }),
|
|
3150
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
|
|
3151
|
-
const amount = swap.difference_due;
|
|
3152
|
-
if (amount == null || amount === void 0) {
|
|
3153
|
-
return "—";
|
|
3154
|
-
}
|
|
3155
|
-
const displayAmount = Number(amount) / 100;
|
|
3156
|
-
const currency = swap.currency_code || "$";
|
|
3157
|
-
const sign = displayAmount >= 0 ? "+" : "";
|
|
3158
|
-
return `${sign}${currency}${displayAmount.toFixed(2)}`;
|
|
3159
|
-
})() }),
|
|
3160
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(swap.created_at).toLocaleDateString("en-US", {
|
|
3161
|
-
year: "numeric",
|
|
3162
|
-
month: "short",
|
|
3163
|
-
day: "numeric",
|
|
3164
|
-
hour: "numeric",
|
|
3165
|
-
minute: "2-digit",
|
|
3166
|
-
hour12: true
|
|
3167
|
-
}) }),
|
|
3168
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
|
|
3169
|
-
Button,
|
|
3170
|
-
{
|
|
3171
|
-
variant: "transparent",
|
|
3172
|
-
size: "small",
|
|
3173
|
-
onClick: (e) => {
|
|
3174
|
-
e.stopPropagation();
|
|
3175
|
-
navigate(`/app/orders/${swap.order_id}`);
|
|
3176
|
-
},
|
|
3177
|
-
children: "Go to order"
|
|
3178
|
-
}
|
|
3179
|
-
) })
|
|
3180
|
-
]
|
|
3181
|
-
},
|
|
3182
|
-
swap.id
|
|
3183
|
-
)) })
|
|
3184
|
-
] }) }),
|
|
3185
|
-
hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
|
|
3186
|
-
Button,
|
|
3187
|
-
{
|
|
3188
|
-
variant: "secondary",
|
|
3189
|
-
isLoading: isFetchingMore,
|
|
3190
|
-
onClick: () => loadSwaps(offset, false),
|
|
3191
|
-
children: "Load more"
|
|
3192
|
-
}
|
|
3193
|
-
) }) : null
|
|
3194
|
-
] }) });
|
|
3195
|
-
};
|
|
3196
|
-
const config$4 = defineRouteConfig({
|
|
3197
|
-
label: "Exchanges",
|
|
3198
|
-
icon: ArrowPath
|
|
3199
|
-
});
|
|
3200
|
-
const getStatusBadgeClass$3 = (status) => {
|
|
3201
|
-
const s2 = status.toLowerCase();
|
|
3202
|
-
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
3203
|
-
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
3204
|
-
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
3205
|
-
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
3206
|
-
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
3207
|
-
};
|
|
3208
|
-
const PaymentDetailPage = () => {
|
|
3186
|
+
}
|
|
3187
|
+
const DeletedRecordDetailPage = () => {
|
|
3209
3188
|
var _a;
|
|
3210
3189
|
const navigate = useNavigate();
|
|
3211
|
-
const
|
|
3212
|
-
const id =
|
|
3213
|
-
const [
|
|
3214
|
-
const [
|
|
3215
|
-
const
|
|
3216
|
-
|
|
3217
|
-
if (
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
|
|
3231
|
-
}).finally(() => {
|
|
3232
|
-
if (!cancelled) setLoading(false);
|
|
3190
|
+
const location = useLocation();
|
|
3191
|
+
const { id = "" } = useParams();
|
|
3192
|
+
const [state, setState] = useState({ status: "loading" });
|
|
3193
|
+
const [reloadToken, setReloadToken] = useState(0);
|
|
3194
|
+
const cameFromList = ((_a = location.state) == null ? void 0 : _a.fromList) === true;
|
|
3195
|
+
const goBack = () => {
|
|
3196
|
+
if (cameFromList) navigate(-1);
|
|
3197
|
+
else navigate(`/deleted-records-audit${readLastListSearch()}`);
|
|
3198
|
+
};
|
|
3199
|
+
useEffect(() => {
|
|
3200
|
+
const controller = new AbortController();
|
|
3201
|
+
setState({ status: "loading" });
|
|
3202
|
+
fetchAuditDetail(id, controller.signal).then((audit) => setState({ status: "ready", audit })).catch((e) => {
|
|
3203
|
+
if (controller.signal.aborted) return;
|
|
3204
|
+
setState({
|
|
3205
|
+
status: "error",
|
|
3206
|
+
message: e instanceof Error ? e.message : "Unknown error",
|
|
3207
|
+
notFound: e instanceof AuditApiError && e.status === 404
|
|
3208
|
+
});
|
|
3233
3209
|
});
|
|
3234
|
-
return () =>
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
const paymentStatusRaw = (detail == null ? void 0 : detail.payment_id) != null ? (detail == null ? void 0 : detail.payment_status) ?? "—" : "—";
|
|
3241
|
-
const displayAmount = detail ? `${(detail.currency_code ?? "USD").toUpperCase()} ${Number(detail.amount)}` : "";
|
|
3242
|
-
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: [
|
|
3243
|
-
/* @__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: [
|
|
3244
|
-
/* @__PURE__ */ jsx(Button, { variant: "transparent", size: "small", onClick: () => navigate("/payments"), children: "← Payments" }),
|
|
3245
|
-
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Payment session" }),
|
|
3246
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: id ?? "—" })
|
|
3210
|
+
return () => controller.abort();
|
|
3211
|
+
}, [id, reloadToken]);
|
|
3212
|
+
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: [
|
|
3213
|
+
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(Button, { variant: "transparent", size: "small", onClick: goBack, className: "-ml-2", children: [
|
|
3214
|
+
/* @__PURE__ */ jsx(ArrowLeft, {}),
|
|
3215
|
+
"Back to Deleted Records"
|
|
3247
3216
|
] }) }),
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
{
|
|
3258
|
-
variant: "transparent",
|
|
3259
|
-
size: "small",
|
|
3260
|
-
onClick: () => navigate(`/orders/${detail.order_id}`),
|
|
3261
|
-
children: detail.order_id
|
|
3262
|
-
}
|
|
3263
|
-
) : /* @__PURE__ */ jsx(Text, { children: "—" }) })
|
|
3264
|
-
] }),
|
|
3265
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
3266
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
|
|
3267
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: displayAmount })
|
|
3268
|
-
] }),
|
|
3269
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
3270
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
|
|
3271
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.provider_id })
|
|
3272
|
-
] }),
|
|
3273
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
3274
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
|
|
3275
|
-
/* @__PURE__ */ jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsx(
|
|
3276
|
-
Badge,
|
|
3277
|
-
{
|
|
3278
|
-
size: "2xsmall",
|
|
3279
|
-
className: `uppercase ${getStatusBadgeClass$3(displayStatus)}`,
|
|
3280
|
-
children: displayStatus !== "—" ? displayStatus.replace(/_/g, " ") : "—"
|
|
3281
|
-
}
|
|
3282
|
-
) })
|
|
3283
|
-
] }),
|
|
3284
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
3285
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Session status (DB)" }),
|
|
3286
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: sessionStatusRaw })
|
|
3287
|
-
] }),
|
|
3288
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
3289
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Payment status (DB)" }),
|
|
3290
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: paymentStatusRaw })
|
|
3291
|
-
] }),
|
|
3292
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
3293
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Finalized" }),
|
|
3294
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.payment_id != null ? "Yes" : "No" })
|
|
3295
|
-
] }),
|
|
3296
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
3297
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Created" }),
|
|
3298
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: new Date(detail.created_at).toLocaleDateString("en-US", {
|
|
3299
|
-
year: "numeric",
|
|
3300
|
-
month: "short",
|
|
3301
|
-
day: "numeric",
|
|
3302
|
-
hour: "numeric",
|
|
3303
|
-
minute: "2-digit",
|
|
3304
|
-
hour12: true
|
|
3305
|
-
}) })
|
|
3306
|
-
] })
|
|
3307
|
-
] }) }),
|
|
3308
|
-
Object.keys(detail.data ?? {}).length > 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
3309
|
-
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "text-lg mb-4", children: "Provider data" }),
|
|
3310
|
-
/* @__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) })
|
|
3311
|
-
] }) : /* @__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." }) })
|
|
3312
|
-
] }) : null
|
|
3217
|
+
state.status === "loading" ? /* @__PURE__ */ jsx(DetailSkeleton, {}) : state.status === "error" ? /* @__PURE__ */ jsx(
|
|
3218
|
+
DetailError,
|
|
3219
|
+
{
|
|
3220
|
+
notFound: state.notFound,
|
|
3221
|
+
message: state.message,
|
|
3222
|
+
onRetry: () => setReloadToken((t) => t + 1),
|
|
3223
|
+
onBack: goBack
|
|
3224
|
+
}
|
|
3225
|
+
) : /* @__PURE__ */ jsx(DetailContent, { audit: state.audit })
|
|
3313
3226
|
] }) });
|
|
3314
3227
|
};
|
|
3315
|
-
const
|
|
3316
|
-
label: "Payment details",
|
|
3317
|
-
icon: CreditCard
|
|
3318
|
-
});
|
|
3319
|
-
const getStatusBadgeClass$2 = (status) => {
|
|
3320
|
-
const s2 = status.toLowerCase();
|
|
3321
|
-
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
3322
|
-
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
3323
|
-
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
3324
|
-
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
3325
|
-
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
3326
|
-
};
|
|
3327
|
-
const formatAmount = (value) => {
|
|
3328
|
-
return String(value);
|
|
3329
|
-
};
|
|
3330
|
-
const RefundDetailPage = () => {
|
|
3331
|
-
var _a, _b, _c;
|
|
3228
|
+
const DetailContent = ({ audit }) => {
|
|
3332
3229
|
const navigate = useNavigate();
|
|
3333
|
-
const
|
|
3334
|
-
const
|
|
3335
|
-
const
|
|
3336
|
-
const
|
|
3337
|
-
const
|
|
3338
|
-
const
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3230
|
+
const entity = getEntityInfo(audit.table_name);
|
|
3231
|
+
const source = describeSource(audit.source);
|
|
3232
|
+
const summary = useMemo(() => summarizeOldData(audit.table_name, audit.old_data), [audit]);
|
|
3233
|
+
const masked = useMemo(() => maskSensitiveData(audit.old_data, audit.table_name), [audit]);
|
|
3234
|
+
const guidance = getNextSteps(entity.category.id);
|
|
3235
|
+
const related = getRelatedLinks(audit.table_name, audit.old_data);
|
|
3236
|
+
const [showRaw, setShowRaw] = useState(false);
|
|
3237
|
+
const copyJson = async () => {
|
|
3238
|
+
try {
|
|
3239
|
+
await navigator.clipboard.writeText(JSON.stringify(masked.value, null, 2));
|
|
3240
|
+
toast.success("Record data copied", {
|
|
3241
|
+
description: masked.maskedCount ? "Sensitive values were left hidden." : void 0
|
|
3242
|
+
});
|
|
3243
|
+
} catch {
|
|
3244
|
+
toast.error("Couldn’t copy to clipboard");
|
|
3343
3245
|
}
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
|
|
3354
|
-
}).finally(() => {
|
|
3355
|
-
if (!cancelled) setLoading(false);
|
|
3356
|
-
});
|
|
3357
|
-
return () => {
|
|
3358
|
-
cancelled = true;
|
|
3359
|
-
};
|
|
3360
|
-
}, [id]);
|
|
3361
|
-
const paymentStatus = ((_b = detail == null ? void 0 : detail.payment) == null ? void 0 : _b.status) ?? "—";
|
|
3362
|
-
const hasGatewayData = ((_c = detail == null ? void 0 : detail.payment) == null ? void 0 : _c.payment_data) && typeof detail.payment.payment_data === "object" && Object.keys(detail.payment.payment_data).length > 0;
|
|
3363
|
-
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: [
|
|
3364
|
-
/* @__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: [
|
|
3365
|
-
/* @__PURE__ */ jsx(Button, { variant: "transparent", size: "small", onClick: () => navigate("/refunds"), children: "← Refunds" }),
|
|
3366
|
-
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Refund details" }),
|
|
3367
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle font-mono", children: id ?? "—" })
|
|
3368
|
-
] }) }),
|
|
3369
|
-
error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
3370
|
-
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
3371
|
-
/* @__PURE__ */ jsx(Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/refunds"), children: "Back to list" })
|
|
3372
|
-
] }) : 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: [
|
|
3373
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
3374
|
-
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "text-lg mb-4", children: "Refund summary" }),
|
|
3375
|
-
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
3376
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
3377
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Refund ID" }),
|
|
3378
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.id })
|
|
3379
|
-
] }),
|
|
3380
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
3381
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
|
|
3382
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.refund.amount) })
|
|
3383
|
-
] }),
|
|
3384
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
3385
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Note" }),
|
|
3386
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.refund.note ?? "—" })
|
|
3387
|
-
] }),
|
|
3388
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
3389
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Created at" }),
|
|
3390
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: new Date(detail.refund.created_at).toLocaleDateString("en-US", {
|
|
3391
|
-
year: "numeric",
|
|
3392
|
-
month: "short",
|
|
3393
|
-
day: "numeric",
|
|
3394
|
-
hour: "numeric",
|
|
3395
|
-
minute: "2-digit",
|
|
3396
|
-
hour12: true
|
|
3397
|
-
}) })
|
|
3398
|
-
] }),
|
|
3399
|
-
detail.refund.created_by ? /* @__PURE__ */ jsxs("div", { children: [
|
|
3400
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Created by" }),
|
|
3401
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.created_by })
|
|
3402
|
-
] }) : null
|
|
3403
|
-
] })
|
|
3404
|
-
] }),
|
|
3405
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
3406
|
-
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "text-lg mb-4", children: "Payment summary" }),
|
|
3407
|
-
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
3408
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
3409
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Payment amount" }),
|
|
3410
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.payment.payment_amount) })
|
|
3411
|
-
] }),
|
|
3412
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
3413
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Captured amount" }),
|
|
3414
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.payment.captured_amount) })
|
|
3415
|
-
] }),
|
|
3416
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
3417
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Refunded amount" }),
|
|
3418
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.payment.refunded_amount) })
|
|
3419
|
-
] }),
|
|
3420
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
3421
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
|
|
3422
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.payment.provider_id || "—" })
|
|
3423
|
-
] }),
|
|
3424
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
3425
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
|
|
3426
|
-
/* @__PURE__ */ jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsx(
|
|
3427
|
-
Badge,
|
|
3428
|
-
{
|
|
3429
|
-
size: "2xsmall",
|
|
3430
|
-
className: `uppercase ${getStatusBadgeClass$2(paymentStatus)}`,
|
|
3431
|
-
children: paymentStatus !== "—" ? paymentStatus.replace(/_/g, " ") : "—"
|
|
3432
|
-
}
|
|
3433
|
-
) })
|
|
3434
|
-
] }),
|
|
3435
|
-
detail.computed ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3436
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
3437
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Full refund" }),
|
|
3438
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.computed.is_full_refund ? "Yes" : "No" })
|
|
3439
|
-
] }),
|
|
3440
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
3441
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Remaining refundable" }),
|
|
3442
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.computed.remaining_refundable_amount) })
|
|
3443
|
-
] }),
|
|
3444
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
3445
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Refund %" }),
|
|
3446
|
-
/* @__PURE__ */ jsxs(Text, { className: "mt-1 block", children: [
|
|
3447
|
-
detail.computed.refund_percentage.toFixed(1),
|
|
3448
|
-
"%"
|
|
3449
|
-
] })
|
|
3450
|
-
] })
|
|
3451
|
-
] }) : null
|
|
3452
|
-
] })
|
|
3246
|
+
};
|
|
3247
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3248
|
+
/* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3", children: [
|
|
3249
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
3250
|
+
/* @__PURE__ */ jsxs(Badge, { size: "small", color: "red", children: [
|
|
3251
|
+
/* @__PURE__ */ jsx(Trash, {}),
|
|
3252
|
+
"Deleted"
|
|
3253
|
+
] }),
|
|
3254
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: entity.category.label })
|
|
3453
3255
|
] }),
|
|
3454
|
-
/* @__PURE__ */ jsxs(
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3256
|
+
/* @__PURE__ */ jsxs(Heading, { level: "h1", children: [
|
|
3257
|
+
"Deleted ",
|
|
3258
|
+
entity.label
|
|
3259
|
+
] }),
|
|
3260
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3261
|
+
/* @__PURE__ */ jsx(CopyableId, { value: audit.record_id, emptyLabel: "This record type has no ID column", className: "text-sm" }),
|
|
3262
|
+
/* @__PURE__ */ jsxs(Text, { size: "xsmall", className: "text-ui-fg-muted", children: [
|
|
3263
|
+
"Database table: ",
|
|
3264
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono", children: audit.table_name })
|
|
3265
|
+
] })
|
|
3266
|
+
] })
|
|
3267
|
+
] }),
|
|
3268
|
+
/* @__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: [
|
|
3269
|
+
/* @__PURE__ */ jsx(InformationCircle, { className: "mt-0.5 shrink-0 text-ui-tag-orange-icon" }),
|
|
3270
|
+
/* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-tag-orange-text", children: [
|
|
3271
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: "This is a historical snapshot" }),
|
|
3272
|
+
" captured immediately before deletion. The record no longer exists in the database, so changes elsewhere in the admin are not reflected here."
|
|
3273
|
+
] })
|
|
3274
|
+
] }),
|
|
3275
|
+
/* @__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: [
|
|
3276
|
+
/* @__PURE__ */ jsx(Field, { label: "Deleted", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
3277
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: formatExactDateTime(audit.occurred_at) }),
|
|
3278
|
+
/* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 text-xs text-ui-fg-muted", children: [
|
|
3279
|
+
/* @__PURE__ */ jsx(ClockSolid, { className: "size-3" }),
|
|
3280
|
+
formatRelativeTime(audit.occurred_at)
|
|
3281
|
+
] })
|
|
3282
|
+
] }) }),
|
|
3283
|
+
/* @__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" }) }),
|
|
3284
|
+
/* @__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 }) }),
|
|
3285
|
+
/* @__PURE__ */ jsx(Field, { label: "Action", children: /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Permanently deleted" }) })
|
|
3286
|
+
] }) }),
|
|
3287
|
+
/* @__PURE__ */ jsx(
|
|
3288
|
+
Section,
|
|
3289
|
+
{
|
|
3290
|
+
title: "Record summary",
|
|
3291
|
+
description: `Key details of this ${entity.label.toLowerCase()} at the moment it was deleted.`,
|
|
3292
|
+
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." })
|
|
3293
|
+
}
|
|
3294
|
+
),
|
|
3295
|
+
/* @__PURE__ */ jsx(
|
|
3296
|
+
Section,
|
|
3297
|
+
{
|
|
3298
|
+
title: "Original record data",
|
|
3299
|
+
description: "The complete data captured before deletion.",
|
|
3300
|
+
actions: showRaw && audit.old_data ? /* @__PURE__ */ jsxs(Button, { variant: "secondary", size: "small", onClick: copyJson, children: [
|
|
3301
|
+
/* @__PURE__ */ jsx(SquareTwoStack, {}),
|
|
3302
|
+
"Copy JSON"
|
|
3303
|
+
] }) : null,
|
|
3304
|
+
children: audit.old_data ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
3305
|
+
masked.maskedCount > 0 ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3306
|
+
/* @__PURE__ */ jsx(ShieldCheck, { className: "shrink-0 text-ui-fg-muted" }),
|
|
3307
|
+
/* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
3308
|
+
masked.maskedCount,
|
|
3309
|
+
" sensitive ",
|
|
3310
|
+
masked.maskedCount === 1 ? "value is" : "values are",
|
|
3311
|
+
" hidden for security (passwords, tokens, card or account numbers)."
|
|
3312
|
+
] })
|
|
3480
3313
|
] }) : null,
|
|
3481
|
-
|
|
3482
|
-
/* @__PURE__ */ jsx(
|
|
3483
|
-
|
|
3484
|
-
] })
|
|
3485
|
-
|
|
3314
|
+
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(Button, { variant: "secondary", size: "small", onClick: () => setShowRaw((s2) => !s2), "aria-expanded": showRaw, children: [
|
|
3315
|
+
showRaw ? /* @__PURE__ */ jsx(ChevronDownMini, {}) : /* @__PURE__ */ jsx(ChevronRightMini, {}),
|
|
3316
|
+
showRaw ? "Hide full record" : "View full record"
|
|
3317
|
+
] }) }),
|
|
3318
|
+
showRaw ? /* @__PURE__ */ jsx(JsonViewer, { data: masked.value }) : null
|
|
3319
|
+
] }) : /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "No data was captured for this deletion." })
|
|
3320
|
+
}
|
|
3321
|
+
),
|
|
3322
|
+
/* @__PURE__ */ jsx(Section, { title: "What you can do now", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
3323
|
+
/* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-base", children: [
|
|
3324
|
+
"This record was permanently deleted. ",
|
|
3325
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: "Automatic restoration is not available" }),
|
|
3326
|
+
" ",
|
|
3327
|
+
"from this screen."
|
|
3486
3328
|
] }),
|
|
3487
|
-
/* @__PURE__ */ jsxs("
|
|
3488
|
-
/* @__PURE__ */ jsxs(
|
|
3489
|
-
"
|
|
3329
|
+
/* @__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: [
|
|
3330
|
+
/* @__PURE__ */ jsxs("li", { children: [
|
|
3331
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-ui-fg-base", children: "Check whether this was expected." }),
|
|
3332
|
+
" ",
|
|
3333
|
+
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)}.`,
|
|
3334
|
+
" ",
|
|
3335
|
+
guidance.headline
|
|
3336
|
+
] }),
|
|
3337
|
+
/* @__PURE__ */ jsxs("li", { children: [
|
|
3338
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-ui-fg-base", children: "If it needs to come back:" }),
|
|
3339
|
+
" ",
|
|
3340
|
+
guidance.recreate
|
|
3341
|
+
] }),
|
|
3342
|
+
/* @__PURE__ */ jsxs("li", { children: [
|
|
3343
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-ui-fg-base", children: "Need the details?" }),
|
|
3344
|
+
" Use “View full record” above to see or copy everything that was stored. Sensitive values stay hidden."
|
|
3345
|
+
] })
|
|
3346
|
+
] }),
|
|
3347
|
+
guidance.adminSection || related.length ? /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
3348
|
+
guidance.adminSection ? /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "small", onClick: () => navigate(guidance.adminSection.path), children: guidance.adminSection.label }) : null,
|
|
3349
|
+
related.map((link) => /* @__PURE__ */ jsxs(
|
|
3350
|
+
Button,
|
|
3490
3351
|
{
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
onClick: () =>
|
|
3494
|
-
|
|
3495
|
-
"aria-label": gatewayExpanded ? "Collapse gateway data" : "Expand gateway data",
|
|
3352
|
+
variant: "transparent",
|
|
3353
|
+
size: "small",
|
|
3354
|
+
onClick: () => navigate(link.path),
|
|
3355
|
+
title: `Opens ${link.label.toLowerCase()} ${link.id} if it still exists`,
|
|
3496
3356
|
children: [
|
|
3497
|
-
|
|
3498
|
-
|
|
3357
|
+
"Open related ",
|
|
3358
|
+
link.label.toLowerCase(),
|
|
3359
|
+
/* @__PURE__ */ jsx(ChevronRightMini, {})
|
|
3499
3360
|
]
|
|
3500
|
-
}
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
] })
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
};
|
|
3507
|
-
const config$2 = defineRouteConfig({
|
|
3508
|
-
label: "Refund details",
|
|
3509
|
-
icon: Receipt
|
|
3510
|
-
});
|
|
3511
|
-
const MASKED_VALUE = "••••••••••••";
|
|
3512
|
-
const SENSITIVE_KEY_PATTERNS = [
|
|
3513
|
-
/password|passwd|passphrase/i,
|
|
3514
|
-
/secret/i,
|
|
3515
|
-
/token/i,
|
|
3516
|
-
/api_?key$/i,
|
|
3517
|
-
/private_?key/i,
|
|
3518
|
-
/access_?key/i,
|
|
3519
|
-
/(^|_)hash(ed)?($|_)/i,
|
|
3520
|
-
/(^|_)salt$/i,
|
|
3521
|
-
/^cvv$|^cvc$|security_code/i,
|
|
3522
|
-
/card_?number/i,
|
|
3523
|
-
/account_?number/i,
|
|
3524
|
-
/credential/i,
|
|
3525
|
-
/authorization/i,
|
|
3526
|
-
/recovery_?code/i,
|
|
3527
|
-
/(^|_)otp($|_)/i,
|
|
3528
|
-
/verification_?code/i,
|
|
3529
|
-
/^code_hash$/i,
|
|
3530
|
-
/webhook_?signature/i
|
|
3531
|
-
];
|
|
3532
|
-
const TABLE_SENSITIVE_KEYS = {
|
|
3533
|
-
otp_verification: /* @__PURE__ */ new Set(["code", "value"]),
|
|
3534
|
-
auth_verification: /* @__PURE__ */ new Set(["code", "value"]),
|
|
3535
|
-
auth_mfa_factor: /* @__PURE__ */ new Set(["value", "config"])
|
|
3361
|
+
},
|
|
3362
|
+
link.path
|
|
3363
|
+
))
|
|
3364
|
+
] }) : null,
|
|
3365
|
+
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
|
|
3366
|
+
] }) })
|
|
3367
|
+
] });
|
|
3536
3368
|
};
|
|
3537
|
-
const
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
return SENSITIVE_KEY_PATTERNS.some((pattern) => pattern.test(normalized));
|
|
3548
|
-
}
|
|
3549
|
-
const FULLY_SECRET_TABLES = /* @__PURE__ */ new Set(["auth_mfa_recovery_code", "auth_password_reset_token"]);
|
|
3550
|
-
const ALWAYS_VISIBLE_KEYS = /* @__PURE__ */ new Set(["id", "created_at", "updated_at", "deleted_at", "expires_at", "used_at"]);
|
|
3551
|
-
function maskValue(value, ctx, depth) {
|
|
3552
|
-
var _a;
|
|
3553
|
-
if (Array.isArray(value)) return value.map((item) => maskValue(item, ctx, depth + 1));
|
|
3554
|
-
if (value !== null && typeof value === "object") {
|
|
3555
|
-
const out = {};
|
|
3556
|
-
for (const [key, inner] of Object.entries(value)) {
|
|
3557
|
-
const topLevel = depth === 0;
|
|
3558
|
-
const secret = inner !== null && inner !== void 0 && inner !== "" && (isSensitiveKey(key) || topLevel && ((_a = ctx.tableKeys) == null ? void 0 : _a.has(key.toLowerCase())) === true || topLevel && ctx.maskAll && !ALWAYS_VISIBLE_KEYS.has(key) && !key.endsWith("_id"));
|
|
3559
|
-
if (secret) {
|
|
3560
|
-
ctx.count += 1;
|
|
3561
|
-
out[key] = MASKED_VALUE;
|
|
3562
|
-
} else {
|
|
3563
|
-
out[key] = maskValue(inner, ctx, depth + 1);
|
|
3564
|
-
}
|
|
3565
|
-
}
|
|
3566
|
-
return out;
|
|
3567
|
-
}
|
|
3568
|
-
return value;
|
|
3569
|
-
}
|
|
3570
|
-
function maskSensitiveData(data, tableName) {
|
|
3571
|
-
const ctx = {
|
|
3572
|
-
count: 0,
|
|
3573
|
-
maskAll: tableName ? FULLY_SECRET_TABLES.has(tableName) : false,
|
|
3574
|
-
tableKeys: tableName ? TABLE_SENSITIVE_KEYS[tableName] : void 0
|
|
3575
|
-
};
|
|
3576
|
-
const value = maskValue(data, ctx, 0);
|
|
3577
|
-
return { value, maskedCount: ctx.count };
|
|
3578
|
-
}
|
|
3579
|
-
const AUTO_EXPAND_DEPTH = 1;
|
|
3580
|
-
const LONG_STRING = 200;
|
|
3581
|
-
const JsonViewer = ({ data }) => {
|
|
3582
|
-
const [generation, setGeneration] = useState(0);
|
|
3583
|
-
const [expandAll, setExpandAll] = useState(null);
|
|
3584
|
-
const setAll = (value) => {
|
|
3585
|
-
setExpandAll(value);
|
|
3586
|
-
setGeneration((g) => g + 1);
|
|
3587
|
-
};
|
|
3588
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
3589
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
3590
|
-
/* @__PURE__ */ jsx(Button, { variant: "transparent", size: "small", onClick: () => setAll(true), children: "Expand all" }),
|
|
3591
|
-
/* @__PURE__ */ jsx(Button, { variant: "transparent", size: "small", onClick: () => setAll(false), children: "Collapse all" })
|
|
3369
|
+
const Section = ({
|
|
3370
|
+
title,
|
|
3371
|
+
description,
|
|
3372
|
+
actions,
|
|
3373
|
+
children
|
|
3374
|
+
}) => /* @__PURE__ */ jsxs("section", { className: "flex flex-col gap-4 rounded-lg border border-ui-border-base p-5", children: [
|
|
3375
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-start justify-between gap-2", children: [
|
|
3376
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
3377
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", children: title }),
|
|
3378
|
+
description ? /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: description }) : null
|
|
3592
3379
|
] }),
|
|
3593
|
-
|
|
3594
|
-
] })
|
|
3380
|
+
actions
|
|
3381
|
+
] }),
|
|
3382
|
+
children
|
|
3383
|
+
] });
|
|
3384
|
+
const Field = ({ label, children }) => /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
|
|
3385
|
+
/* @__PURE__ */ jsx("dt", { className: "text-xs font-medium uppercase tracking-wide text-ui-fg-muted", children: label }),
|
|
3386
|
+
/* @__PURE__ */ jsx("dd", { className: "min-w-0", children })
|
|
3387
|
+
] });
|
|
3388
|
+
const DetailSkeleton = () => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", "aria-busy": "true", children: [
|
|
3389
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
3390
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-24 rounded-full" }),
|
|
3391
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-64" }),
|
|
3392
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-48" })
|
|
3393
|
+
] }),
|
|
3394
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-14 w-full" }),
|
|
3395
|
+
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: [
|
|
3396
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-40" }),
|
|
3397
|
+
/* @__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: [
|
|
3398
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-20" }),
|
|
3399
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-36" })
|
|
3400
|
+
] }, j)) })
|
|
3401
|
+
] }, i))
|
|
3402
|
+
] });
|
|
3403
|
+
const DetailError = ({
|
|
3404
|
+
notFound,
|
|
3405
|
+
message,
|
|
3406
|
+
onRetry,
|
|
3407
|
+
onBack
|
|
3408
|
+
}) => /* @__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: [
|
|
3409
|
+
/* @__PURE__ */ jsx(ExclamationCircle, { className: clx(notFound ? "text-ui-fg-muted" : "text-ui-fg-error") }),
|
|
3410
|
+
/* @__PURE__ */ jsx(Heading, { level: "h3", children: notFound ? "Audit entry not found" : "Unable to load this deleted record" }),
|
|
3411
|
+
/* @__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." }),
|
|
3412
|
+
!notFound ? /* @__PURE__ */ jsx(Text, { size: "xsmall", className: "max-w-md font-mono text-ui-fg-muted", children: message }) : null,
|
|
3413
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex gap-2", children: [
|
|
3414
|
+
/* @__PURE__ */ jsx(Button, { variant: "secondary", size: "small", onClick: onBack, children: "Back to Deleted Records" }),
|
|
3415
|
+
!notFound ? /* @__PURE__ */ jsx(Button, { variant: "primary", size: "small", onClick: onRetry, children: "Try again" }) : null
|
|
3416
|
+
] })
|
|
3417
|
+
] });
|
|
3418
|
+
defineRouteConfig({});
|
|
3419
|
+
const useDebounce$1 = (value, delay) => {
|
|
3420
|
+
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
3421
|
+
useEffect(() => {
|
|
3422
|
+
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
3423
|
+
return () => clearTimeout(handler);
|
|
3424
|
+
}, [value, delay]);
|
|
3425
|
+
return debouncedValue;
|
|
3595
3426
|
};
|
|
3596
|
-
const
|
|
3597
|
-
const
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
name,
|
|
3601
|
-
/* @__PURE__ */ jsx("span", { className: "text-ui-fg-muted", children: ": " })
|
|
3602
|
-
] }) : null;
|
|
3603
|
-
if (!isContainer) {
|
|
3604
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-start", style: { paddingLeft: depth ? 16 : 0 }, children: [
|
|
3605
|
-
/* @__PURE__ */ jsx("span", { className: "w-4 shrink-0" }),
|
|
3606
|
-
/* @__PURE__ */ jsxs("span", { className: "min-w-0 break-words [overflow-wrap:anywhere]", children: [
|
|
3607
|
-
label,
|
|
3608
|
-
/* @__PURE__ */ jsx(Primitive, { value })
|
|
3609
|
-
] })
|
|
3610
|
-
] });
|
|
3427
|
+
const getStatusBadgeClass$5 = (status) => {
|
|
3428
|
+
const statusLower = status.toLowerCase();
|
|
3429
|
+
if (statusLower === "requested") {
|
|
3430
|
+
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
3611
3431
|
}
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
const summary = Array.isArray(value) ? `${entries.length} items` : `${entries.length} keys`;
|
|
3615
|
-
return /* @__PURE__ */ jsxs("div", { style: { paddingLeft: depth ? 16 : 0 }, children: [
|
|
3616
|
-
/* @__PURE__ */ jsxs(
|
|
3617
|
-
"button",
|
|
3618
|
-
{
|
|
3619
|
-
type: "button",
|
|
3620
|
-
onClick: () => setOpen((o) => !o),
|
|
3621
|
-
className: "flex items-start text-left hover:bg-ui-bg-base-hover",
|
|
3622
|
-
"aria-expanded": open,
|
|
3623
|
-
children: [
|
|
3624
|
-
/* @__PURE__ */ jsx("span", { className: "flex w-4 shrink-0 items-center pt-0.5 text-ui-fg-muted", children: entries.length ? open ? /* @__PURE__ */ jsx(ChevronDownMini, {}) : /* @__PURE__ */ jsx(ChevronRightMini, {}) : null }),
|
|
3625
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
3626
|
-
label,
|
|
3627
|
-
/* @__PURE__ */ jsx("span", { className: "text-ui-fg-muted", children: openBracket }),
|
|
3628
|
-
!open || entries.length === 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3629
|
-
entries.length ? /* @__PURE__ */ jsx("span", { className: "px-1 italic text-ui-fg-muted", children: summary }) : null,
|
|
3630
|
-
/* @__PURE__ */ jsx("span", { className: "text-ui-fg-muted", children: closeBracket })
|
|
3631
|
-
] }) : null
|
|
3632
|
-
] })
|
|
3633
|
-
]
|
|
3634
|
-
}
|
|
3635
|
-
),
|
|
3636
|
-
open && entries.length ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3637
|
-
entries.map(([key, child]) => /* @__PURE__ */ jsx(JsonNode, { name: key, value: child, depth: depth + 1, forceExpand }, key)),
|
|
3638
|
-
/* @__PURE__ */ jsx("div", { style: { paddingLeft: 16 }, className: "text-ui-fg-muted", children: closeBracket })
|
|
3639
|
-
] }) : null
|
|
3640
|
-
] });
|
|
3641
|
-
};
|
|
3642
|
-
const Primitive = ({ value }) => {
|
|
3643
|
-
const [showFull, setShowFull] = useState(false);
|
|
3644
|
-
if (value === MASKED_VALUE) {
|
|
3645
|
-
return /* @__PURE__ */ jsx("span", { className: "rounded bg-ui-tag-orange-bg px-1 text-ui-tag-orange-text", title: "Hidden for security", children: MASKED_VALUE });
|
|
3432
|
+
if (statusLower === "approved") {
|
|
3433
|
+
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
3646
3434
|
}
|
|
3647
|
-
if (
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
'"',
|
|
3656
|
-
text.length > LONG_STRING ? /* @__PURE__ */ jsx(
|
|
3657
|
-
"button",
|
|
3658
|
-
{
|
|
3659
|
-
type: "button",
|
|
3660
|
-
onClick: () => setShowFull((s2) => !s2),
|
|
3661
|
-
className: "ml-1 font-sans text-ui-fg-interactive hover:underline",
|
|
3662
|
-
children: showFull ? "show less" : `show all (${text.length} chars)`
|
|
3663
|
-
}
|
|
3664
|
-
) : null
|
|
3665
|
-
] });
|
|
3666
|
-
};
|
|
3667
|
-
const GUIDANCE = {
|
|
3668
|
-
orders: {
|
|
3669
|
-
headline: "Order data affects customers, payments and reports.",
|
|
3670
|
-
recreate: "Orders can’t be recreated identically from the admin. If this deletion was not intended, ask a developer to restore it from a database backup using the snapshot on this page.",
|
|
3671
|
-
adminSection: { label: "Go to Orders", path: "/orders" }
|
|
3672
|
-
},
|
|
3673
|
-
carts: {
|
|
3674
|
-
headline: "Carts are usually cleaned up automatically.",
|
|
3675
|
-
recreate: "No action is normally needed. Customers can simply add items to a new cart."
|
|
3676
|
-
},
|
|
3677
|
-
customers: {
|
|
3678
|
-
headline: "Customer data may be needed for orders, support and compliance.",
|
|
3679
|
-
recreate: "If it was deleted by mistake, recreate it from Customers using the values shown above. A recreated customer gets a new ID and must reset their password.",
|
|
3680
|
-
adminSection: { label: "Go to Customers", path: "/customers" }
|
|
3681
|
-
},
|
|
3682
|
-
catalog: {
|
|
3683
|
-
headline: "Catalog changes affect what customers can see and buy.",
|
|
3684
|
-
recreate: "If it was deleted by mistake, recreate it from Products using the values shown above. It will get a new ID.",
|
|
3685
|
-
adminSection: { label: "Go to Products", path: "/products" }
|
|
3686
|
-
},
|
|
3687
|
-
pricing: {
|
|
3688
|
-
headline: "Pricing and promotions affect what customers pay.",
|
|
3689
|
-
recreate: "If it was deleted by mistake, recreate it from Promotions or Price Lists using the values shown above.",
|
|
3690
|
-
adminSection: { label: "Go to Promotions", path: "/promotions" }
|
|
3691
|
-
},
|
|
3692
|
-
payments: {
|
|
3693
|
-
headline: "Payment records are financial data.",
|
|
3694
|
-
recreate: "Do not recreate payment records by hand—this can make balances inconsistent. If this deletion was not expected, escalate to a developer or your finance team."
|
|
3695
|
-
},
|
|
3696
|
-
fulfillment: {
|
|
3697
|
-
headline: "Shipping and fulfillment settings affect checkout and delivery.",
|
|
3698
|
-
recreate: "If it was deleted by mistake, recreate it from Settings → Locations & Shipping using the values shown above.",
|
|
3699
|
-
adminSection: { label: "Go to Settings", path: "/settings" }
|
|
3700
|
-
},
|
|
3701
|
-
inventory: {
|
|
3702
|
-
headline: "Inventory changes can affect stock levels and availability.",
|
|
3703
|
-
recreate: "If it was deleted by mistake, recreate it from Inventory using the values shown above and re-check stock quantities.",
|
|
3704
|
-
adminSection: { label: "Go to Inventory", path: "/inventory" }
|
|
3705
|
-
},
|
|
3706
|
-
wallet: {
|
|
3707
|
-
headline: "Wallet and credit records are financial data.",
|
|
3708
|
-
recreate: "Do not recreate balances by hand. If this deletion was not expected, escalate to a developer or your finance team so balances can be verified."
|
|
3709
|
-
},
|
|
3710
|
-
access: {
|
|
3711
|
-
headline: "Access records control who can sign in.",
|
|
3712
|
-
recreate: "Secrets such as passwords and keys can’t be restored. Re-invite the user or create a new API key if access is still needed.",
|
|
3713
|
-
adminSection: { label: "Go to Settings", path: "/settings" }
|
|
3714
|
-
},
|
|
3715
|
-
store: {
|
|
3716
|
-
headline: "Store settings affect regions, currencies and taxes.",
|
|
3717
|
-
recreate: "If it was deleted by mistake, recreate it from Settings using the values shown above.",
|
|
3718
|
-
adminSection: { label: "Go to Settings", path: "/settings" }
|
|
3719
|
-
},
|
|
3720
|
-
engagement: {
|
|
3721
|
-
headline: "Customer-generated content.",
|
|
3722
|
-
recreate: "These usually can’t be recreated on the customer’s behalf. Keep the snapshot on this page if you need a record of it."
|
|
3723
|
-
},
|
|
3724
|
-
notifications: {
|
|
3725
|
-
headline: "Notification records are usually cleaned up automatically.",
|
|
3726
|
-
recreate: "No action is normally needed."
|
|
3727
|
-
},
|
|
3728
|
-
system: {
|
|
3729
|
-
headline: "Internal system data, usually removed automatically by the platform.",
|
|
3730
|
-
recreate: "No action is normally needed. If you suspect a problem, share this page with a developer."
|
|
3435
|
+
if (statusLower === "rejected") {
|
|
3436
|
+
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
3437
|
+
}
|
|
3438
|
+
if (statusLower === "completed") {
|
|
3439
|
+
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
3440
|
+
}
|
|
3441
|
+
if (statusLower === "cancelled") {
|
|
3442
|
+
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
3731
3443
|
}
|
|
3444
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
3732
3445
|
};
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
const
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
];
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3446
|
+
const SwapsPage = () => {
|
|
3447
|
+
const navigate = useNavigate();
|
|
3448
|
+
const [items, setItems] = useState([]);
|
|
3449
|
+
const [statusFilter, setStatusFilter] = useState("all");
|
|
3450
|
+
const [createdByFilter, setCreatedByFilter] = useState("all");
|
|
3451
|
+
const [searchQuery, setSearchQuery] = useState("");
|
|
3452
|
+
const debouncedSearchQuery = useDebounce$1(searchQuery, 300);
|
|
3453
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
3454
|
+
const [isFetchingMore, setIsFetchingMore] = useState(false);
|
|
3455
|
+
const [error, setError] = useState(null);
|
|
3456
|
+
const [offset, setOffset] = useState(0);
|
|
3457
|
+
const [count, setCount] = useState(0);
|
|
3458
|
+
const limit = 50;
|
|
3459
|
+
const loadSwaps = useCallback(
|
|
3460
|
+
async (nextOffset, replace = false) => {
|
|
3461
|
+
var _a;
|
|
3462
|
+
try {
|
|
3463
|
+
if (replace) {
|
|
3464
|
+
setIsLoading(true);
|
|
3465
|
+
} else {
|
|
3466
|
+
setIsFetchingMore(true);
|
|
3467
|
+
}
|
|
3468
|
+
setError(null);
|
|
3469
|
+
const params = new URLSearchParams();
|
|
3470
|
+
params.set("limit", String(limit));
|
|
3471
|
+
params.set("offset", String(nextOffset));
|
|
3472
|
+
if (statusFilter !== "all") {
|
|
3473
|
+
params.set("status", statusFilter);
|
|
3474
|
+
}
|
|
3475
|
+
if (debouncedSearchQuery.trim()) {
|
|
3476
|
+
params.set("order_id", debouncedSearchQuery.trim());
|
|
3477
|
+
}
|
|
3478
|
+
if (createdByFilter !== "all") {
|
|
3479
|
+
params.set("created_by", createdByFilter);
|
|
3480
|
+
}
|
|
3481
|
+
const response = await fetch(
|
|
3482
|
+
`/admin/swaps?${params.toString()}`,
|
|
3483
|
+
{ credentials: "include" }
|
|
3484
|
+
);
|
|
3485
|
+
if (!response.ok) {
|
|
3486
|
+
const message = await response.text();
|
|
3487
|
+
throw new Error(message || "Unable to load swaps");
|
|
3488
|
+
}
|
|
3489
|
+
const payload = await response.json();
|
|
3490
|
+
setCount(payload.count ?? 0);
|
|
3491
|
+
setOffset(nextOffset + (((_a = payload.swaps) == null ? void 0 : _a.length) ?? 0));
|
|
3492
|
+
setItems(
|
|
3493
|
+
(prev) => replace ? payload.swaps ?? [] : [...prev, ...payload.swaps ?? []]
|
|
3494
|
+
);
|
|
3495
|
+
} catch (loadError) {
|
|
3496
|
+
const message = loadError instanceof Error ? loadError.message : "Unable to load swaps";
|
|
3497
|
+
setError(message);
|
|
3498
|
+
} finally {
|
|
3499
|
+
setIsLoading(false);
|
|
3500
|
+
setIsFetchingMore(false);
|
|
3501
|
+
}
|
|
3502
|
+
},
|
|
3503
|
+
[statusFilter, createdByFilter, debouncedSearchQuery]
|
|
3752
3504
|
);
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
const
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
{
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
]
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
]
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
]
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3505
|
+
useEffect(() => {
|
|
3506
|
+
void loadSwaps(0, true);
|
|
3507
|
+
}, [statusFilter, createdByFilter, debouncedSearchQuery, loadSwaps]);
|
|
3508
|
+
const hasMore = useMemo(() => offset < count, [offset, count]);
|
|
3509
|
+
const availableStatuses = useMemo(() => {
|
|
3510
|
+
const statuses = /* @__PURE__ */ new Set();
|
|
3511
|
+
items.forEach((item) => statuses.add(item.status));
|
|
3512
|
+
return Array.from(statuses).sort();
|
|
3513
|
+
}, [items]);
|
|
3514
|
+
return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
|
|
3515
|
+
/* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
3516
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3517
|
+
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Exchanges" }),
|
|
3518
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "View and manage all customer exchange requests" })
|
|
3519
|
+
] }),
|
|
3520
|
+
/* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () => loadSwaps(0, true), children: "Refresh" })
|
|
3521
|
+
] }),
|
|
3522
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
3523
|
+
/* @__PURE__ */ jsx(
|
|
3524
|
+
Input,
|
|
3525
|
+
{
|
|
3526
|
+
placeholder: "Search by swap ID or order ID",
|
|
3527
|
+
value: searchQuery,
|
|
3528
|
+
onChange: (event) => setSearchQuery(event.target.value),
|
|
3529
|
+
className: "md:max-w-sm"
|
|
3530
|
+
}
|
|
3531
|
+
),
|
|
3532
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
|
|
3533
|
+
/* @__PURE__ */ jsxs(
|
|
3534
|
+
"select",
|
|
3535
|
+
{
|
|
3536
|
+
value: createdByFilter,
|
|
3537
|
+
onChange: (event) => setCreatedByFilter(event.target.value),
|
|
3538
|
+
className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-xs",
|
|
3539
|
+
children: [
|
|
3540
|
+
/* @__PURE__ */ jsx("option", { value: "all", children: "All (Created by)" }),
|
|
3541
|
+
/* @__PURE__ */ jsx("option", { value: "customer", children: "Customer" }),
|
|
3542
|
+
/* @__PURE__ */ jsx("option", { value: "admin", children: "Admin" })
|
|
3543
|
+
]
|
|
3544
|
+
}
|
|
3545
|
+
),
|
|
3546
|
+
/* @__PURE__ */ jsxs(
|
|
3547
|
+
"select",
|
|
3548
|
+
{
|
|
3549
|
+
value: statusFilter,
|
|
3550
|
+
onChange: (event) => setStatusFilter(event.target.value),
|
|
3551
|
+
className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-xs",
|
|
3552
|
+
children: [
|
|
3553
|
+
/* @__PURE__ */ jsx("option", { value: "all", children: "All Statuses" }),
|
|
3554
|
+
availableStatuses.map((status) => /* @__PURE__ */ jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
|
|
3555
|
+
]
|
|
3556
|
+
}
|
|
3557
|
+
)
|
|
3558
|
+
] })
|
|
3559
|
+
] }),
|
|
3560
|
+
error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
3561
|
+
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
3562
|
+
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(
|
|
3563
|
+
Button,
|
|
3564
|
+
{
|
|
3565
|
+
variant: "secondary",
|
|
3566
|
+
onClick: () => loadSwaps(0, true),
|
|
3567
|
+
children: "Try again"
|
|
3568
|
+
}
|
|
3569
|
+
) })
|
|
3570
|
+
] }) : null,
|
|
3571
|
+
isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading swaps..." }) }) : items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
3572
|
+
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No exchanges yet" }),
|
|
3573
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Exchange requests created by customers will appear here." })
|
|
3574
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
3575
|
+
/* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
3576
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Exchange ID" }),
|
|
3577
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
3578
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
3579
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Difference Due" }),
|
|
3580
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
3581
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
3582
|
+
] }) }),
|
|
3583
|
+
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((swap) => /* @__PURE__ */ jsxs(
|
|
3584
|
+
"tr",
|
|
3585
|
+
{
|
|
3586
|
+
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
3587
|
+
onClick: () => navigate(`/swaps/${swap.id}`),
|
|
3588
|
+
children: [
|
|
3589
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children: /* @__PURE__ */ jsx("span", { children: swap.id }) }) }),
|
|
3590
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: swap.order_id }),
|
|
3591
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
|
|
3592
|
+
Badge,
|
|
3593
|
+
{
|
|
3594
|
+
size: "2xsmall",
|
|
3595
|
+
className: `uppercase ${getStatusBadgeClass$5(swap.status)}`,
|
|
3596
|
+
children: swap.status.replace(/_/g, " ")
|
|
3597
|
+
}
|
|
3598
|
+
) }),
|
|
3599
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
|
|
3600
|
+
const amount = swap.difference_due;
|
|
3601
|
+
if (amount == null || amount === void 0) {
|
|
3602
|
+
return "—";
|
|
3603
|
+
}
|
|
3604
|
+
const displayAmount = Number(amount) / 100;
|
|
3605
|
+
const currency = swap.currency_code || "$";
|
|
3606
|
+
const sign = displayAmount >= 0 ? "+" : "";
|
|
3607
|
+
return `${sign}${currency}${displayAmount.toFixed(2)}`;
|
|
3608
|
+
})() }),
|
|
3609
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(swap.created_at).toLocaleDateString("en-US", {
|
|
3610
|
+
year: "numeric",
|
|
3611
|
+
month: "short",
|
|
3612
|
+
day: "numeric",
|
|
3613
|
+
hour: "numeric",
|
|
3614
|
+
minute: "2-digit",
|
|
3615
|
+
hour12: true
|
|
3616
|
+
}) }),
|
|
3617
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
|
|
3618
|
+
Button,
|
|
3619
|
+
{
|
|
3620
|
+
variant: "transparent",
|
|
3621
|
+
size: "small",
|
|
3622
|
+
onClick: (e) => {
|
|
3623
|
+
e.stopPropagation();
|
|
3624
|
+
navigate(`/app/orders/${swap.order_id}`);
|
|
3625
|
+
},
|
|
3626
|
+
children: "Go to order"
|
|
3627
|
+
}
|
|
3628
|
+
) })
|
|
3629
|
+
]
|
|
3630
|
+
},
|
|
3631
|
+
swap.id
|
|
3632
|
+
)) })
|
|
3633
|
+
] }) }),
|
|
3634
|
+
hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
|
|
3635
|
+
Button,
|
|
3636
|
+
{
|
|
3637
|
+
variant: "secondary",
|
|
3638
|
+
isLoading: isFetchingMore,
|
|
3639
|
+
onClick: () => loadSwaps(offset, false),
|
|
3640
|
+
children: "Load more"
|
|
3641
|
+
}
|
|
3642
|
+
) }) : null
|
|
3643
|
+
] }) });
|
|
3644
|
+
};
|
|
3645
|
+
const config$5 = defineRouteConfig({
|
|
3646
|
+
label: "Exchanges",
|
|
3647
|
+
icon: ArrowPath
|
|
3648
|
+
});
|
|
3649
|
+
const useDebounce = (value, delay) => {
|
|
3650
|
+
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
3651
|
+
useEffect(() => {
|
|
3652
|
+
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
3653
|
+
return () => clearTimeout(handler);
|
|
3654
|
+
}, [value, delay]);
|
|
3655
|
+
return debouncedValue;
|
|
3656
|
+
};
|
|
3657
|
+
const getStatusBadgeClass$4 = (status) => {
|
|
3658
|
+
const s2 = status.toLowerCase();
|
|
3659
|
+
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
3660
|
+
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
3661
|
+
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
3662
|
+
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
3663
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
3664
|
+
};
|
|
3665
|
+
const RefundsPage = () => {
|
|
3666
|
+
const navigate = useNavigate();
|
|
3667
|
+
const [items, setItems] = useState([]);
|
|
3668
|
+
const [orderIdSearch, setOrderIdSearch] = useState("");
|
|
3669
|
+
const debouncedOrderId = useDebounce(orderIdSearch, 300);
|
|
3670
|
+
const [paymentStatusFilter, setPaymentStatusFilter] = useState("all");
|
|
3671
|
+
const [providerSearch, setProviderSearch] = useState("");
|
|
3672
|
+
const debouncedProvider = useDebounce(providerSearch, 300);
|
|
3673
|
+
const [currencySearch, setCurrencySearch] = useState("");
|
|
3674
|
+
const debouncedCurrency = useDebounce(currencySearch, 300);
|
|
3675
|
+
const [dateFrom, setDateFrom] = useState("");
|
|
3676
|
+
const [dateTo, setDateTo] = useState("");
|
|
3677
|
+
const [amountMin, setAmountMin] = useState("");
|
|
3678
|
+
const [amountMax, setAmountMax] = useState("");
|
|
3679
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
3680
|
+
const [isFetchingMore, setIsFetchingMore] = useState(false);
|
|
3681
|
+
const [error, setError] = useState(null);
|
|
3682
|
+
const [offset, setOffset] = useState(0);
|
|
3683
|
+
const [count, setCount] = useState(0);
|
|
3684
|
+
const limit = 50;
|
|
3685
|
+
const loadRefunds = useCallback(
|
|
3686
|
+
async (nextOffset, replace) => {
|
|
3687
|
+
try {
|
|
3688
|
+
if (replace) setIsLoading(true);
|
|
3689
|
+
else setIsFetchingMore(true);
|
|
3690
|
+
setError(null);
|
|
3691
|
+
const params = new URLSearchParams();
|
|
3692
|
+
params.set("limit", String(limit));
|
|
3693
|
+
params.set("offset", String(nextOffset));
|
|
3694
|
+
if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
|
|
3695
|
+
if (paymentStatusFilter !== "all") params.set("payment_status", paymentStatusFilter);
|
|
3696
|
+
if (debouncedProvider.trim()) params.set("provider_id", debouncedProvider.trim());
|
|
3697
|
+
if (debouncedCurrency.trim()) params.set("currency_code", debouncedCurrency.trim());
|
|
3698
|
+
if (dateFrom.trim()) params.set("date_from", dateFrom.trim());
|
|
3699
|
+
if (dateTo.trim()) params.set("date_to", dateTo.trim());
|
|
3700
|
+
const min = amountMin.trim() ? Number(amountMin) : void 0;
|
|
3701
|
+
const max = amountMax.trim() ? Number(amountMax) : void 0;
|
|
3702
|
+
if (min != null && !Number.isNaN(min)) params.set("amount_min", String(min));
|
|
3703
|
+
if (max != null && !Number.isNaN(max)) params.set("amount_max", String(max));
|
|
3704
|
+
const response = await fetch(`/admin/refunds?${params.toString()}`, {
|
|
3705
|
+
credentials: "include"
|
|
3706
|
+
});
|
|
3707
|
+
if (!response.ok) {
|
|
3708
|
+
const text = await response.text();
|
|
3709
|
+
throw new Error(text || "Failed to load refunds");
|
|
3710
|
+
}
|
|
3711
|
+
const payload = await response.json();
|
|
3712
|
+
const list = payload.refunds ?? [];
|
|
3713
|
+
setCount(payload.count ?? 0);
|
|
3714
|
+
setOffset(nextOffset + list.length);
|
|
3715
|
+
setItems((prev) => replace ? list : [...prev, ...list]);
|
|
3716
|
+
} catch (e) {
|
|
3717
|
+
setError(e instanceof Error ? e.message : "Failed to load");
|
|
3718
|
+
} finally {
|
|
3719
|
+
setIsLoading(false);
|
|
3720
|
+
setIsFetchingMore(false);
|
|
3721
|
+
}
|
|
3722
|
+
},
|
|
3723
|
+
[
|
|
3724
|
+
debouncedOrderId,
|
|
3725
|
+
paymentStatusFilter,
|
|
3726
|
+
debouncedProvider,
|
|
3727
|
+
debouncedCurrency,
|
|
3728
|
+
dateFrom,
|
|
3729
|
+
dateTo,
|
|
3730
|
+
amountMin,
|
|
3731
|
+
amountMax
|
|
3732
|
+
]
|
|
3733
|
+
);
|
|
3734
|
+
useEffect(() => {
|
|
3735
|
+
void loadRefunds(0, true);
|
|
3736
|
+
}, [loadRefunds]);
|
|
3737
|
+
const hasMore = useMemo(() => offset < count, [offset, count]);
|
|
3738
|
+
const displayAmount = (r) => {
|
|
3739
|
+
const code = (r.currency_code ?? "USD").toUpperCase();
|
|
3740
|
+
return `${code} ${Number(r.amount)}`;
|
|
3741
|
+
};
|
|
3742
|
+
const displayStatus = (r) => {
|
|
3743
|
+
const s2 = r.payment_status ?? "";
|
|
3744
|
+
return s2 !== "" ? s2 : "—";
|
|
3745
|
+
};
|
|
3746
|
+
return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
|
|
3747
|
+
/* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
3748
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3749
|
+
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Refunds" }),
|
|
3750
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Refund records — amount, order, payment status" })
|
|
3751
|
+
] }),
|
|
3752
|
+
/* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () => loadRefunds(0, true), children: "Refresh" })
|
|
3753
|
+
] }),
|
|
3754
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
3755
|
+
/* @__PURE__ */ jsx(
|
|
3756
|
+
Input,
|
|
3757
|
+
{
|
|
3758
|
+
placeholder: "Order ID",
|
|
3759
|
+
value: orderIdSearch,
|
|
3760
|
+
onChange: (e) => setOrderIdSearch(e.target.value),
|
|
3761
|
+
className: "md:max-w-[180px]",
|
|
3762
|
+
"aria-label": "Filter by order ID"
|
|
3763
|
+
}
|
|
3764
|
+
),
|
|
3765
|
+
/* @__PURE__ */ jsx(
|
|
3766
|
+
Input,
|
|
3767
|
+
{
|
|
3768
|
+
placeholder: "Provider",
|
|
3769
|
+
value: providerSearch,
|
|
3770
|
+
onChange: (e) => setProviderSearch(e.target.value),
|
|
3771
|
+
className: "md:max-w-[140px]",
|
|
3772
|
+
"aria-label": "Filter by provider"
|
|
3773
|
+
}
|
|
3774
|
+
),
|
|
3775
|
+
/* @__PURE__ */ jsx(
|
|
3776
|
+
Input,
|
|
3777
|
+
{
|
|
3778
|
+
placeholder: "Currency",
|
|
3779
|
+
value: currencySearch,
|
|
3780
|
+
onChange: (e) => setCurrencySearch(e.target.value),
|
|
3781
|
+
className: "md:max-w-[100px]",
|
|
3782
|
+
"aria-label": "Filter by currency"
|
|
3783
|
+
}
|
|
3784
|
+
),
|
|
3785
|
+
/* @__PURE__ */ jsxs(
|
|
3786
|
+
"select",
|
|
3787
|
+
{
|
|
3788
|
+
value: paymentStatusFilter,
|
|
3789
|
+
onChange: (e) => setPaymentStatusFilter(e.target.value),
|
|
3790
|
+
className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-[160px]",
|
|
3791
|
+
"aria-label": "Filter by payment status",
|
|
3792
|
+
children: [
|
|
3793
|
+
/* @__PURE__ */ jsx("option", { value: "all", children: "All statuses" }),
|
|
3794
|
+
/* @__PURE__ */ jsx("option", { value: "pending", children: "Pending" }),
|
|
3795
|
+
/* @__PURE__ */ jsx("option", { value: "requires_more", children: "Requires more" }),
|
|
3796
|
+
/* @__PURE__ */ jsx("option", { value: "error", children: "Error" }),
|
|
3797
|
+
/* @__PURE__ */ jsx("option", { value: "canceled", children: "Canceled" }),
|
|
3798
|
+
/* @__PURE__ */ jsx("option", { value: "authorized", children: "Authorized" }),
|
|
3799
|
+
/* @__PURE__ */ jsx("option", { value: "captured", children: "Captured" })
|
|
3800
|
+
]
|
|
3801
|
+
}
|
|
3802
|
+
),
|
|
3803
|
+
/* @__PURE__ */ jsx(
|
|
3804
|
+
Input,
|
|
3805
|
+
{
|
|
3806
|
+
type: "date",
|
|
3807
|
+
placeholder: "From",
|
|
3808
|
+
value: dateFrom,
|
|
3809
|
+
onChange: (e) => setDateFrom(e.target.value),
|
|
3810
|
+
className: "md:max-w-[140px]",
|
|
3811
|
+
"aria-label": "Date from"
|
|
3812
|
+
}
|
|
3813
|
+
),
|
|
3814
|
+
/* @__PURE__ */ jsx(
|
|
3815
|
+
Input,
|
|
3816
|
+
{
|
|
3817
|
+
type: "date",
|
|
3818
|
+
placeholder: "To",
|
|
3819
|
+
value: dateTo,
|
|
3820
|
+
onChange: (e) => setDateTo(e.target.value),
|
|
3821
|
+
className: "md:max-w-[140px]",
|
|
3822
|
+
"aria-label": "Date to"
|
|
3823
|
+
}
|
|
3824
|
+
),
|
|
3825
|
+
/* @__PURE__ */ jsx(
|
|
3826
|
+
Input,
|
|
3827
|
+
{
|
|
3828
|
+
placeholder: "Amount min",
|
|
3829
|
+
value: amountMin,
|
|
3830
|
+
onChange: (e) => setAmountMin(e.target.value),
|
|
3831
|
+
type: "number",
|
|
3832
|
+
min: 0,
|
|
3833
|
+
className: "md:max-w-[100px]",
|
|
3834
|
+
"aria-label": "Refund amount minimum"
|
|
3835
|
+
}
|
|
3836
|
+
),
|
|
3837
|
+
/* @__PURE__ */ jsx(
|
|
3838
|
+
Input,
|
|
3839
|
+
{
|
|
3840
|
+
placeholder: "Amount max",
|
|
3841
|
+
value: amountMax,
|
|
3842
|
+
onChange: (e) => setAmountMax(e.target.value),
|
|
3843
|
+
type: "number",
|
|
3844
|
+
min: 0,
|
|
3845
|
+
className: "md:max-w-[100px]",
|
|
3846
|
+
"aria-label": "Refund amount maximum"
|
|
3847
|
+
}
|
|
3848
|
+
)
|
|
3849
|
+
] }) }),
|
|
3850
|
+
error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
3851
|
+
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
3852
|
+
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => loadRefunds(0, true), children: "Try again" }) })
|
|
3853
|
+
] }) : null,
|
|
3854
|
+
isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading refunds…" }) }) : items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
3855
|
+
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No refunds yet" }),
|
|
3856
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Refund records will appear here." })
|
|
3857
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "w-full overflow-x-auto rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "w-full table-fixed divide-y divide-ui-border-base", style: { minWidth: 0 }, children: [
|
|
3858
|
+
/* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
3859
|
+
/* @__PURE__ */ jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Refund ID" }),
|
|
3860
|
+
/* @__PURE__ */ jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
3861
|
+
/* @__PURE__ */ jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Payment ID" }),
|
|
3862
|
+
/* @__PURE__ */ jsx("th", { className: "w-[8%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Amount" }),
|
|
3863
|
+
/* @__PURE__ */ jsx("th", { className: "w-[6%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Currency" }),
|
|
3864
|
+
/* @__PURE__ */ jsx("th", { className: "w-[10%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Provider" }),
|
|
3865
|
+
/* @__PURE__ */ jsx("th", { className: "w-[10%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Payment Status" }),
|
|
3866
|
+
/* @__PURE__ */ jsx("th", { className: "w-[14%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Note" }),
|
|
3867
|
+
/* @__PURE__ */ jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
3868
|
+
/* @__PURE__ */ jsx("th", { className: "w-[8%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
3869
|
+
] }) }),
|
|
3870
|
+
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((r) => /* @__PURE__ */ jsxs(
|
|
3871
|
+
"tr",
|
|
3872
|
+
{
|
|
3873
|
+
className: "cursor-pointer hover:bg-ui-bg-subtle/60",
|
|
3874
|
+
onClick: () => navigate(`/refunds/${r.refund_id}`),
|
|
3875
|
+
children: [
|
|
3876
|
+
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 font-mono text-sm text-ui-fg-base", title: r.refund_id, children: r.refund_id }),
|
|
3877
|
+
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 font-medium text-ui-fg-base", title: r.order_id ?? void 0, children: r.order_id ?? "—" }),
|
|
3878
|
+
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 font-mono text-sm text-ui-fg-subtle", title: r.payment_id, children: r.payment_id }),
|
|
3879
|
+
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", children: displayAmount(r) }),
|
|
3880
|
+
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle uppercase", children: r.currency_code || "—" }),
|
|
3881
|
+
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", title: r.provider_id || void 0, children: r.provider_id || "—" }),
|
|
3882
|
+
/* @__PURE__ */ jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsx(
|
|
3883
|
+
Badge,
|
|
3884
|
+
{
|
|
3885
|
+
size: "2xsmall",
|
|
3886
|
+
className: `uppercase ${getStatusBadgeClass$4(displayStatus(r))}`,
|
|
3887
|
+
children: displayStatus(r) !== "—" ? displayStatus(r).replace(/_/g, " ") : "—"
|
|
3888
|
+
}
|
|
3889
|
+
) }),
|
|
3890
|
+
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", title: r.note ?? void 0, children: r.note ?? "—" }),
|
|
3891
|
+
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle text-xs", children: new Date(r.created_at).toLocaleDateString("en-US", {
|
|
3892
|
+
month: "short",
|
|
3893
|
+
day: "numeric",
|
|
3894
|
+
hour: "numeric",
|
|
3895
|
+
minute: "2-digit",
|
|
3896
|
+
hour12: true
|
|
3897
|
+
}) }),
|
|
3898
|
+
/* @__PURE__ */ jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1", children: [
|
|
3899
|
+
/* @__PURE__ */ jsx(
|
|
3900
|
+
Button,
|
|
3901
|
+
{
|
|
3902
|
+
variant: "transparent",
|
|
3903
|
+
size: "small",
|
|
3904
|
+
onClick: (e) => {
|
|
3905
|
+
e.stopPropagation();
|
|
3906
|
+
navigate(`/refunds/${r.refund_id}`);
|
|
3907
|
+
},
|
|
3908
|
+
children: "Details"
|
|
3909
|
+
}
|
|
3910
|
+
),
|
|
3911
|
+
r.order_id ? /* @__PURE__ */ jsx(
|
|
3912
|
+
Button,
|
|
3913
|
+
{
|
|
3914
|
+
variant: "transparent",
|
|
3915
|
+
size: "small",
|
|
3916
|
+
onClick: (e) => {
|
|
3917
|
+
e.stopPropagation();
|
|
3918
|
+
navigate(`/orders/${r.order_id}`);
|
|
3919
|
+
},
|
|
3920
|
+
children: "Order"
|
|
3921
|
+
}
|
|
3922
|
+
) : null
|
|
3923
|
+
] }) })
|
|
3924
|
+
]
|
|
3925
|
+
},
|
|
3926
|
+
r.refund_id
|
|
3927
|
+
)) })
|
|
3928
|
+
] }) }),
|
|
3929
|
+
hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
|
|
3930
|
+
Button,
|
|
3931
|
+
{
|
|
3932
|
+
variant: "secondary",
|
|
3933
|
+
isLoading: isFetchingMore,
|
|
3934
|
+
onClick: () => loadRefunds(offset, false),
|
|
3935
|
+
children: "Load more"
|
|
3936
|
+
}
|
|
3937
|
+
) }) : null
|
|
3938
|
+
] }) });
|
|
3939
3939
|
};
|
|
3940
|
-
const
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3940
|
+
const config$4 = defineRouteConfig({
|
|
3941
|
+
label: "Refunds",
|
|
3942
|
+
icon: Receipt
|
|
3943
|
+
});
|
|
3944
|
+
const getStatusBadgeClass$3 = (status) => {
|
|
3945
|
+
const s2 = status.toLowerCase();
|
|
3946
|
+
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
3947
|
+
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
3948
|
+
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
3949
|
+
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
3950
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
3951
|
+
};
|
|
3952
|
+
const PaymentDetailPage = () => {
|
|
3953
|
+
var _a;
|
|
3954
|
+
const navigate = useNavigate();
|
|
3955
|
+
const params = useParams();
|
|
3956
|
+
const id = (_a = params == null ? void 0 : params.id) == null ? void 0 : _a.trim();
|
|
3957
|
+
const [detail, setDetail] = useState(null);
|
|
3958
|
+
const [loading, setLoading] = useState(!!id);
|
|
3959
|
+
const [error, setError] = useState(null);
|
|
3960
|
+
useEffect(() => {
|
|
3961
|
+
if (!id) {
|
|
3962
|
+
setLoading(false);
|
|
3963
|
+
return;
|
|
3964
|
+
}
|
|
3965
|
+
let cancelled = false;
|
|
3966
|
+
setLoading(true);
|
|
3967
|
+
setError(null);
|
|
3968
|
+
fetch(`/admin/payment-transactions/${id}`, { credentials: "include" }).then((res) => {
|
|
3969
|
+
if (!res.ok) throw new Error(res.statusText || "Failed to load");
|
|
3970
|
+
return res.json();
|
|
3971
|
+
}).then((data) => {
|
|
3972
|
+
if (!cancelled) setDetail(data);
|
|
3973
|
+
}).catch((e) => {
|
|
3974
|
+
if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
|
|
3975
|
+
}).finally(() => {
|
|
3976
|
+
if (!cancelled) setLoading(false);
|
|
3977
|
+
});
|
|
3978
|
+
return () => {
|
|
3979
|
+
cancelled = true;
|
|
3980
|
+
};
|
|
3981
|
+
}, [id]);
|
|
3982
|
+
const displayStatus = detail ? (detail.payment_id != null && detail.payment_status != null && detail.payment_status !== "" ? detail.payment_status : detail.session_status ?? "") || "—" : "";
|
|
3983
|
+
const sessionStatusRaw = (detail == null ? void 0 : detail.session_status) ?? "—";
|
|
3984
|
+
const paymentStatusRaw = (detail == null ? void 0 : detail.payment_id) != null ? (detail == null ? void 0 : detail.payment_status) ?? "—" : "—";
|
|
3985
|
+
const displayAmount = detail ? `${(detail.currency_code ?? "USD").toUpperCase()} ${Number(detail.amount)}` : "";
|
|
3986
|
+
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: [
|
|
3987
|
+
/* @__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: [
|
|
3988
|
+
/* @__PURE__ */ jsx(Button, { variant: "transparent", size: "small", onClick: () => navigate("/payments"), children: "← Payments" }),
|
|
3989
|
+
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Payment session" }),
|
|
3990
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: id ?? "—" })
|
|
3991
|
+
] }) }),
|
|
3992
|
+
error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
3993
|
+
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
3994
|
+
/* @__PURE__ */ jsx(Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/payments"), children: "Back to list" })
|
|
3995
|
+
] }) : 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: [
|
|
3996
|
+
/* @__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: [
|
|
3997
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
3998
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Order ID" }),
|
|
3999
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1", children: detail.order_id ? /* @__PURE__ */ jsx(
|
|
4000
|
+
Button,
|
|
4001
|
+
{
|
|
4002
|
+
variant: "transparent",
|
|
4003
|
+
size: "small",
|
|
4004
|
+
onClick: () => navigate(`/orders/${detail.order_id}`),
|
|
4005
|
+
children: detail.order_id
|
|
4006
|
+
}
|
|
4007
|
+
) : /* @__PURE__ */ jsx(Text, { children: "—" }) })
|
|
4008
|
+
] }),
|
|
4009
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4010
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
|
|
4011
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: displayAmount })
|
|
4012
|
+
] }),
|
|
4013
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4014
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
|
|
4015
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.provider_id })
|
|
4016
|
+
] }),
|
|
4017
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4018
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
|
|
4019
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsx(
|
|
4020
|
+
Badge,
|
|
4021
|
+
{
|
|
4022
|
+
size: "2xsmall",
|
|
4023
|
+
className: `uppercase ${getStatusBadgeClass$3(displayStatus)}`,
|
|
4024
|
+
children: displayStatus !== "—" ? displayStatus.replace(/_/g, " ") : "—"
|
|
4025
|
+
}
|
|
4026
|
+
) })
|
|
4027
|
+
] }),
|
|
4028
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4029
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Session status (DB)" }),
|
|
4030
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: sessionStatusRaw })
|
|
4031
|
+
] }),
|
|
4032
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4033
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Payment status (DB)" }),
|
|
4034
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: paymentStatusRaw })
|
|
4035
|
+
] }),
|
|
4036
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4037
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Finalized" }),
|
|
4038
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.payment_id != null ? "Yes" : "No" })
|
|
4039
|
+
] }),
|
|
4040
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4041
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Created" }),
|
|
4042
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: new Date(detail.created_at).toLocaleDateString("en-US", {
|
|
4043
|
+
year: "numeric",
|
|
4044
|
+
month: "short",
|
|
4045
|
+
day: "numeric",
|
|
4046
|
+
hour: "numeric",
|
|
4047
|
+
minute: "2-digit",
|
|
4048
|
+
hour12: true
|
|
4049
|
+
}) })
|
|
4050
|
+
] })
|
|
4051
|
+
] }) }),
|
|
4052
|
+
Object.keys(detail.data ?? {}).length > 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4053
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "text-lg mb-4", children: "Provider data" }),
|
|
4054
|
+
/* @__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) })
|
|
4055
|
+
] }) : /* @__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." }) })
|
|
4056
|
+
] }) : null
|
|
4057
|
+
] }) });
|
|
4058
|
+
};
|
|
4059
|
+
const config$3 = defineRouteConfig({
|
|
4060
|
+
label: "Payment details",
|
|
4061
|
+
icon: CreditCard
|
|
4062
|
+
});
|
|
4063
|
+
const getStatusBadgeClass$2 = (status) => {
|
|
4064
|
+
const statusLower = status.toLowerCase();
|
|
4065
|
+
if (statusLower === "requested") {
|
|
4066
|
+
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
3969
4067
|
}
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
function formatValue(raw, kind, row) {
|
|
3973
|
-
if (raw === null || raw === void 0 || raw === "") return null;
|
|
3974
|
-
if (raw === MASKED_VALUE) return { value: MASKED_VALUE, kind: "masked" };
|
|
3975
|
-
switch (kind) {
|
|
3976
|
-
case "money": {
|
|
3977
|
-
const amount = amountOf(raw);
|
|
3978
|
-
if (amount === null) return null;
|
|
3979
|
-
const currency = typeof row.currency_code === "string" ? row.currency_code : null;
|
|
3980
|
-
return { value: formatMoney(amount, currency), kind };
|
|
3981
|
-
}
|
|
3982
|
-
case "date":
|
|
3983
|
-
return typeof raw === "string" || raw instanceof Date ? { value: formatDate(raw), kind } : null;
|
|
3984
|
-
case "boolean":
|
|
3985
|
-
return { value: raw === true || raw === "true" ? "Yes" : "No", kind };
|
|
3986
|
-
case "number": {
|
|
3987
|
-
const n = amountOf(raw);
|
|
3988
|
-
return n === null ? null : { value: formatNumber(n), kind };
|
|
3989
|
-
}
|
|
3990
|
-
case "status":
|
|
3991
|
-
return { value: String(raw).replace(/_/g, " "), kind };
|
|
3992
|
-
default:
|
|
3993
|
-
if (typeof raw === "object") return null;
|
|
3994
|
-
if (typeof raw === "string" && raw.length > 160) return { value: `${raw.slice(0, 157)}…`, kind };
|
|
3995
|
-
return { value: String(raw), kind };
|
|
4068
|
+
if (statusLower === "approved") {
|
|
4069
|
+
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
3996
4070
|
}
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
if (!oldData) return [];
|
|
4000
|
-
const { value: row } = maskSensitiveData(oldData, tableName);
|
|
4001
|
-
const specific = ENTITY_FIELDS[tableName];
|
|
4002
|
-
const specs = specific ?? GENERIC_FIELDS;
|
|
4003
|
-
const fields = [];
|
|
4004
|
-
const seenLabels = /* @__PURE__ */ new Set();
|
|
4005
|
-
for (const spec of specs) {
|
|
4006
|
-
const raw = spec.derive ? spec.derive(row) : row[spec.key];
|
|
4007
|
-
const formatted = formatValue(raw, spec.kind ?? "text", row);
|
|
4008
|
-
if (!formatted || seenLabels.has(spec.label)) continue;
|
|
4009
|
-
seenLabels.add(spec.label);
|
|
4010
|
-
const value = spec.key === "currency_code" ? formatted.value.toUpperCase() : formatted.value;
|
|
4011
|
-
fields.push({ key: spec.key, label: spec.label, value, kind: formatted.kind });
|
|
4012
|
-
if (!specific && fields.length >= MAX_GENERIC_FIELDS) break;
|
|
4071
|
+
if (statusLower === "rejected") {
|
|
4072
|
+
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
4013
4073
|
}
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
function readLastListSearch() {
|
|
4017
|
-
try {
|
|
4018
|
-
return window.sessionStorage.getItem(LAST_LIST_URL_KEY) ?? "";
|
|
4019
|
-
} catch {
|
|
4020
|
-
return "";
|
|
4074
|
+
if (statusLower === "completed") {
|
|
4075
|
+
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
4021
4076
|
}
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4077
|
+
if (statusLower === "cancelled" || statusLower === "canceled") {
|
|
4078
|
+
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
4079
|
+
}
|
|
4080
|
+
if (statusLower === "pending") {
|
|
4081
|
+
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
4082
|
+
}
|
|
4083
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
4084
|
+
};
|
|
4085
|
+
const SwapDetailPage = () => {
|
|
4086
|
+
var _a, _b, _c;
|
|
4025
4087
|
const navigate = useNavigate();
|
|
4026
|
-
const
|
|
4027
|
-
const
|
|
4028
|
-
const [
|
|
4029
|
-
const [
|
|
4030
|
-
|
|
4031
|
-
const
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4088
|
+
const { id } = useParams();
|
|
4089
|
+
const [swap, setSwap] = useState(null);
|
|
4090
|
+
const [order, setOrder] = useState(null);
|
|
4091
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
4092
|
+
useState(false);
|
|
4093
|
+
const [isCancelling, setIsCancelling] = useState(false);
|
|
4094
|
+
const [error, setError] = useState(null);
|
|
4095
|
+
const [updateError, setUpdateError] = useState(null);
|
|
4096
|
+
const [updateSuccess, setUpdateSuccess] = useState(false);
|
|
4035
4097
|
useEffect(() => {
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
onBack: goBack
|
|
4098
|
+
if (!id) {
|
|
4099
|
+
navigate("/swaps");
|
|
4100
|
+
return;
|
|
4101
|
+
}
|
|
4102
|
+
const loadSwap = async () => {
|
|
4103
|
+
try {
|
|
4104
|
+
setIsLoading(true);
|
|
4105
|
+
setError(null);
|
|
4106
|
+
const response = await fetch(`/admin/swaps/${id}`, {
|
|
4107
|
+
credentials: "include"
|
|
4108
|
+
});
|
|
4109
|
+
if (!response.ok) {
|
|
4110
|
+
const message = await response.text();
|
|
4111
|
+
throw new Error(message || "Unable to load swap");
|
|
4112
|
+
}
|
|
4113
|
+
const payload = await response.json();
|
|
4114
|
+
setSwap(payload.swap);
|
|
4115
|
+
setOrder(payload.order || null);
|
|
4116
|
+
} catch (loadError) {
|
|
4117
|
+
const message = loadError instanceof Error ? loadError.message : "Unable to load swap";
|
|
4118
|
+
setError(message);
|
|
4119
|
+
} finally {
|
|
4120
|
+
setIsLoading(false);
|
|
4060
4121
|
}
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
};
|
|
4064
|
-
const
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
const summary = useMemo(() => summarizeOldData(audit.table_name, audit.old_data), [audit]);
|
|
4069
|
-
const masked = useMemo(() => maskSensitiveData(audit.old_data, audit.table_name), [audit]);
|
|
4070
|
-
const guidance = getNextSteps(entity.category.id);
|
|
4071
|
-
const related = getRelatedLinks(audit.table_name, audit.old_data);
|
|
4072
|
-
const [showRaw, setShowRaw] = useState(false);
|
|
4073
|
-
const copyJson = async () => {
|
|
4122
|
+
};
|
|
4123
|
+
void loadSwap();
|
|
4124
|
+
}, [id, navigate]);
|
|
4125
|
+
const handleCancelExchange = async () => {
|
|
4126
|
+
if (!id) {
|
|
4127
|
+
return;
|
|
4128
|
+
}
|
|
4074
4129
|
try {
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4130
|
+
setIsCancelling(true);
|
|
4131
|
+
setUpdateError(null);
|
|
4132
|
+
setUpdateSuccess(false);
|
|
4133
|
+
const response = await fetch(`/admin/swaps/${id}/cancel`, {
|
|
4134
|
+
method: "POST",
|
|
4135
|
+
headers: {
|
|
4136
|
+
"Content-Type": "application/json"
|
|
4137
|
+
},
|
|
4138
|
+
credentials: "include"
|
|
4078
4139
|
});
|
|
4079
|
-
|
|
4080
|
-
|
|
4140
|
+
if (!response.ok) {
|
|
4141
|
+
const message = await response.text();
|
|
4142
|
+
throw new Error(message || "Unable to cancel exchange");
|
|
4143
|
+
}
|
|
4144
|
+
const payload = await response.json();
|
|
4145
|
+
setSwap(payload.swap);
|
|
4146
|
+
setUpdateSuccess(true);
|
|
4147
|
+
setTimeout(() => setUpdateSuccess(false), 3e3);
|
|
4148
|
+
const detailResponse = await fetch(`/admin/swaps/${id}`, {
|
|
4149
|
+
credentials: "include"
|
|
4150
|
+
});
|
|
4151
|
+
if (detailResponse.ok) {
|
|
4152
|
+
const detailPayload = await detailResponse.json();
|
|
4153
|
+
setSwap(detailPayload.swap);
|
|
4154
|
+
setOrder(detailPayload.order || null);
|
|
4155
|
+
}
|
|
4156
|
+
} catch (cancelErr) {
|
|
4157
|
+
const message = cancelErr instanceof Error ? cancelErr.message : "Unable to cancel exchange";
|
|
4158
|
+
setUpdateError(message);
|
|
4159
|
+
} finally {
|
|
4160
|
+
setIsCancelling(false);
|
|
4081
4161
|
}
|
|
4082
4162
|
};
|
|
4083
|
-
|
|
4163
|
+
const isOrderExchange = Boolean(swap == null ? void 0 : swap.exchange_id);
|
|
4164
|
+
const canCancelExchange = isOrderExchange && swap && !["cancelled", "canceled", "completed", "declined"].includes(
|
|
4165
|
+
((_a = swap.status) == null ? void 0 : _a.toLowerCase()) ?? ""
|
|
4166
|
+
);
|
|
4167
|
+
if (isLoading) {
|
|
4168
|
+
return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsx(Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading swap..." }) }) }) });
|
|
4169
|
+
}
|
|
4170
|
+
if (error || !swap) {
|
|
4171
|
+
return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsx(Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
4172
|
+
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error || "Swap not found" }),
|
|
4173
|
+
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => navigate("/swaps"), children: "Back to list" }) })
|
|
4174
|
+
] }) }) });
|
|
4175
|
+
}
|
|
4176
|
+
const statusHistory = ((_b = swap.metadata) == null ? void 0 : _b.status_history) || [];
|
|
4177
|
+
return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: [
|
|
4084
4178
|
/* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3", children: [
|
|
4085
|
-
/* @__PURE__ */ jsxs(
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
"
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
/* @__PURE__ */ jsx(
|
|
4101
|
-
|
|
4179
|
+
/* @__PURE__ */ jsxs(
|
|
4180
|
+
Button,
|
|
4181
|
+
{
|
|
4182
|
+
variant: "transparent",
|
|
4183
|
+
size: "small",
|
|
4184
|
+
onClick: () => navigate("/swaps"),
|
|
4185
|
+
className: "w-fit",
|
|
4186
|
+
children: [
|
|
4187
|
+
/* @__PURE__ */ jsx(ArrowLeft, { className: "mr-2" }),
|
|
4188
|
+
"Back to list"
|
|
4189
|
+
]
|
|
4190
|
+
}
|
|
4191
|
+
),
|
|
4192
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 md:flex-row md:items-center md:justify-between", children: [
|
|
4193
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
4194
|
+
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Exchange Details" }),
|
|
4195
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: swap.id })
|
|
4196
|
+
] }),
|
|
4197
|
+
/* @__PURE__ */ jsx(
|
|
4198
|
+
Badge,
|
|
4199
|
+
{
|
|
4200
|
+
size: "small",
|
|
4201
|
+
className: `uppercase ${getStatusBadgeClass$2(swap.status)}`,
|
|
4202
|
+
children: swap.status.replace(/_/g, " ")
|
|
4203
|
+
}
|
|
4204
|
+
)
|
|
4102
4205
|
] })
|
|
4103
4206
|
] }),
|
|
4104
|
-
/* @__PURE__ */ jsxs("div", { className: "flex
|
|
4105
|
-
/* @__PURE__ */ jsx(
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4207
|
+
canCancelExchange && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
4208
|
+
/* @__PURE__ */ jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsx(
|
|
4209
|
+
Button,
|
|
4210
|
+
{
|
|
4211
|
+
variant: "danger",
|
|
4212
|
+
onClick: handleCancelExchange,
|
|
4213
|
+
disabled: isCancelling,
|
|
4214
|
+
isLoading: isCancelling,
|
|
4215
|
+
children: "Cancel Exchange"
|
|
4216
|
+
}
|
|
4217
|
+
) }),
|
|
4218
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "This will cancel the exchange request. The order will remain unchanged." })
|
|
4110
4219
|
] }),
|
|
4111
|
-
/* @__PURE__ */
|
|
4112
|
-
/* @__PURE__ */
|
|
4113
|
-
/* @__PURE__ */ jsx("
|
|
4114
|
-
/* @__PURE__ */ jsxs("
|
|
4115
|
-
/* @__PURE__ */
|
|
4116
|
-
|
|
4220
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-6 md:grid-cols-2", children: [
|
|
4221
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4222
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Exchange Information" }),
|
|
4223
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
4224
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4225
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Exchange ID" }),
|
|
4226
|
+
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: swap.id })
|
|
4227
|
+
] }),
|
|
4228
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4229
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Status" }),
|
|
4230
|
+
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: swap.status })
|
|
4231
|
+
] }),
|
|
4232
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4233
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Difference Due" }),
|
|
4234
|
+
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: swap.difference_due != null ? `${swap.currency_code || "$"}${(Number(swap.difference_due) / 100).toFixed(2)}` : "—" })
|
|
4235
|
+
] }),
|
|
4236
|
+
swap.reason && /* @__PURE__ */ jsxs("div", { children: [
|
|
4237
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Reason" }),
|
|
4238
|
+
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: swap.reason })
|
|
4239
|
+
] }),
|
|
4240
|
+
swap.note && /* @__PURE__ */ jsxs("div", { children: [
|
|
4241
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Note" }),
|
|
4242
|
+
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: swap.note })
|
|
4243
|
+
] }),
|
|
4244
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4245
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Created" }),
|
|
4246
|
+
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: new Date(swap.created_at).toLocaleString() })
|
|
4247
|
+
] }),
|
|
4248
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4249
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Last Updated" }),
|
|
4250
|
+
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: new Date(swap.updated_at).toLocaleString() })
|
|
4251
|
+
] }),
|
|
4252
|
+
swap.exchange_id && /* @__PURE__ */ jsxs("div", { children: [
|
|
4253
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Exchange ID" }),
|
|
4254
|
+
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: swap.exchange_id })
|
|
4255
|
+
] })
|
|
4117
4256
|
] })
|
|
4118
|
-
] }) }),
|
|
4119
|
-
/* @__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" }) }),
|
|
4120
|
-
/* @__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 }) }),
|
|
4121
|
-
/* @__PURE__ */ jsx(Field, { label: "Action", children: /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Permanently deleted" }) })
|
|
4122
|
-
] }) }),
|
|
4123
|
-
/* @__PURE__ */ jsx(
|
|
4124
|
-
Section,
|
|
4125
|
-
{
|
|
4126
|
-
title: "Record summary",
|
|
4127
|
-
description: `Key details of this ${entity.label.toLowerCase()} at the moment it was deleted.`,
|
|
4128
|
-
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." })
|
|
4129
|
-
}
|
|
4130
|
-
),
|
|
4131
|
-
/* @__PURE__ */ jsx(
|
|
4132
|
-
Section,
|
|
4133
|
-
{
|
|
4134
|
-
title: "Original record data",
|
|
4135
|
-
description: "The complete data captured before deletion.",
|
|
4136
|
-
actions: showRaw && audit.old_data ? /* @__PURE__ */ jsxs(Button, { variant: "secondary", size: "small", onClick: copyJson, children: [
|
|
4137
|
-
/* @__PURE__ */ jsx(SquareTwoStack, {}),
|
|
4138
|
-
"Copy JSON"
|
|
4139
|
-
] }) : null,
|
|
4140
|
-
children: audit.old_data ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
4141
|
-
masked.maskedCount > 0 ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
4142
|
-
/* @__PURE__ */ jsx(ShieldCheck, { className: "shrink-0 text-ui-fg-muted" }),
|
|
4143
|
-
/* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
4144
|
-
masked.maskedCount,
|
|
4145
|
-
" sensitive ",
|
|
4146
|
-
masked.maskedCount === 1 ? "value is" : "values are",
|
|
4147
|
-
" hidden for security (passwords, tokens, card or account numbers)."
|
|
4148
|
-
] })
|
|
4149
|
-
] }) : null,
|
|
4150
|
-
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(Button, { variant: "secondary", size: "small", onClick: () => setShowRaw((s2) => !s2), "aria-expanded": showRaw, children: [
|
|
4151
|
-
showRaw ? /* @__PURE__ */ jsx(ChevronDownMini, {}) : /* @__PURE__ */ jsx(ChevronRightMini, {}),
|
|
4152
|
-
showRaw ? "Hide full record" : "View full record"
|
|
4153
|
-
] }) }),
|
|
4154
|
-
showRaw ? /* @__PURE__ */ jsx(JsonViewer, { data: masked.value }) : null
|
|
4155
|
-
] }) : /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "No data was captured for this deletion." })
|
|
4156
|
-
}
|
|
4157
|
-
),
|
|
4158
|
-
/* @__PURE__ */ jsx(Section, { title: "What you can do now", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
4159
|
-
/* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-base", children: [
|
|
4160
|
-
"This record was permanently deleted. ",
|
|
4161
|
-
/* @__PURE__ */ jsx("span", { className: "font-medium", children: "Automatic restoration is not available" }),
|
|
4162
|
-
" ",
|
|
4163
|
-
"from this screen."
|
|
4164
4257
|
] }),
|
|
4165
|
-
/* @__PURE__ */ jsxs("
|
|
4166
|
-
/* @__PURE__ */
|
|
4167
|
-
|
|
4168
|
-
"
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4258
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4259
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Status History" }),
|
|
4260
|
+
statusHistory.length > 0 ? /* @__PURE__ */ jsx("div", { className: "space-y-2", children: statusHistory.map((entry, index) => /* @__PURE__ */ jsx(
|
|
4261
|
+
"div",
|
|
4262
|
+
{
|
|
4263
|
+
className: "flex items-center justify-between border-b border-ui-border-subtle pb-2 last:border-0",
|
|
4264
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
4265
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx(
|
|
4266
|
+
Badge,
|
|
4267
|
+
{
|
|
4268
|
+
size: "2xsmall",
|
|
4269
|
+
className: `uppercase ${getStatusBadgeClass$2(entry.status)}`,
|
|
4270
|
+
children: entry.status.replace(/_/g, " ")
|
|
4271
|
+
}
|
|
4272
|
+
) }),
|
|
4273
|
+
/* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
4274
|
+
new Date(entry.timestamp).toLocaleString(),
|
|
4275
|
+
entry.admin_id && ` by ${entry.admin_id}`,
|
|
4276
|
+
entry.reason && ` - ${entry.reason}`
|
|
4277
|
+
] })
|
|
4278
|
+
] })
|
|
4279
|
+
},
|
|
4280
|
+
index
|
|
4281
|
+
)) }) : /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "No status history available" })
|
|
4282
|
+
] })
|
|
4283
|
+
] }),
|
|
4284
|
+
order && /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4285
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Related Order Information" }),
|
|
4286
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
4287
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4288
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Order ID" }),
|
|
4289
|
+
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: order.id })
|
|
4172
4290
|
] }),
|
|
4173
|
-
/* @__PURE__ */ jsxs("
|
|
4174
|
-
/* @__PURE__ */ jsx("
|
|
4175
|
-
" "
|
|
4176
|
-
guidance.recreate
|
|
4291
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4292
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Status" }),
|
|
4293
|
+
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: order.status || "—" })
|
|
4177
4294
|
] }),
|
|
4178
|
-
/* @__PURE__ */ jsxs("
|
|
4179
|
-
/* @__PURE__ */ jsx("
|
|
4180
|
-
|
|
4295
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4296
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Customer" }),
|
|
4297
|
+
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: ((_c = order.customer) == null ? void 0 : _c.email) || order.email || "—" })
|
|
4298
|
+
] }),
|
|
4299
|
+
order.total && /* @__PURE__ */ jsxs("div", { children: [
|
|
4300
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Total" }),
|
|
4301
|
+
/* @__PURE__ */ jsxs(Text, { className: "font-medium", children: [
|
|
4302
|
+
order.currency_code || "$",
|
|
4303
|
+
(Number(order.total) / 100).toFixed(2)
|
|
4304
|
+
] })
|
|
4181
4305
|
] })
|
|
4182
|
-
] })
|
|
4183
|
-
guidance.adminSection || related.length ? /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
4184
|
-
guidance.adminSection ? /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "small", onClick: () => navigate(guidance.adminSection.path), children: guidance.adminSection.label }) : null,
|
|
4185
|
-
related.map((link) => /* @__PURE__ */ jsxs(
|
|
4186
|
-
Button,
|
|
4187
|
-
{
|
|
4188
|
-
variant: "transparent",
|
|
4189
|
-
size: "small",
|
|
4190
|
-
onClick: () => navigate(link.path),
|
|
4191
|
-
title: `Opens ${link.label.toLowerCase()} ${link.id} if it still exists`,
|
|
4192
|
-
children: [
|
|
4193
|
-
"Open related ",
|
|
4194
|
-
link.label.toLowerCase(),
|
|
4195
|
-
/* @__PURE__ */ jsx(ChevronRightMini, {})
|
|
4196
|
-
]
|
|
4197
|
-
},
|
|
4198
|
-
link.path
|
|
4199
|
-
))
|
|
4200
|
-
] }) : null,
|
|
4201
|
-
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
|
|
4202
|
-
] }) })
|
|
4203
|
-
] });
|
|
4204
|
-
};
|
|
4205
|
-
const Section = ({
|
|
4206
|
-
title,
|
|
4207
|
-
description,
|
|
4208
|
-
actions,
|
|
4209
|
-
children
|
|
4210
|
-
}) => /* @__PURE__ */ jsxs("section", { className: "flex flex-col gap-4 rounded-lg border border-ui-border-base p-5", children: [
|
|
4211
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-start justify-between gap-2", children: [
|
|
4212
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
4213
|
-
/* @__PURE__ */ jsx(Heading, { level: "h2", children: title }),
|
|
4214
|
-
description ? /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: description }) : null
|
|
4306
|
+
] })
|
|
4215
4307
|
] }),
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
] })
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
})
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
/* @__PURE__ */ jsx(Button, { variant: "secondary", size: "small", onClick: onBack, children: "Back to Deleted Records" }),
|
|
4251
|
-
!notFound ? /* @__PURE__ */ jsx(Button, { variant: "primary", size: "small", onClick: onRetry, children: "Try again" }) : null
|
|
4252
|
-
] })
|
|
4253
|
-
] });
|
|
4254
|
-
defineRouteConfig({});
|
|
4308
|
+
swap.return_items && swap.return_items.length > 0 && /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4309
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Items" }),
|
|
4310
|
+
/* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
4311
|
+
/* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
4312
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Item ID" }),
|
|
4313
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Quantity" }),
|
|
4314
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Reason" })
|
|
4315
|
+
] }) }),
|
|
4316
|
+
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: swap.return_items.map((item, index) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
4317
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: item.id }),
|
|
4318
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.quantity }),
|
|
4319
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.reason || "—" })
|
|
4320
|
+
] }, item.id || index)) })
|
|
4321
|
+
] }) })
|
|
4322
|
+
] }),
|
|
4323
|
+
swap.new_items && swap.new_items.length > 0 && /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4324
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "New Items" }),
|
|
4325
|
+
/* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
4326
|
+
/* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
4327
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Variant ID" }),
|
|
4328
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Quantity" })
|
|
4329
|
+
] }) }),
|
|
4330
|
+
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: swap.new_items.map((item, index) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
4331
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: item.variant_id }),
|
|
4332
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.quantity })
|
|
4333
|
+
] }, item.variant_id || index)) })
|
|
4334
|
+
] }) })
|
|
4335
|
+
] })
|
|
4336
|
+
] }) });
|
|
4337
|
+
};
|
|
4338
|
+
const config$2 = defineRouteConfig({
|
|
4339
|
+
label: "Swap Details",
|
|
4340
|
+
icon: ArrowPath
|
|
4341
|
+
});
|
|
4255
4342
|
const getStatusBadgeClass$1 = (status) => {
|
|
4256
4343
|
const statusLower = status.toLowerCase();
|
|
4257
4344
|
if (statusLower === "requested") {
|
|
@@ -4536,283 +4623,196 @@ const config$1 = defineRouteConfig({
|
|
|
4536
4623
|
icon: CheckCircle
|
|
4537
4624
|
});
|
|
4538
4625
|
const getStatusBadgeClass = (status) => {
|
|
4539
|
-
const
|
|
4540
|
-
if (
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
if (
|
|
4544
|
-
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
4545
|
-
}
|
|
4546
|
-
if (statusLower === "rejected") {
|
|
4547
|
-
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
4548
|
-
}
|
|
4549
|
-
if (statusLower === "completed") {
|
|
4550
|
-
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
4551
|
-
}
|
|
4552
|
-
if (statusLower === "cancelled" || statusLower === "canceled") {
|
|
4553
|
-
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
4554
|
-
}
|
|
4555
|
-
if (statusLower === "pending") {
|
|
4556
|
-
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
4557
|
-
}
|
|
4626
|
+
const s2 = status.toLowerCase();
|
|
4627
|
+
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
4628
|
+
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
4629
|
+
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
4630
|
+
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
4558
4631
|
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
4559
4632
|
};
|
|
4560
|
-
const
|
|
4633
|
+
const formatAmount = (value) => {
|
|
4634
|
+
return String(value);
|
|
4635
|
+
};
|
|
4636
|
+
const RefundDetailPage = () => {
|
|
4561
4637
|
var _a, _b, _c;
|
|
4562
4638
|
const navigate = useNavigate();
|
|
4563
|
-
const
|
|
4564
|
-
const
|
|
4565
|
-
const [
|
|
4566
|
-
const [
|
|
4567
|
-
useState(false);
|
|
4568
|
-
const [isCancelling, setIsCancelling] = useState(false);
|
|
4639
|
+
const params = useParams();
|
|
4640
|
+
const id = (_a = params == null ? void 0 : params.id) == null ? void 0 : _a.trim();
|
|
4641
|
+
const [detail, setDetail] = useState(null);
|
|
4642
|
+
const [loading, setLoading] = useState(!!id);
|
|
4569
4643
|
const [error, setError] = useState(null);
|
|
4570
|
-
const [
|
|
4571
|
-
const [updateSuccess, setUpdateSuccess] = useState(false);
|
|
4644
|
+
const [gatewayExpanded, setGatewayExpanded] = useState(false);
|
|
4572
4645
|
useEffect(() => {
|
|
4573
4646
|
if (!id) {
|
|
4574
|
-
|
|
4647
|
+
setLoading(false);
|
|
4575
4648
|
return;
|
|
4576
4649
|
}
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
const message = loadError instanceof Error ? loadError.message : "Unable to load swap";
|
|
4593
|
-
setError(message);
|
|
4594
|
-
} finally {
|
|
4595
|
-
setIsLoading(false);
|
|
4596
|
-
}
|
|
4650
|
+
let cancelled = false;
|
|
4651
|
+
setLoading(true);
|
|
4652
|
+
setError(null);
|
|
4653
|
+
fetch(`/admin/refunds/${id}`, { credentials: "include" }).then((res) => {
|
|
4654
|
+
if (!res.ok) throw new Error(res.statusText || "Failed to load");
|
|
4655
|
+
return res.json();
|
|
4656
|
+
}).then((data) => {
|
|
4657
|
+
if (!cancelled) setDetail(data);
|
|
4658
|
+
}).catch((e) => {
|
|
4659
|
+
if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
|
|
4660
|
+
}).finally(() => {
|
|
4661
|
+
if (!cancelled) setLoading(false);
|
|
4662
|
+
});
|
|
4663
|
+
return () => {
|
|
4664
|
+
cancelled = true;
|
|
4597
4665
|
};
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
const
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
},
|
|
4613
|
-
|
|
4614
|
-
});
|
|
4615
|
-
if (!response.ok) {
|
|
4616
|
-
const message = await response.text();
|
|
4617
|
-
throw new Error(message || "Unable to cancel exchange");
|
|
4618
|
-
}
|
|
4619
|
-
const payload = await response.json();
|
|
4620
|
-
setSwap(payload.swap);
|
|
4621
|
-
setUpdateSuccess(true);
|
|
4622
|
-
setTimeout(() => setUpdateSuccess(false), 3e3);
|
|
4623
|
-
const detailResponse = await fetch(`/admin/swaps/${id}`, {
|
|
4624
|
-
credentials: "include"
|
|
4625
|
-
});
|
|
4626
|
-
if (detailResponse.ok) {
|
|
4627
|
-
const detailPayload = await detailResponse.json();
|
|
4628
|
-
setSwap(detailPayload.swap);
|
|
4629
|
-
setOrder(detailPayload.order || null);
|
|
4630
|
-
}
|
|
4631
|
-
} catch (cancelErr) {
|
|
4632
|
-
const message = cancelErr instanceof Error ? cancelErr.message : "Unable to cancel exchange";
|
|
4633
|
-
setUpdateError(message);
|
|
4634
|
-
} finally {
|
|
4635
|
-
setIsCancelling(false);
|
|
4636
|
-
}
|
|
4637
|
-
};
|
|
4638
|
-
const isOrderExchange = Boolean(swap == null ? void 0 : swap.exchange_id);
|
|
4639
|
-
const canCancelExchange = isOrderExchange && swap && !["cancelled", "canceled", "completed", "declined"].includes(
|
|
4640
|
-
((_a = swap.status) == null ? void 0 : _a.toLowerCase()) ?? ""
|
|
4641
|
-
);
|
|
4642
|
-
if (isLoading) {
|
|
4643
|
-
return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsx(Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading swap..." }) }) }) });
|
|
4644
|
-
}
|
|
4645
|
-
if (error || !swap) {
|
|
4646
|
-
return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsx(Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
4647
|
-
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error || "Swap not found" }),
|
|
4648
|
-
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => navigate("/swaps"), children: "Back to list" }) })
|
|
4649
|
-
] }) }) });
|
|
4650
|
-
}
|
|
4651
|
-
const statusHistory = ((_b = swap.metadata) == null ? void 0 : _b.status_history) || [];
|
|
4652
|
-
return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: [
|
|
4653
|
-
/* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3", children: [
|
|
4654
|
-
/* @__PURE__ */ jsxs(
|
|
4655
|
-
Button,
|
|
4656
|
-
{
|
|
4657
|
-
variant: "transparent",
|
|
4658
|
-
size: "small",
|
|
4659
|
-
onClick: () => navigate("/swaps"),
|
|
4660
|
-
className: "w-fit",
|
|
4661
|
-
children: [
|
|
4662
|
-
/* @__PURE__ */ jsx(ArrowLeft, { className: "mr-2" }),
|
|
4663
|
-
"Back to list"
|
|
4664
|
-
]
|
|
4665
|
-
}
|
|
4666
|
-
),
|
|
4667
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 md:flex-row md:items-center md:justify-between", children: [
|
|
4668
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
4669
|
-
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Exchange Details" }),
|
|
4670
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: swap.id })
|
|
4671
|
-
] }),
|
|
4672
|
-
/* @__PURE__ */ jsx(
|
|
4673
|
-
Badge,
|
|
4674
|
-
{
|
|
4675
|
-
size: "small",
|
|
4676
|
-
className: `uppercase ${getStatusBadgeClass(swap.status)}`,
|
|
4677
|
-
children: swap.status.replace(/_/g, " ")
|
|
4678
|
-
}
|
|
4679
|
-
)
|
|
4680
|
-
] })
|
|
4681
|
-
] }),
|
|
4682
|
-
canCancelExchange && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
4683
|
-
/* @__PURE__ */ jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsx(
|
|
4684
|
-
Button,
|
|
4685
|
-
{
|
|
4686
|
-
variant: "danger",
|
|
4687
|
-
onClick: handleCancelExchange,
|
|
4688
|
-
disabled: isCancelling,
|
|
4689
|
-
isLoading: isCancelling,
|
|
4690
|
-
children: "Cancel Exchange"
|
|
4691
|
-
}
|
|
4692
|
-
) }),
|
|
4693
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "This will cancel the exchange request. The order will remain unchanged." })
|
|
4694
|
-
] }),
|
|
4695
|
-
/* @__PURE__ */ jsxs("div", { className: "grid gap-6 md:grid-cols-2", children: [
|
|
4696
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4697
|
-
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Exchange Information" }),
|
|
4698
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
4666
|
+
}, [id]);
|
|
4667
|
+
const paymentStatus = ((_b = detail == null ? void 0 : detail.payment) == null ? void 0 : _b.status) ?? "—";
|
|
4668
|
+
const hasGatewayData = ((_c = detail == null ? void 0 : detail.payment) == null ? void 0 : _c.payment_data) && typeof detail.payment.payment_data === "object" && Object.keys(detail.payment.payment_data).length > 0;
|
|
4669
|
+
return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-4xl flex-col gap-6 p-6", children: [
|
|
4670
|
+
/* @__PURE__ */ jsx("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
4671
|
+
/* @__PURE__ */ jsx(Button, { variant: "transparent", size: "small", onClick: () => navigate("/refunds"), children: "← Refunds" }),
|
|
4672
|
+
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Refund details" }),
|
|
4673
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle font-mono", children: id ?? "—" })
|
|
4674
|
+
] }) }),
|
|
4675
|
+
error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
4676
|
+
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
4677
|
+
/* @__PURE__ */ jsx(Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/refunds"), children: "Back to list" })
|
|
4678
|
+
] }) : loading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading…" }) }) : detail ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
4679
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4680
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "text-lg mb-4", children: "Refund summary" }),
|
|
4681
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
4699
4682
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
4700
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-
|
|
4701
|
-
/* @__PURE__ */ jsx(Text, { className: "font-
|
|
4683
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Refund ID" }),
|
|
4684
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.id })
|
|
4685
|
+
] }),
|
|
4686
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4687
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
|
|
4688
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.refund.amount) })
|
|
4689
|
+
] }),
|
|
4690
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4691
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Note" }),
|
|
4692
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.refund.note ?? "—" })
|
|
4693
|
+
] }),
|
|
4694
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4695
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Created at" }),
|
|
4696
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: new Date(detail.refund.created_at).toLocaleDateString("en-US", {
|
|
4697
|
+
year: "numeric",
|
|
4698
|
+
month: "short",
|
|
4699
|
+
day: "numeric",
|
|
4700
|
+
hour: "numeric",
|
|
4701
|
+
minute: "2-digit",
|
|
4702
|
+
hour12: true
|
|
4703
|
+
}) })
|
|
4704
|
+
] }),
|
|
4705
|
+
detail.refund.created_by ? /* @__PURE__ */ jsxs("div", { children: [
|
|
4706
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Created by" }),
|
|
4707
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.created_by })
|
|
4708
|
+
] }) : null
|
|
4709
|
+
] })
|
|
4710
|
+
] }),
|
|
4711
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4712
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "text-lg mb-4", children: "Payment summary" }),
|
|
4713
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
4714
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4715
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Payment amount" }),
|
|
4716
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.payment.payment_amount) })
|
|
4702
4717
|
] }),
|
|
4703
4718
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
4704
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-
|
|
4705
|
-
/* @__PURE__ */ jsx(Text, { className: "
|
|
4719
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Captured amount" }),
|
|
4720
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.payment.captured_amount) })
|
|
4706
4721
|
] }),
|
|
4707
4722
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
4708
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-
|
|
4709
|
-
/* @__PURE__ */ jsx(Text, { className: "
|
|
4710
|
-
] }),
|
|
4711
|
-
swap.reason && /* @__PURE__ */ jsxs("div", { children: [
|
|
4712
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Reason" }),
|
|
4713
|
-
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: swap.reason })
|
|
4714
|
-
] }),
|
|
4715
|
-
swap.note && /* @__PURE__ */ jsxs("div", { children: [
|
|
4716
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Note" }),
|
|
4717
|
-
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: swap.note })
|
|
4723
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Refunded amount" }),
|
|
4724
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.payment.refunded_amount) })
|
|
4718
4725
|
] }),
|
|
4719
4726
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
4720
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-
|
|
4721
|
-
/* @__PURE__ */ jsx(Text, { className: "
|
|
4727
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
|
|
4728
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.payment.provider_id || "—" })
|
|
4722
4729
|
] }),
|
|
4723
4730
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
4724
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-
|
|
4725
|
-
/* @__PURE__ */ jsx(
|
|
4731
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
|
|
4732
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsx(
|
|
4733
|
+
Badge,
|
|
4734
|
+
{
|
|
4735
|
+
size: "2xsmall",
|
|
4736
|
+
className: `uppercase ${getStatusBadgeClass(paymentStatus)}`,
|
|
4737
|
+
children: paymentStatus !== "—" ? paymentStatus.replace(/_/g, " ") : "—"
|
|
4738
|
+
}
|
|
4739
|
+
) })
|
|
4726
4740
|
] }),
|
|
4727
|
-
|
|
4728
|
-
/* @__PURE__ */
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
Badge,
|
|
4742
|
-
{
|
|
4743
|
-
size: "2xsmall",
|
|
4744
|
-
className: `uppercase ${getStatusBadgeClass(entry.status)}`,
|
|
4745
|
-
children: entry.status.replace(/_/g, " ")
|
|
4746
|
-
}
|
|
4747
|
-
) }),
|
|
4748
|
-
/* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
4749
|
-
new Date(entry.timestamp).toLocaleString(),
|
|
4750
|
-
entry.admin_id && ` by ${entry.admin_id}`,
|
|
4751
|
-
entry.reason && ` - ${entry.reason}`
|
|
4741
|
+
detail.computed ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4742
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4743
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Full refund" }),
|
|
4744
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.computed.is_full_refund ? "Yes" : "No" })
|
|
4745
|
+
] }),
|
|
4746
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4747
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Remaining refundable" }),
|
|
4748
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.computed.remaining_refundable_amount) })
|
|
4749
|
+
] }),
|
|
4750
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4751
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Refund %" }),
|
|
4752
|
+
/* @__PURE__ */ jsxs(Text, { className: "mt-1 block", children: [
|
|
4753
|
+
detail.computed.refund_percentage.toFixed(1),
|
|
4754
|
+
"%"
|
|
4752
4755
|
] })
|
|
4753
4756
|
] })
|
|
4754
|
-
}
|
|
4755
|
-
index
|
|
4756
|
-
)) }) : /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "No status history available" })
|
|
4757
|
-
] })
|
|
4758
|
-
] }),
|
|
4759
|
-
order && /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4760
|
-
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Related Order Information" }),
|
|
4761
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
4762
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
4763
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Order ID" }),
|
|
4764
|
-
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: order.id })
|
|
4765
|
-
] }),
|
|
4766
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
4767
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Status" }),
|
|
4768
|
-
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: order.status || "—" })
|
|
4769
|
-
] }),
|
|
4770
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
4771
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Customer" }),
|
|
4772
|
-
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: ((_c = order.customer) == null ? void 0 : _c.email) || order.email || "—" })
|
|
4773
|
-
] }),
|
|
4774
|
-
order.total && /* @__PURE__ */ jsxs("div", { children: [
|
|
4775
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Total" }),
|
|
4776
|
-
/* @__PURE__ */ jsxs(Text, { className: "font-medium", children: [
|
|
4777
|
-
order.currency_code || "$",
|
|
4778
|
-
(Number(order.total) / 100).toFixed(2)
|
|
4779
|
-
] })
|
|
4757
|
+
] }) : null
|
|
4780
4758
|
] })
|
|
4759
|
+
] }),
|
|
4760
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4761
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "text-lg mb-4", children: "Order summary" }),
|
|
4762
|
+
detail.order ? /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
4763
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
4764
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Order" }),
|
|
4765
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsx(
|
|
4766
|
+
Button,
|
|
4767
|
+
{
|
|
4768
|
+
variant: "transparent",
|
|
4769
|
+
size: "small",
|
|
4770
|
+
onClick: () => navigate(`/orders/${detail.order.order_id}`),
|
|
4771
|
+
children: detail.order.order_number ?? detail.order.order_id
|
|
4772
|
+
}
|
|
4773
|
+
) })
|
|
4774
|
+
] }),
|
|
4775
|
+
detail.order.total != null ? /* @__PURE__ */ jsxs("div", { children: [
|
|
4776
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Total" }),
|
|
4777
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: formatAmount(detail.order.total) })
|
|
4778
|
+
] }) : null,
|
|
4779
|
+
detail.order.customer_id ? /* @__PURE__ */ jsxs("div", { children: [
|
|
4780
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Customer ID" }),
|
|
4781
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block font-mono text-sm", children: detail.order.customer_id })
|
|
4782
|
+
] }) : null,
|
|
4783
|
+
detail.order.region ? /* @__PURE__ */ jsxs("div", { children: [
|
|
4784
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Region" }),
|
|
4785
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.order.region })
|
|
4786
|
+
] }) : null,
|
|
4787
|
+
detail.order.fulfillment_status ? /* @__PURE__ */ jsxs("div", { children: [
|
|
4788
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Fulfillment status" }),
|
|
4789
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.order.fulfillment_status })
|
|
4790
|
+
] }) : null
|
|
4791
|
+
] }) : /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "No order linked to this refund." })
|
|
4792
|
+
] }),
|
|
4793
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4794
|
+
/* @__PURE__ */ jsxs(
|
|
4795
|
+
"button",
|
|
4796
|
+
{
|
|
4797
|
+
type: "button",
|
|
4798
|
+
className: "flex w-full items-center justify-between text-left",
|
|
4799
|
+
onClick: () => setGatewayExpanded((prev) => !prev),
|
|
4800
|
+
"aria-expanded": gatewayExpanded,
|
|
4801
|
+
"aria-label": gatewayExpanded ? "Collapse gateway data" : "Expand gateway data",
|
|
4802
|
+
children: [
|
|
4803
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "text-lg", children: "Gateway data" }),
|
|
4804
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: gatewayExpanded ? "Collapse" : "Expand" })
|
|
4805
|
+
]
|
|
4806
|
+
}
|
|
4807
|
+
),
|
|
4808
|
+
gatewayExpanded && /* @__PURE__ */ jsx("div", { className: "mt-4", children: hasGatewayData ? /* @__PURE__ */ jsx("pre", { className: "text-xs bg-ui-bg-subtle p-4 rounded-lg overflow-auto max-h-96", children: JSON.stringify(detail.payment.payment_data, null, 2) }) : /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "No gateway payload for this payment." }) })
|
|
4781
4809
|
] })
|
|
4782
|
-
] })
|
|
4783
|
-
swap.return_items && swap.return_items.length > 0 && /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4784
|
-
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Items" }),
|
|
4785
|
-
/* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
4786
|
-
/* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
4787
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Item ID" }),
|
|
4788
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Quantity" }),
|
|
4789
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Reason" })
|
|
4790
|
-
] }) }),
|
|
4791
|
-
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: swap.return_items.map((item, index) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
4792
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: item.id }),
|
|
4793
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.quantity }),
|
|
4794
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.reason || "—" })
|
|
4795
|
-
] }, item.id || index)) })
|
|
4796
|
-
] }) })
|
|
4797
|
-
] }),
|
|
4798
|
-
swap.new_items && swap.new_items.length > 0 && /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4799
|
-
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "New Items" }),
|
|
4800
|
-
/* @__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: [
|
|
4801
|
-
/* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
4802
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Variant ID" }),
|
|
4803
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Quantity" })
|
|
4804
|
-
] }) }),
|
|
4805
|
-
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: swap.new_items.map((item, index) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
4806
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: item.variant_id }),
|
|
4807
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.quantity })
|
|
4808
|
-
] }, item.variant_id || index)) })
|
|
4809
|
-
] }) })
|
|
4810
|
-
] })
|
|
4810
|
+
] }) : null
|
|
4811
4811
|
] }) });
|
|
4812
4812
|
};
|
|
4813
4813
|
const config = defineRouteConfig({
|
|
4814
|
-
label: "
|
|
4815
|
-
icon:
|
|
4814
|
+
label: "Refund details",
|
|
4815
|
+
icon: Receipt
|
|
4816
4816
|
});
|
|
4817
4817
|
const i18nTranslations0 = {};
|
|
4818
4818
|
const widgetModule = { widgets: [
|
|
@@ -4827,72 +4827,84 @@ const widgetModule = { widgets: [
|
|
|
4827
4827
|
] };
|
|
4828
4828
|
const routeModule = {
|
|
4829
4829
|
routes: [
|
|
4830
|
-
{
|
|
4831
|
-
Component: PaymentsPage,
|
|
4832
|
-
path: "/payments"
|
|
4833
|
-
},
|
|
4834
|
-
{
|
|
4835
|
-
Component: RefundsPage,
|
|
4836
|
-
path: "/refunds"
|
|
4837
|
-
},
|
|
4838
4830
|
{
|
|
4839
4831
|
Component: DeletedRecordsPage,
|
|
4840
4832
|
path: "/deleted-records-audit"
|
|
4841
4833
|
},
|
|
4834
|
+
{
|
|
4835
|
+
Component: PaymentsPage,
|
|
4836
|
+
path: "/payments"
|
|
4837
|
+
},
|
|
4842
4838
|
{
|
|
4843
4839
|
Component: ReturnsPage,
|
|
4844
4840
|
path: "/returns"
|
|
4845
4841
|
},
|
|
4842
|
+
{
|
|
4843
|
+
Component: DeletedRecordDetailPage,
|
|
4844
|
+
path: "/deleted-records-audit/:id"
|
|
4845
|
+
},
|
|
4846
4846
|
{
|
|
4847
4847
|
Component: SwapsPage,
|
|
4848
4848
|
path: "/swaps"
|
|
4849
4849
|
},
|
|
4850
4850
|
{
|
|
4851
|
-
Component:
|
|
4852
|
-
path: "/
|
|
4851
|
+
Component: RefundsPage,
|
|
4852
|
+
path: "/refunds"
|
|
4853
4853
|
},
|
|
4854
4854
|
{
|
|
4855
|
-
Component:
|
|
4856
|
-
path: "/
|
|
4855
|
+
Component: PaymentDetailPage,
|
|
4856
|
+
path: "/payments/:id"
|
|
4857
4857
|
},
|
|
4858
4858
|
{
|
|
4859
|
-
Component:
|
|
4860
|
-
path: "/
|
|
4859
|
+
Component: SwapDetailPage,
|
|
4860
|
+
path: "/swaps/:id"
|
|
4861
4861
|
},
|
|
4862
4862
|
{
|
|
4863
4863
|
Component: ReturnDetailPage,
|
|
4864
4864
|
path: "/returns/:id"
|
|
4865
4865
|
},
|
|
4866
4866
|
{
|
|
4867
|
-
Component:
|
|
4868
|
-
path: "/
|
|
4867
|
+
Component: RefundDetailPage,
|
|
4868
|
+
path: "/refunds/:id"
|
|
4869
4869
|
}
|
|
4870
4870
|
]
|
|
4871
4871
|
};
|
|
4872
4872
|
const menuItemModule = {
|
|
4873
4873
|
menuItems: [
|
|
4874
4874
|
{
|
|
4875
|
-
label: config$
|
|
4876
|
-
icon: config$
|
|
4877
|
-
path: "/
|
|
4875
|
+
label: config$8.label,
|
|
4876
|
+
icon: config$8.icon,
|
|
4877
|
+
path: "/deleted-records-audit",
|
|
4878
4878
|
nested: void 0
|
|
4879
4879
|
},
|
|
4880
4880
|
{
|
|
4881
4881
|
label: config$7.label,
|
|
4882
4882
|
icon: config$7.icon,
|
|
4883
|
-
path: "/
|
|
4883
|
+
path: "/payments",
|
|
4884
|
+
nested: void 0
|
|
4885
|
+
},
|
|
4886
|
+
{
|
|
4887
|
+
label: config$6.label,
|
|
4888
|
+
icon: config$6.icon,
|
|
4889
|
+
path: "/returns",
|
|
4890
|
+
nested: void 0
|
|
4891
|
+
},
|
|
4892
|
+
{
|
|
4893
|
+
label: config$5.label,
|
|
4894
|
+
icon: config$5.icon,
|
|
4895
|
+
path: "/swaps",
|
|
4884
4896
|
nested: void 0
|
|
4885
4897
|
},
|
|
4886
4898
|
{
|
|
4887
4899
|
label: config$4.label,
|
|
4888
4900
|
icon: config$4.icon,
|
|
4889
|
-
path: "/
|
|
4901
|
+
path: "/refunds",
|
|
4890
4902
|
nested: void 0
|
|
4891
4903
|
},
|
|
4892
4904
|
{
|
|
4893
|
-
label: config$
|
|
4894
|
-
icon: config$
|
|
4895
|
-
path: "/
|
|
4905
|
+
label: config$3.label,
|
|
4906
|
+
icon: config$3.icon,
|
|
4907
|
+
path: "/payments/:id",
|
|
4896
4908
|
nested: void 0
|
|
4897
4909
|
},
|
|
4898
4910
|
{
|
|
@@ -4901,28 +4913,16 @@ const menuItemModule = {
|
|
|
4901
4913
|
path: "/returns/:id",
|
|
4902
4914
|
nested: void 0
|
|
4903
4915
|
},
|
|
4904
|
-
{
|
|
4905
|
-
label: config$8.label,
|
|
4906
|
-
icon: config$8.icon,
|
|
4907
|
-
path: "/payments",
|
|
4908
|
-
nested: void 0
|
|
4909
|
-
},
|
|
4910
4916
|
{
|
|
4911
4917
|
label: config$2.label,
|
|
4912
4918
|
icon: config$2.icon,
|
|
4913
|
-
path: "/
|
|
4919
|
+
path: "/swaps/:id",
|
|
4914
4920
|
nested: void 0
|
|
4915
4921
|
},
|
|
4916
4922
|
{
|
|
4917
4923
|
label: config.label,
|
|
4918
4924
|
icon: config.icon,
|
|
4919
|
-
path: "/
|
|
4920
|
-
nested: void 0
|
|
4921
|
-
},
|
|
4922
|
-
{
|
|
4923
|
-
label: config$3.label,
|
|
4924
|
-
icon: config$3.icon,
|
|
4925
|
-
path: "/payments/:id",
|
|
4925
|
+
path: "/refunds/:id",
|
|
4926
4926
|
nested: void 0
|
|
4927
4927
|
}
|
|
4928
4928
|
]
|