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