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