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.
@@ -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$6 = adminSdk.defineRouteConfig({
2230
+ const config$8 = adminSdk.defineRouteConfig({
2726
2231
  label: "Deleted Records",
2727
2232
  icon: icons.Trash
2728
2233
  });
2729
- const useDebounce$1 = (value, delay) => {
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$5 = (status) => {
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$1(searchQuery, 300);
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$5(returnOrder.status)}`,
2909
- children: returnOrder.status.replace(/_/g, " ")
2910
- }
2911
- ) }),
2912
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
2913
- const calc = returnOrder.refund;
2914
- if ((calc == null ? void 0 : calc.is_processed) && calc.final_refund_amount != null) {
2915
- return formatRefundCurrency(
2916
- calc.final_refund_amount,
2917
- calc.currency_code || returnOrder.currency_code
2918
- );
2919
- }
2920
- if (calc) {
2921
- return "Pending";
2922
- }
2923
- if (returnOrder.refund_amount == null) {
2924
- return "—";
2925
- }
2926
- return formatRefundCurrency(
2927
- Number(returnOrder.refund_amount),
2928
- returnOrder.currency_code
2929
- );
2930
- })() }),
2931
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(returnOrder.created_at).toLocaleDateString("en-US", {
2932
- year: "numeric",
2933
- month: "short",
2934
- day: "numeric",
2935
- hour: "numeric",
2936
- minute: "2-digit",
2937
- hour12: true
2938
- }) }),
2939
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
2940
- ui.Button,
2941
- {
2942
- variant: "transparent",
2943
- size: "small",
2944
- onClick: (e) => {
2945
- e.stopPropagation();
2946
- navigate(`/app/orders/${returnOrder.order_id}`);
2947
- },
2948
- children: "Go to order"
2949
- }
2950
- ) })
2951
- ]
2952
- },
2953
- returnOrder.id
2954
- )) })
2955
- ] }) }),
2956
- hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
2957
- ui.Button,
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
- variant: "secondary",
2960
- isLoading: isFetchingMore,
2961
- onClick: () => loadReturns(offset, false),
2962
- children: "Load more"
2784
+ type: "button",
2785
+ onClick: () => setOpen((o) => !o),
2786
+ className: "flex items-start text-left hover:bg-ui-bg-base-hover",
2787
+ "aria-expanded": open,
2788
+ children: [
2789
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex w-4 shrink-0 items-center pt-0.5 text-ui-fg-muted", children: entries.length ? open ? /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDownMini, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRightMini, {}) : null }),
2790
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
2791
+ label,
2792
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: openBracket }),
2793
+ !open || entries.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2794
+ entries.length ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-1 italic text-ui-fg-muted", children: summary }) : null,
2795
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: closeBracket })
2796
+ ] }) : null
2797
+ ] })
2798
+ ]
2963
2799
  }
2964
- ) }) : null
2965
- ] }) });
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 config$5 = adminSdk.defineRouteConfig({
2968
- label: "Return Orders",
2969
- icon: icons.ArrowPath
2970
- });
2971
- const useDebounce = (value, delay) => {
2972
- const [debouncedValue, setDebouncedValue] = react.useState(value);
2973
- react.useEffect(() => {
2974
- const handler = setTimeout(() => setDebouncedValue(value), delay);
2975
- return () => clearTimeout(handler);
2976
- }, [value, delay]);
2977
- return debouncedValue;
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 getStatusBadgeClass$4 = (status) => {
2980
- const statusLower = status.toLowerCase();
2981
- if (statusLower === "requested") {
2982
- return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
2983
- }
2984
- if (statusLower === "approved") {
2985
- return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
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
- if (statusLower === "rejected") {
2988
- return "bg-ui-tag-red-bg text-ui-tag-red-text";
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
- if (statusLower === "completed") {
2991
- return "bg-ui-tag-green-bg text-ui-tag-green-text";
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
- if (statusLower === "cancelled") {
2994
- return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
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
- return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
2997
- };
2998
- const SwapsPage = () => {
2999
- const navigate = reactRouterDom.useNavigate();
3000
- const [items, setItems] = react.useState([]);
3001
- const [statusFilter, setStatusFilter] = react.useState("all");
3002
- const [createdByFilter, setCreatedByFilter] = react.useState("all");
3003
- const [searchQuery, setSearchQuery] = react.useState("");
3004
- const debouncedSearchQuery = useDebounce(searchQuery, 300);
3005
- const [isLoading, setIsLoading] = react.useState(true);
3006
- const [isFetchingMore, setIsFetchingMore] = react.useState(false);
3007
- const [error, setError] = react.useState(null);
3008
- const [offset, setOffset] = react.useState(0);
3009
- const [count, setCount] = react.useState(0);
3010
- const limit = 50;
3011
- const loadSwaps = react.useCallback(
3012
- async (nextOffset, replace = false) => {
3013
- var _a;
3014
- try {
3015
- if (replace) {
3016
- setIsLoading(true);
3017
- } else {
3018
- setIsFetchingMore(true);
3019
- }
3020
- setError(null);
3021
- const params = new URLSearchParams();
3022
- params.set("limit", String(limit));
3023
- params.set("offset", String(nextOffset));
3024
- if (statusFilter !== "all") {
3025
- params.set("status", statusFilter);
3026
- }
3027
- if (debouncedSearchQuery.trim()) {
3028
- params.set("order_id", debouncedSearchQuery.trim());
3029
- }
3030
- if (createdByFilter !== "all") {
3031
- params.set("created_by", createdByFilter);
3032
- }
3033
- const response = await fetch(
3034
- `/admin/swaps?${params.toString()}`,
3035
- { credentials: "include" }
3036
- );
3037
- if (!response.ok) {
3038
- const message = await response.text();
3039
- throw new Error(message || "Unable to load swaps");
3040
- }
3041
- const payload = await response.json();
3042
- setCount(payload.count ?? 0);
3043
- setOffset(nextOffset + (((_a = payload.swaps) == null ? void 0 : _a.length) ?? 0));
3044
- setItems(
3045
- (prev) => replace ? payload.swaps ?? [] : [...prev, ...payload.swaps ?? []]
3046
- );
3047
- } catch (loadError) {
3048
- const message = loadError instanceof Error ? loadError.message : "Unable to load swaps";
3049
- setError(message);
3050
- } finally {
3051
- setIsLoading(false);
3052
- setIsFetchingMore(false);
3053
- }
3054
- },
3055
- [statusFilter, createdByFilter, debouncedSearchQuery]
3056
- );
3057
- react.useEffect(() => {
3058
- void loadSwaps(0, true);
3059
- }, [statusFilter, createdByFilter, debouncedSearchQuery, loadSwaps]);
3060
- const hasMore = react.useMemo(() => offset < count, [offset, count]);
3061
- const availableStatuses = react.useMemo(() => {
3062
- const statuses = /* @__PURE__ */ new Set();
3063
- items.forEach((item) => statuses.add(item.status));
3064
- return Array.from(statuses).sort();
3065
- }, [items]);
3066
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
3067
- /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
3068
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
3069
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Exchanges" }),
3070
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "View and manage all customer exchange requests" })
3071
- ] }),
3072
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => loadSwaps(0, true), children: "Refresh" })
3073
- ] }),
3074
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
3075
- /* @__PURE__ */ jsxRuntime.jsx(
3076
- ui.Input,
3077
- {
3078
- placeholder: "Search by swap ID or order ID",
3079
- value: searchQuery,
3080
- onChange: (event) => setSearchQuery(event.target.value),
3081
- className: "md:max-w-sm"
3082
- }
3083
- ),
3084
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
3085
- /* @__PURE__ */ jsxRuntime.jsxs(
3086
- "select",
3087
- {
3088
- value: createdByFilter,
3089
- onChange: (event) => setCreatedByFilter(event.target.value),
3090
- className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-xs",
3091
- children: [
3092
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All (Created by)" }),
3093
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "customer", children: "Customer" }),
3094
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "admin", children: "Admin" })
3095
- ]
3096
- }
3097
- ),
3098
- /* @__PURE__ */ jsxRuntime.jsxs(
3099
- "select",
3100
- {
3101
- value: statusFilter,
3102
- onChange: (event) => setStatusFilter(event.target.value),
3103
- className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-xs",
3104
- children: [
3105
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All Statuses" }),
3106
- availableStatuses.map((status) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
3107
- ]
3108
- }
3109
- )
3110
- ] })
3111
- ] }),
3112
- error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
3113
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
3114
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
3115
- ui.Button,
3116
- {
3117
- variant: "secondary",
3118
- onClick: () => loadSwaps(0, true),
3119
- children: "Try again"
3120
- }
3121
- ) })
3122
- ] }) : null,
3123
- isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading swaps..." }) }) : items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
3124
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No exchanges yet" }),
3125
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Exchange requests created by customers will appear here." })
3126
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
3127
- /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
3128
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Exchange ID" }),
3129
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
3130
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
3131
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Difference Due" }),
3132
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
3133
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
3134
- ] }) }),
3135
- /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((swap) => /* @__PURE__ */ jsxRuntime.jsxs(
3136
- "tr",
3137
- {
3138
- className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
3139
- onClick: () => navigate(`/swaps/${swap.id}`),
3140
- children: [
3141
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-0.5", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: swap.id }) }) }),
3142
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: swap.order_id }),
3143
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
3144
- ui.Badge,
3145
- {
3146
- size: "2xsmall",
3147
- className: `uppercase ${getStatusBadgeClass$4(swap.status)}`,
3148
- children: swap.status.replace(/_/g, " ")
3149
- }
3150
- ) }),
3151
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
3152
- const amount = swap.difference_due;
3153
- if (amount == null || amount === void 0) {
3154
- return "—";
3155
- }
3156
- const displayAmount = Number(amount) / 100;
3157
- const currency = swap.currency_code || "$";
3158
- const sign = displayAmount >= 0 ? "+" : "";
3159
- return `${sign}${currency}${displayAmount.toFixed(2)}`;
3160
- })() }),
3161
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(swap.created_at).toLocaleDateString("en-US", {
3162
- year: "numeric",
3163
- month: "short",
3164
- day: "numeric",
3165
- hour: "numeric",
3166
- minute: "2-digit",
3167
- hour12: true
3168
- }) }),
3169
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
3170
- ui.Button,
3171
- {
3172
- variant: "transparent",
3173
- size: "small",
3174
- onClick: (e) => {
3175
- e.stopPropagation();
3176
- navigate(`/app/orders/${swap.order_id}`);
3177
- },
3178
- children: "Go to order"
3179
- }
3180
- ) })
3181
- ]
3182
- },
3183
- swap.id
3184
- )) })
3185
- ] }) }),
3186
- hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
3187
- ui.Button,
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 params = reactRouterDom.useParams();
3213
- const id = (_a = params == null ? void 0 : params.id) == null ? void 0 : _a.trim();
3214
- const [detail, setDetail] = react.useState(null);
3215
- const [loading, setLoading] = react.useState(!!id);
3216
- const [error, setError] = react.useState(null);
3217
- react.useEffect(() => {
3218
- if (!id) {
3219
- setLoading(false);
3220
- return;
3221
- }
3222
- let cancelled = false;
3223
- setLoading(true);
3224
- setError(null);
3225
- fetch(`/admin/payment-transactions/${id}`, { credentials: "include" }).then((res) => {
3226
- if (!res.ok) throw new Error(res.statusText || "Failed to load");
3227
- return res.json();
3228
- }).then((data) => {
3229
- if (!cancelled) setDetail(data);
3230
- }).catch((e) => {
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
- cancelled = true;
3237
- };
3238
- }, [id]);
3239
- const displayStatus = detail ? (detail.payment_id != null && detail.payment_status != null && detail.payment_status !== "" ? detail.payment_status : detail.session_status ?? "") || "—" : "";
3240
- const sessionStatusRaw = (detail == null ? void 0 : detail.session_status) ?? "—";
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
- error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
3250
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
3251
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/payments"), children: "Back to list" })
3252
- ] }) : 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: [
3253
- /* @__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: [
3254
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3255
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Order ID" }),
3256
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: detail.order_id ? /* @__PURE__ */ jsxRuntime.jsx(
3257
- ui.Button,
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 config$3 = adminSdk.defineRouteConfig({
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 params = reactRouterDom.useParams();
3335
- const id = (_a = params == null ? void 0 : params.id) == null ? void 0 : _a.trim();
3336
- const [detail, setDetail] = react.useState(null);
3337
- const [loading, setLoading] = react.useState(!!id);
3338
- const [error, setError] = react.useState(null);
3339
- const [gatewayExpanded, setGatewayExpanded] = react.useState(false);
3340
- react.useEffect(() => {
3341
- if (!id) {
3342
- setLoading(false);
3343
- return;
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
- let cancelled = false;
3346
- setLoading(true);
3347
- setError(null);
3348
- fetch(`/admin/refunds/${id}`, { credentials: "include" }).then((res) => {
3349
- if (!res.ok) throw new Error(res.statusText || "Failed to load");
3350
- return res.json();
3351
- }).then((data) => {
3352
- if (!cancelled) setDetail(data);
3353
- }).catch((e) => {
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("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
3456
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Order summary" }),
3457
- detail.order ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
3458
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3459
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Order" }),
3460
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
3461
- ui.Button,
3462
- {
3463
- variant: "transparent",
3464
- size: "small",
3465
- onClick: () => navigate(`/orders/${detail.order.order_id}`),
3466
- children: detail.order.order_number ?? detail.order.order_id
3467
- }
3468
- ) })
3469
- ] }),
3470
- detail.order.total != null ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3471
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Total" }),
3472
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.order.total) })
3473
- ] }) : null,
3474
- detail.order.customer_id ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3475
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Customer ID" }),
3476
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.order.customer_id })
3477
- ] }) : null,
3478
- detail.order.region ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3479
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Region" }),
3480
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.region })
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
- detail.order.fulfillment_status ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3483
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Fulfillment status" }),
3484
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.fulfillment_status })
3485
- ] }) : null
3486
- ] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No order linked to this refund." })
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("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
3489
- /* @__PURE__ */ jsxRuntime.jsxs(
3490
- "button",
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
- type: "button",
3493
- className: "flex w-full items-center justify-between text-left",
3494
- onClick: () => setGatewayExpanded((prev) => !prev),
3495
- "aria-expanded": gatewayExpanded,
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
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg", children: "Gateway data" }),
3499
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: gatewayExpanded ? "Collapse" : "Expand" })
3358
+ "Open related ",
3359
+ link.label.toLowerCase(),
3360
+ /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRightMini, {})
3500
3361
  ]
3501
- }
3502
- ),
3503
- 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." }) })
3504
- ] })
3505
- ] }) : null
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 SAFE_KEYS = /* @__PURE__ */ new Set([
3539
- "token_type",
3540
- "redacted",
3541
- "api_key_id",
3542
- "token_id",
3543
- "notification_token_id"
3544
- ]);
3545
- function isSensitiveKey(key) {
3546
- const normalized = key.trim().toLowerCase();
3547
- if (SAFE_KEYS.has(normalized)) return false;
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
- /* @__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) })
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 JsonNode = ({ name, value, depth, forceExpand }) => {
3598
- const isContainer = value !== null && typeof value === "object";
3599
- const [open, setOpen] = react.useState(forceExpand ?? depth < AUTO_EXPAND_DEPTH);
3600
- const label = name !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-fg-subtle", children: [
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
- const entries = Array.isArray(value) ? value.map((v, i) => [String(i), v]) : Object.entries(value);
3614
- const [openBracket, closeBracket] = Array.isArray(value) ? ["[", "]"] : ["{", "}"];
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 (value === null || value === void 0) return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: "null" });
3649
- if (typeof value === "boolean") return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-tag-purple-text", children: String(value) });
3650
- if (typeof value === "number") return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-tag-blue-text", children: value });
3651
- const text = String(value);
3652
- const truncated = !showFull && text.length > LONG_STRING;
3653
- return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: ui.clx("text-ui-tag-green-text"), children: [
3654
- '"',
3655
- truncated ? `${text.slice(0, LONG_STRING)}…` : text,
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
- function getNextSteps(category) {
3735
- return GUIDANCE[category];
3736
- }
3737
- const RELATED_LINKS = [
3738
- { key: "order_id", label: "Order", path: (id) => `/orders/${id}`, selfTables: ["order"] },
3739
- { key: "customer_id", label: "Customer", path: (id) => `/customers/${id}`, selfTables: ["customer"] },
3740
- { key: "product_id", label: "Product", path: (id) => `/products/${id}`, selfTables: ["product"] }
3741
- ];
3742
- function getRelatedLinks(tableName, oldData) {
3743
- if (!oldData) return [];
3744
- return RELATED_LINKS.flatMap((link) => {
3745
- const id = oldData[link.key];
3746
- if (link.selfTables.includes(tableName) || typeof id !== "string" || !id.trim()) return [];
3747
- return [{ label: link.label, id, path: link.path(id) }];
3748
- });
3749
- }
3750
- const fullName = (row) => {
3751
- const parts = [row.first_name, row.last_name].filter(
3752
- (part) => typeof part === "string" && part.trim() !== ""
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
- return parts.length ? parts.join(" ") : void 0;
3755
- };
3756
- const addressLine = (row) => {
3757
- 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());
3758
- return parts.length ? parts.join(", ") : void 0;
3759
- };
3760
- const NAME = { key: "name", label: "Name", derive: fullName };
3761
- const ADDRESS = { key: "address", label: "Address", derive: addressLine };
3762
- const CREATED = { key: "created_at", label: "Created", kind: "date" };
3763
- const ENTITY_FIELDS = {
3764
- order: [
3765
- { key: "display_id", label: "Order number" },
3766
- { key: "status", label: "Status", kind: "status" },
3767
- { key: "email", label: "Customer email" },
3768
- { key: "customer_id", label: "Customer ID", kind: "id" },
3769
- { key: "currency_code", label: "Currency" },
3770
- { key: "region_id", label: "Region ID", kind: "id" },
3771
- { key: "sales_channel_id", label: "Sales channel ID", kind: "id" },
3772
- { key: "canceled_at", label: "Canceled", kind: "date" },
3773
- CREATED
3774
- ],
3775
- order_line_item: [
3776
- { key: "title", label: "Item" },
3777
- { key: "variant_title", label: "Variant" },
3778
- { key: "variant_sku", label: "SKU" },
3779
- { key: "unit_price", label: "Unit price", kind: "money" },
3780
- { key: "product_id", label: "Product ID", kind: "id" },
3781
- { key: "variant_id", label: "Variant ID", kind: "id" },
3782
- CREATED
3783
- ],
3784
- cart_line_item: [
3785
- { key: "title", label: "Item" },
3786
- { key: "variant_sku", label: "SKU" },
3787
- { key: "quantity", label: "Quantity", kind: "number" },
3788
- { key: "unit_price", label: "Unit price", kind: "money" },
3789
- { key: "cart_id", label: "Cart ID", kind: "id" },
3790
- { key: "variant_id", label: "Variant ID", kind: "id" },
3791
- CREATED
3792
- ],
3793
- cart: [
3794
- { key: "email", label: "Email" },
3795
- { key: "customer_id", label: "Customer ID", kind: "id" },
3796
- { key: "currency_code", label: "Currency" },
3797
- { key: "region_id", label: "Region ID", kind: "id" },
3798
- { key: "completed_at", label: "Completed", kind: "date" },
3799
- CREATED
3800
- ],
3801
- customer: [
3802
- NAME,
3803
- { key: "email", label: "Email" },
3804
- { key: "phone", label: "Phone" },
3805
- { key: "company_name", label: "Company" },
3806
- { key: "has_account", label: "Registered account", kind: "boolean" },
3807
- CREATED
3808
- ],
3809
- customer_address: [
3810
- { key: "address_name", label: "Label" },
3811
- NAME,
3812
- ADDRESS,
3813
- { key: "phone", label: "Phone" },
3814
- { key: "customer_id", label: "Customer ID", kind: "id" },
3815
- { key: "is_default_shipping", label: "Default shipping", kind: "boolean" },
3816
- CREATED
3817
- ],
3818
- order_address: [NAME, ADDRESS, { key: "phone", label: "Phone" }, CREATED],
3819
- cart_address: [NAME, ADDRESS, { key: "phone", label: "Phone" }, CREATED],
3820
- product: [
3821
- { key: "title", label: "Title" },
3822
- { key: "status", label: "Status", kind: "status" },
3823
- { key: "handle", label: "Handle" },
3824
- { key: "subtitle", label: "Subtitle" },
3825
- { key: "collection_id", label: "Collection ID", kind: "id" },
3826
- { key: "is_giftcard", label: "Gift card", kind: "boolean" },
3827
- CREATED
3828
- ],
3829
- product_variant: [
3830
- { key: "title", label: "Title" },
3831
- { key: "sku", label: "SKU" },
3832
- { key: "barcode", label: "Barcode" },
3833
- { key: "product_id", label: "Product ID", kind: "id" },
3834
- { key: "manage_inventory", label: "Manages inventory", kind: "boolean" },
3835
- CREATED
3836
- ],
3837
- product_category: [
3838
- { key: "name", label: "Name" },
3839
- { key: "handle", label: "Handle" },
3840
- { key: "is_active", label: "Active", kind: "boolean" },
3841
- { key: "parent_category_id", label: "Parent category ID", kind: "id" },
3842
- CREATED
3843
- ],
3844
- product_collection: [{ key: "title", label: "Title" }, { key: "handle", label: "Handle" }, CREATED],
3845
- payment: [
3846
- { key: "amount", label: "Amount", kind: "money" },
3847
- { key: "currency_code", label: "Currency" },
3848
- { key: "provider_id", label: "Provider" },
3849
- { key: "captured_at", label: "Captured", kind: "date" },
3850
- { key: "canceled_at", label: "Canceled", kind: "date" },
3851
- { key: "payment_collection_id", label: "Payment collection ID", kind: "id" },
3852
- CREATED
3853
- ],
3854
- payment_session: [
3855
- { key: "amount", label: "Amount", kind: "money" },
3856
- { key: "currency_code", label: "Currency" },
3857
- { key: "provider_id", label: "Provider" },
3858
- { key: "status", label: "Status", kind: "status" },
3859
- { key: "payment_collection_id", label: "Payment collection ID", kind: "id" },
3860
- CREATED
3861
- ],
3862
- payment_collection: [
3863
- { key: "amount", label: "Amount", kind: "money" },
3864
- { key: "currency_code", label: "Currency" },
3865
- { key: "status", label: "Status", kind: "status" },
3866
- CREATED
3867
- ],
3868
- refund: [
3869
- { key: "amount", label: "Amount", kind: "money" },
3870
- { key: "payment_id", label: "Payment ID", kind: "id" },
3871
- { key: "refund_reason_id", label: "Refund reason ID", kind: "id" },
3872
- { key: "note", label: "Note" },
3873
- { key: "created_by", label: "Created by" },
3874
- CREATED
3875
- ],
3876
- return: [
3877
- { key: "display_id", label: "Return number" },
3878
- { key: "status", label: "Status", kind: "status" },
3879
- { key: "order_id", label: "Order ID", kind: "id" },
3880
- { key: "refund_amount", label: "Refund amount", kind: "money" },
3881
- { key: "received_at", label: "Received", kind: "date" },
3882
- CREATED
3883
- ],
3884
- payment_detail: [
3885
- { key: "type", label: "Method type" },
3886
- { key: "customer_id", label: "Customer ID", kind: "id" },
3887
- { key: "is_default", label: "Default method", kind: "boolean" },
3888
- CREATED
3889
- ],
3890
- user: [NAME, { key: "email", label: "Email" }, CREATED],
3891
- invite: [
3892
- { key: "email", label: "Email" },
3893
- { key: "accepted", label: "Accepted", kind: "boolean" },
3894
- { key: "expires_at", label: "Expires", kind: "date" },
3895
- CREATED
3896
- ],
3897
- api_key: [
3898
- { key: "title", label: "Title" },
3899
- { key: "type", label: "Type" },
3900
- { key: "redacted", label: "Key (redacted)" },
3901
- { key: "revoked_at", label: "Revoked", kind: "date" },
3902
- CREATED
3903
- ],
3904
- promotion: [
3905
- { key: "code", label: "Promotion code" },
3906
- { key: "type", label: "Type" },
3907
- { key: "status", label: "Status", kind: "status" },
3908
- { key: "is_automatic", label: "Automatic", kind: "boolean" },
3909
- CREATED
3910
- ],
3911
- fulfillment: [
3912
- { key: "provider_id", label: "Provider" },
3913
- { key: "location_id", label: "Location ID", kind: "id" },
3914
- { key: "shipped_at", label: "Shipped", kind: "date" },
3915
- { key: "delivered_at", label: "Delivered", kind: "date" },
3916
- { key: "canceled_at", label: "Canceled", kind: "date" },
3917
- CREATED
3918
- ],
3919
- inventory_item: [
3920
- { key: "sku", label: "SKU" },
3921
- { key: "title", label: "Title" },
3922
- { key: "requires_shipping", label: "Requires shipping", kind: "boolean" },
3923
- CREATED
3924
- ],
3925
- inventory_level: [
3926
- { key: "inventory_item_id", label: "Inventory item ID", kind: "id" },
3927
- { key: "location_id", label: "Location ID", kind: "id" },
3928
- { key: "stocked_quantity", label: "Stocked", kind: "number" },
3929
- { key: "reserved_quantity", label: "Reserved", kind: "number" },
3930
- CREATED
3931
- ],
3932
- review: [
3933
- { key: "title", label: "Title" },
3934
- { key: "rating", label: "Rating", kind: "number" },
3935
- { key: "status", label: "Status", kind: "status" },
3936
- { key: "product_id", label: "Product ID", kind: "id" },
3937
- { key: "customer_id", label: "Customer ID", kind: "id" },
3938
- CREATED
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 GENERIC_FIELDS = [
3942
- { key: "display_id", label: "Number" },
3943
- { key: "title", label: "Title" },
3944
- { key: "name", label: "Name" },
3945
- NAME,
3946
- { key: "email", label: "Email" },
3947
- { key: "phone", label: "Phone" },
3948
- { key: "handle", label: "Handle" },
3949
- { key: "sku", label: "SKU" },
3950
- { key: "code", label: "Code" },
3951
- { key: "status", label: "Status", kind: "status" },
3952
- { key: "type", label: "Type" },
3953
- { key: "amount", label: "Amount", kind: "money" },
3954
- { key: "quantity", label: "Quantity", kind: "number" },
3955
- { key: "currency_code", label: "Currency" },
3956
- { key: "order_id", label: "Order ID", kind: "id" },
3957
- { key: "customer_id", label: "Customer ID", kind: "id" },
3958
- { key: "product_id", label: "Product ID", kind: "id" },
3959
- { key: "payment_id", label: "Payment ID", kind: "id" },
3960
- { key: "provider_id", label: "Provider" },
3961
- CREATED,
3962
- { key: "updated_at", label: "Last updated", kind: "date" }
3963
- ];
3964
- const MAX_GENERIC_FIELDS = 8;
3965
- function amountOf(value) {
3966
- if (typeof value === "number" && Number.isFinite(value)) return value;
3967
- if (typeof value === "string" && value.trim() !== "" && Number.isFinite(Number(value))) return Number(value);
3968
- if (value !== null && typeof value === "object" && "value" in value) {
3969
- return amountOf(value.value);
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
- return null;
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
- function summarizeOldData(tableName, oldData) {
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
- return fields;
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
- const DeletedRecordDetailPage = () => {
4025
- var _a;
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 location = reactRouterDom.useLocation();
4028
- const { id = "" } = reactRouterDom.useParams();
4029
- const [state, setState] = react.useState({ status: "loading" });
4030
- const [reloadToken, setReloadToken] = react.useState(0);
4031
- const cameFromList = ((_a = location.state) == null ? void 0 : _a.fromList) === true;
4032
- const goBack = () => {
4033
- if (cameFromList) navigate(-1);
4034
- else navigate(`/deleted-records-audit${readLastListSearch()}`);
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
- const controller = new AbortController();
4038
- setState({ status: "loading" });
4039
- fetchAuditDetail(id, controller.signal).then((audit) => setState({ status: "ready", audit })).catch((e) => {
4040
- if (controller.signal.aborted) return;
4041
- setState({
4042
- status: "error",
4043
- message: e instanceof Error ? e.message : "Unknown error",
4044
- notFound: e instanceof AuditApiError && e.status === 404
4045
- });
4046
- });
4047
- return () => controller.abort();
4048
- }, [id, reloadToken]);
4049
- 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: [
4050
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: "transparent", size: "small", onClick: goBack, className: "-ml-2", children: [
4051
- /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, {}),
4052
- "Back to Deleted Records"
4053
- ] }) }),
4054
- state.status === "loading" ? /* @__PURE__ */ jsxRuntime.jsx(DetailSkeleton, {}) : state.status === "error" ? /* @__PURE__ */ jsxRuntime.jsx(
4055
- DetailError,
4056
- {
4057
- notFound: state.notFound,
4058
- message: state.message,
4059
- onRetry: () => setReloadToken((t) => t + 1),
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
- ) : /* @__PURE__ */ jsxRuntime.jsx(DetailContent, { audit: state.audit })
4063
- ] }) });
4064
- };
4065
- const DetailContent = ({ audit }) => {
4066
- const navigate = reactRouterDom.useNavigate();
4067
- const entity = getEntityInfo(audit.table_name);
4068
- const source = describeSource(audit.source);
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
- await navigator.clipboard.writeText(JSON.stringify(masked.value, null, 2));
4077
- ui.toast.success("Record data copied", {
4078
- description: masked.maskedCount ? "Sensitive values were left hidden." : void 0
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
- } catch {
4081
- ui.toast.error("Couldn’t copy to clipboard");
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
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
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("div", { className: "flex flex-wrap items-center gap-2", children: [
4087
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Badge, { size: "small", color: "red", children: [
4088
- /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, {}),
4089
- "Deleted"
4090
- ] }),
4091
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: entity.category.label })
4092
- ] }),
4093
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Heading, { level: "h1", children: [
4094
- "Deleted ",
4095
- entity.label
4096
- ] }),
4097
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
4098
- /* @__PURE__ */ jsxRuntime.jsx(CopyableId, { value: audit.record_id, emptyLabel: "This record type has no ID column", className: "text-sm" }),
4099
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: [
4100
- "Database table: ",
4101
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: audit.table_name })
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 items-start gap-3 rounded-lg border border-ui-tag-orange-border bg-ui-tag-orange-bg px-4 py-3", children: [
4106
- /* @__PURE__ */ jsxRuntime.jsx(icons.InformationCircle, { className: "mt-0.5 shrink-0 text-ui-tag-orange-icon" }),
4107
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-tag-orange-text", children: [
4108
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "This is a historical snapshot" }),
4109
- " captured immediately before deletion. The record no longer exists in the database, so changes elsewhere in the admin are not reflected here."
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.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: [
4113
- /* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Deleted", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
4114
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: formatExactDateTime(audit.occurred_at) }),
4115
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1 text-xs text-ui-fg-muted", children: [
4116
- /* @__PURE__ */ jsxRuntime.jsx(icons.ClockSolid, { className: "size-3" }),
4117
- formatRelativeTime(audit.occurred_at)
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("ol", { className: "flex list-decimal flex-col gap-3 pl-5 text-sm text-ui-fg-subtle marker:text-ui-fg-muted", children: [
4167
- /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
4168
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: "Check whether this was expected." }),
4169
- " ",
4170
- 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)}.`,
4171
- " ",
4172
- guidance.headline
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("li", { children: [
4175
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: "If it needs to come back:" }),
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("li", { children: [
4180
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: "Need the details?" }),
4181
- " Use “View full record” above to see or copy everything that was stored. Sensitive values stay hidden."
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
- actions
4218
- ] }),
4219
- children
4220
- ] });
4221
- const Field = ({ label, children }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
4222
- /* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-xs font-medium uppercase tracking-wide text-ui-fg-muted", children: label }),
4223
- /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "min-w-0", children })
4224
- ] });
4225
- const DetailSkeleton = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", "aria-busy": "true", children: [
4226
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
4227
- /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-5 w-24 rounded-full" }),
4228
- /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-8 w-64" }),
4229
- /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-4 w-48" })
4230
- ] }),
4231
- /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-14 w-full" }),
4232
- 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: [
4233
- /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-5 w-40" }),
4234
- /* @__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: [
4235
- /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-3 w-20" }),
4236
- /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-4 w-36" })
4237
- ] }, j)) })
4238
- ] }, i))
4239
- ] });
4240
- const DetailError = ({
4241
- notFound,
4242
- message,
4243
- onRetry,
4244
- onBack
4245
- }) => /* @__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: [
4246
- /* @__PURE__ */ jsxRuntime.jsx(icons.ExclamationCircle, { className: ui.clx(notFound ? "text-ui-fg-muted" : "text-ui-fg-error") }),
4247
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: notFound ? "Audit entry not found" : "Unable to load this deleted record" }),
4248
- /* @__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." }),
4249
- !notFound ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "max-w-md font-mono text-ui-fg-muted", children: message }) : null,
4250
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex gap-2", children: [
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 statusLower = status.toLowerCase();
4541
- if (statusLower === "requested") {
4542
- return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
4543
- }
4544
- if (statusLower === "approved") {
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 SwapDetailPage = () => {
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 { id } = reactRouterDom.useParams();
4565
- const [swap, setSwap] = react.useState(null);
4566
- const [order, setOrder] = react.useState(null);
4567
- const [isLoading, setIsLoading] = react.useState(true);
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 [updateError, setUpdateError] = react.useState(null);
4572
- const [updateSuccess, setUpdateSuccess] = react.useState(false);
4645
+ const [gatewayExpanded, setGatewayExpanded] = react.useState(false);
4573
4646
  react.useEffect(() => {
4574
4647
  if (!id) {
4575
- navigate("/swaps");
4648
+ setLoading(false);
4576
4649
  return;
4577
4650
  }
4578
- const loadSwap = async () => {
4579
- try {
4580
- setIsLoading(true);
4581
- setError(null);
4582
- const response = await fetch(`/admin/swaps/${id}`, {
4583
- credentials: "include"
4584
- });
4585
- if (!response.ok) {
4586
- const message = await response.text();
4587
- throw new Error(message || "Unable to load swap");
4588
- }
4589
- const payload = await response.json();
4590
- setSwap(payload.swap);
4591
- setOrder(payload.order || null);
4592
- } catch (loadError) {
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
- void loadSwap();
4600
- }, [id, navigate]);
4601
- const handleCancelExchange = async () => {
4602
- if (!id) {
4603
- return;
4604
- }
4605
- try {
4606
- setIsCancelling(true);
4607
- setUpdateError(null);
4608
- setUpdateSuccess(false);
4609
- const response = await fetch(`/admin/swaps/${id}/cancel`, {
4610
- method: "POST",
4611
- headers: {
4612
- "Content-Type": "application/json"
4613
- },
4614
- credentials: "include"
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-subtle", children: "Exchange ID" }),
4702
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.id })
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-subtle", children: "Status" }),
4706
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.status })
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-subtle", children: "Difference Due" }),
4710
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.difference_due != null ? `${swap.currency_code || "$"}${(Number(swap.difference_due) / 100).toFixed(2)}` : "—" })
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-subtle", children: "Created" }),
4722
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(swap.created_at).toLocaleString() })
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-subtle", children: "Last Updated" }),
4726
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(swap.updated_at).toLocaleString() })
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
- swap.exchange_id && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
4729
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Exchange ID" }),
4730
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.exchange_id })
4731
- ] })
4732
- ] })
4733
- ] }),
4734
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
4735
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Status History" }),
4736
- statusHistory.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: statusHistory.map((entry, index) => /* @__PURE__ */ jsxRuntime.jsx(
4737
- "div",
4738
- {
4739
- className: "flex items-center justify-between border-b border-ui-border-subtle pb-2 last:border-0",
4740
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
4741
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
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: "Swap Details",
4816
- icon: icons.ArrowPath
4815
+ label: "Refund details",
4816
+ icon: icons.Receipt
4817
4817
  });
4818
4818
  const i18nTranslations0 = {};
4819
4819
  const widgetModule = { widgets: [
@@ -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: PaymentDetailPage,
4853
- path: "/payments/:id"
4852
+ Component: RefundsPage,
4853
+ path: "/refunds"
4854
4854
  },
4855
4855
  {
4856
- Component: RefundDetailPage,
4857
- path: "/refunds/:id"
4856
+ Component: PaymentDetailPage,
4857
+ path: "/payments/:id"
4858
4858
  },
4859
4859
  {
4860
- Component: DeletedRecordDetailPage,
4861
- path: "/deleted-records-audit/:id"
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: SwapDetailPage,
4869
- path: "/swaps/:id"
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$5.label,
4877
- icon: config$5.icon,
4878
- path: "/returns",
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: "/refunds",
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: "/swaps",
4902
+ path: "/refunds",
4891
4903
  nested: void 0
4892
4904
  },
4893
4905
  {
4894
- label: config$6.label,
4895
- icon: config$6.icon,
4896
- path: "/deleted-records-audit",
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: "/refunds/:id",
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: "/swaps/:id",
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
  ]