order-management 0.0.85 → 0.0.86
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.
|
@@ -2,7 +2,7 @@ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
|
2
2
|
import { defineWidgetConfig, defineRouteConfig } from "@medusajs/admin-sdk";
|
|
3
3
|
import { useState, useEffect, useRef, useCallback, useMemo } from "react";
|
|
4
4
|
import { Container, Text, Heading, Badge, Button, Label, Select, Textarea, Input } from "@medusajs/ui";
|
|
5
|
-
import { CashSolid, PencilSquareSolid, Trash,
|
|
5
|
+
import { CashSolid, PencilSquareSolid, Trash, ArrowPath, CreditCard, Receipt, ArrowLeft, CheckCircle } from "@medusajs/icons";
|
|
6
6
|
import { useNavigate, useParams } from "react-router-dom";
|
|
7
7
|
function roundRectPath(ctx, x, y, w, h, r) {
|
|
8
8
|
ctx.beginPath();
|
|
@@ -865,206 +865,6 @@ const useDebounce$3 = (value, delay) => {
|
|
|
865
865
|
return debouncedValue;
|
|
866
866
|
};
|
|
867
867
|
const getStatusBadgeClass$7 = (status) => {
|
|
868
|
-
const s2 = status.toLowerCase();
|
|
869
|
-
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
870
|
-
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
871
|
-
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
872
|
-
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
873
|
-
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
874
|
-
};
|
|
875
|
-
const PaymentsPage = () => {
|
|
876
|
-
const navigate = useNavigate();
|
|
877
|
-
const [items, setItems] = useState([]);
|
|
878
|
-
const [statusFilter, setStatusFilter] = useState("all");
|
|
879
|
-
const [orderIdSearch, setOrderIdSearch] = useState("");
|
|
880
|
-
const debouncedOrderId = useDebounce$3(orderIdSearch, 300);
|
|
881
|
-
const [isLoading, setIsLoading] = useState(true);
|
|
882
|
-
const [isFetchingMore, setIsFetchingMore] = useState(false);
|
|
883
|
-
const [error, setError] = useState(null);
|
|
884
|
-
const [offset, setOffset] = useState(0);
|
|
885
|
-
const [count, setCount] = useState(0);
|
|
886
|
-
const limit = 50;
|
|
887
|
-
const loadTransactions = useCallback(
|
|
888
|
-
async (nextOffset, replace) => {
|
|
889
|
-
try {
|
|
890
|
-
if (replace) setIsLoading(true);
|
|
891
|
-
else setIsFetchingMore(true);
|
|
892
|
-
setError(null);
|
|
893
|
-
const params = new URLSearchParams();
|
|
894
|
-
params.set("limit", String(limit));
|
|
895
|
-
params.set("offset", String(nextOffset));
|
|
896
|
-
if (statusFilter !== "all") params.set("status", statusFilter);
|
|
897
|
-
if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
|
|
898
|
-
const response = await fetch(
|
|
899
|
-
`/admin/payment-transactions?${params.toString()}`,
|
|
900
|
-
{ credentials: "include" }
|
|
901
|
-
);
|
|
902
|
-
if (!response.ok) {
|
|
903
|
-
const text = await response.text();
|
|
904
|
-
throw new Error(text || "Failed to load payment transactions");
|
|
905
|
-
}
|
|
906
|
-
const payload = await response.json();
|
|
907
|
-
const list = payload.transactions ?? [];
|
|
908
|
-
setCount(payload.count ?? 0);
|
|
909
|
-
setOffset(nextOffset + list.length);
|
|
910
|
-
setItems((prev) => replace ? list : [...prev, ...list]);
|
|
911
|
-
} catch (e) {
|
|
912
|
-
setError(e instanceof Error ? e.message : "Failed to load");
|
|
913
|
-
} finally {
|
|
914
|
-
setIsLoading(false);
|
|
915
|
-
setIsFetchingMore(false);
|
|
916
|
-
}
|
|
917
|
-
},
|
|
918
|
-
[statusFilter, debouncedOrderId]
|
|
919
|
-
);
|
|
920
|
-
useEffect(() => {
|
|
921
|
-
void loadTransactions(0, true);
|
|
922
|
-
}, [loadTransactions]);
|
|
923
|
-
const hasMore = useMemo(() => offset < count, [offset, count]);
|
|
924
|
-
const displayStatus = (t) => {
|
|
925
|
-
const s2 = t.payment_id != null && t.payment_status != null && t.payment_status !== "" ? t.payment_status : t.session_status ?? "";
|
|
926
|
-
return s2 !== "" ? s2 : "—";
|
|
927
|
-
};
|
|
928
|
-
const displayAmount = (t) => {
|
|
929
|
-
const code = (t.currency_code ?? "USD").toUpperCase();
|
|
930
|
-
return `${code} ${Number(t.amount)}`;
|
|
931
|
-
};
|
|
932
|
-
return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
|
|
933
|
-
/* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
934
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
935
|
-
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Payments" }),
|
|
936
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "All payment attempts — completed, pending, failed, requires action" })
|
|
937
|
-
] }),
|
|
938
|
-
/* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () => loadTransactions(0, true), children: "Refresh" })
|
|
939
|
-
] }),
|
|
940
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
941
|
-
/* @__PURE__ */ jsx(
|
|
942
|
-
Input,
|
|
943
|
-
{
|
|
944
|
-
placeholder: "Search by Order ID",
|
|
945
|
-
value: orderIdSearch,
|
|
946
|
-
onChange: (e) => setOrderIdSearch(e.target.value),
|
|
947
|
-
className: "md:max-w-sm",
|
|
948
|
-
"aria-label": "Search by order ID"
|
|
949
|
-
}
|
|
950
|
-
),
|
|
951
|
-
/* @__PURE__ */ jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsxs(
|
|
952
|
-
"select",
|
|
953
|
-
{
|
|
954
|
-
value: statusFilter,
|
|
955
|
-
onChange: (e) => setStatusFilter(e.target.value),
|
|
956
|
-
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",
|
|
957
|
-
"aria-label": "Filter by status",
|
|
958
|
-
children: [
|
|
959
|
-
/* @__PURE__ */ jsx("option", { value: "all", children: "All statuses" }),
|
|
960
|
-
/* @__PURE__ */ jsx("option", { value: "pending", children: "Pending" }),
|
|
961
|
-
/* @__PURE__ */ jsx("option", { value: "requires_more", children: "Requires more" }),
|
|
962
|
-
/* @__PURE__ */ jsx("option", { value: "error", children: "Error" }),
|
|
963
|
-
/* @__PURE__ */ jsx("option", { value: "canceled", children: "Canceled" }),
|
|
964
|
-
/* @__PURE__ */ jsx("option", { value: "authorized", children: "Authorized" }),
|
|
965
|
-
/* @__PURE__ */ jsx("option", { value: "captured", children: "Captured" })
|
|
966
|
-
]
|
|
967
|
-
}
|
|
968
|
-
) })
|
|
969
|
-
] }),
|
|
970
|
-
error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
971
|
-
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
972
|
-
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => loadTransactions(0, true), children: "Try again" }) })
|
|
973
|
-
] }) : null,
|
|
974
|
-
isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading payments…" }) }) : items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
975
|
-
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No payment transactions yet" }),
|
|
976
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Payment attempts will appear here." })
|
|
977
|
-
] }) : /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
978
|
-
/* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
979
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
980
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Amount" }),
|
|
981
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Provider" }),
|
|
982
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
983
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Finalized" }),
|
|
984
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
985
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
986
|
-
] }) }),
|
|
987
|
-
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((t) => /* @__PURE__ */ jsxs(
|
|
988
|
-
"tr",
|
|
989
|
-
{
|
|
990
|
-
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
991
|
-
onClick: () => navigate(`/payments/${t.payment_session_id}`),
|
|
992
|
-
children: [
|
|
993
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: t.order_id ?? "—" }),
|
|
994
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: displayAmount(t) }),
|
|
995
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.provider_id }),
|
|
996
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
|
|
997
|
-
Badge,
|
|
998
|
-
{
|
|
999
|
-
size: "2xsmall",
|
|
1000
|
-
className: `uppercase ${getStatusBadgeClass$7(displayStatus(t))}`,
|
|
1001
|
-
children: displayStatus(t) !== "—" ? displayStatus(t).replace(/_/g, " ") : "—"
|
|
1002
|
-
}
|
|
1003
|
-
) }),
|
|
1004
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.payment_id != null ? "Yes" : "No" }),
|
|
1005
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(t.created_at).toLocaleDateString("en-US", {
|
|
1006
|
-
year: "numeric",
|
|
1007
|
-
month: "short",
|
|
1008
|
-
day: "numeric",
|
|
1009
|
-
hour: "numeric",
|
|
1010
|
-
minute: "2-digit",
|
|
1011
|
-
hour12: true
|
|
1012
|
-
}) }),
|
|
1013
|
-
/* @__PURE__ */ jsxs("td", { className: "px-4 py-4", children: [
|
|
1014
|
-
/* @__PURE__ */ jsx(
|
|
1015
|
-
Button,
|
|
1016
|
-
{
|
|
1017
|
-
variant: "transparent",
|
|
1018
|
-
size: "small",
|
|
1019
|
-
onClick: (e) => {
|
|
1020
|
-
e.stopPropagation();
|
|
1021
|
-
navigate(`/payments/${t.payment_session_id}`);
|
|
1022
|
-
},
|
|
1023
|
-
children: "View details"
|
|
1024
|
-
}
|
|
1025
|
-
),
|
|
1026
|
-
t.order_id ? /* @__PURE__ */ jsx(
|
|
1027
|
-
Button,
|
|
1028
|
-
{
|
|
1029
|
-
variant: "transparent",
|
|
1030
|
-
size: "small",
|
|
1031
|
-
onClick: (e) => {
|
|
1032
|
-
e.stopPropagation();
|
|
1033
|
-
navigate(`/orders/${t.order_id}`);
|
|
1034
|
-
},
|
|
1035
|
-
children: "Order"
|
|
1036
|
-
}
|
|
1037
|
-
) : null
|
|
1038
|
-
] })
|
|
1039
|
-
]
|
|
1040
|
-
},
|
|
1041
|
-
t.payment_session_id
|
|
1042
|
-
)) })
|
|
1043
|
-
] }) }),
|
|
1044
|
-
hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
|
|
1045
|
-
Button,
|
|
1046
|
-
{
|
|
1047
|
-
variant: "secondary",
|
|
1048
|
-
isLoading: isFetchingMore,
|
|
1049
|
-
onClick: () => loadTransactions(offset, false),
|
|
1050
|
-
children: "Load more"
|
|
1051
|
-
}
|
|
1052
|
-
) }) : null
|
|
1053
|
-
] }) });
|
|
1054
|
-
};
|
|
1055
|
-
const config$7 = defineRouteConfig({
|
|
1056
|
-
label: "Payments",
|
|
1057
|
-
icon: CreditCard
|
|
1058
|
-
});
|
|
1059
|
-
const useDebounce$2 = (value, delay) => {
|
|
1060
|
-
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
1061
|
-
useEffect(() => {
|
|
1062
|
-
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
1063
|
-
return () => clearTimeout(handler);
|
|
1064
|
-
}, [value, delay]);
|
|
1065
|
-
return debouncedValue;
|
|
1066
|
-
};
|
|
1067
|
-
const getStatusBadgeClass$6 = (status) => {
|
|
1068
868
|
const statusLower = status.toLowerCase();
|
|
1069
869
|
if (statusLower === "requested") {
|
|
1070
870
|
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
@@ -1089,7 +889,7 @@ const SwapsPage = () => {
|
|
|
1089
889
|
const [statusFilter, setStatusFilter] = useState("all");
|
|
1090
890
|
const [createdByFilter, setCreatedByFilter] = useState("all");
|
|
1091
891
|
const [searchQuery, setSearchQuery] = useState("");
|
|
1092
|
-
const debouncedSearchQuery = useDebounce$
|
|
892
|
+
const debouncedSearchQuery = useDebounce$3(searchQuery, 300);
|
|
1093
893
|
const [isLoading, setIsLoading] = useState(true);
|
|
1094
894
|
const [isFetchingMore, setIsFetchingMore] = useState(false);
|
|
1095
895
|
const [error, setError] = useState(null);
|
|
@@ -1232,7 +1032,7 @@ const SwapsPage = () => {
|
|
|
1232
1032
|
Badge,
|
|
1233
1033
|
{
|
|
1234
1034
|
size: "2xsmall",
|
|
1235
|
-
className: `uppercase ${getStatusBadgeClass$
|
|
1035
|
+
className: `uppercase ${getStatusBadgeClass$7(swap.status)}`,
|
|
1236
1036
|
children: swap.status.replace(/_/g, " ")
|
|
1237
1037
|
}
|
|
1238
1038
|
) }),
|
|
@@ -1282,11 +1082,11 @@ const SwapsPage = () => {
|
|
|
1282
1082
|
) }) : null
|
|
1283
1083
|
] }) });
|
|
1284
1084
|
};
|
|
1285
|
-
const config$
|
|
1085
|
+
const config$7 = defineRouteConfig({
|
|
1286
1086
|
label: "Exchanges",
|
|
1287
1087
|
icon: ArrowPath
|
|
1288
1088
|
});
|
|
1289
|
-
const useDebounce$
|
|
1089
|
+
const useDebounce$2 = (value, delay) => {
|
|
1290
1090
|
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
1291
1091
|
useEffect(() => {
|
|
1292
1092
|
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
@@ -1294,276 +1094,213 @@ const useDebounce$1 = (value, delay) => {
|
|
|
1294
1094
|
}, [value, delay]);
|
|
1295
1095
|
return debouncedValue;
|
|
1296
1096
|
};
|
|
1297
|
-
const getStatusBadgeClass$
|
|
1298
|
-
const
|
|
1299
|
-
if (
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
if (
|
|
1097
|
+
const getStatusBadgeClass$6 = (status) => {
|
|
1098
|
+
const statusLower = status.toLowerCase();
|
|
1099
|
+
if (statusLower === "requested") {
|
|
1100
|
+
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
1101
|
+
}
|
|
1102
|
+
if (statusLower === "received") {
|
|
1103
|
+
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
1104
|
+
}
|
|
1105
|
+
if (statusLower === "requires_action") {
|
|
1106
|
+
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
1107
|
+
}
|
|
1108
|
+
if (statusLower === "completed") {
|
|
1109
|
+
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
1110
|
+
}
|
|
1111
|
+
if (statusLower === "canceled") {
|
|
1112
|
+
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
1113
|
+
}
|
|
1303
1114
|
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
1304
1115
|
};
|
|
1305
|
-
const
|
|
1116
|
+
const ReturnsPage = () => {
|
|
1306
1117
|
const navigate = useNavigate();
|
|
1307
1118
|
const [items, setItems] = useState([]);
|
|
1308
|
-
const [
|
|
1309
|
-
const
|
|
1310
|
-
const [
|
|
1311
|
-
const
|
|
1312
|
-
const debouncedProvider = useDebounce$1(providerSearch, 300);
|
|
1313
|
-
const [currencySearch, setCurrencySearch] = useState("");
|
|
1314
|
-
const debouncedCurrency = useDebounce$1(currencySearch, 300);
|
|
1315
|
-
const [dateFrom, setDateFrom] = useState("");
|
|
1316
|
-
const [dateTo, setDateTo] = useState("");
|
|
1317
|
-
const [amountMin, setAmountMin] = useState("");
|
|
1318
|
-
const [amountMax, setAmountMax] = useState("");
|
|
1119
|
+
const [statusFilter, setStatusFilter] = useState("all");
|
|
1120
|
+
const [createdByFilter, setCreatedByFilter] = useState("all");
|
|
1121
|
+
const [searchQuery, setSearchQuery] = useState("");
|
|
1122
|
+
const debouncedSearchQuery = useDebounce$2(searchQuery, 300);
|
|
1319
1123
|
const [isLoading, setIsLoading] = useState(true);
|
|
1320
1124
|
const [isFetchingMore, setIsFetchingMore] = useState(false);
|
|
1321
1125
|
const [error, setError] = useState(null);
|
|
1322
1126
|
const [offset, setOffset] = useState(0);
|
|
1323
1127
|
const [count, setCount] = useState(0);
|
|
1324
1128
|
const limit = 50;
|
|
1325
|
-
const
|
|
1326
|
-
async (nextOffset, replace) => {
|
|
1129
|
+
const loadReturns = useCallback(
|
|
1130
|
+
async (nextOffset, replace = false) => {
|
|
1131
|
+
var _a;
|
|
1327
1132
|
try {
|
|
1328
|
-
if (replace)
|
|
1329
|
-
|
|
1133
|
+
if (replace) {
|
|
1134
|
+
setIsLoading(true);
|
|
1135
|
+
} else {
|
|
1136
|
+
setIsFetchingMore(true);
|
|
1137
|
+
}
|
|
1330
1138
|
setError(null);
|
|
1331
1139
|
const params = new URLSearchParams();
|
|
1332
1140
|
params.set("limit", String(limit));
|
|
1333
1141
|
params.set("offset", String(nextOffset));
|
|
1334
|
-
if (
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
if (
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
const response = await fetch(
|
|
1345
|
-
|
|
1346
|
-
|
|
1142
|
+
if (statusFilter !== "all") {
|
|
1143
|
+
params.set("status", statusFilter);
|
|
1144
|
+
}
|
|
1145
|
+
if (debouncedSearchQuery.trim()) {
|
|
1146
|
+
params.set("q", debouncedSearchQuery.trim());
|
|
1147
|
+
}
|
|
1148
|
+
if (createdByFilter !== "all") {
|
|
1149
|
+
params.set("created_by", createdByFilter);
|
|
1150
|
+
}
|
|
1151
|
+
params.set("order", "created_at");
|
|
1152
|
+
const response = await fetch(
|
|
1153
|
+
`/admin/return?${params.toString()}`,
|
|
1154
|
+
{ credentials: "include" }
|
|
1155
|
+
);
|
|
1347
1156
|
if (!response.ok) {
|
|
1348
|
-
const
|
|
1349
|
-
throw new Error(
|
|
1157
|
+
const message = await response.text();
|
|
1158
|
+
throw new Error(message || "Unable to load return orders");
|
|
1350
1159
|
}
|
|
1351
1160
|
const payload = await response.json();
|
|
1352
|
-
const list = payload.refunds ?? [];
|
|
1353
1161
|
setCount(payload.count ?? 0);
|
|
1354
|
-
setOffset(nextOffset +
|
|
1355
|
-
setItems(
|
|
1356
|
-
|
|
1357
|
-
|
|
1162
|
+
setOffset(nextOffset + (((_a = payload.returns) == null ? void 0 : _a.length) ?? 0));
|
|
1163
|
+
setItems(
|
|
1164
|
+
(prev) => replace ? payload.returns ?? [] : [...prev, ...payload.returns ?? []]
|
|
1165
|
+
);
|
|
1166
|
+
} catch (loadError) {
|
|
1167
|
+
const message = loadError instanceof Error ? loadError.message : "Unable to load return orders";
|
|
1168
|
+
setError(message);
|
|
1358
1169
|
} finally {
|
|
1359
1170
|
setIsLoading(false);
|
|
1360
1171
|
setIsFetchingMore(false);
|
|
1361
1172
|
}
|
|
1362
1173
|
},
|
|
1363
|
-
[
|
|
1364
|
-
debouncedOrderId,
|
|
1365
|
-
paymentStatusFilter,
|
|
1366
|
-
debouncedProvider,
|
|
1367
|
-
debouncedCurrency,
|
|
1368
|
-
dateFrom,
|
|
1369
|
-
dateTo,
|
|
1370
|
-
amountMin,
|
|
1371
|
-
amountMax
|
|
1372
|
-
]
|
|
1174
|
+
[statusFilter, createdByFilter, debouncedSearchQuery]
|
|
1373
1175
|
);
|
|
1374
1176
|
useEffect(() => {
|
|
1375
|
-
void
|
|
1376
|
-
}, [
|
|
1177
|
+
void loadReturns(0, true);
|
|
1178
|
+
}, [statusFilter, createdByFilter, debouncedSearchQuery, loadReturns]);
|
|
1377
1179
|
const hasMore = useMemo(() => offset < count, [offset, count]);
|
|
1378
|
-
const
|
|
1379
|
-
const
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
const s2 = r.payment_status ?? "";
|
|
1384
|
-
return s2 !== "" ? s2 : "—";
|
|
1385
|
-
};
|
|
1180
|
+
const availableStatuses = useMemo(() => {
|
|
1181
|
+
const statuses = /* @__PURE__ */ new Set();
|
|
1182
|
+
items.forEach((item) => statuses.add(item.status));
|
|
1183
|
+
return Array.from(statuses).sort();
|
|
1184
|
+
}, [items]);
|
|
1386
1185
|
return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
|
|
1387
1186
|
/* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
1388
1187
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1389
|
-
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "
|
|
1390
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "
|
|
1188
|
+
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Return Orders" }),
|
|
1189
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "View and manage all customer return orders" })
|
|
1391
1190
|
] }),
|
|
1392
|
-
/* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () =>
|
|
1191
|
+
/* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () => loadReturns(0, true), children: "Refresh" })
|
|
1393
1192
|
] }),
|
|
1394
|
-
/* @__PURE__ */
|
|
1395
|
-
/* @__PURE__ */ jsx(
|
|
1396
|
-
Input,
|
|
1397
|
-
{
|
|
1398
|
-
placeholder: "Order ID",
|
|
1399
|
-
value: orderIdSearch,
|
|
1400
|
-
onChange: (e) => setOrderIdSearch(e.target.value),
|
|
1401
|
-
className: "md:max-w-[180px]",
|
|
1402
|
-
"aria-label": "Filter by order ID"
|
|
1403
|
-
}
|
|
1404
|
-
),
|
|
1405
|
-
/* @__PURE__ */ jsx(
|
|
1406
|
-
Input,
|
|
1407
|
-
{
|
|
1408
|
-
placeholder: "Provider",
|
|
1409
|
-
value: providerSearch,
|
|
1410
|
-
onChange: (e) => setProviderSearch(e.target.value),
|
|
1411
|
-
className: "md:max-w-[140px]",
|
|
1412
|
-
"aria-label": "Filter by provider"
|
|
1413
|
-
}
|
|
1414
|
-
),
|
|
1415
|
-
/* @__PURE__ */ jsx(
|
|
1416
|
-
Input,
|
|
1417
|
-
{
|
|
1418
|
-
placeholder: "Currency",
|
|
1419
|
-
value: currencySearch,
|
|
1420
|
-
onChange: (e) => setCurrencySearch(e.target.value),
|
|
1421
|
-
className: "md:max-w-[100px]",
|
|
1422
|
-
"aria-label": "Filter by currency"
|
|
1423
|
-
}
|
|
1424
|
-
),
|
|
1425
|
-
/* @__PURE__ */ jsxs(
|
|
1426
|
-
"select",
|
|
1427
|
-
{
|
|
1428
|
-
value: paymentStatusFilter,
|
|
1429
|
-
onChange: (e) => setPaymentStatusFilter(e.target.value),
|
|
1430
|
-
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]",
|
|
1431
|
-
"aria-label": "Filter by payment status",
|
|
1432
|
-
children: [
|
|
1433
|
-
/* @__PURE__ */ jsx("option", { value: "all", children: "All statuses" }),
|
|
1434
|
-
/* @__PURE__ */ jsx("option", { value: "pending", children: "Pending" }),
|
|
1435
|
-
/* @__PURE__ */ jsx("option", { value: "requires_more", children: "Requires more" }),
|
|
1436
|
-
/* @__PURE__ */ jsx("option", { value: "error", children: "Error" }),
|
|
1437
|
-
/* @__PURE__ */ jsx("option", { value: "canceled", children: "Canceled" }),
|
|
1438
|
-
/* @__PURE__ */ jsx("option", { value: "authorized", children: "Authorized" }),
|
|
1439
|
-
/* @__PURE__ */ jsx("option", { value: "captured", children: "Captured" })
|
|
1440
|
-
]
|
|
1441
|
-
}
|
|
1442
|
-
),
|
|
1443
|
-
/* @__PURE__ */ jsx(
|
|
1444
|
-
Input,
|
|
1445
|
-
{
|
|
1446
|
-
type: "date",
|
|
1447
|
-
placeholder: "From",
|
|
1448
|
-
value: dateFrom,
|
|
1449
|
-
onChange: (e) => setDateFrom(e.target.value),
|
|
1450
|
-
className: "md:max-w-[140px]",
|
|
1451
|
-
"aria-label": "Date from"
|
|
1452
|
-
}
|
|
1453
|
-
),
|
|
1454
|
-
/* @__PURE__ */ jsx(
|
|
1455
|
-
Input,
|
|
1456
|
-
{
|
|
1457
|
-
type: "date",
|
|
1458
|
-
placeholder: "To",
|
|
1459
|
-
value: dateTo,
|
|
1460
|
-
onChange: (e) => setDateTo(e.target.value),
|
|
1461
|
-
className: "md:max-w-[140px]",
|
|
1462
|
-
"aria-label": "Date to"
|
|
1463
|
-
}
|
|
1464
|
-
),
|
|
1193
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
1465
1194
|
/* @__PURE__ */ jsx(
|
|
1466
1195
|
Input,
|
|
1467
1196
|
{
|
|
1468
|
-
placeholder: "
|
|
1469
|
-
value:
|
|
1470
|
-
onChange: (
|
|
1471
|
-
|
|
1472
|
-
min: 0,
|
|
1473
|
-
className: "md:max-w-[100px]",
|
|
1474
|
-
"aria-label": "Refund amount minimum"
|
|
1197
|
+
placeholder: "Search by return ID, order ID, or customer email",
|
|
1198
|
+
value: searchQuery,
|
|
1199
|
+
onChange: (event) => setSearchQuery(event.target.value),
|
|
1200
|
+
className: "md:max-w-sm"
|
|
1475
1201
|
}
|
|
1476
1202
|
),
|
|
1477
|
-
/* @__PURE__ */
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1203
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
|
|
1204
|
+
/* @__PURE__ */ jsxs(
|
|
1205
|
+
"select",
|
|
1206
|
+
{
|
|
1207
|
+
value: createdByFilter,
|
|
1208
|
+
onChange: (event) => setCreatedByFilter(event.target.value),
|
|
1209
|
+
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",
|
|
1210
|
+
children: [
|
|
1211
|
+
/* @__PURE__ */ jsx("option", { value: "all", children: "All (Created by)" }),
|
|
1212
|
+
/* @__PURE__ */ jsx("option", { value: "customer", children: "Customer" }),
|
|
1213
|
+
/* @__PURE__ */ jsx("option", { value: "admin", children: "Admin" })
|
|
1214
|
+
]
|
|
1215
|
+
}
|
|
1216
|
+
),
|
|
1217
|
+
/* @__PURE__ */ jsxs(
|
|
1218
|
+
"select",
|
|
1219
|
+
{
|
|
1220
|
+
value: statusFilter,
|
|
1221
|
+
onChange: (event) => setStatusFilter(event.target.value),
|
|
1222
|
+
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",
|
|
1223
|
+
children: [
|
|
1224
|
+
/* @__PURE__ */ jsx("option", { value: "all", children: "All Statuses" }),
|
|
1225
|
+
availableStatuses.map((status) => /* @__PURE__ */ jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
|
|
1226
|
+
]
|
|
1227
|
+
}
|
|
1228
|
+
)
|
|
1229
|
+
] })
|
|
1230
|
+
] }),
|
|
1490
1231
|
error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
1491
1232
|
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
1492
|
-
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(
|
|
1233
|
+
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(
|
|
1234
|
+
Button,
|
|
1235
|
+
{
|
|
1236
|
+
variant: "secondary",
|
|
1237
|
+
onClick: () => loadReturns(0, true),
|
|
1238
|
+
children: "Try again"
|
|
1239
|
+
}
|
|
1240
|
+
) })
|
|
1493
1241
|
] }) : null,
|
|
1494
|
-
isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading
|
|
1495
|
-
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No
|
|
1496
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "
|
|
1497
|
-
] }) : /* @__PURE__ */ jsx("div", { className: "
|
|
1242
|
+
isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading return orders..." }) }) : items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
1243
|
+
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No return orders yet" }),
|
|
1244
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Return orders created by customers will appear here." })
|
|
1245
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
1498
1246
|
/* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
1499
|
-
/* @__PURE__ */ jsx("th", { className: "
|
|
1500
|
-
/* @__PURE__ */ jsx("th", { className: "
|
|
1501
|
-
/* @__PURE__ */ jsx("th", { className: "
|
|
1502
|
-
/* @__PURE__ */ jsx("th", { className: "
|
|
1503
|
-
/* @__PURE__ */ jsx("th", { className: "
|
|
1504
|
-
/* @__PURE__ */ jsx("th", { className: "
|
|
1505
|
-
/* @__PURE__ */ jsx("th", { className: "
|
|
1506
|
-
/* @__PURE__ */ jsx("th", { className: "w-[14%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Note" }),
|
|
1507
|
-
/* @__PURE__ */ jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
1508
|
-
/* @__PURE__ */ jsx("th", { className: "w-[8%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
1247
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Return ID" }),
|
|
1248
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
1249
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Customer" }),
|
|
1250
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
1251
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Refund Amount" }),
|
|
1252
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
1253
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
1509
1254
|
] }) }),
|
|
1510
|
-
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((
|
|
1255
|
+
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((returnOrder) => /* @__PURE__ */ jsxs(
|
|
1511
1256
|
"tr",
|
|
1512
1257
|
{
|
|
1513
|
-
className: "
|
|
1514
|
-
onClick: () => navigate(`/
|
|
1258
|
+
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
1259
|
+
onClick: () => navigate(`/returns/${returnOrder.id}`),
|
|
1515
1260
|
children: [
|
|
1516
|
-
/* @__PURE__ */ jsx("td", { className: "
|
|
1517
|
-
/* @__PURE__ */ jsx("td", { className: "
|
|
1518
|
-
/* @__PURE__ */ jsx("td", { className: "
|
|
1519
|
-
/* @__PURE__ */ jsx("td", { className: "
|
|
1520
|
-
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle uppercase", children: r.currency_code || "—" }),
|
|
1521
|
-
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", title: r.provider_id || void 0, children: r.provider_id || "—" }),
|
|
1522
|
-
/* @__PURE__ */ jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsx(
|
|
1261
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children: /* @__PURE__ */ jsx("span", { children: returnOrder.id }) }) }),
|
|
1262
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.order_id }),
|
|
1263
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.customer_email || returnOrder.order_email || "—" }),
|
|
1264
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
|
|
1523
1265
|
Badge,
|
|
1524
1266
|
{
|
|
1525
1267
|
size: "2xsmall",
|
|
1526
|
-
className: `uppercase ${getStatusBadgeClass$
|
|
1527
|
-
children:
|
|
1268
|
+
className: `uppercase ${getStatusBadgeClass$6(returnOrder.status)}`,
|
|
1269
|
+
children: returnOrder.status.replace(/_/g, " ")
|
|
1528
1270
|
}
|
|
1529
1271
|
) }),
|
|
1530
|
-
/* @__PURE__ */ jsx("td", { className: "
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1272
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
|
|
1273
|
+
const amount = returnOrder.refund_amount;
|
|
1274
|
+
if (amount == null || amount === void 0) {
|
|
1275
|
+
return "—";
|
|
1276
|
+
}
|
|
1277
|
+
const displayAmount = Number(amount) / 100;
|
|
1278
|
+
const currency = returnOrder.currency_code || "$";
|
|
1279
|
+
return `${currency}${displayAmount.toFixed(2)}`;
|
|
1280
|
+
})() }),
|
|
1281
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(returnOrder.created_at).toLocaleDateString("en-US", {
|
|
1282
|
+
year: "numeric",
|
|
1283
|
+
month: "short",
|
|
1284
|
+
day: "numeric",
|
|
1285
|
+
hour: "numeric",
|
|
1535
1286
|
minute: "2-digit",
|
|
1536
1287
|
hour12: true
|
|
1537
1288
|
}) }),
|
|
1538
|
-
/* @__PURE__ */ jsx("td", { className: "
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
),
|
|
1551
|
-
r.order_id ? /* @__PURE__ */ jsx(
|
|
1552
|
-
Button,
|
|
1553
|
-
{
|
|
1554
|
-
variant: "transparent",
|
|
1555
|
-
size: "small",
|
|
1556
|
-
onClick: (e) => {
|
|
1557
|
-
e.stopPropagation();
|
|
1558
|
-
navigate(`/orders/${r.order_id}`);
|
|
1559
|
-
},
|
|
1560
|
-
children: "Order"
|
|
1561
|
-
}
|
|
1562
|
-
) : null
|
|
1563
|
-
] }) })
|
|
1289
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
|
|
1290
|
+
Button,
|
|
1291
|
+
{
|
|
1292
|
+
variant: "transparent",
|
|
1293
|
+
size: "small",
|
|
1294
|
+
onClick: (e) => {
|
|
1295
|
+
e.stopPropagation();
|
|
1296
|
+
navigate(`/app/orders/${returnOrder.order_id}`);
|
|
1297
|
+
},
|
|
1298
|
+
children: "Go to order"
|
|
1299
|
+
}
|
|
1300
|
+
) })
|
|
1564
1301
|
]
|
|
1565
1302
|
},
|
|
1566
|
-
|
|
1303
|
+
returnOrder.id
|
|
1567
1304
|
)) })
|
|
1568
1305
|
] }) }),
|
|
1569
1306
|
hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
|
|
@@ -1571,17 +1308,17 @@ const RefundsPage = () => {
|
|
|
1571
1308
|
{
|
|
1572
1309
|
variant: "secondary",
|
|
1573
1310
|
isLoading: isFetchingMore,
|
|
1574
|
-
onClick: () =>
|
|
1311
|
+
onClick: () => loadReturns(offset, false),
|
|
1575
1312
|
children: "Load more"
|
|
1576
1313
|
}
|
|
1577
1314
|
) }) : null
|
|
1578
1315
|
] }) });
|
|
1579
1316
|
};
|
|
1580
|
-
const config$
|
|
1581
|
-
label: "
|
|
1582
|
-
icon:
|
|
1317
|
+
const config$6 = defineRouteConfig({
|
|
1318
|
+
label: "Return Orders",
|
|
1319
|
+
icon: ArrowPath
|
|
1583
1320
|
});
|
|
1584
|
-
const useDebounce = (value, delay) => {
|
|
1321
|
+
const useDebounce$1 = (value, delay) => {
|
|
1585
1322
|
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
1586
1323
|
useEffect(() => {
|
|
1587
1324
|
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
@@ -1589,191 +1326,145 @@ const useDebounce = (value, delay) => {
|
|
|
1589
1326
|
}, [value, delay]);
|
|
1590
1327
|
return debouncedValue;
|
|
1591
1328
|
};
|
|
1592
|
-
const getStatusBadgeClass$
|
|
1593
|
-
const
|
|
1594
|
-
if (
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
if (
|
|
1598
|
-
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
1599
|
-
}
|
|
1600
|
-
if (statusLower === "requires_action") {
|
|
1601
|
-
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
1602
|
-
}
|
|
1603
|
-
if (statusLower === "completed") {
|
|
1604
|
-
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
1605
|
-
}
|
|
1606
|
-
if (statusLower === "canceled") {
|
|
1607
|
-
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
1608
|
-
}
|
|
1329
|
+
const getStatusBadgeClass$5 = (status) => {
|
|
1330
|
+
const s2 = status.toLowerCase();
|
|
1331
|
+
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
1332
|
+
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
1333
|
+
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
1334
|
+
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
1609
1335
|
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
1610
1336
|
};
|
|
1611
|
-
const
|
|
1337
|
+
const PaymentsPage = () => {
|
|
1612
1338
|
const navigate = useNavigate();
|
|
1613
1339
|
const [items, setItems] = useState([]);
|
|
1614
1340
|
const [statusFilter, setStatusFilter] = useState("all");
|
|
1615
|
-
const [
|
|
1616
|
-
const
|
|
1617
|
-
const debouncedSearchQuery = useDebounce(searchQuery, 300);
|
|
1341
|
+
const [orderIdSearch, setOrderIdSearch] = useState("");
|
|
1342
|
+
const debouncedOrderId = useDebounce$1(orderIdSearch, 300);
|
|
1618
1343
|
const [isLoading, setIsLoading] = useState(true);
|
|
1619
1344
|
const [isFetchingMore, setIsFetchingMore] = useState(false);
|
|
1620
1345
|
const [error, setError] = useState(null);
|
|
1621
1346
|
const [offset, setOffset] = useState(0);
|
|
1622
1347
|
const [count, setCount] = useState(0);
|
|
1623
1348
|
const limit = 50;
|
|
1624
|
-
const
|
|
1625
|
-
async (nextOffset, replace
|
|
1626
|
-
var _a;
|
|
1349
|
+
const loadTransactions = useCallback(
|
|
1350
|
+
async (nextOffset, replace) => {
|
|
1627
1351
|
try {
|
|
1628
|
-
if (replace)
|
|
1629
|
-
|
|
1630
|
-
} else {
|
|
1631
|
-
setIsFetchingMore(true);
|
|
1632
|
-
}
|
|
1352
|
+
if (replace) setIsLoading(true);
|
|
1353
|
+
else setIsFetchingMore(true);
|
|
1633
1354
|
setError(null);
|
|
1634
1355
|
const params = new URLSearchParams();
|
|
1635
1356
|
params.set("limit", String(limit));
|
|
1636
1357
|
params.set("offset", String(nextOffset));
|
|
1637
|
-
if (statusFilter !== "all")
|
|
1638
|
-
|
|
1639
|
-
}
|
|
1640
|
-
if (debouncedSearchQuery.trim()) {
|
|
1641
|
-
params.set("q", debouncedSearchQuery.trim());
|
|
1642
|
-
}
|
|
1643
|
-
if (createdByFilter !== "all") {
|
|
1644
|
-
params.set("created_by", createdByFilter);
|
|
1645
|
-
}
|
|
1646
|
-
params.set("order", "created_at");
|
|
1358
|
+
if (statusFilter !== "all") params.set("status", statusFilter);
|
|
1359
|
+
if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
|
|
1647
1360
|
const response = await fetch(
|
|
1648
|
-
`/admin/
|
|
1361
|
+
`/admin/payment-transactions?${params.toString()}`,
|
|
1649
1362
|
{ credentials: "include" }
|
|
1650
1363
|
);
|
|
1651
1364
|
if (!response.ok) {
|
|
1652
|
-
const
|
|
1653
|
-
throw new Error(
|
|
1365
|
+
const text = await response.text();
|
|
1366
|
+
throw new Error(text || "Failed to load payment transactions");
|
|
1654
1367
|
}
|
|
1655
1368
|
const payload = await response.json();
|
|
1369
|
+
const list = payload.transactions ?? [];
|
|
1656
1370
|
setCount(payload.count ?? 0);
|
|
1657
|
-
setOffset(nextOffset +
|
|
1658
|
-
setItems(
|
|
1659
|
-
|
|
1660
|
-
);
|
|
1661
|
-
} catch (loadError) {
|
|
1662
|
-
const message = loadError instanceof Error ? loadError.message : "Unable to load return orders";
|
|
1663
|
-
setError(message);
|
|
1371
|
+
setOffset(nextOffset + list.length);
|
|
1372
|
+
setItems((prev) => replace ? list : [...prev, ...list]);
|
|
1373
|
+
} catch (e) {
|
|
1374
|
+
setError(e instanceof Error ? e.message : "Failed to load");
|
|
1664
1375
|
} finally {
|
|
1665
1376
|
setIsLoading(false);
|
|
1666
1377
|
setIsFetchingMore(false);
|
|
1667
1378
|
}
|
|
1668
1379
|
},
|
|
1669
|
-
[statusFilter,
|
|
1380
|
+
[statusFilter, debouncedOrderId]
|
|
1670
1381
|
);
|
|
1671
1382
|
useEffect(() => {
|
|
1672
|
-
void
|
|
1673
|
-
}, [
|
|
1383
|
+
void loadTransactions(0, true);
|
|
1384
|
+
}, [loadTransactions]);
|
|
1674
1385
|
const hasMore = useMemo(() => offset < count, [offset, count]);
|
|
1675
|
-
const
|
|
1676
|
-
const
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1386
|
+
const displayStatus = (t) => {
|
|
1387
|
+
const s2 = t.payment_id != null && t.payment_status != null && t.payment_status !== "" ? t.payment_status : t.session_status ?? "";
|
|
1388
|
+
return s2 !== "" ? s2 : "—";
|
|
1389
|
+
};
|
|
1390
|
+
const displayAmount = (t) => {
|
|
1391
|
+
const code = (t.currency_code ?? "USD").toUpperCase();
|
|
1392
|
+
return `${code} ${Number(t.amount)}`;
|
|
1393
|
+
};
|
|
1680
1394
|
return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
|
|
1681
1395
|
/* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
1682
1396
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1683
|
-
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "
|
|
1684
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "
|
|
1397
|
+
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Payments" }),
|
|
1398
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "All payment attempts — completed, pending, failed, requires action" })
|
|
1685
1399
|
] }),
|
|
1686
|
-
/* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () =>
|
|
1400
|
+
/* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () => loadTransactions(0, true), children: "Refresh" })
|
|
1687
1401
|
] }),
|
|
1688
1402
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
1689
1403
|
/* @__PURE__ */ jsx(
|
|
1690
1404
|
Input,
|
|
1691
1405
|
{
|
|
1692
|
-
placeholder: "Search by
|
|
1693
|
-
value:
|
|
1694
|
-
onChange: (
|
|
1695
|
-
className: "md:max-w-sm"
|
|
1406
|
+
placeholder: "Search by Order ID",
|
|
1407
|
+
value: orderIdSearch,
|
|
1408
|
+
onChange: (e) => setOrderIdSearch(e.target.value),
|
|
1409
|
+
className: "md:max-w-sm",
|
|
1410
|
+
"aria-label": "Search by order ID"
|
|
1696
1411
|
}
|
|
1697
1412
|
),
|
|
1698
|
-
/* @__PURE__ */
|
|
1699
|
-
|
|
1700
|
-
"select",
|
|
1701
|
-
{
|
|
1702
|
-
value: createdByFilter,
|
|
1703
|
-
onChange: (event) => setCreatedByFilter(event.target.value),
|
|
1704
|
-
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",
|
|
1705
|
-
children: [
|
|
1706
|
-
/* @__PURE__ */ jsx("option", { value: "all", children: "All (Created by)" }),
|
|
1707
|
-
/* @__PURE__ */ jsx("option", { value: "customer", children: "Customer" }),
|
|
1708
|
-
/* @__PURE__ */ jsx("option", { value: "admin", children: "Admin" })
|
|
1709
|
-
]
|
|
1710
|
-
}
|
|
1711
|
-
),
|
|
1712
|
-
/* @__PURE__ */ jsxs(
|
|
1713
|
-
"select",
|
|
1714
|
-
{
|
|
1715
|
-
value: statusFilter,
|
|
1716
|
-
onChange: (event) => setStatusFilter(event.target.value),
|
|
1717
|
-
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",
|
|
1718
|
-
children: [
|
|
1719
|
-
/* @__PURE__ */ jsx("option", { value: "all", children: "All Statuses" }),
|
|
1720
|
-
availableStatuses.map((status) => /* @__PURE__ */ jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
|
|
1721
|
-
]
|
|
1722
|
-
}
|
|
1723
|
-
)
|
|
1724
|
-
] })
|
|
1725
|
-
] }),
|
|
1726
|
-
error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
1727
|
-
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
1728
|
-
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(
|
|
1729
|
-
Button,
|
|
1413
|
+
/* @__PURE__ */ jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsxs(
|
|
1414
|
+
"select",
|
|
1730
1415
|
{
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1416
|
+
value: statusFilter,
|
|
1417
|
+
onChange: (e) => setStatusFilter(e.target.value),
|
|
1418
|
+
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",
|
|
1419
|
+
"aria-label": "Filter by status",
|
|
1420
|
+
children: [
|
|
1421
|
+
/* @__PURE__ */ jsx("option", { value: "all", children: "All statuses" }),
|
|
1422
|
+
/* @__PURE__ */ jsx("option", { value: "pending", children: "Pending" }),
|
|
1423
|
+
/* @__PURE__ */ jsx("option", { value: "requires_more", children: "Requires more" }),
|
|
1424
|
+
/* @__PURE__ */ jsx("option", { value: "error", children: "Error" }),
|
|
1425
|
+
/* @__PURE__ */ jsx("option", { value: "canceled", children: "Canceled" }),
|
|
1426
|
+
/* @__PURE__ */ jsx("option", { value: "authorized", children: "Authorized" }),
|
|
1427
|
+
/* @__PURE__ */ jsx("option", { value: "captured", children: "Captured" })
|
|
1428
|
+
]
|
|
1734
1429
|
}
|
|
1735
1430
|
) })
|
|
1431
|
+
] }),
|
|
1432
|
+
error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
1433
|
+
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
1434
|
+
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => loadTransactions(0, true), children: "Try again" }) })
|
|
1736
1435
|
] }) : null,
|
|
1737
|
-
isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading
|
|
1738
|
-
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No
|
|
1739
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "
|
|
1436
|
+
isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading payments…" }) }) : items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
1437
|
+
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No payment transactions yet" }),
|
|
1438
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Payment attempts will appear here." })
|
|
1740
1439
|
] }) : /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
1741
1440
|
/* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
1742
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Return ID" }),
|
|
1743
1441
|
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
1744
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "
|
|
1442
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Amount" }),
|
|
1443
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Provider" }),
|
|
1745
1444
|
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
1746
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "
|
|
1445
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Finalized" }),
|
|
1747
1446
|
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
1748
1447
|
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
1749
1448
|
] }) }),
|
|
1750
|
-
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((
|
|
1449
|
+
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((t) => /* @__PURE__ */ jsxs(
|
|
1751
1450
|
"tr",
|
|
1752
1451
|
{
|
|
1753
1452
|
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
1754
|
-
onClick: () => navigate(`/
|
|
1453
|
+
onClick: () => navigate(`/payments/${t.payment_session_id}`),
|
|
1755
1454
|
children: [
|
|
1756
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children:
|
|
1757
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children:
|
|
1758
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children:
|
|
1455
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: t.order_id ?? "—" }),
|
|
1456
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: displayAmount(t) }),
|
|
1457
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.provider_id }),
|
|
1759
1458
|
/* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
|
|
1760
1459
|
Badge,
|
|
1761
1460
|
{
|
|
1762
1461
|
size: "2xsmall",
|
|
1763
|
-
className: `uppercase ${getStatusBadgeClass$
|
|
1764
|
-
children:
|
|
1462
|
+
className: `uppercase ${getStatusBadgeClass$5(displayStatus(t))}`,
|
|
1463
|
+
children: displayStatus(t) !== "—" ? displayStatus(t).replace(/_/g, " ") : "—"
|
|
1765
1464
|
}
|
|
1766
1465
|
) }),
|
|
1767
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children:
|
|
1768
|
-
|
|
1769
|
-
if (amount == null || amount === void 0) {
|
|
1770
|
-
return "—";
|
|
1771
|
-
}
|
|
1772
|
-
const displayAmount = Number(amount) / 100;
|
|
1773
|
-
const currency = returnOrder.currency_code || "$";
|
|
1774
|
-
return `${currency}${displayAmount.toFixed(2)}`;
|
|
1775
|
-
})() }),
|
|
1776
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(returnOrder.created_at).toLocaleDateString("en-US", {
|
|
1466
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.payment_id != null ? "Yes" : "No" }),
|
|
1467
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(t.created_at).toLocaleDateString("en-US", {
|
|
1777
1468
|
year: "numeric",
|
|
1778
1469
|
month: "short",
|
|
1779
1470
|
day: "numeric",
|
|
@@ -1781,21 +1472,35 @@ const ReturnsPage = () => {
|
|
|
1781
1472
|
minute: "2-digit",
|
|
1782
1473
|
hour12: true
|
|
1783
1474
|
}) }),
|
|
1784
|
-
/* @__PURE__ */
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
e
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1475
|
+
/* @__PURE__ */ jsxs("td", { className: "px-4 py-4", children: [
|
|
1476
|
+
/* @__PURE__ */ jsx(
|
|
1477
|
+
Button,
|
|
1478
|
+
{
|
|
1479
|
+
variant: "transparent",
|
|
1480
|
+
size: "small",
|
|
1481
|
+
onClick: (e) => {
|
|
1482
|
+
e.stopPropagation();
|
|
1483
|
+
navigate(`/payments/${t.payment_session_id}`);
|
|
1484
|
+
},
|
|
1485
|
+
children: "View details"
|
|
1486
|
+
}
|
|
1487
|
+
),
|
|
1488
|
+
t.order_id ? /* @__PURE__ */ jsx(
|
|
1489
|
+
Button,
|
|
1490
|
+
{
|
|
1491
|
+
variant: "transparent",
|
|
1492
|
+
size: "small",
|
|
1493
|
+
onClick: (e) => {
|
|
1494
|
+
e.stopPropagation();
|
|
1495
|
+
navigate(`/orders/${t.order_id}`);
|
|
1496
|
+
},
|
|
1497
|
+
children: "Order"
|
|
1498
|
+
}
|
|
1499
|
+
) : null
|
|
1500
|
+
] })
|
|
1796
1501
|
]
|
|
1797
1502
|
},
|
|
1798
|
-
|
|
1503
|
+
t.payment_session_id
|
|
1799
1504
|
)) })
|
|
1800
1505
|
] }) }),
|
|
1801
1506
|
hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
|
|
@@ -1803,17 +1508,25 @@ const ReturnsPage = () => {
|
|
|
1803
1508
|
{
|
|
1804
1509
|
variant: "secondary",
|
|
1805
1510
|
isLoading: isFetchingMore,
|
|
1806
|
-
onClick: () =>
|
|
1511
|
+
onClick: () => loadTransactions(offset, false),
|
|
1807
1512
|
children: "Load more"
|
|
1808
1513
|
}
|
|
1809
1514
|
) }) : null
|
|
1810
1515
|
] }) });
|
|
1811
1516
|
};
|
|
1812
|
-
const config$
|
|
1813
|
-
label: "
|
|
1814
|
-
icon:
|
|
1517
|
+
const config$5 = defineRouteConfig({
|
|
1518
|
+
label: "Payments",
|
|
1519
|
+
icon: CreditCard
|
|
1815
1520
|
});
|
|
1816
|
-
const
|
|
1521
|
+
const useDebounce = (value, delay) => {
|
|
1522
|
+
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
1523
|
+
useEffect(() => {
|
|
1524
|
+
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
1525
|
+
return () => clearTimeout(handler);
|
|
1526
|
+
}, [value, delay]);
|
|
1527
|
+
return debouncedValue;
|
|
1528
|
+
};
|
|
1529
|
+
const getStatusBadgeClass$4 = (status) => {
|
|
1817
1530
|
const s2 = status.toLowerCase();
|
|
1818
1531
|
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
1819
1532
|
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
@@ -1821,118 +1534,286 @@ const getStatusBadgeClass$3 = (status) => {
|
|
|
1821
1534
|
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
1822
1535
|
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
1823
1536
|
};
|
|
1824
|
-
const
|
|
1825
|
-
var _a;
|
|
1537
|
+
const RefundsPage = () => {
|
|
1826
1538
|
const navigate = useNavigate();
|
|
1827
|
-
const
|
|
1828
|
-
const
|
|
1829
|
-
const
|
|
1830
|
-
const [
|
|
1539
|
+
const [items, setItems] = useState([]);
|
|
1540
|
+
const [orderIdSearch, setOrderIdSearch] = useState("");
|
|
1541
|
+
const debouncedOrderId = useDebounce(orderIdSearch, 300);
|
|
1542
|
+
const [paymentStatusFilter, setPaymentStatusFilter] = useState("all");
|
|
1543
|
+
const [providerSearch, setProviderSearch] = useState("");
|
|
1544
|
+
const debouncedProvider = useDebounce(providerSearch, 300);
|
|
1545
|
+
const [currencySearch, setCurrencySearch] = useState("");
|
|
1546
|
+
const debouncedCurrency = useDebounce(currencySearch, 300);
|
|
1547
|
+
const [dateFrom, setDateFrom] = useState("");
|
|
1548
|
+
const [dateTo, setDateTo] = useState("");
|
|
1549
|
+
const [amountMin, setAmountMin] = useState("");
|
|
1550
|
+
const [amountMax, setAmountMax] = useState("");
|
|
1551
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
1552
|
+
const [isFetchingMore, setIsFetchingMore] = useState(false);
|
|
1831
1553
|
const [error, setError] = useState(null);
|
|
1554
|
+
const [offset, setOffset] = useState(0);
|
|
1555
|
+
const [count, setCount] = useState(0);
|
|
1556
|
+
const limit = 50;
|
|
1557
|
+
const loadRefunds = useCallback(
|
|
1558
|
+
async (nextOffset, replace) => {
|
|
1559
|
+
try {
|
|
1560
|
+
if (replace) setIsLoading(true);
|
|
1561
|
+
else setIsFetchingMore(true);
|
|
1562
|
+
setError(null);
|
|
1563
|
+
const params = new URLSearchParams();
|
|
1564
|
+
params.set("limit", String(limit));
|
|
1565
|
+
params.set("offset", String(nextOffset));
|
|
1566
|
+
if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
|
|
1567
|
+
if (paymentStatusFilter !== "all") params.set("payment_status", paymentStatusFilter);
|
|
1568
|
+
if (debouncedProvider.trim()) params.set("provider_id", debouncedProvider.trim());
|
|
1569
|
+
if (debouncedCurrency.trim()) params.set("currency_code", debouncedCurrency.trim());
|
|
1570
|
+
if (dateFrom.trim()) params.set("date_from", dateFrom.trim());
|
|
1571
|
+
if (dateTo.trim()) params.set("date_to", dateTo.trim());
|
|
1572
|
+
const min = amountMin.trim() ? Number(amountMin) : void 0;
|
|
1573
|
+
const max = amountMax.trim() ? Number(amountMax) : void 0;
|
|
1574
|
+
if (min != null && !Number.isNaN(min)) params.set("amount_min", String(min));
|
|
1575
|
+
if (max != null && !Number.isNaN(max)) params.set("amount_max", String(max));
|
|
1576
|
+
const response = await fetch(`/admin/refunds?${params.toString()}`, {
|
|
1577
|
+
credentials: "include"
|
|
1578
|
+
});
|
|
1579
|
+
if (!response.ok) {
|
|
1580
|
+
const text = await response.text();
|
|
1581
|
+
throw new Error(text || "Failed to load refunds");
|
|
1582
|
+
}
|
|
1583
|
+
const payload = await response.json();
|
|
1584
|
+
const list = payload.refunds ?? [];
|
|
1585
|
+
setCount(payload.count ?? 0);
|
|
1586
|
+
setOffset(nextOffset + list.length);
|
|
1587
|
+
setItems((prev) => replace ? list : [...prev, ...list]);
|
|
1588
|
+
} catch (e) {
|
|
1589
|
+
setError(e instanceof Error ? e.message : "Failed to load");
|
|
1590
|
+
} finally {
|
|
1591
|
+
setIsLoading(false);
|
|
1592
|
+
setIsFetchingMore(false);
|
|
1593
|
+
}
|
|
1594
|
+
},
|
|
1595
|
+
[
|
|
1596
|
+
debouncedOrderId,
|
|
1597
|
+
paymentStatusFilter,
|
|
1598
|
+
debouncedProvider,
|
|
1599
|
+
debouncedCurrency,
|
|
1600
|
+
dateFrom,
|
|
1601
|
+
dateTo,
|
|
1602
|
+
amountMin,
|
|
1603
|
+
amountMax
|
|
1604
|
+
]
|
|
1605
|
+
);
|
|
1832
1606
|
useEffect(() => {
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1607
|
+
void loadRefunds(0, true);
|
|
1608
|
+
}, [loadRefunds]);
|
|
1609
|
+
const hasMore = useMemo(() => offset < count, [offset, count]);
|
|
1610
|
+
const displayAmount = (r) => {
|
|
1611
|
+
const code = (r.currency_code ?? "USD").toUpperCase();
|
|
1612
|
+
return `${code} ${Number(r.amount)}`;
|
|
1613
|
+
};
|
|
1614
|
+
const displayStatus = (r) => {
|
|
1615
|
+
const s2 = r.payment_status ?? "";
|
|
1616
|
+
return s2 !== "" ? s2 : "—";
|
|
1617
|
+
};
|
|
1618
|
+
return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
|
|
1619
|
+
/* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
1620
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1621
|
+
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Refunds" }),
|
|
1622
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Refund records — amount, order, payment status" })
|
|
1623
|
+
] }),
|
|
1624
|
+
/* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () => loadRefunds(0, true), children: "Refresh" })
|
|
1625
|
+
] }),
|
|
1626
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
1627
|
+
/* @__PURE__ */ jsx(
|
|
1628
|
+
Input,
|
|
1629
|
+
{
|
|
1630
|
+
placeholder: "Order ID",
|
|
1631
|
+
value: orderIdSearch,
|
|
1632
|
+
onChange: (e) => setOrderIdSearch(e.target.value),
|
|
1633
|
+
className: "md:max-w-[180px]",
|
|
1634
|
+
"aria-label": "Filter by order ID"
|
|
1635
|
+
}
|
|
1636
|
+
),
|
|
1637
|
+
/* @__PURE__ */ jsx(
|
|
1638
|
+
Input,
|
|
1639
|
+
{
|
|
1640
|
+
placeholder: "Provider",
|
|
1641
|
+
value: providerSearch,
|
|
1642
|
+
onChange: (e) => setProviderSearch(e.target.value),
|
|
1643
|
+
className: "md:max-w-[140px]",
|
|
1644
|
+
"aria-label": "Filter by provider"
|
|
1645
|
+
}
|
|
1646
|
+
),
|
|
1647
|
+
/* @__PURE__ */ jsx(
|
|
1648
|
+
Input,
|
|
1649
|
+
{
|
|
1650
|
+
placeholder: "Currency",
|
|
1651
|
+
value: currencySearch,
|
|
1652
|
+
onChange: (e) => setCurrencySearch(e.target.value),
|
|
1653
|
+
className: "md:max-w-[100px]",
|
|
1654
|
+
"aria-label": "Filter by currency"
|
|
1655
|
+
}
|
|
1656
|
+
),
|
|
1657
|
+
/* @__PURE__ */ jsxs(
|
|
1658
|
+
"select",
|
|
1659
|
+
{
|
|
1660
|
+
value: paymentStatusFilter,
|
|
1661
|
+
onChange: (e) => setPaymentStatusFilter(e.target.value),
|
|
1662
|
+
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]",
|
|
1663
|
+
"aria-label": "Filter by payment status",
|
|
1664
|
+
children: [
|
|
1665
|
+
/* @__PURE__ */ jsx("option", { value: "all", children: "All statuses" }),
|
|
1666
|
+
/* @__PURE__ */ jsx("option", { value: "pending", children: "Pending" }),
|
|
1667
|
+
/* @__PURE__ */ jsx("option", { value: "requires_more", children: "Requires more" }),
|
|
1668
|
+
/* @__PURE__ */ jsx("option", { value: "error", children: "Error" }),
|
|
1669
|
+
/* @__PURE__ */ jsx("option", { value: "canceled", children: "Canceled" }),
|
|
1670
|
+
/* @__PURE__ */ jsx("option", { value: "authorized", children: "Authorized" }),
|
|
1671
|
+
/* @__PURE__ */ jsx("option", { value: "captured", children: "Captured" })
|
|
1672
|
+
]
|
|
1673
|
+
}
|
|
1674
|
+
),
|
|
1675
|
+
/* @__PURE__ */ jsx(
|
|
1676
|
+
Input,
|
|
1677
|
+
{
|
|
1678
|
+
type: "date",
|
|
1679
|
+
placeholder: "From",
|
|
1680
|
+
value: dateFrom,
|
|
1681
|
+
onChange: (e) => setDateFrom(e.target.value),
|
|
1682
|
+
className: "md:max-w-[140px]",
|
|
1683
|
+
"aria-label": "Date from"
|
|
1684
|
+
}
|
|
1685
|
+
),
|
|
1686
|
+
/* @__PURE__ */ jsx(
|
|
1687
|
+
Input,
|
|
1688
|
+
{
|
|
1689
|
+
type: "date",
|
|
1690
|
+
placeholder: "To",
|
|
1691
|
+
value: dateTo,
|
|
1692
|
+
onChange: (e) => setDateTo(e.target.value),
|
|
1693
|
+
className: "md:max-w-[140px]",
|
|
1694
|
+
"aria-label": "Date to"
|
|
1695
|
+
}
|
|
1696
|
+
),
|
|
1697
|
+
/* @__PURE__ */ jsx(
|
|
1698
|
+
Input,
|
|
1699
|
+
{
|
|
1700
|
+
placeholder: "Amount min",
|
|
1701
|
+
value: amountMin,
|
|
1702
|
+
onChange: (e) => setAmountMin(e.target.value),
|
|
1703
|
+
type: "number",
|
|
1704
|
+
min: 0,
|
|
1705
|
+
className: "md:max-w-[100px]",
|
|
1706
|
+
"aria-label": "Refund amount minimum"
|
|
1707
|
+
}
|
|
1708
|
+
),
|
|
1709
|
+
/* @__PURE__ */ jsx(
|
|
1710
|
+
Input,
|
|
1711
|
+
{
|
|
1712
|
+
placeholder: "Amount max",
|
|
1713
|
+
value: amountMax,
|
|
1714
|
+
onChange: (e) => setAmountMax(e.target.value),
|
|
1715
|
+
type: "number",
|
|
1716
|
+
min: 0,
|
|
1717
|
+
className: "md:max-w-[100px]",
|
|
1718
|
+
"aria-label": "Refund amount maximum"
|
|
1719
|
+
}
|
|
1720
|
+
)
|
|
1863
1721
|
] }) }),
|
|
1864
1722
|
error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
1865
1723
|
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
1866
|
-
/* @__PURE__ */ jsx(
|
|
1867
|
-
] }) :
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
] }),
|
|
1881
|
-
/* @__PURE__ */
|
|
1882
|
-
|
|
1883
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: displayAmount })
|
|
1884
|
-
] }),
|
|
1885
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1886
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
|
|
1887
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.provider_id })
|
|
1888
|
-
] }),
|
|
1889
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1890
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
|
|
1891
|
-
/* @__PURE__ */ jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsx(
|
|
1892
|
-
Badge,
|
|
1893
|
-
{
|
|
1894
|
-
size: "2xsmall",
|
|
1895
|
-
className: `uppercase ${getStatusBadgeClass$3(displayStatus)}`,
|
|
1896
|
-
children: displayStatus !== "—" ? displayStatus.replace(/_/g, " ") : "—"
|
|
1897
|
-
}
|
|
1898
|
-
) })
|
|
1899
|
-
] }),
|
|
1900
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1901
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Session status (DB)" }),
|
|
1902
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: sessionStatusRaw })
|
|
1903
|
-
] }),
|
|
1904
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1905
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Payment status (DB)" }),
|
|
1906
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: paymentStatusRaw })
|
|
1907
|
-
] }),
|
|
1908
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1909
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Finalized" }),
|
|
1910
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.payment_id != null ? "Yes" : "No" })
|
|
1911
|
-
] }),
|
|
1912
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1913
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Created" }),
|
|
1914
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: new Date(detail.created_at).toLocaleDateString("en-US", {
|
|
1915
|
-
year: "numeric",
|
|
1916
|
-
month: "short",
|
|
1917
|
-
day: "numeric",
|
|
1918
|
-
hour: "numeric",
|
|
1919
|
-
minute: "2-digit",
|
|
1920
|
-
hour12: true
|
|
1921
|
-
}) })
|
|
1922
|
-
] })
|
|
1724
|
+
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => loadRefunds(0, true), children: "Try again" }) })
|
|
1725
|
+
] }) : null,
|
|
1726
|
+
isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading refunds…" }) }) : items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
1727
|
+
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No refunds yet" }),
|
|
1728
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Refund records will appear here." })
|
|
1729
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "w-full overflow-x-auto rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "w-full table-fixed divide-y divide-ui-border-base", style: { minWidth: 0 }, children: [
|
|
1730
|
+
/* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
1731
|
+
/* @__PURE__ */ jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Refund ID" }),
|
|
1732
|
+
/* @__PURE__ */ jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
1733
|
+
/* @__PURE__ */ jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Payment ID" }),
|
|
1734
|
+
/* @__PURE__ */ jsx("th", { className: "w-[8%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Amount" }),
|
|
1735
|
+
/* @__PURE__ */ jsx("th", { className: "w-[6%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Currency" }),
|
|
1736
|
+
/* @__PURE__ */ jsx("th", { className: "w-[10%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Provider" }),
|
|
1737
|
+
/* @__PURE__ */ jsx("th", { className: "w-[10%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Payment Status" }),
|
|
1738
|
+
/* @__PURE__ */ jsx("th", { className: "w-[14%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Note" }),
|
|
1739
|
+
/* @__PURE__ */ jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
1740
|
+
/* @__PURE__ */ jsx("th", { className: "w-[8%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
1923
1741
|
] }) }),
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1742
|
+
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((r) => /* @__PURE__ */ jsxs(
|
|
1743
|
+
"tr",
|
|
1744
|
+
{
|
|
1745
|
+
className: "cursor-pointer hover:bg-ui-bg-subtle/60",
|
|
1746
|
+
onClick: () => navigate(`/refunds/${r.refund_id}`),
|
|
1747
|
+
children: [
|
|
1748
|
+
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 font-mono text-sm text-ui-fg-base", title: r.refund_id, children: r.refund_id }),
|
|
1749
|
+
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 font-medium text-ui-fg-base", title: r.order_id ?? void 0, children: r.order_id ?? "—" }),
|
|
1750
|
+
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 font-mono text-sm text-ui-fg-subtle", title: r.payment_id, children: r.payment_id }),
|
|
1751
|
+
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", children: displayAmount(r) }),
|
|
1752
|
+
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle uppercase", children: r.currency_code || "—" }),
|
|
1753
|
+
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", title: r.provider_id || void 0, children: r.provider_id || "—" }),
|
|
1754
|
+
/* @__PURE__ */ jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsx(
|
|
1755
|
+
Badge,
|
|
1756
|
+
{
|
|
1757
|
+
size: "2xsmall",
|
|
1758
|
+
className: `uppercase ${getStatusBadgeClass$4(displayStatus(r))}`,
|
|
1759
|
+
children: displayStatus(r) !== "—" ? displayStatus(r).replace(/_/g, " ") : "—"
|
|
1760
|
+
}
|
|
1761
|
+
) }),
|
|
1762
|
+
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", title: r.note ?? void 0, children: r.note ?? "—" }),
|
|
1763
|
+
/* @__PURE__ */ jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle text-xs", children: new Date(r.created_at).toLocaleDateString("en-US", {
|
|
1764
|
+
month: "short",
|
|
1765
|
+
day: "numeric",
|
|
1766
|
+
hour: "numeric",
|
|
1767
|
+
minute: "2-digit",
|
|
1768
|
+
hour12: true
|
|
1769
|
+
}) }),
|
|
1770
|
+
/* @__PURE__ */ jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1", children: [
|
|
1771
|
+
/* @__PURE__ */ jsx(
|
|
1772
|
+
Button,
|
|
1773
|
+
{
|
|
1774
|
+
variant: "transparent",
|
|
1775
|
+
size: "small",
|
|
1776
|
+
onClick: (e) => {
|
|
1777
|
+
e.stopPropagation();
|
|
1778
|
+
navigate(`/refunds/${r.refund_id}`);
|
|
1779
|
+
},
|
|
1780
|
+
children: "Details"
|
|
1781
|
+
}
|
|
1782
|
+
),
|
|
1783
|
+
r.order_id ? /* @__PURE__ */ jsx(
|
|
1784
|
+
Button,
|
|
1785
|
+
{
|
|
1786
|
+
variant: "transparent",
|
|
1787
|
+
size: "small",
|
|
1788
|
+
onClick: (e) => {
|
|
1789
|
+
e.stopPropagation();
|
|
1790
|
+
navigate(`/orders/${r.order_id}`);
|
|
1791
|
+
},
|
|
1792
|
+
children: "Order"
|
|
1793
|
+
}
|
|
1794
|
+
) : null
|
|
1795
|
+
] }) })
|
|
1796
|
+
]
|
|
1797
|
+
},
|
|
1798
|
+
r.refund_id
|
|
1799
|
+
)) })
|
|
1800
|
+
] }) }),
|
|
1801
|
+
hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
|
|
1802
|
+
Button,
|
|
1803
|
+
{
|
|
1804
|
+
variant: "secondary",
|
|
1805
|
+
isLoading: isFetchingMore,
|
|
1806
|
+
onClick: () => loadRefunds(offset, false),
|
|
1807
|
+
children: "Load more"
|
|
1808
|
+
}
|
|
1809
|
+
) }) : null
|
|
1929
1810
|
] }) });
|
|
1930
1811
|
};
|
|
1931
|
-
const config$
|
|
1932
|
-
label: "
|
|
1933
|
-
icon:
|
|
1812
|
+
const config$4 = defineRouteConfig({
|
|
1813
|
+
label: "Refunds",
|
|
1814
|
+
icon: Receipt
|
|
1934
1815
|
});
|
|
1935
|
-
const getStatusBadgeClass$
|
|
1816
|
+
const getStatusBadgeClass$3 = (status) => {
|
|
1936
1817
|
const statusLower = status.toLowerCase();
|
|
1937
1818
|
if (statusLower === "requested") {
|
|
1938
1819
|
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
@@ -2070,7 +1951,7 @@ const SwapDetailPage = () => {
|
|
|
2070
1951
|
Badge,
|
|
2071
1952
|
{
|
|
2072
1953
|
size: "small",
|
|
2073
|
-
className: `uppercase ${getStatusBadgeClass$
|
|
1954
|
+
className: `uppercase ${getStatusBadgeClass$3(swap.status)}`,
|
|
2074
1955
|
children: swap.status.replace(/_/g, " ")
|
|
2075
1956
|
}
|
|
2076
1957
|
)
|
|
@@ -2138,7 +2019,7 @@ const SwapDetailPage = () => {
|
|
|
2138
2019
|
Badge,
|
|
2139
2020
|
{
|
|
2140
2021
|
size: "2xsmall",
|
|
2141
|
-
className: `uppercase ${getStatusBadgeClass$
|
|
2022
|
+
className: `uppercase ${getStatusBadgeClass$3(entry.status)}`,
|
|
2142
2023
|
children: entry.status.replace(/_/g, " ")
|
|
2143
2024
|
}
|
|
2144
2025
|
) }),
|
|
@@ -2207,11 +2088,11 @@ const SwapDetailPage = () => {
|
|
|
2207
2088
|
] })
|
|
2208
2089
|
] }) });
|
|
2209
2090
|
};
|
|
2210
|
-
const config$
|
|
2091
|
+
const config$3 = defineRouteConfig({
|
|
2211
2092
|
label: "Swap Details",
|
|
2212
2093
|
icon: ArrowPath
|
|
2213
2094
|
});
|
|
2214
|
-
const getStatusBadgeClass$
|
|
2095
|
+
const getStatusBadgeClass$2 = (status) => {
|
|
2215
2096
|
const statusLower = status.toLowerCase();
|
|
2216
2097
|
if (statusLower === "requested") {
|
|
2217
2098
|
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
@@ -2345,7 +2226,7 @@ const ReturnDetailPage = () => {
|
|
|
2345
2226
|
Badge,
|
|
2346
2227
|
{
|
|
2347
2228
|
size: "small",
|
|
2348
|
-
className: `uppercase ${getStatusBadgeClass$
|
|
2229
|
+
className: `uppercase ${getStatusBadgeClass$2(returnOrder.status)}`,
|
|
2349
2230
|
children: returnOrder.status.replace(/_/g, " ")
|
|
2350
2231
|
}
|
|
2351
2232
|
)
|
|
@@ -2427,7 +2308,7 @@ const ReturnDetailPage = () => {
|
|
|
2427
2308
|
Badge,
|
|
2428
2309
|
{
|
|
2429
2310
|
size: "2xsmall",
|
|
2430
|
-
className: `uppercase ${getStatusBadgeClass$
|
|
2311
|
+
className: `uppercase ${getStatusBadgeClass$2(entry.status)}`,
|
|
2431
2312
|
children: entry.status.replace(/_/g, " ")
|
|
2432
2313
|
}
|
|
2433
2314
|
) }),
|
|
@@ -2485,10 +2366,129 @@ const ReturnDetailPage = () => {
|
|
|
2485
2366
|
updateSuccess && /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-ui-border-success bg-ui-bg-success-subtle p-4", children: /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-success", children: "Action completed successfully" }) })
|
|
2486
2367
|
] }) });
|
|
2487
2368
|
};
|
|
2488
|
-
const config$
|
|
2369
|
+
const config$2 = defineRouteConfig({
|
|
2489
2370
|
label: "Return Order Details",
|
|
2490
2371
|
icon: CheckCircle
|
|
2491
2372
|
});
|
|
2373
|
+
const getStatusBadgeClass$1 = (status) => {
|
|
2374
|
+
const s2 = status.toLowerCase();
|
|
2375
|
+
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
2376
|
+
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
2377
|
+
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
2378
|
+
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
2379
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
2380
|
+
};
|
|
2381
|
+
const PaymentDetailPage = () => {
|
|
2382
|
+
var _a;
|
|
2383
|
+
const navigate = useNavigate();
|
|
2384
|
+
const params = useParams();
|
|
2385
|
+
const id = (_a = params == null ? void 0 : params.id) == null ? void 0 : _a.trim();
|
|
2386
|
+
const [detail, setDetail] = useState(null);
|
|
2387
|
+
const [loading, setLoading] = useState(!!id);
|
|
2388
|
+
const [error, setError] = useState(null);
|
|
2389
|
+
useEffect(() => {
|
|
2390
|
+
if (!id) {
|
|
2391
|
+
setLoading(false);
|
|
2392
|
+
return;
|
|
2393
|
+
}
|
|
2394
|
+
let cancelled = false;
|
|
2395
|
+
setLoading(true);
|
|
2396
|
+
setError(null);
|
|
2397
|
+
fetch(`/admin/payment-transactions/${id}`, { credentials: "include" }).then((res) => {
|
|
2398
|
+
if (!res.ok) throw new Error(res.statusText || "Failed to load");
|
|
2399
|
+
return res.json();
|
|
2400
|
+
}).then((data) => {
|
|
2401
|
+
if (!cancelled) setDetail(data);
|
|
2402
|
+
}).catch((e) => {
|
|
2403
|
+
if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
|
|
2404
|
+
}).finally(() => {
|
|
2405
|
+
if (!cancelled) setLoading(false);
|
|
2406
|
+
});
|
|
2407
|
+
return () => {
|
|
2408
|
+
cancelled = true;
|
|
2409
|
+
};
|
|
2410
|
+
}, [id]);
|
|
2411
|
+
const displayStatus = detail ? (detail.payment_id != null && detail.payment_status != null && detail.payment_status !== "" ? detail.payment_status : detail.session_status ?? "") || "—" : "";
|
|
2412
|
+
const sessionStatusRaw = (detail == null ? void 0 : detail.session_status) ?? "—";
|
|
2413
|
+
const paymentStatusRaw = (detail == null ? void 0 : detail.payment_id) != null ? (detail == null ? void 0 : detail.payment_status) ?? "—" : "—";
|
|
2414
|
+
const displayAmount = detail ? `${(detail.currency_code ?? "USD").toUpperCase()} ${Number(detail.amount)}` : "";
|
|
2415
|
+
return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-4xl flex-col gap-6 p-6", children: [
|
|
2416
|
+
/* @__PURE__ */ jsx("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
2417
|
+
/* @__PURE__ */ jsx(Button, { variant: "transparent", size: "small", onClick: () => navigate("/payments"), children: "← Payments" }),
|
|
2418
|
+
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Payment session" }),
|
|
2419
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: id ?? "—" })
|
|
2420
|
+
] }) }),
|
|
2421
|
+
error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
2422
|
+
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
2423
|
+
/* @__PURE__ */ jsx(Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/payments"), children: "Back to list" })
|
|
2424
|
+
] }) : loading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading…" }) }) : detail ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
2425
|
+
/* @__PURE__ */ jsx("div", { className: "rounded-xl border border-ui-border-base p-6 flex flex-col gap-4", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
2426
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2427
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Order ID" }),
|
|
2428
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1", children: detail.order_id ? /* @__PURE__ */ jsx(
|
|
2429
|
+
Button,
|
|
2430
|
+
{
|
|
2431
|
+
variant: "transparent",
|
|
2432
|
+
size: "small",
|
|
2433
|
+
onClick: () => navigate(`/orders/${detail.order_id}`),
|
|
2434
|
+
children: detail.order_id
|
|
2435
|
+
}
|
|
2436
|
+
) : /* @__PURE__ */ jsx(Text, { children: "—" }) })
|
|
2437
|
+
] }),
|
|
2438
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2439
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
|
|
2440
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: displayAmount })
|
|
2441
|
+
] }),
|
|
2442
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2443
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
|
|
2444
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.provider_id })
|
|
2445
|
+
] }),
|
|
2446
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2447
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
|
|
2448
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsx(
|
|
2449
|
+
Badge,
|
|
2450
|
+
{
|
|
2451
|
+
size: "2xsmall",
|
|
2452
|
+
className: `uppercase ${getStatusBadgeClass$1(displayStatus)}`,
|
|
2453
|
+
children: displayStatus !== "—" ? displayStatus.replace(/_/g, " ") : "—"
|
|
2454
|
+
}
|
|
2455
|
+
) })
|
|
2456
|
+
] }),
|
|
2457
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2458
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Session status (DB)" }),
|
|
2459
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: sessionStatusRaw })
|
|
2460
|
+
] }),
|
|
2461
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2462
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Payment status (DB)" }),
|
|
2463
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: paymentStatusRaw })
|
|
2464
|
+
] }),
|
|
2465
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2466
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Finalized" }),
|
|
2467
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: detail.payment_id != null ? "Yes" : "No" })
|
|
2468
|
+
] }),
|
|
2469
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2470
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Created" }),
|
|
2471
|
+
/* @__PURE__ */ jsx(Text, { className: "mt-1 block", children: new Date(detail.created_at).toLocaleDateString("en-US", {
|
|
2472
|
+
year: "numeric",
|
|
2473
|
+
month: "short",
|
|
2474
|
+
day: "numeric",
|
|
2475
|
+
hour: "numeric",
|
|
2476
|
+
minute: "2-digit",
|
|
2477
|
+
hour12: true
|
|
2478
|
+
}) })
|
|
2479
|
+
] })
|
|
2480
|
+
] }) }),
|
|
2481
|
+
Object.keys(detail.data ?? {}).length > 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
2482
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "text-lg mb-4", children: "Provider data" }),
|
|
2483
|
+
/* @__PURE__ */ jsx("pre", { className: "text-xs bg-ui-bg-subtle p-4 rounded-lg overflow-auto max-h-96", children: JSON.stringify(detail.data, null, 2) })
|
|
2484
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "rounded-xl border border-ui-border-base p-6", children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "No provider data for this session." }) })
|
|
2485
|
+
] }) : null
|
|
2486
|
+
] }) });
|
|
2487
|
+
};
|
|
2488
|
+
const config$1 = defineRouteConfig({
|
|
2489
|
+
label: "Payment details",
|
|
2490
|
+
icon: CreditCard
|
|
2491
|
+
});
|
|
2492
2492
|
const getStatusBadgeClass = (status) => {
|
|
2493
2493
|
const s2 = status.toLowerCase();
|
|
2494
2494
|
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
@@ -2694,25 +2694,21 @@ const widgetModule = { widgets: [
|
|
|
2694
2694
|
] };
|
|
2695
2695
|
const routeModule = {
|
|
2696
2696
|
routes: [
|
|
2697
|
-
{
|
|
2698
|
-
Component: PaymentsPage,
|
|
2699
|
-
path: "/payments"
|
|
2700
|
-
},
|
|
2701
2697
|
{
|
|
2702
2698
|
Component: SwapsPage,
|
|
2703
2699
|
path: "/swaps"
|
|
2704
2700
|
},
|
|
2705
|
-
{
|
|
2706
|
-
Component: RefundsPage,
|
|
2707
|
-
path: "/refunds"
|
|
2708
|
-
},
|
|
2709
2701
|
{
|
|
2710
2702
|
Component: ReturnsPage,
|
|
2711
2703
|
path: "/returns"
|
|
2712
2704
|
},
|
|
2713
2705
|
{
|
|
2714
|
-
Component:
|
|
2715
|
-
path: "/payments
|
|
2706
|
+
Component: PaymentsPage,
|
|
2707
|
+
path: "/payments"
|
|
2708
|
+
},
|
|
2709
|
+
{
|
|
2710
|
+
Component: RefundsPage,
|
|
2711
|
+
path: "/refunds"
|
|
2716
2712
|
},
|
|
2717
2713
|
{
|
|
2718
2714
|
Component: SwapDetailPage,
|
|
@@ -2722,6 +2718,10 @@ const routeModule = {
|
|
|
2722
2718
|
Component: ReturnDetailPage,
|
|
2723
2719
|
path: "/returns/:id"
|
|
2724
2720
|
},
|
|
2721
|
+
{
|
|
2722
|
+
Component: PaymentDetailPage,
|
|
2723
|
+
path: "/payments/:id"
|
|
2724
|
+
},
|
|
2725
2725
|
{
|
|
2726
2726
|
Component: RefundDetailPage,
|
|
2727
2727
|
path: "/refunds/:id"
|
|
@@ -2733,31 +2733,25 @@ const menuItemModule = {
|
|
|
2733
2733
|
{
|
|
2734
2734
|
label: config$4.label,
|
|
2735
2735
|
icon: config$4.icon,
|
|
2736
|
-
path: "/
|
|
2736
|
+
path: "/refunds",
|
|
2737
2737
|
nested: void 0
|
|
2738
2738
|
},
|
|
2739
2739
|
{
|
|
2740
2740
|
label: config$5.label,
|
|
2741
2741
|
icon: config$5.icon,
|
|
2742
|
-
path: "/
|
|
2742
|
+
path: "/payments",
|
|
2743
2743
|
nested: void 0
|
|
2744
2744
|
},
|
|
2745
2745
|
{
|
|
2746
2746
|
label: config$7.label,
|
|
2747
2747
|
icon: config$7.icon,
|
|
2748
|
-
path: "/
|
|
2748
|
+
path: "/swaps",
|
|
2749
2749
|
nested: void 0
|
|
2750
2750
|
},
|
|
2751
2751
|
{
|
|
2752
2752
|
label: config$6.label,
|
|
2753
2753
|
icon: config$6.icon,
|
|
2754
|
-
path: "/
|
|
2755
|
-
nested: void 0
|
|
2756
|
-
},
|
|
2757
|
-
{
|
|
2758
|
-
label: config$1.label,
|
|
2759
|
-
icon: config$1.icon,
|
|
2760
|
-
path: "/returns/:id",
|
|
2754
|
+
path: "/returns",
|
|
2761
2755
|
nested: void 0
|
|
2762
2756
|
},
|
|
2763
2757
|
{
|
|
@@ -2767,14 +2761,20 @@ const menuItemModule = {
|
|
|
2767
2761
|
nested: void 0
|
|
2768
2762
|
},
|
|
2769
2763
|
{
|
|
2770
|
-
label: config$
|
|
2771
|
-
icon: config$
|
|
2764
|
+
label: config$1.label,
|
|
2765
|
+
icon: config$1.icon,
|
|
2772
2766
|
path: "/payments/:id",
|
|
2773
2767
|
nested: void 0
|
|
2774
2768
|
},
|
|
2775
2769
|
{
|
|
2776
2770
|
label: config$2.label,
|
|
2777
2771
|
icon: config$2.icon,
|
|
2772
|
+
path: "/returns/:id",
|
|
2773
|
+
nested: void 0
|
|
2774
|
+
},
|
|
2775
|
+
{
|
|
2776
|
+
label: config$3.label,
|
|
2777
|
+
icon: config$3.icon,
|
|
2778
2778
|
path: "/swaps/:id",
|
|
2779
2779
|
nested: void 0
|
|
2780
2780
|
}
|