order-management 0.0.100 → 0.0.102
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.medusa/server/src/admin/index.js +1340 -1330
- package/.medusa/server/src/admin/index.mjs +1343 -1333
- package/.medusa/server/src/api/store/carts/[id]/pickup/route.js +113 -0
- package/.medusa/server/src/api/store/guest-orders/[id]/returns/route.js +12 -1
- package/.medusa/server/src/api/store/guest-orders/[id]/swaps/route.js +14 -2
- package/.medusa/server/src/api/store/pickup-locations/route.js +20 -0
- package/.medusa/server/src/api/store/returns/route.js +15 -3
- package/.medusa/server/src/api/store/swaps/route.js +17 -2
- package/.medusa/server/src/config.js +4 -1
- package/.medusa/server/src/helpers/pickup-locations.js +155 -0
- package/.medusa/server/src/subscribers/order-status-change.js +37 -2
- package/.medusa/server/src/utils/order-fulfillment-metadata.js +68 -0
- package/README.md +10 -1
- package/package.json +1 -1
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
2
|
const jsxRuntime = require("react/jsx-runtime");
|
|
6
3
|
const adminSdk = require("@medusajs/admin-sdk");
|
|
7
4
|
const react = require("react");
|
|
@@ -378,15 +375,14 @@ const s = {
|
|
|
378
375
|
const OrderGiftItemsWidget = ({ data }) => {
|
|
379
376
|
const [fetchedItems, setFetchedItems] = react.useState(null);
|
|
380
377
|
react.useEffect(() => {
|
|
381
|
-
if (!
|
|
378
|
+
if (!data?.id) return;
|
|
382
379
|
fetch(
|
|
383
380
|
`/admin/orders/${data.id}?fields=*items,items.metadata`
|
|
384
|
-
).then((r) => r.json()).then(({ order }) => setFetchedItems(
|
|
385
|
-
}, [data
|
|
386
|
-
const items = fetchedItems ??
|
|
381
|
+
).then((r) => r.json()).then(({ order }) => setFetchedItems(order?.items ?? [])).catch(() => setFetchedItems(data?.items ?? []));
|
|
382
|
+
}, [data?.id]);
|
|
383
|
+
const items = fetchedItems ?? data?.items ?? [];
|
|
387
384
|
const giftedItems = items.filter((i) => {
|
|
388
|
-
|
|
389
|
-
const flag = (_a = i.metadata) == null ? void 0 : _a.is_gift;
|
|
385
|
+
const flag = i.metadata?.is_gift;
|
|
390
386
|
return flag === "true" || flag === true;
|
|
391
387
|
});
|
|
392
388
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: s.widget, children: [
|
|
@@ -415,9 +411,9 @@ const OrderGiftItemsWidget = ({ data }) => {
|
|
|
415
411
|
),
|
|
416
412
|
giftedItems.map((item) => {
|
|
417
413
|
const meta = item.metadata;
|
|
418
|
-
const from = meta
|
|
419
|
-
const to = meta
|
|
420
|
-
const message = meta
|
|
414
|
+
const from = meta?.gift_from;
|
|
415
|
+
const to = meta?.gift_to;
|
|
416
|
+
const message = meta?.gift_message;
|
|
421
417
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: s.card, children: [
|
|
422
418
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: s.ribbon, children: [
|
|
423
419
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: s.bowCenter, children: "🎀" }),
|
|
@@ -481,7 +477,7 @@ function formatRefundCurrency(amount, currencyCode = "inr", options) {
|
|
|
481
477
|
minimumFractionDigits: 2,
|
|
482
478
|
maximumFractionDigits: 2
|
|
483
479
|
}).format(amount);
|
|
484
|
-
if (
|
|
480
|
+
if (options?.signed && amount > 0) {
|
|
485
481
|
return `−${formatted}`;
|
|
486
482
|
}
|
|
487
483
|
return formatted;
|
|
@@ -536,8 +532,7 @@ function getOrderIdFromPath() {
|
|
|
536
532
|
return m ? m[1] : void 0;
|
|
537
533
|
}
|
|
538
534
|
const OrderRefundContextWidget = (props) => {
|
|
539
|
-
|
|
540
|
-
const orderId = ((_a = props.order) == null ? void 0 : _a.id) ?? ((_c = (_b = props.data) == null ? void 0 : _b.order) == null ? void 0 : _c.id) ?? getOrderIdFromPath();
|
|
535
|
+
const orderId = props.order?.id ?? props.data?.order?.id ?? getOrderIdFromPath();
|
|
541
536
|
const [context, setContext] = react.useState(null);
|
|
542
537
|
const [loading, setLoading] = react.useState(!!orderId);
|
|
543
538
|
const [error, setError] = react.useState(null);
|
|
@@ -575,7 +570,7 @@ const OrderRefundContextWidget = (props) => {
|
|
|
575
570
|
};
|
|
576
571
|
}, [orderId]);
|
|
577
572
|
const handleMarkRefunded = async () => {
|
|
578
|
-
if (!
|
|
573
|
+
if (!context?.return_id || !context?.refund_mapping || context.refund_mapping.is_refunded || !context.can_process_refund) {
|
|
579
574
|
return;
|
|
580
575
|
}
|
|
581
576
|
setMarking(true);
|
|
@@ -592,17 +587,14 @@ const OrderRefundContextWidget = (props) => {
|
|
|
592
587
|
}
|
|
593
588
|
const data = await res.json();
|
|
594
589
|
setContext(
|
|
595
|
-
(prev) => {
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
}
|
|
604
|
-
} : prev;
|
|
605
|
-
}
|
|
590
|
+
(prev) => prev && prev.refund_mapping ? {
|
|
591
|
+
...prev,
|
|
592
|
+
can_process_refund: false,
|
|
593
|
+
refund_mapping: {
|
|
594
|
+
...prev.refund_mapping,
|
|
595
|
+
is_refunded: data.refund_payment_mapping?.is_refunded ?? true
|
|
596
|
+
}
|
|
597
|
+
} : prev
|
|
606
598
|
);
|
|
607
599
|
} catch (e) {
|
|
608
600
|
setMarkError(e instanceof Error ? e.message : "Failed to mark refunded");
|
|
@@ -611,20 +603,19 @@ const OrderRefundContextWidget = (props) => {
|
|
|
611
603
|
}
|
|
612
604
|
};
|
|
613
605
|
const handleEditClick = () => {
|
|
614
|
-
const mapping = context
|
|
615
|
-
const mode = mapping
|
|
606
|
+
const mapping = context?.refund_mapping;
|
|
607
|
+
const mode = mapping?.refund_mode;
|
|
616
608
|
setEditRefundMode(
|
|
617
609
|
mode === "offline" || mode === "online" ? mode : ""
|
|
618
610
|
);
|
|
619
|
-
setEditDetails(
|
|
620
|
-
setEditImageUrls(
|
|
611
|
+
setEditDetails(mapping?.details ?? "");
|
|
612
|
+
setEditImageUrls(mapping?.images ?? []);
|
|
621
613
|
setSaveError(null);
|
|
622
614
|
setUploadError(null);
|
|
623
615
|
setEditing(true);
|
|
624
616
|
};
|
|
625
617
|
const handleUploadImage = async (e) => {
|
|
626
|
-
|
|
627
|
-
const file = (_a2 = e.target.files) == null ? void 0 : _a2[0];
|
|
618
|
+
const file = e.target.files?.[0];
|
|
628
619
|
if (!file) return;
|
|
629
620
|
setUploading(true);
|
|
630
621
|
setUploadError(null);
|
|
@@ -641,7 +632,7 @@ const OrderRefundContextWidget = (props) => {
|
|
|
641
632
|
throw new Error(data2.message || "Upload failed");
|
|
642
633
|
}
|
|
643
634
|
const data = await res.json();
|
|
644
|
-
const url =
|
|
635
|
+
const url = data.files?.[0]?.url;
|
|
645
636
|
if (url) setEditImageUrls((prev) => [...prev, url]);
|
|
646
637
|
} catch (err) {
|
|
647
638
|
setUploadError(err instanceof Error ? err.message : "Upload failed");
|
|
@@ -654,7 +645,7 @@ const OrderRefundContextWidget = (props) => {
|
|
|
654
645
|
setEditImageUrls((prev) => prev.filter((_, i) => i !== index));
|
|
655
646
|
};
|
|
656
647
|
const handleSaveAdminFields = async () => {
|
|
657
|
-
if (!
|
|
648
|
+
if (!context?.return_id) return;
|
|
658
649
|
setSaving(true);
|
|
659
650
|
setSaveError(null);
|
|
660
651
|
try {
|
|
@@ -691,14 +682,14 @@ const OrderRefundContextWidget = (props) => {
|
|
|
691
682
|
if (error) {
|
|
692
683
|
return /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "mt-6 divide-y p-0", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-error", children: error }) }) });
|
|
693
684
|
}
|
|
694
|
-
const hasReturn = !!
|
|
695
|
-
const hasMapping = !!
|
|
696
|
-
const canMarkRefunded = Boolean(context
|
|
697
|
-
const returnStatus =
|
|
698
|
-
const showReceiveFirstHint = hasReturn && !
|
|
699
|
-
const paymentDetail = context
|
|
700
|
-
const paymentDetails =
|
|
701
|
-
const orderPayment = context
|
|
685
|
+
const hasReturn = !!context?.return_id;
|
|
686
|
+
const hasMapping = !!context?.refund_mapping;
|
|
687
|
+
const canMarkRefunded = Boolean(context?.can_process_refund);
|
|
688
|
+
const returnStatus = context?.return_status ?? null;
|
|
689
|
+
const showReceiveFirstHint = hasReturn && !context?.refund_mapping?.is_refunded && returnStatus !== "received" && returnStatus !== "canceled";
|
|
690
|
+
const paymentDetail = context?.payment_detail;
|
|
691
|
+
const paymentDetails = context?.payment_details && context.payment_details.length > 0 ? context.payment_details : paymentDetail ? [paymentDetail] : [];
|
|
692
|
+
const orderPayment = context?.order_payment;
|
|
702
693
|
return /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "mt-6 divide-y p-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 py-4", children: [
|
|
703
694
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Heading, { level: "h2", className: "flex items-center gap-2", children: [
|
|
704
695
|
/* @__PURE__ */ jsxRuntime.jsx(icons.CashSolid, { className: "text-ui-fg-subtle" }),
|
|
@@ -710,7 +701,7 @@ const OrderRefundContextWidget = (props) => {
|
|
|
710
701
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
711
702
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", className: "text-ui-fg-subtle", children: "Return" }),
|
|
712
703
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: context.return_id }),
|
|
713
|
-
|
|
704
|
+
context.refund_mapping?.is_refunded ? /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: "green", children: "Refunded" }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: "orange", children: "Not refunded" })
|
|
714
705
|
] }),
|
|
715
706
|
context.refund ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 border-t border-ui-border-base pt-3", children: /* @__PURE__ */ jsxRuntime.jsx(RefundCalculationBlock, { refund: context.refund }) }) : null,
|
|
716
707
|
orderPayment && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 space-y-2 border-t border-ui-border-base pt-3", children: [
|
|
@@ -724,17 +715,17 @@ const OrderRefundContextWidget = (props) => {
|
|
|
724
715
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 space-y-2 border-t border-ui-border-base pt-3", children: [
|
|
725
716
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
726
717
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", className: "text-ui-fg-subtle", children: "Payment method (refund destination)" }),
|
|
727
|
-
|
|
718
|
+
context.refund_mapping?.payment_id ? /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: "green", children: "Customer specified" }) : paymentDetail ? /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: "orange", children: "Customer default" }) : orderPayment && !orderPayment.is_cod ? /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: "blue", children: "Original payment method" }) : null
|
|
728
719
|
] }),
|
|
729
|
-
|
|
730
|
-
!
|
|
731
|
-
!
|
|
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: [
|
|
732
723
|
"Refund will go to the original payment method (",
|
|
733
724
|
orderPayment.label,
|
|
734
725
|
")."
|
|
735
726
|
] }) }),
|
|
736
|
-
!
|
|
737
|
-
!
|
|
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." }) }),
|
|
738
729
|
paymentDetails.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: paymentDetails.map((detail) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
739
730
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
740
731
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { children: detail.type.toUpperCase() }),
|
|
@@ -746,7 +737,7 @@ const OrderRefundContextWidget = (props) => {
|
|
|
746
737
|
] }, `${detail.id}-${k}`)) })
|
|
747
738
|
] }, detail.id)) })
|
|
748
739
|
] }),
|
|
749
|
-
|
|
740
|
+
context?.refund_mapping && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 space-y-3 border-t border-ui-border-base pt-3", children: [
|
|
750
741
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
751
742
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", className: "text-ui-fg-subtle", children: "Refund mode, details & images" }),
|
|
752
743
|
!editing ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -834,10 +825,7 @@ const OrderRefundContextWidget = (props) => {
|
|
|
834
825
|
variant: "secondary",
|
|
835
826
|
type: "button",
|
|
836
827
|
disabled: uploading,
|
|
837
|
-
onClick: () =>
|
|
838
|
-
var _a2;
|
|
839
|
-
return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
|
|
840
|
-
},
|
|
828
|
+
onClick: () => fileInputRef.current?.click(),
|
|
841
829
|
children: uploading ? "Uploading…" : "Upload image"
|
|
842
830
|
}
|
|
843
831
|
),
|
|
@@ -888,7 +876,7 @@ const OrderRefundContextWidget = (props) => {
|
|
|
888
876
|
] }),
|
|
889
877
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
890
878
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", weight: "plus", className: "text-ui-fg-muted", children: "Images" }),
|
|
891
|
-
|
|
879
|
+
context.refund_mapping.images?.length ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 flex flex-wrap gap-2", children: context.refund_mapping.images.map((url, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
892
880
|
"a",
|
|
893
881
|
{
|
|
894
882
|
href: url,
|
|
@@ -918,10 +906,10 @@ const OrderRefundContextWidget = (props) => {
|
|
|
918
906
|
),
|
|
919
907
|
markError && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-error", children: markError })
|
|
920
908
|
] }),
|
|
921
|
-
hasMapping && !canMarkRefunded && !
|
|
909
|
+
hasMapping && !canMarkRefunded && !context.refund_mapping?.is_refunded && showReceiveFirstHint && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-4 text-ui-fg-muted", children: "Mark refunded is available after the return is received." })
|
|
922
910
|
] }),
|
|
923
911
|
hasReturn && !hasMapping && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-4", children: [
|
|
924
|
-
|
|
912
|
+
context?.refund ? /* @__PURE__ */ jsxRuntime.jsx(RefundCalculationBlock, { refund: context.refund }) : null,
|
|
925
913
|
orderPayment && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-3 space-y-1", children: [
|
|
926
914
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", className: "text-ui-fg-subtle", children: "Order payment method" }),
|
|
927
915
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
@@ -936,501 +924,6 @@ const OrderRefundContextWidget = (props) => {
|
|
|
936
924
|
adminSdk.defineWidgetConfig({
|
|
937
925
|
zone: "order.details.after"
|
|
938
926
|
});
|
|
939
|
-
const useDebounce$3 = (value, delay) => {
|
|
940
|
-
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
941
|
-
react.useEffect(() => {
|
|
942
|
-
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
943
|
-
return () => clearTimeout(handler);
|
|
944
|
-
}, [value, delay]);
|
|
945
|
-
return debouncedValue;
|
|
946
|
-
};
|
|
947
|
-
const getStatusBadgeClass$7 = (status) => {
|
|
948
|
-
const s2 = status.toLowerCase();
|
|
949
|
-
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
950
|
-
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
951
|
-
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
952
|
-
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
953
|
-
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
954
|
-
};
|
|
955
|
-
const PaymentsPage = () => {
|
|
956
|
-
const navigate = reactRouterDom.useNavigate();
|
|
957
|
-
const [items, setItems] = react.useState([]);
|
|
958
|
-
const [statusFilter, setStatusFilter] = react.useState("all");
|
|
959
|
-
const [orderIdSearch, setOrderIdSearch] = react.useState("");
|
|
960
|
-
const debouncedOrderId = useDebounce$3(orderIdSearch, 300);
|
|
961
|
-
const [isLoading, setIsLoading] = react.useState(true);
|
|
962
|
-
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
963
|
-
const [error, setError] = react.useState(null);
|
|
964
|
-
const [offset, setOffset] = react.useState(0);
|
|
965
|
-
const [count, setCount] = react.useState(0);
|
|
966
|
-
const limit = 50;
|
|
967
|
-
const loadTransactions = react.useCallback(
|
|
968
|
-
async (nextOffset, replace) => {
|
|
969
|
-
try {
|
|
970
|
-
if (replace) setIsLoading(true);
|
|
971
|
-
else setIsFetchingMore(true);
|
|
972
|
-
setError(null);
|
|
973
|
-
const params = new URLSearchParams();
|
|
974
|
-
params.set("limit", String(limit));
|
|
975
|
-
params.set("offset", String(nextOffset));
|
|
976
|
-
if (statusFilter !== "all") params.set("status", statusFilter);
|
|
977
|
-
if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
|
|
978
|
-
const response = await fetch(
|
|
979
|
-
`/admin/payment-transactions?${params.toString()}`,
|
|
980
|
-
{ credentials: "include" }
|
|
981
|
-
);
|
|
982
|
-
if (!response.ok) {
|
|
983
|
-
const text = await response.text();
|
|
984
|
-
throw new Error(text || "Failed to load payment transactions");
|
|
985
|
-
}
|
|
986
|
-
const payload = await response.json();
|
|
987
|
-
const list = payload.transactions ?? [];
|
|
988
|
-
setCount(payload.count ?? 0);
|
|
989
|
-
setOffset(nextOffset + list.length);
|
|
990
|
-
setItems((prev) => replace ? list : [...prev, ...list]);
|
|
991
|
-
} catch (e) {
|
|
992
|
-
setError(e instanceof Error ? e.message : "Failed to load");
|
|
993
|
-
} finally {
|
|
994
|
-
setIsLoading(false);
|
|
995
|
-
setIsFetchingMore(false);
|
|
996
|
-
}
|
|
997
|
-
},
|
|
998
|
-
[statusFilter, debouncedOrderId]
|
|
999
|
-
);
|
|
1000
|
-
react.useEffect(() => {
|
|
1001
|
-
void loadTransactions(0, true);
|
|
1002
|
-
}, [loadTransactions]);
|
|
1003
|
-
const hasMore = react.useMemo(() => offset < count, [offset, count]);
|
|
1004
|
-
const displayStatus = (t) => {
|
|
1005
|
-
const s2 = t.payment_id != null && t.payment_status != null && t.payment_status !== "" ? t.payment_status : t.session_status ?? "";
|
|
1006
|
-
return s2 !== "" ? s2 : "—";
|
|
1007
|
-
};
|
|
1008
|
-
const displayAmount = (t) => {
|
|
1009
|
-
const code = (t.currency_code ?? "USD").toUpperCase();
|
|
1010
|
-
return `${code} ${Number(t.amount)}`;
|
|
1011
|
-
};
|
|
1012
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
|
|
1013
|
-
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
1014
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1015
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Payments" }),
|
|
1016
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "All payment attempts — completed, pending, failed, requires action" })
|
|
1017
|
-
] }),
|
|
1018
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => loadTransactions(0, true), children: "Refresh" })
|
|
1019
|
-
] }),
|
|
1020
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
1021
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1022
|
-
ui.Input,
|
|
1023
|
-
{
|
|
1024
|
-
placeholder: "Search by Order ID",
|
|
1025
|
-
value: orderIdSearch,
|
|
1026
|
-
onChange: (e) => setOrderIdSearch(e.target.value),
|
|
1027
|
-
className: "md:max-w-sm",
|
|
1028
|
-
"aria-label": "Search by order ID"
|
|
1029
|
-
}
|
|
1030
|
-
),
|
|
1031
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1032
|
-
"select",
|
|
1033
|
-
{
|
|
1034
|
-
value: statusFilter,
|
|
1035
|
-
onChange: (e) => setStatusFilter(e.target.value),
|
|
1036
|
-
className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-xs",
|
|
1037
|
-
"aria-label": "Filter by status",
|
|
1038
|
-
children: [
|
|
1039
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All statuses" }),
|
|
1040
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "pending", children: "Pending" }),
|
|
1041
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "requires_more", children: "Requires more" }),
|
|
1042
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "error", children: "Error" }),
|
|
1043
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "canceled", children: "Canceled" }),
|
|
1044
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "authorized", children: "Authorized" }),
|
|
1045
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "captured", children: "Captured" })
|
|
1046
|
-
]
|
|
1047
|
-
}
|
|
1048
|
-
) })
|
|
1049
|
-
] }),
|
|
1050
|
-
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
1051
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
1052
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => loadTransactions(0, true), children: "Try again" }) })
|
|
1053
|
-
] }) : null,
|
|
1054
|
-
isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading payments…" }) }) : items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
1055
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No payment transactions yet" }),
|
|
1056
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Payment attempts will appear here." })
|
|
1057
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
1058
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
1059
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
1060
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Amount" }),
|
|
1061
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Provider" }),
|
|
1062
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
1063
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Finalized" }),
|
|
1064
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
1065
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
1066
|
-
] }) }),
|
|
1067
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((t) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1068
|
-
"tr",
|
|
1069
|
-
{
|
|
1070
|
-
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
1071
|
-
onClick: () => navigate(`/payments/${t.payment_session_id}`),
|
|
1072
|
-
children: [
|
|
1073
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: t.order_id ?? "—" }),
|
|
1074
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: displayAmount(t) }),
|
|
1075
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.provider_id }),
|
|
1076
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1077
|
-
ui.Badge,
|
|
1078
|
-
{
|
|
1079
|
-
size: "2xsmall",
|
|
1080
|
-
className: `uppercase ${getStatusBadgeClass$7(displayStatus(t))}`,
|
|
1081
|
-
children: displayStatus(t) !== "—" ? displayStatus(t).replace(/_/g, " ") : "—"
|
|
1082
|
-
}
|
|
1083
|
-
) }),
|
|
1084
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.payment_id != null ? "Yes" : "No" }),
|
|
1085
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(t.created_at).toLocaleDateString("en-US", {
|
|
1086
|
-
year: "numeric",
|
|
1087
|
-
month: "short",
|
|
1088
|
-
day: "numeric",
|
|
1089
|
-
hour: "numeric",
|
|
1090
|
-
minute: "2-digit",
|
|
1091
|
-
hour12: true
|
|
1092
|
-
}) }),
|
|
1093
|
-
/* @__PURE__ */ jsxRuntime.jsxs("td", { className: "px-4 py-4", children: [
|
|
1094
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1095
|
-
ui.Button,
|
|
1096
|
-
{
|
|
1097
|
-
variant: "transparent",
|
|
1098
|
-
size: "small",
|
|
1099
|
-
onClick: (e) => {
|
|
1100
|
-
e.stopPropagation();
|
|
1101
|
-
navigate(`/payments/${t.payment_session_id}`);
|
|
1102
|
-
},
|
|
1103
|
-
children: "View details"
|
|
1104
|
-
}
|
|
1105
|
-
),
|
|
1106
|
-
t.order_id ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1107
|
-
ui.Button,
|
|
1108
|
-
{
|
|
1109
|
-
variant: "transparent",
|
|
1110
|
-
size: "small",
|
|
1111
|
-
onClick: (e) => {
|
|
1112
|
-
e.stopPropagation();
|
|
1113
|
-
navigate(`/orders/${t.order_id}`);
|
|
1114
|
-
},
|
|
1115
|
-
children: "Order"
|
|
1116
|
-
}
|
|
1117
|
-
) : null
|
|
1118
|
-
] })
|
|
1119
|
-
]
|
|
1120
|
-
},
|
|
1121
|
-
t.payment_session_id
|
|
1122
|
-
)) })
|
|
1123
|
-
] }) }),
|
|
1124
|
-
hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1125
|
-
ui.Button,
|
|
1126
|
-
{
|
|
1127
|
-
variant: "secondary",
|
|
1128
|
-
isLoading: isFetchingMore,
|
|
1129
|
-
onClick: () => loadTransactions(offset, false),
|
|
1130
|
-
children: "Load more"
|
|
1131
|
-
}
|
|
1132
|
-
) }) : null
|
|
1133
|
-
] }) });
|
|
1134
|
-
};
|
|
1135
|
-
const config$8 = adminSdk.defineRouteConfig({
|
|
1136
|
-
label: "Payments",
|
|
1137
|
-
icon: icons.CreditCard
|
|
1138
|
-
});
|
|
1139
|
-
const useDebounce$2 = (value, delay) => {
|
|
1140
|
-
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
1141
|
-
react.useEffect(() => {
|
|
1142
|
-
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
1143
|
-
return () => clearTimeout(handler);
|
|
1144
|
-
}, [value, delay]);
|
|
1145
|
-
return debouncedValue;
|
|
1146
|
-
};
|
|
1147
|
-
const getStatusBadgeClass$6 = (status) => {
|
|
1148
|
-
const s2 = status.toLowerCase();
|
|
1149
|
-
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
1150
|
-
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
1151
|
-
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
1152
|
-
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
1153
|
-
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
1154
|
-
};
|
|
1155
|
-
const RefundsPage = () => {
|
|
1156
|
-
const navigate = reactRouterDom.useNavigate();
|
|
1157
|
-
const [items, setItems] = react.useState([]);
|
|
1158
|
-
const [orderIdSearch, setOrderIdSearch] = react.useState("");
|
|
1159
|
-
const debouncedOrderId = useDebounce$2(orderIdSearch, 300);
|
|
1160
|
-
const [paymentStatusFilter, setPaymentStatusFilter] = react.useState("all");
|
|
1161
|
-
const [providerSearch, setProviderSearch] = react.useState("");
|
|
1162
|
-
const debouncedProvider = useDebounce$2(providerSearch, 300);
|
|
1163
|
-
const [currencySearch, setCurrencySearch] = react.useState("");
|
|
1164
|
-
const debouncedCurrency = useDebounce$2(currencySearch, 300);
|
|
1165
|
-
const [dateFrom, setDateFrom] = react.useState("");
|
|
1166
|
-
const [dateTo, setDateTo] = react.useState("");
|
|
1167
|
-
const [amountMin, setAmountMin] = react.useState("");
|
|
1168
|
-
const [amountMax, setAmountMax] = react.useState("");
|
|
1169
|
-
const [isLoading, setIsLoading] = react.useState(true);
|
|
1170
|
-
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
1171
|
-
const [error, setError] = react.useState(null);
|
|
1172
|
-
const [offset, setOffset] = react.useState(0);
|
|
1173
|
-
const [count, setCount] = react.useState(0);
|
|
1174
|
-
const limit = 50;
|
|
1175
|
-
const loadRefunds = react.useCallback(
|
|
1176
|
-
async (nextOffset, replace) => {
|
|
1177
|
-
try {
|
|
1178
|
-
if (replace) setIsLoading(true);
|
|
1179
|
-
else setIsFetchingMore(true);
|
|
1180
|
-
setError(null);
|
|
1181
|
-
const params = new URLSearchParams();
|
|
1182
|
-
params.set("limit", String(limit));
|
|
1183
|
-
params.set("offset", String(nextOffset));
|
|
1184
|
-
if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
|
|
1185
|
-
if (paymentStatusFilter !== "all") params.set("payment_status", paymentStatusFilter);
|
|
1186
|
-
if (debouncedProvider.trim()) params.set("provider_id", debouncedProvider.trim());
|
|
1187
|
-
if (debouncedCurrency.trim()) params.set("currency_code", debouncedCurrency.trim());
|
|
1188
|
-
if (dateFrom.trim()) params.set("date_from", dateFrom.trim());
|
|
1189
|
-
if (dateTo.trim()) params.set("date_to", dateTo.trim());
|
|
1190
|
-
const min = amountMin.trim() ? Number(amountMin) : void 0;
|
|
1191
|
-
const max = amountMax.trim() ? Number(amountMax) : void 0;
|
|
1192
|
-
if (min != null && !Number.isNaN(min)) params.set("amount_min", String(min));
|
|
1193
|
-
if (max != null && !Number.isNaN(max)) params.set("amount_max", String(max));
|
|
1194
|
-
const response = await fetch(`/admin/refunds?${params.toString()}`, {
|
|
1195
|
-
credentials: "include"
|
|
1196
|
-
});
|
|
1197
|
-
if (!response.ok) {
|
|
1198
|
-
const text = await response.text();
|
|
1199
|
-
throw new Error(text || "Failed to load refunds");
|
|
1200
|
-
}
|
|
1201
|
-
const payload = await response.json();
|
|
1202
|
-
const list = payload.refunds ?? [];
|
|
1203
|
-
setCount(payload.count ?? 0);
|
|
1204
|
-
setOffset(nextOffset + list.length);
|
|
1205
|
-
setItems((prev) => replace ? list : [...prev, ...list]);
|
|
1206
|
-
} catch (e) {
|
|
1207
|
-
setError(e instanceof Error ? e.message : "Failed to load");
|
|
1208
|
-
} finally {
|
|
1209
|
-
setIsLoading(false);
|
|
1210
|
-
setIsFetchingMore(false);
|
|
1211
|
-
}
|
|
1212
|
-
},
|
|
1213
|
-
[
|
|
1214
|
-
debouncedOrderId,
|
|
1215
|
-
paymentStatusFilter,
|
|
1216
|
-
debouncedProvider,
|
|
1217
|
-
debouncedCurrency,
|
|
1218
|
-
dateFrom,
|
|
1219
|
-
dateTo,
|
|
1220
|
-
amountMin,
|
|
1221
|
-
amountMax
|
|
1222
|
-
]
|
|
1223
|
-
);
|
|
1224
|
-
react.useEffect(() => {
|
|
1225
|
-
void loadRefunds(0, true);
|
|
1226
|
-
}, [loadRefunds]);
|
|
1227
|
-
const hasMore = react.useMemo(() => offset < count, [offset, count]);
|
|
1228
|
-
const displayAmount = (r) => {
|
|
1229
|
-
const code = (r.currency_code ?? "USD").toUpperCase();
|
|
1230
|
-
return `${code} ${Number(r.amount)}`;
|
|
1231
|
-
};
|
|
1232
|
-
const displayStatus = (r) => {
|
|
1233
|
-
const s2 = r.payment_status ?? "";
|
|
1234
|
-
return s2 !== "" ? s2 : "—";
|
|
1235
|
-
};
|
|
1236
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
|
|
1237
|
-
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
1238
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1239
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Refunds" }),
|
|
1240
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Refund records — amount, order, payment status" })
|
|
1241
|
-
] }),
|
|
1242
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => loadRefunds(0, true), children: "Refresh" })
|
|
1243
|
-
] }),
|
|
1244
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
1245
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1246
|
-
ui.Input,
|
|
1247
|
-
{
|
|
1248
|
-
placeholder: "Order ID",
|
|
1249
|
-
value: orderIdSearch,
|
|
1250
|
-
onChange: (e) => setOrderIdSearch(e.target.value),
|
|
1251
|
-
className: "md:max-w-[180px]",
|
|
1252
|
-
"aria-label": "Filter by order ID"
|
|
1253
|
-
}
|
|
1254
|
-
),
|
|
1255
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1256
|
-
ui.Input,
|
|
1257
|
-
{
|
|
1258
|
-
placeholder: "Provider",
|
|
1259
|
-
value: providerSearch,
|
|
1260
|
-
onChange: (e) => setProviderSearch(e.target.value),
|
|
1261
|
-
className: "md:max-w-[140px]",
|
|
1262
|
-
"aria-label": "Filter by provider"
|
|
1263
|
-
}
|
|
1264
|
-
),
|
|
1265
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1266
|
-
ui.Input,
|
|
1267
|
-
{
|
|
1268
|
-
placeholder: "Currency",
|
|
1269
|
-
value: currencySearch,
|
|
1270
|
-
onChange: (e) => setCurrencySearch(e.target.value),
|
|
1271
|
-
className: "md:max-w-[100px]",
|
|
1272
|
-
"aria-label": "Filter by currency"
|
|
1273
|
-
}
|
|
1274
|
-
),
|
|
1275
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1276
|
-
"select",
|
|
1277
|
-
{
|
|
1278
|
-
value: paymentStatusFilter,
|
|
1279
|
-
onChange: (e) => setPaymentStatusFilter(e.target.value),
|
|
1280
|
-
className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-[160px]",
|
|
1281
|
-
"aria-label": "Filter by payment status",
|
|
1282
|
-
children: [
|
|
1283
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All statuses" }),
|
|
1284
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "pending", children: "Pending" }),
|
|
1285
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "requires_more", children: "Requires more" }),
|
|
1286
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "error", children: "Error" }),
|
|
1287
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "canceled", children: "Canceled" }),
|
|
1288
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "authorized", children: "Authorized" }),
|
|
1289
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "captured", children: "Captured" })
|
|
1290
|
-
]
|
|
1291
|
-
}
|
|
1292
|
-
),
|
|
1293
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1294
|
-
ui.Input,
|
|
1295
|
-
{
|
|
1296
|
-
type: "date",
|
|
1297
|
-
placeholder: "From",
|
|
1298
|
-
value: dateFrom,
|
|
1299
|
-
onChange: (e) => setDateFrom(e.target.value),
|
|
1300
|
-
className: "md:max-w-[140px]",
|
|
1301
|
-
"aria-label": "Date from"
|
|
1302
|
-
}
|
|
1303
|
-
),
|
|
1304
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1305
|
-
ui.Input,
|
|
1306
|
-
{
|
|
1307
|
-
type: "date",
|
|
1308
|
-
placeholder: "To",
|
|
1309
|
-
value: dateTo,
|
|
1310
|
-
onChange: (e) => setDateTo(e.target.value),
|
|
1311
|
-
className: "md:max-w-[140px]",
|
|
1312
|
-
"aria-label": "Date to"
|
|
1313
|
-
}
|
|
1314
|
-
),
|
|
1315
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1316
|
-
ui.Input,
|
|
1317
|
-
{
|
|
1318
|
-
placeholder: "Amount min",
|
|
1319
|
-
value: amountMin,
|
|
1320
|
-
onChange: (e) => setAmountMin(e.target.value),
|
|
1321
|
-
type: "number",
|
|
1322
|
-
min: 0,
|
|
1323
|
-
className: "md:max-w-[100px]",
|
|
1324
|
-
"aria-label": "Refund amount minimum"
|
|
1325
|
-
}
|
|
1326
|
-
),
|
|
1327
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1328
|
-
ui.Input,
|
|
1329
|
-
{
|
|
1330
|
-
placeholder: "Amount max",
|
|
1331
|
-
value: amountMax,
|
|
1332
|
-
onChange: (e) => setAmountMax(e.target.value),
|
|
1333
|
-
type: "number",
|
|
1334
|
-
min: 0,
|
|
1335
|
-
className: "md:max-w-[100px]",
|
|
1336
|
-
"aria-label": "Refund amount maximum"
|
|
1337
|
-
}
|
|
1338
|
-
)
|
|
1339
|
-
] }) }),
|
|
1340
|
-
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
1341
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
1342
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => loadRefunds(0, true), children: "Try again" }) })
|
|
1343
|
-
] }) : null,
|
|
1344
|
-
isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading refunds…" }) }) : items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
1345
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No refunds yet" }),
|
|
1346
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Refund records will appear here." })
|
|
1347
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full overflow-x-auto rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full table-fixed divide-y divide-ui-border-base", style: { minWidth: 0 }, children: [
|
|
1348
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
1349
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Refund ID" }),
|
|
1350
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
1351
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Payment ID" }),
|
|
1352
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[8%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Amount" }),
|
|
1353
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[6%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Currency" }),
|
|
1354
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[10%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Provider" }),
|
|
1355
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[10%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Payment Status" }),
|
|
1356
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[14%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Note" }),
|
|
1357
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
1358
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[8%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
1359
|
-
] }) }),
|
|
1360
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((r) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1361
|
-
"tr",
|
|
1362
|
-
{
|
|
1363
|
-
className: "cursor-pointer hover:bg-ui-bg-subtle/60",
|
|
1364
|
-
onClick: () => navigate(`/refunds/${r.refund_id}`),
|
|
1365
|
-
children: [
|
|
1366
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 font-mono text-sm text-ui-fg-base", title: r.refund_id, children: r.refund_id }),
|
|
1367
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 font-medium text-ui-fg-base", title: r.order_id ?? void 0, children: r.order_id ?? "—" }),
|
|
1368
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 font-mono text-sm text-ui-fg-subtle", title: r.payment_id, children: r.payment_id }),
|
|
1369
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", children: displayAmount(r) }),
|
|
1370
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle uppercase", children: r.currency_code || "—" }),
|
|
1371
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", title: r.provider_id || void 0, children: r.provider_id || "—" }),
|
|
1372
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1373
|
-
ui.Badge,
|
|
1374
|
-
{
|
|
1375
|
-
size: "2xsmall",
|
|
1376
|
-
className: `uppercase ${getStatusBadgeClass$6(displayStatus(r))}`,
|
|
1377
|
-
children: displayStatus(r) !== "—" ? displayStatus(r).replace(/_/g, " ") : "—"
|
|
1378
|
-
}
|
|
1379
|
-
) }),
|
|
1380
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", title: r.note ?? void 0, children: r.note ?? "—" }),
|
|
1381
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle text-xs", children: new Date(r.created_at).toLocaleDateString("en-US", {
|
|
1382
|
-
month: "short",
|
|
1383
|
-
day: "numeric",
|
|
1384
|
-
hour: "numeric",
|
|
1385
|
-
minute: "2-digit",
|
|
1386
|
-
hour12: true
|
|
1387
|
-
}) }),
|
|
1388
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-1", children: [
|
|
1389
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1390
|
-
ui.Button,
|
|
1391
|
-
{
|
|
1392
|
-
variant: "transparent",
|
|
1393
|
-
size: "small",
|
|
1394
|
-
onClick: (e) => {
|
|
1395
|
-
e.stopPropagation();
|
|
1396
|
-
navigate(`/refunds/${r.refund_id}`);
|
|
1397
|
-
},
|
|
1398
|
-
children: "Details"
|
|
1399
|
-
}
|
|
1400
|
-
),
|
|
1401
|
-
r.order_id ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1402
|
-
ui.Button,
|
|
1403
|
-
{
|
|
1404
|
-
variant: "transparent",
|
|
1405
|
-
size: "small",
|
|
1406
|
-
onClick: (e) => {
|
|
1407
|
-
e.stopPropagation();
|
|
1408
|
-
navigate(`/orders/${r.order_id}`);
|
|
1409
|
-
},
|
|
1410
|
-
children: "Order"
|
|
1411
|
-
}
|
|
1412
|
-
) : null
|
|
1413
|
-
] }) })
|
|
1414
|
-
]
|
|
1415
|
-
},
|
|
1416
|
-
r.refund_id
|
|
1417
|
-
)) })
|
|
1418
|
-
] }) }),
|
|
1419
|
-
hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1420
|
-
ui.Button,
|
|
1421
|
-
{
|
|
1422
|
-
variant: "secondary",
|
|
1423
|
-
isLoading: isFetchingMore,
|
|
1424
|
-
onClick: () => loadRefunds(offset, false),
|
|
1425
|
-
children: "Load more"
|
|
1426
|
-
}
|
|
1427
|
-
) }) : null
|
|
1428
|
-
] }) });
|
|
1429
|
-
};
|
|
1430
|
-
const config$7 = adminSdk.defineRouteConfig({
|
|
1431
|
-
label: "Refunds",
|
|
1432
|
-
icon: icons.Receipt
|
|
1433
|
-
});
|
|
1434
927
|
const AUDITED_TABLE_NAMES = [
|
|
1435
928
|
"account_deletion_request",
|
|
1436
929
|
"account_holder",
|
|
@@ -1854,7 +1347,7 @@ function getEntityInfo(tableName) {
|
|
|
1854
1347
|
const def = ENTITY_DEFINITIONS[tableName];
|
|
1855
1348
|
return {
|
|
1856
1349
|
tableName,
|
|
1857
|
-
label:
|
|
1350
|
+
label: def?.label ?? humanizeTableName(tableName),
|
|
1858
1351
|
category: def && CATEGORY_BY_ID.get(def.category) || SYSTEM_CATEGORY
|
|
1859
1352
|
};
|
|
1860
1353
|
}
|
|
@@ -1879,13 +1372,11 @@ function getTablesForCategory(id) {
|
|
|
1879
1372
|
}
|
|
1880
1373
|
const GROUPS = getEntitiesByCategory();
|
|
1881
1374
|
function triggerLabel(entity, category) {
|
|
1882
|
-
var _a;
|
|
1883
1375
|
if (entity) return getEntityInfo(entity).label;
|
|
1884
|
-
if (category) return `All ${
|
|
1376
|
+
if (category) return `All ${getCategory(category)?.label ?? category}`;
|
|
1885
1377
|
return "All entities";
|
|
1886
1378
|
}
|
|
1887
1379
|
const EntityPicker = ({ entity, category, onChange }) => {
|
|
1888
|
-
var _a;
|
|
1889
1380
|
const [open, setOpen] = react.useState(false);
|
|
1890
1381
|
const [search, setSearch] = react.useState("");
|
|
1891
1382
|
const searchRef = react.useRef(null);
|
|
@@ -1905,7 +1396,7 @@ const EntityPicker = ({ entity, category, onChange }) => {
|
|
|
1905
1396
|
setOpen(false);
|
|
1906
1397
|
setSearch("");
|
|
1907
1398
|
};
|
|
1908
|
-
const firstMatch =
|
|
1399
|
+
const firstMatch = filteredGroups[0]?.entities[0];
|
|
1909
1400
|
const isAll = !entity && !category;
|
|
1910
1401
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1911
1402
|
ui.Popover,
|
|
@@ -1938,9 +1429,8 @@ const EntityPicker = ({ entity, category, onChange }) => {
|
|
|
1938
1429
|
align: "start",
|
|
1939
1430
|
className: "w-[min(360px,calc(100vw-2rem))] p-0",
|
|
1940
1431
|
onOpenAutoFocus: (event) => {
|
|
1941
|
-
var _a2;
|
|
1942
1432
|
event.preventDefault();
|
|
1943
|
-
|
|
1433
|
+
searchRef.current?.focus();
|
|
1944
1434
|
},
|
|
1945
1435
|
children: [
|
|
1946
1436
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-ui-border-base p-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2080,7 +1570,7 @@ function formatNumber(value) {
|
|
|
2080
1570
|
return new Intl.NumberFormat().format(value);
|
|
2081
1571
|
}
|
|
2082
1572
|
function formatMoney(amount, currencyCode) {
|
|
2083
|
-
const code = currencyCode
|
|
1573
|
+
const code = currencyCode?.trim().toUpperCase();
|
|
2084
1574
|
if (code && /^[A-Z]{3}$/.test(code)) {
|
|
2085
1575
|
try {
|
|
2086
1576
|
return new Intl.NumberFormat(void 0, { style: "currency", currency: code }).format(amount);
|
|
@@ -2147,9 +1637,9 @@ const SummaryCards = ({ stats, loading, failed }) => {
|
|
|
2147
1637
|
};
|
|
2148
1638
|
const BASE = "/admin/deleted-records-audit";
|
|
2149
1639
|
class AuditApiError extends Error {
|
|
1640
|
+
status;
|
|
2150
1641
|
constructor(message, status) {
|
|
2151
1642
|
super(message);
|
|
2152
|
-
__publicField(this, "status");
|
|
2153
1643
|
this.status = status;
|
|
2154
1644
|
}
|
|
2155
1645
|
}
|
|
@@ -2214,10 +1704,7 @@ const URL_KEYS = {
|
|
|
2214
1704
|
const DATE_PRESET_VALUES = new Set(DATE_PRESETS.map((p) => p.value));
|
|
2215
1705
|
const DAY_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
2216
1706
|
function filtersFromSearchParams(params) {
|
|
2217
|
-
const read = (key) =>
|
|
2218
|
-
var _a;
|
|
2219
|
-
return ((_a = params.get(URL_KEYS[key])) == null ? void 0 : _a.trim()) ?? "";
|
|
2220
|
-
};
|
|
1707
|
+
const read = (key) => params.get(URL_KEYS[key])?.trim() ?? "";
|
|
2221
1708
|
const date = read("date");
|
|
2222
1709
|
const from = read("from");
|
|
2223
1710
|
const to = read("to");
|
|
@@ -2371,9 +1858,9 @@ const DeletedRecordsPage = () => {
|
|
|
2371
1858
|
try {
|
|
2372
1859
|
setStats(await fetchAuditStats(signal));
|
|
2373
1860
|
} catch (e) {
|
|
2374
|
-
if (!
|
|
1861
|
+
if (!signal?.aborted) setStatsFailed(true);
|
|
2375
1862
|
} finally {
|
|
2376
|
-
if (!
|
|
1863
|
+
if (!signal?.aborted) setStatsLoading(false);
|
|
2377
1864
|
}
|
|
2378
1865
|
}, []);
|
|
2379
1866
|
react.useEffect(() => {
|
|
@@ -2430,7 +1917,7 @@ const DeletedRecordsPage = () => {
|
|
|
2430
1917
|
const visible = Array.from(document.querySelectorAll(`[data-audit-row="${lastViewed}"]`)).find(
|
|
2431
1918
|
(el) => el.offsetParent !== null
|
|
2432
1919
|
);
|
|
2433
|
-
visible
|
|
1920
|
+
visible?.scrollIntoView({ block: "center" });
|
|
2434
1921
|
});
|
|
2435
1922
|
const handle = setTimeout(() => setHighlightId(null), 2500);
|
|
2436
1923
|
return () => clearTimeout(handle);
|
|
@@ -2457,8 +1944,8 @@ const DeletedRecordsPage = () => {
|
|
|
2457
1944
|
};
|
|
2458
1945
|
const refresh = () => setReloadToken((t) => t + 1);
|
|
2459
1946
|
const hasMore = items.length < count;
|
|
2460
|
-
const knownSources =
|
|
2461
|
-
const knownDeletedBy =
|
|
1947
|
+
const knownSources = stats?.sources ?? [];
|
|
1948
|
+
const knownDeletedBy = stats?.deleted_by ?? [];
|
|
2462
1949
|
const attributionMissing = !!stats && stats.total > 0 && knownSources.length === 0 && knownDeletedBy.length === 0;
|
|
2463
1950
|
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-7xl flex-col gap-6 p-4 md:p-6", children: [
|
|
2464
1951
|
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-start md:justify-between", children: [
|
|
@@ -2722,11 +2209,11 @@ const ErrorState = ({ onRetry, detail }) => /* @__PURE__ */ jsxRuntime.jsxs("div
|
|
|
2722
2209
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "max-w-md font-mono text-ui-fg-muted", children: detail }),
|
|
2723
2210
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", size: "small", className: "mt-2", onClick: onRetry, children: "Try again" })
|
|
2724
2211
|
] });
|
|
2725
|
-
const config$
|
|
2212
|
+
const config$9 = adminSdk.defineRouteConfig({
|
|
2726
2213
|
label: "Deleted Records",
|
|
2727
2214
|
icon: icons.Trash
|
|
2728
2215
|
});
|
|
2729
|
-
const useDebounce$
|
|
2216
|
+
const useDebounce$3 = (value, delay) => {
|
|
2730
2217
|
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
2731
2218
|
react.useEffect(() => {
|
|
2732
2219
|
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
@@ -2734,201 +2221,145 @@ const useDebounce$1 = (value, delay) => {
|
|
|
2734
2221
|
}, [value, delay]);
|
|
2735
2222
|
return debouncedValue;
|
|
2736
2223
|
};
|
|
2737
|
-
const getStatusBadgeClass$
|
|
2738
|
-
const
|
|
2739
|
-
if (
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
if (
|
|
2743
|
-
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
2744
|
-
}
|
|
2745
|
-
if (statusLower === "requires_action") {
|
|
2746
|
-
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
2747
|
-
}
|
|
2748
|
-
if (statusLower === "completed") {
|
|
2749
|
-
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
2750
|
-
}
|
|
2751
|
-
if (statusLower === "canceled") {
|
|
2752
|
-
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
2753
|
-
}
|
|
2224
|
+
const getStatusBadgeClass$7 = (status) => {
|
|
2225
|
+
const s2 = status.toLowerCase();
|
|
2226
|
+
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
2227
|
+
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
2228
|
+
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
2229
|
+
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
2754
2230
|
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
2755
2231
|
};
|
|
2756
|
-
const
|
|
2232
|
+
const PaymentsPage = () => {
|
|
2757
2233
|
const navigate = reactRouterDom.useNavigate();
|
|
2758
2234
|
const [items, setItems] = react.useState([]);
|
|
2759
2235
|
const [statusFilter, setStatusFilter] = react.useState("all");
|
|
2760
|
-
const [
|
|
2761
|
-
const
|
|
2762
|
-
const debouncedSearchQuery = useDebounce$1(searchQuery, 300);
|
|
2236
|
+
const [orderIdSearch, setOrderIdSearch] = react.useState("");
|
|
2237
|
+
const debouncedOrderId = useDebounce$3(orderIdSearch, 300);
|
|
2763
2238
|
const [isLoading, setIsLoading] = react.useState(true);
|
|
2764
2239
|
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
2765
2240
|
const [error, setError] = react.useState(null);
|
|
2766
2241
|
const [offset, setOffset] = react.useState(0);
|
|
2767
2242
|
const [count, setCount] = react.useState(0);
|
|
2768
2243
|
const limit = 50;
|
|
2769
|
-
const
|
|
2770
|
-
async (nextOffset, replace
|
|
2771
|
-
var _a;
|
|
2244
|
+
const loadTransactions = react.useCallback(
|
|
2245
|
+
async (nextOffset, replace) => {
|
|
2772
2246
|
try {
|
|
2773
|
-
if (replace)
|
|
2774
|
-
|
|
2775
|
-
} else {
|
|
2776
|
-
setIsFetchingMore(true);
|
|
2777
|
-
}
|
|
2247
|
+
if (replace) setIsLoading(true);
|
|
2248
|
+
else setIsFetchingMore(true);
|
|
2778
2249
|
setError(null);
|
|
2779
2250
|
const params = new URLSearchParams();
|
|
2780
2251
|
params.set("limit", String(limit));
|
|
2781
2252
|
params.set("offset", String(nextOffset));
|
|
2782
|
-
if (statusFilter !== "all")
|
|
2783
|
-
|
|
2784
|
-
}
|
|
2785
|
-
if (debouncedSearchQuery.trim()) {
|
|
2786
|
-
params.set("q", debouncedSearchQuery.trim());
|
|
2787
|
-
}
|
|
2788
|
-
if (createdByFilter !== "all") {
|
|
2789
|
-
params.set("created_by", createdByFilter);
|
|
2790
|
-
}
|
|
2791
|
-
params.set("order", "created_at");
|
|
2253
|
+
if (statusFilter !== "all") params.set("status", statusFilter);
|
|
2254
|
+
if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
|
|
2792
2255
|
const response = await fetch(
|
|
2793
|
-
`/admin/
|
|
2256
|
+
`/admin/payment-transactions?${params.toString()}`,
|
|
2794
2257
|
{ credentials: "include" }
|
|
2795
2258
|
);
|
|
2796
2259
|
if (!response.ok) {
|
|
2797
|
-
const
|
|
2798
|
-
throw new Error(
|
|
2260
|
+
const text = await response.text();
|
|
2261
|
+
throw new Error(text || "Failed to load payment transactions");
|
|
2799
2262
|
}
|
|
2800
2263
|
const payload = await response.json();
|
|
2264
|
+
const list = payload.transactions ?? [];
|
|
2801
2265
|
setCount(payload.count ?? 0);
|
|
2802
|
-
setOffset(nextOffset +
|
|
2803
|
-
setItems(
|
|
2804
|
-
|
|
2805
|
-
);
|
|
2806
|
-
} catch (loadError) {
|
|
2807
|
-
const message = loadError instanceof Error ? loadError.message : "Unable to load return orders";
|
|
2808
|
-
setError(message);
|
|
2266
|
+
setOffset(nextOffset + list.length);
|
|
2267
|
+
setItems((prev) => replace ? list : [...prev, ...list]);
|
|
2268
|
+
} catch (e) {
|
|
2269
|
+
setError(e instanceof Error ? e.message : "Failed to load");
|
|
2809
2270
|
} finally {
|
|
2810
2271
|
setIsLoading(false);
|
|
2811
2272
|
setIsFetchingMore(false);
|
|
2812
2273
|
}
|
|
2813
2274
|
},
|
|
2814
|
-
[statusFilter,
|
|
2275
|
+
[statusFilter, debouncedOrderId]
|
|
2815
2276
|
);
|
|
2816
2277
|
react.useEffect(() => {
|
|
2817
|
-
void
|
|
2818
|
-
}, [
|
|
2278
|
+
void loadTransactions(0, true);
|
|
2279
|
+
}, [loadTransactions]);
|
|
2819
2280
|
const hasMore = react.useMemo(() => offset < count, [offset, count]);
|
|
2820
|
-
const
|
|
2821
|
-
const
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2281
|
+
const displayStatus = (t) => {
|
|
2282
|
+
const s2 = t.payment_id != null && t.payment_status != null && t.payment_status !== "" ? t.payment_status : t.session_status ?? "";
|
|
2283
|
+
return s2 !== "" ? s2 : "—";
|
|
2284
|
+
};
|
|
2285
|
+
const displayAmount = (t) => {
|
|
2286
|
+
const code = (t.currency_code ?? "USD").toUpperCase();
|
|
2287
|
+
return `${code} ${Number(t.amount)}`;
|
|
2288
|
+
};
|
|
2825
2289
|
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: [
|
|
2826
2290
|
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
2827
2291
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
2828
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "
|
|
2829
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "
|
|
2292
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Payments" }),
|
|
2293
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "All payment attempts — completed, pending, failed, requires action" })
|
|
2830
2294
|
] }),
|
|
2831
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () =>
|
|
2295
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => loadTransactions(0, true), children: "Refresh" })
|
|
2832
2296
|
] }),
|
|
2833
2297
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
2834
2298
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2835
2299
|
ui.Input,
|
|
2836
2300
|
{
|
|
2837
|
-
placeholder: "Search by
|
|
2838
|
-
value:
|
|
2839
|
-
onChange: (
|
|
2840
|
-
className: "md:max-w-sm"
|
|
2301
|
+
placeholder: "Search by Order ID",
|
|
2302
|
+
value: orderIdSearch,
|
|
2303
|
+
onChange: (e) => setOrderIdSearch(e.target.value),
|
|
2304
|
+
className: "md:max-w-sm",
|
|
2305
|
+
"aria-label": "Search by order ID"
|
|
2841
2306
|
}
|
|
2842
2307
|
),
|
|
2843
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2844
|
-
|
|
2845
|
-
"select",
|
|
2846
|
-
{
|
|
2847
|
-
value: createdByFilter,
|
|
2848
|
-
onChange: (event) => setCreatedByFilter(event.target.value),
|
|
2849
|
-
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",
|
|
2850
|
-
children: [
|
|
2851
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All (Created by)" }),
|
|
2852
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "customer", children: "Customer" }),
|
|
2853
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "admin", children: "Admin" })
|
|
2854
|
-
]
|
|
2855
|
-
}
|
|
2856
|
-
),
|
|
2857
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2858
|
-
"select",
|
|
2859
|
-
{
|
|
2860
|
-
value: statusFilter,
|
|
2861
|
-
onChange: (event) => setStatusFilter(event.target.value),
|
|
2862
|
-
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",
|
|
2863
|
-
children: [
|
|
2864
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All Statuses" }),
|
|
2865
|
-
availableStatuses.map((status) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
|
|
2866
|
-
]
|
|
2867
|
-
}
|
|
2868
|
-
)
|
|
2869
|
-
] })
|
|
2870
|
-
] }),
|
|
2871
|
-
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
2872
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
2873
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2874
|
-
ui.Button,
|
|
2308
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2309
|
+
"select",
|
|
2875
2310
|
{
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2311
|
+
value: statusFilter,
|
|
2312
|
+
onChange: (e) => setStatusFilter(e.target.value),
|
|
2313
|
+
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",
|
|
2314
|
+
"aria-label": "Filter by status",
|
|
2315
|
+
children: [
|
|
2316
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All statuses" }),
|
|
2317
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "pending", children: "Pending" }),
|
|
2318
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "requires_more", children: "Requires more" }),
|
|
2319
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "error", children: "Error" }),
|
|
2320
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "canceled", children: "Canceled" }),
|
|
2321
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "authorized", children: "Authorized" }),
|
|
2322
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "captured", children: "Captured" })
|
|
2323
|
+
]
|
|
2879
2324
|
}
|
|
2880
2325
|
) })
|
|
2326
|
+
] }),
|
|
2327
|
+
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
2328
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
2329
|
+
/* @__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" }) })
|
|
2881
2330
|
] }) : null,
|
|
2882
|
-
isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading
|
|
2883
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No
|
|
2884
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "
|
|
2331
|
+
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: [
|
|
2332
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No payment transactions yet" }),
|
|
2333
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Payment attempts will appear here." })
|
|
2885
2334
|
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
2886
2335
|
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
2887
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Return ID" }),
|
|
2888
2336
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
2889
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "
|
|
2337
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Amount" }),
|
|
2338
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Provider" }),
|
|
2890
2339
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
2891
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "
|
|
2340
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Finalized" }),
|
|
2892
2341
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
2893
2342
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
2894
2343
|
] }) }),
|
|
2895
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((
|
|
2344
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((t) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2896
2345
|
"tr",
|
|
2897
2346
|
{
|
|
2898
2347
|
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
2899
|
-
onClick: () => navigate(`/
|
|
2348
|
+
onClick: () => navigate(`/payments/${t.payment_session_id}`),
|
|
2900
2349
|
children: [
|
|
2901
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children:
|
|
2902
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children:
|
|
2903
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children:
|
|
2350
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: t.order_id ?? "—" }),
|
|
2351
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: displayAmount(t) }),
|
|
2352
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.provider_id }),
|
|
2904
2353
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2905
2354
|
ui.Badge,
|
|
2906
2355
|
{
|
|
2907
2356
|
size: "2xsmall",
|
|
2908
|
-
className: `uppercase ${getStatusBadgeClass$
|
|
2909
|
-
children:
|
|
2357
|
+
className: `uppercase ${getStatusBadgeClass$7(displayStatus(t))}`,
|
|
2358
|
+
children: displayStatus(t) !== "—" ? displayStatus(t).replace(/_/g, " ") : "—"
|
|
2910
2359
|
}
|
|
2911
2360
|
) }),
|
|
2912
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children:
|
|
2913
|
-
|
|
2914
|
-
if ((calc == null ? void 0 : calc.is_processed) && calc.final_refund_amount != null) {
|
|
2915
|
-
return formatRefundCurrency(
|
|
2916
|
-
calc.final_refund_amount,
|
|
2917
|
-
calc.currency_code || returnOrder.currency_code
|
|
2918
|
-
);
|
|
2919
|
-
}
|
|
2920
|
-
if (calc) {
|
|
2921
|
-
return "Pending";
|
|
2922
|
-
}
|
|
2923
|
-
if (returnOrder.refund_amount == null) {
|
|
2924
|
-
return "—";
|
|
2925
|
-
}
|
|
2926
|
-
return formatRefundCurrency(
|
|
2927
|
-
Number(returnOrder.refund_amount),
|
|
2928
|
-
returnOrder.currency_code
|
|
2929
|
-
);
|
|
2930
|
-
})() }),
|
|
2931
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(returnOrder.created_at).toLocaleDateString("en-US", {
|
|
2361
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.payment_id != null ? "Yes" : "No" }),
|
|
2362
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(t.created_at).toLocaleDateString("en-US", {
|
|
2932
2363
|
year: "numeric",
|
|
2933
2364
|
month: "short",
|
|
2934
2365
|
day: "numeric",
|
|
@@ -2936,21 +2367,35 @@ const ReturnsPage = () => {
|
|
|
2936
2367
|
minute: "2-digit",
|
|
2937
2368
|
hour12: true
|
|
2938
2369
|
}) }),
|
|
2939
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
e
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2370
|
+
/* @__PURE__ */ jsxRuntime.jsxs("td", { className: "px-4 py-4", children: [
|
|
2371
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2372
|
+
ui.Button,
|
|
2373
|
+
{
|
|
2374
|
+
variant: "transparent",
|
|
2375
|
+
size: "small",
|
|
2376
|
+
onClick: (e) => {
|
|
2377
|
+
e.stopPropagation();
|
|
2378
|
+
navigate(`/payments/${t.payment_session_id}`);
|
|
2379
|
+
},
|
|
2380
|
+
children: "View details"
|
|
2381
|
+
}
|
|
2382
|
+
),
|
|
2383
|
+
t.order_id ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2384
|
+
ui.Button,
|
|
2385
|
+
{
|
|
2386
|
+
variant: "transparent",
|
|
2387
|
+
size: "small",
|
|
2388
|
+
onClick: (e) => {
|
|
2389
|
+
e.stopPropagation();
|
|
2390
|
+
navigate(`/orders/${t.order_id}`);
|
|
2391
|
+
},
|
|
2392
|
+
children: "Order"
|
|
2393
|
+
}
|
|
2394
|
+
) : null
|
|
2395
|
+
] })
|
|
2951
2396
|
]
|
|
2952
2397
|
},
|
|
2953
|
-
|
|
2398
|
+
t.payment_session_id
|
|
2954
2399
|
)) })
|
|
2955
2400
|
] }) }),
|
|
2956
2401
|
hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2958,17 +2403,17 @@ const ReturnsPage = () => {
|
|
|
2958
2403
|
{
|
|
2959
2404
|
variant: "secondary",
|
|
2960
2405
|
isLoading: isFetchingMore,
|
|
2961
|
-
onClick: () =>
|
|
2406
|
+
onClick: () => loadTransactions(offset, false),
|
|
2962
2407
|
children: "Load more"
|
|
2963
2408
|
}
|
|
2964
2409
|
) }) : null
|
|
2965
2410
|
] }) });
|
|
2966
2411
|
};
|
|
2967
|
-
const config$
|
|
2968
|
-
label: "
|
|
2969
|
-
icon: icons.
|
|
2412
|
+
const config$8 = adminSdk.defineRouteConfig({
|
|
2413
|
+
label: "Payments",
|
|
2414
|
+
icon: icons.CreditCard
|
|
2970
2415
|
});
|
|
2971
|
-
const useDebounce = (value, delay) => {
|
|
2416
|
+
const useDebounce$2 = (value, delay) => {
|
|
2972
2417
|
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
2973
2418
|
react.useEffect(() => {
|
|
2974
2419
|
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
@@ -2976,547 +2421,771 @@ const useDebounce = (value, delay) => {
|
|
|
2976
2421
|
}, [value, delay]);
|
|
2977
2422
|
return debouncedValue;
|
|
2978
2423
|
};
|
|
2979
|
-
const getStatusBadgeClass$
|
|
2980
|
-
const
|
|
2981
|
-
if (
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
if (
|
|
2985
|
-
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
2986
|
-
}
|
|
2987
|
-
if (statusLower === "rejected") {
|
|
2988
|
-
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
2989
|
-
}
|
|
2990
|
-
if (statusLower === "completed") {
|
|
2991
|
-
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
2992
|
-
}
|
|
2993
|
-
if (statusLower === "cancelled") {
|
|
2994
|
-
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
2995
|
-
}
|
|
2424
|
+
const getStatusBadgeClass$6 = (status) => {
|
|
2425
|
+
const s2 = status.toLowerCase();
|
|
2426
|
+
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
2427
|
+
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
2428
|
+
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
2429
|
+
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
2996
2430
|
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
2997
2431
|
};
|
|
2998
|
-
const
|
|
2432
|
+
const RefundsPage = () => {
|
|
2999
2433
|
const navigate = reactRouterDom.useNavigate();
|
|
3000
2434
|
const [items, setItems] = react.useState([]);
|
|
3001
|
-
const [
|
|
3002
|
-
const
|
|
3003
|
-
const [
|
|
3004
|
-
const
|
|
2435
|
+
const [orderIdSearch, setOrderIdSearch] = react.useState("");
|
|
2436
|
+
const debouncedOrderId = useDebounce$2(orderIdSearch, 300);
|
|
2437
|
+
const [paymentStatusFilter, setPaymentStatusFilter] = react.useState("all");
|
|
2438
|
+
const [providerSearch, setProviderSearch] = react.useState("");
|
|
2439
|
+
const debouncedProvider = useDebounce$2(providerSearch, 300);
|
|
2440
|
+
const [currencySearch, setCurrencySearch] = react.useState("");
|
|
2441
|
+
const debouncedCurrency = useDebounce$2(currencySearch, 300);
|
|
2442
|
+
const [dateFrom, setDateFrom] = react.useState("");
|
|
2443
|
+
const [dateTo, setDateTo] = react.useState("");
|
|
2444
|
+
const [amountMin, setAmountMin] = react.useState("");
|
|
2445
|
+
const [amountMax, setAmountMax] = react.useState("");
|
|
3005
2446
|
const [isLoading, setIsLoading] = react.useState(true);
|
|
3006
2447
|
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
3007
2448
|
const [error, setError] = react.useState(null);
|
|
3008
2449
|
const [offset, setOffset] = react.useState(0);
|
|
3009
2450
|
const [count, setCount] = react.useState(0);
|
|
3010
2451
|
const limit = 50;
|
|
3011
|
-
const
|
|
3012
|
-
async (nextOffset, replace
|
|
3013
|
-
var _a;
|
|
2452
|
+
const loadRefunds = react.useCallback(
|
|
2453
|
+
async (nextOffset, replace) => {
|
|
3014
2454
|
try {
|
|
3015
|
-
if (replace)
|
|
3016
|
-
|
|
3017
|
-
} else {
|
|
3018
|
-
setIsFetchingMore(true);
|
|
3019
|
-
}
|
|
2455
|
+
if (replace) setIsLoading(true);
|
|
2456
|
+
else setIsFetchingMore(true);
|
|
3020
2457
|
setError(null);
|
|
3021
2458
|
const params = new URLSearchParams();
|
|
3022
2459
|
params.set("limit", String(limit));
|
|
3023
2460
|
params.set("offset", String(nextOffset));
|
|
3024
|
-
if (
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
if (
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
);
|
|
2461
|
+
if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
|
|
2462
|
+
if (paymentStatusFilter !== "all") params.set("payment_status", paymentStatusFilter);
|
|
2463
|
+
if (debouncedProvider.trim()) params.set("provider_id", debouncedProvider.trim());
|
|
2464
|
+
if (debouncedCurrency.trim()) params.set("currency_code", debouncedCurrency.trim());
|
|
2465
|
+
if (dateFrom.trim()) params.set("date_from", dateFrom.trim());
|
|
2466
|
+
if (dateTo.trim()) params.set("date_to", dateTo.trim());
|
|
2467
|
+
const min = amountMin.trim() ? Number(amountMin) : void 0;
|
|
2468
|
+
const max = amountMax.trim() ? Number(amountMax) : void 0;
|
|
2469
|
+
if (min != null && !Number.isNaN(min)) params.set("amount_min", String(min));
|
|
2470
|
+
if (max != null && !Number.isNaN(max)) params.set("amount_max", String(max));
|
|
2471
|
+
const response = await fetch(`/admin/refunds?${params.toString()}`, {
|
|
2472
|
+
credentials: "include"
|
|
2473
|
+
});
|
|
3037
2474
|
if (!response.ok) {
|
|
3038
|
-
const
|
|
3039
|
-
throw new Error(
|
|
2475
|
+
const text = await response.text();
|
|
2476
|
+
throw new Error(text || "Failed to load refunds");
|
|
3040
2477
|
}
|
|
3041
2478
|
const payload = await response.json();
|
|
2479
|
+
const list = payload.refunds ?? [];
|
|
3042
2480
|
setCount(payload.count ?? 0);
|
|
3043
|
-
setOffset(nextOffset +
|
|
3044
|
-
setItems(
|
|
3045
|
-
|
|
3046
|
-
);
|
|
3047
|
-
} catch (loadError) {
|
|
3048
|
-
const message = loadError instanceof Error ? loadError.message : "Unable to load swaps";
|
|
3049
|
-
setError(message);
|
|
2481
|
+
setOffset(nextOffset + list.length);
|
|
2482
|
+
setItems((prev) => replace ? list : [...prev, ...list]);
|
|
2483
|
+
} catch (e) {
|
|
2484
|
+
setError(e instanceof Error ? e.message : "Failed to load");
|
|
3050
2485
|
} finally {
|
|
3051
2486
|
setIsLoading(false);
|
|
3052
2487
|
setIsFetchingMore(false);
|
|
3053
2488
|
}
|
|
3054
2489
|
},
|
|
3055
|
-
[
|
|
2490
|
+
[
|
|
2491
|
+
debouncedOrderId,
|
|
2492
|
+
paymentStatusFilter,
|
|
2493
|
+
debouncedProvider,
|
|
2494
|
+
debouncedCurrency,
|
|
2495
|
+
dateFrom,
|
|
2496
|
+
dateTo,
|
|
2497
|
+
amountMin,
|
|
2498
|
+
amountMax
|
|
2499
|
+
]
|
|
3056
2500
|
);
|
|
3057
2501
|
react.useEffect(() => {
|
|
3058
|
-
void
|
|
3059
|
-
}, [
|
|
2502
|
+
void loadRefunds(0, true);
|
|
2503
|
+
}, [loadRefunds]);
|
|
3060
2504
|
const hasMore = react.useMemo(() => offset < count, [offset, count]);
|
|
3061
|
-
const
|
|
3062
|
-
const
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
2505
|
+
const displayAmount = (r) => {
|
|
2506
|
+
const code = (r.currency_code ?? "USD").toUpperCase();
|
|
2507
|
+
return `${code} ${Number(r.amount)}`;
|
|
2508
|
+
};
|
|
2509
|
+
const displayStatus = (r) => {
|
|
2510
|
+
const s2 = r.payment_status ?? "";
|
|
2511
|
+
return s2 !== "" ? s2 : "—";
|
|
2512
|
+
};
|
|
3066
2513
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
|
|
3067
2514
|
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
3068
2515
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3069
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "
|
|
3070
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "
|
|
2516
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Refunds" }),
|
|
2517
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Refund records — amount, order, payment status" })
|
|
3071
2518
|
] }),
|
|
3072
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () =>
|
|
2519
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => loadRefunds(0, true), children: "Refresh" })
|
|
3073
2520
|
] }),
|
|
3074
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2521
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
3075
2522
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3076
2523
|
ui.Input,
|
|
3077
2524
|
{
|
|
3078
|
-
placeholder: "
|
|
3079
|
-
value:
|
|
3080
|
-
onChange: (
|
|
3081
|
-
className: "md:max-w-
|
|
2525
|
+
placeholder: "Order ID",
|
|
2526
|
+
value: orderIdSearch,
|
|
2527
|
+
onChange: (e) => setOrderIdSearch(e.target.value),
|
|
2528
|
+
className: "md:max-w-[180px]",
|
|
2529
|
+
"aria-label": "Filter by order ID"
|
|
3082
2530
|
}
|
|
3083
2531
|
),
|
|
3084
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3085
|
-
|
|
3086
|
-
"select",
|
|
3087
|
-
{
|
|
3088
|
-
value: createdByFilter,
|
|
3089
|
-
onChange: (event) => setCreatedByFilter(event.target.value),
|
|
3090
|
-
className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-xs",
|
|
3091
|
-
children: [
|
|
3092
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All (Created by)" }),
|
|
3093
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "customer", children: "Customer" }),
|
|
3094
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "admin", children: "Admin" })
|
|
3095
|
-
]
|
|
3096
|
-
}
|
|
3097
|
-
),
|
|
3098
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3099
|
-
"select",
|
|
3100
|
-
{
|
|
3101
|
-
value: statusFilter,
|
|
3102
|
-
onChange: (event) => setStatusFilter(event.target.value),
|
|
3103
|
-
className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-xs",
|
|
3104
|
-
children: [
|
|
3105
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All Statuses" }),
|
|
3106
|
-
availableStatuses.map((status) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
|
|
3107
|
-
]
|
|
3108
|
-
}
|
|
3109
|
-
)
|
|
3110
|
-
] })
|
|
3111
|
-
] }),
|
|
3112
|
-
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
3113
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
3114
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3115
|
-
ui.Button,
|
|
2532
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2533
|
+
ui.Input,
|
|
3116
2534
|
{
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
2535
|
+
placeholder: "Provider",
|
|
2536
|
+
value: providerSearch,
|
|
2537
|
+
onChange: (e) => setProviderSearch(e.target.value),
|
|
2538
|
+
className: "md:max-w-[140px]",
|
|
2539
|
+
"aria-label": "Filter by provider"
|
|
3120
2540
|
}
|
|
3121
|
-
)
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No exchanges yet" }),
|
|
3125
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Exchange requests created by customers will appear here." })
|
|
3126
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
3127
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
3128
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Exchange ID" }),
|
|
3129
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
3130
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
3131
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Difference Due" }),
|
|
3132
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
3133
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
3134
|
-
] }) }),
|
|
3135
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((swap) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3136
|
-
"tr",
|
|
2541
|
+
),
|
|
2542
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2543
|
+
ui.Input,
|
|
3137
2544
|
{
|
|
3138
|
-
|
|
3139
|
-
|
|
2545
|
+
placeholder: "Currency",
|
|
2546
|
+
value: currencySearch,
|
|
2547
|
+
onChange: (e) => setCurrencySearch(e.target.value),
|
|
2548
|
+
className: "md:max-w-[100px]",
|
|
2549
|
+
"aria-label": "Filter by currency"
|
|
2550
|
+
}
|
|
2551
|
+
),
|
|
2552
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2553
|
+
"select",
|
|
2554
|
+
{
|
|
2555
|
+
value: paymentStatusFilter,
|
|
2556
|
+
onChange: (e) => setPaymentStatusFilter(e.target.value),
|
|
2557
|
+
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]",
|
|
2558
|
+
"aria-label": "Filter by payment status",
|
|
3140
2559
|
children: [
|
|
3141
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
3142
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
3143
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
children: swap.status.replace(/_/g, " ")
|
|
3149
|
-
}
|
|
3150
|
-
) }),
|
|
3151
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
|
|
3152
|
-
const amount = swap.difference_due;
|
|
3153
|
-
if (amount == null || amount === void 0) {
|
|
3154
|
-
return "—";
|
|
3155
|
-
}
|
|
3156
|
-
const displayAmount = Number(amount) / 100;
|
|
3157
|
-
const currency = swap.currency_code || "$";
|
|
3158
|
-
const sign = displayAmount >= 0 ? "+" : "";
|
|
3159
|
-
return `${sign}${currency}${displayAmount.toFixed(2)}`;
|
|
3160
|
-
})() }),
|
|
3161
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(swap.created_at).toLocaleDateString("en-US", {
|
|
3162
|
-
year: "numeric",
|
|
3163
|
-
month: "short",
|
|
3164
|
-
day: "numeric",
|
|
3165
|
-
hour: "numeric",
|
|
3166
|
-
minute: "2-digit",
|
|
3167
|
-
hour12: true
|
|
3168
|
-
}) }),
|
|
3169
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3170
|
-
ui.Button,
|
|
3171
|
-
{
|
|
3172
|
-
variant: "transparent",
|
|
3173
|
-
size: "small",
|
|
3174
|
-
onClick: (e) => {
|
|
3175
|
-
e.stopPropagation();
|
|
3176
|
-
navigate(`/app/orders/${swap.order_id}`);
|
|
3177
|
-
},
|
|
3178
|
-
children: "Go to order"
|
|
3179
|
-
}
|
|
3180
|
-
) })
|
|
2560
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All statuses" }),
|
|
2561
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "pending", children: "Pending" }),
|
|
2562
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "requires_more", children: "Requires more" }),
|
|
2563
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "error", children: "Error" }),
|
|
2564
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "canceled", children: "Canceled" }),
|
|
2565
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "authorized", children: "Authorized" }),
|
|
2566
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "captured", children: "Captured" })
|
|
3181
2567
|
]
|
|
3182
|
-
}
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
2568
|
+
}
|
|
2569
|
+
),
|
|
2570
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2571
|
+
ui.Input,
|
|
2572
|
+
{
|
|
2573
|
+
type: "date",
|
|
2574
|
+
placeholder: "From",
|
|
2575
|
+
value: dateFrom,
|
|
2576
|
+
onChange: (e) => setDateFrom(e.target.value),
|
|
2577
|
+
className: "md:max-w-[140px]",
|
|
2578
|
+
"aria-label": "Date from"
|
|
2579
|
+
}
|
|
2580
|
+
),
|
|
2581
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2582
|
+
ui.Input,
|
|
2583
|
+
{
|
|
2584
|
+
type: "date",
|
|
2585
|
+
placeholder: "To",
|
|
2586
|
+
value: dateTo,
|
|
2587
|
+
onChange: (e) => setDateTo(e.target.value),
|
|
2588
|
+
className: "md:max-w-[140px]",
|
|
2589
|
+
"aria-label": "Date to"
|
|
2590
|
+
}
|
|
2591
|
+
),
|
|
2592
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2593
|
+
ui.Input,
|
|
2594
|
+
{
|
|
2595
|
+
placeholder: "Amount min",
|
|
2596
|
+
value: amountMin,
|
|
2597
|
+
onChange: (e) => setAmountMin(e.target.value),
|
|
2598
|
+
type: "number",
|
|
2599
|
+
min: 0,
|
|
2600
|
+
className: "md:max-w-[100px]",
|
|
2601
|
+
"aria-label": "Refund amount minimum"
|
|
2602
|
+
}
|
|
2603
|
+
),
|
|
2604
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2605
|
+
ui.Input,
|
|
2606
|
+
{
|
|
2607
|
+
placeholder: "Amount max",
|
|
2608
|
+
value: amountMax,
|
|
2609
|
+
onChange: (e) => setAmountMax(e.target.value),
|
|
2610
|
+
type: "number",
|
|
2611
|
+
min: 0,
|
|
2612
|
+
className: "md:max-w-[100px]",
|
|
2613
|
+
"aria-label": "Refund amount maximum"
|
|
2614
|
+
}
|
|
2615
|
+
)
|
|
2616
|
+
] }) }),
|
|
2617
|
+
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
2618
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
2619
|
+
/* @__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" }) })
|
|
2620
|
+
] }) : null,
|
|
2621
|
+
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: [
|
|
2622
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No refunds yet" }),
|
|
2623
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Refund records will appear here." })
|
|
2624
|
+
] }) : /* @__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: [
|
|
2625
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
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: "Refund ID" }),
|
|
2627
|
+
/* @__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" }),
|
|
2628
|
+
/* @__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" }),
|
|
2629
|
+
/* @__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" }),
|
|
2630
|
+
/* @__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" }),
|
|
2631
|
+
/* @__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" }),
|
|
2632
|
+
/* @__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" }),
|
|
2633
|
+
/* @__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" }),
|
|
2634
|
+
/* @__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" }),
|
|
2635
|
+
/* @__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" })
|
|
2636
|
+
] }) }),
|
|
2637
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((r) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2638
|
+
"tr",
|
|
2639
|
+
{
|
|
2640
|
+
className: "cursor-pointer hover:bg-ui-bg-subtle/60",
|
|
2641
|
+
onClick: () => navigate(`/refunds/${r.refund_id}`),
|
|
2642
|
+
children: [
|
|
2643
|
+
/* @__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 }),
|
|
2644
|
+
/* @__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 ?? "—" }),
|
|
2645
|
+
/* @__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 }),
|
|
2646
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", children: displayAmount(r) }),
|
|
2647
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle uppercase", children: r.currency_code || "—" }),
|
|
2648
|
+
/* @__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 || "—" }),
|
|
2649
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2650
|
+
ui.Badge,
|
|
2651
|
+
{
|
|
2652
|
+
size: "2xsmall",
|
|
2653
|
+
className: `uppercase ${getStatusBadgeClass$6(displayStatus(r))}`,
|
|
2654
|
+
children: displayStatus(r) !== "—" ? displayStatus(r).replace(/_/g, " ") : "—"
|
|
2655
|
+
}
|
|
2656
|
+
) }),
|
|
2657
|
+
/* @__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 ?? "—" }),
|
|
2658
|
+
/* @__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", {
|
|
2659
|
+
month: "short",
|
|
2660
|
+
day: "numeric",
|
|
2661
|
+
hour: "numeric",
|
|
2662
|
+
minute: "2-digit",
|
|
2663
|
+
hour12: true
|
|
2664
|
+
}) }),
|
|
2665
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-1", children: [
|
|
2666
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2667
|
+
ui.Button,
|
|
2668
|
+
{
|
|
2669
|
+
variant: "transparent",
|
|
2670
|
+
size: "small",
|
|
2671
|
+
onClick: (e) => {
|
|
2672
|
+
e.stopPropagation();
|
|
2673
|
+
navigate(`/refunds/${r.refund_id}`);
|
|
2674
|
+
},
|
|
2675
|
+
children: "Details"
|
|
2676
|
+
}
|
|
2677
|
+
),
|
|
2678
|
+
r.order_id ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2679
|
+
ui.Button,
|
|
2680
|
+
{
|
|
2681
|
+
variant: "transparent",
|
|
2682
|
+
size: "small",
|
|
2683
|
+
onClick: (e) => {
|
|
2684
|
+
e.stopPropagation();
|
|
2685
|
+
navigate(`/orders/${r.order_id}`);
|
|
2686
|
+
},
|
|
2687
|
+
children: "Order"
|
|
2688
|
+
}
|
|
2689
|
+
) : null
|
|
2690
|
+
] }) })
|
|
2691
|
+
]
|
|
2692
|
+
},
|
|
2693
|
+
r.refund_id
|
|
2694
|
+
)) })
|
|
2695
|
+
] }) }),
|
|
2696
|
+
hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3187
2697
|
ui.Button,
|
|
3188
2698
|
{
|
|
3189
2699
|
variant: "secondary",
|
|
3190
2700
|
isLoading: isFetchingMore,
|
|
3191
|
-
onClick: () =>
|
|
2701
|
+
onClick: () => loadRefunds(offset, false),
|
|
3192
2702
|
children: "Load more"
|
|
3193
2703
|
}
|
|
3194
2704
|
) }) : null
|
|
3195
2705
|
] }) });
|
|
3196
2706
|
};
|
|
3197
|
-
const config$
|
|
3198
|
-
label: "
|
|
3199
|
-
icon: icons.
|
|
2707
|
+
const config$7 = adminSdk.defineRouteConfig({
|
|
2708
|
+
label: "Refunds",
|
|
2709
|
+
icon: icons.Receipt
|
|
3200
2710
|
});
|
|
3201
|
-
const
|
|
3202
|
-
const
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
2711
|
+
const useDebounce$1 = (value, delay) => {
|
|
2712
|
+
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
2713
|
+
react.useEffect(() => {
|
|
2714
|
+
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
2715
|
+
return () => clearTimeout(handler);
|
|
2716
|
+
}, [value, delay]);
|
|
2717
|
+
return debouncedValue;
|
|
2718
|
+
};
|
|
2719
|
+
const getStatusBadgeClass$5 = (status) => {
|
|
2720
|
+
const statusLower = status.toLowerCase();
|
|
2721
|
+
if (statusLower === "requested") {
|
|
2722
|
+
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
2723
|
+
}
|
|
2724
|
+
if (statusLower === "received") {
|
|
2725
|
+
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
2726
|
+
}
|
|
2727
|
+
if (statusLower === "requires_action") {
|
|
2728
|
+
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
2729
|
+
}
|
|
2730
|
+
if (statusLower === "completed") {
|
|
2731
|
+
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
2732
|
+
}
|
|
2733
|
+
if (statusLower === "canceled") {
|
|
2734
|
+
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
2735
|
+
}
|
|
3207
2736
|
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
3208
2737
|
};
|
|
3209
|
-
const
|
|
3210
|
-
var _a;
|
|
2738
|
+
const ReturnsPage = () => {
|
|
3211
2739
|
const navigate = reactRouterDom.useNavigate();
|
|
3212
|
-
const
|
|
3213
|
-
const
|
|
3214
|
-
const [
|
|
3215
|
-
const [
|
|
2740
|
+
const [items, setItems] = react.useState([]);
|
|
2741
|
+
const [statusFilter, setStatusFilter] = react.useState("all");
|
|
2742
|
+
const [createdByFilter, setCreatedByFilter] = react.useState("all");
|
|
2743
|
+
const [searchQuery, setSearchQuery] = react.useState("");
|
|
2744
|
+
const debouncedSearchQuery = useDebounce$1(searchQuery, 300);
|
|
2745
|
+
const [isLoading, setIsLoading] = react.useState(true);
|
|
2746
|
+
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
3216
2747
|
const [error, setError] = react.useState(null);
|
|
2748
|
+
const [offset, setOffset] = react.useState(0);
|
|
2749
|
+
const [count, setCount] = react.useState(0);
|
|
2750
|
+
const limit = 50;
|
|
2751
|
+
const loadReturns = react.useCallback(
|
|
2752
|
+
async (nextOffset, replace = false) => {
|
|
2753
|
+
try {
|
|
2754
|
+
if (replace) {
|
|
2755
|
+
setIsLoading(true);
|
|
2756
|
+
} else {
|
|
2757
|
+
setIsFetchingMore(true);
|
|
2758
|
+
}
|
|
2759
|
+
setError(null);
|
|
2760
|
+
const params = new URLSearchParams();
|
|
2761
|
+
params.set("limit", String(limit));
|
|
2762
|
+
params.set("offset", String(nextOffset));
|
|
2763
|
+
if (statusFilter !== "all") {
|
|
2764
|
+
params.set("status", statusFilter);
|
|
2765
|
+
}
|
|
2766
|
+
if (debouncedSearchQuery.trim()) {
|
|
2767
|
+
params.set("q", debouncedSearchQuery.trim());
|
|
2768
|
+
}
|
|
2769
|
+
if (createdByFilter !== "all") {
|
|
2770
|
+
params.set("created_by", createdByFilter);
|
|
2771
|
+
}
|
|
2772
|
+
params.set("order", "created_at");
|
|
2773
|
+
const response = await fetch(
|
|
2774
|
+
`/admin/return?${params.toString()}`,
|
|
2775
|
+
{ credentials: "include" }
|
|
2776
|
+
);
|
|
2777
|
+
if (!response.ok) {
|
|
2778
|
+
const message = await response.text();
|
|
2779
|
+
throw new Error(message || "Unable to load return orders");
|
|
2780
|
+
}
|
|
2781
|
+
const payload = await response.json();
|
|
2782
|
+
setCount(payload.count ?? 0);
|
|
2783
|
+
setOffset(nextOffset + (payload.returns?.length ?? 0));
|
|
2784
|
+
setItems(
|
|
2785
|
+
(prev) => replace ? payload.returns ?? [] : [...prev, ...payload.returns ?? []]
|
|
2786
|
+
);
|
|
2787
|
+
} catch (loadError) {
|
|
2788
|
+
const message = loadError instanceof Error ? loadError.message : "Unable to load return orders";
|
|
2789
|
+
setError(message);
|
|
2790
|
+
} finally {
|
|
2791
|
+
setIsLoading(false);
|
|
2792
|
+
setIsFetchingMore(false);
|
|
2793
|
+
}
|
|
2794
|
+
},
|
|
2795
|
+
[statusFilter, createdByFilter, debouncedSearchQuery]
|
|
2796
|
+
);
|
|
3217
2797
|
react.useEffect(() => {
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
2798
|
+
void loadReturns(0, true);
|
|
2799
|
+
}, [statusFilter, createdByFilter, debouncedSearchQuery, loadReturns]);
|
|
2800
|
+
const hasMore = react.useMemo(() => offset < count, [offset, count]);
|
|
2801
|
+
const availableStatuses = react.useMemo(() => {
|
|
2802
|
+
const statuses = /* @__PURE__ */ new Set();
|
|
2803
|
+
items.forEach((item) => statuses.add(item.status));
|
|
2804
|
+
return Array.from(statuses).sort();
|
|
2805
|
+
}, [items]);
|
|
2806
|
+
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: [
|
|
2807
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
2808
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
2809
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Return Orders" }),
|
|
2810
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "View and manage all customer return orders" })
|
|
2811
|
+
] }),
|
|
2812
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => loadReturns(0, true), children: "Refresh" })
|
|
2813
|
+
] }),
|
|
2814
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
2815
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2816
|
+
ui.Input,
|
|
2817
|
+
{
|
|
2818
|
+
placeholder: "Search by return ID, order ID, or customer email",
|
|
2819
|
+
value: searchQuery,
|
|
2820
|
+
onChange: (event) => setSearchQuery(event.target.value),
|
|
2821
|
+
className: "md:max-w-sm"
|
|
2822
|
+
}
|
|
2823
|
+
),
|
|
2824
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
|
|
2825
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2826
|
+
"select",
|
|
2827
|
+
{
|
|
2828
|
+
value: createdByFilter,
|
|
2829
|
+
onChange: (event) => setCreatedByFilter(event.target.value),
|
|
2830
|
+
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",
|
|
2831
|
+
children: [
|
|
2832
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All (Created by)" }),
|
|
2833
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "customer", children: "Customer" }),
|
|
2834
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "admin", children: "Admin" })
|
|
2835
|
+
]
|
|
2836
|
+
}
|
|
2837
|
+
),
|
|
2838
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2839
|
+
"select",
|
|
2840
|
+
{
|
|
2841
|
+
value: statusFilter,
|
|
2842
|
+
onChange: (event) => setStatusFilter(event.target.value),
|
|
2843
|
+
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",
|
|
2844
|
+
children: [
|
|
2845
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All Statuses" }),
|
|
2846
|
+
availableStatuses.map((status) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
|
|
2847
|
+
]
|
|
2848
|
+
}
|
|
2849
|
+
)
|
|
2850
|
+
] })
|
|
2851
|
+
] }),
|
|
3249
2852
|
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
3250
2853
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
3251
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3271
|
-
|
|
3272
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.provider_id })
|
|
3273
|
-
] }),
|
|
3274
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3275
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
|
|
3276
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3277
|
-
ui.Badge,
|
|
3278
|
-
{
|
|
3279
|
-
size: "2xsmall",
|
|
3280
|
-
className: `uppercase ${getStatusBadgeClass$3(displayStatus)}`,
|
|
3281
|
-
children: displayStatus !== "—" ? displayStatus.replace(/_/g, " ") : "—"
|
|
3282
|
-
}
|
|
3283
|
-
) })
|
|
3284
|
-
] }),
|
|
3285
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3286
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Session status (DB)" }),
|
|
3287
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: sessionStatusRaw })
|
|
3288
|
-
] }),
|
|
3289
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3290
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Payment status (DB)" }),
|
|
3291
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: paymentStatusRaw })
|
|
3292
|
-
] }),
|
|
3293
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3294
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Finalized" }),
|
|
3295
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.payment_id != null ? "Yes" : "No" })
|
|
3296
|
-
] }),
|
|
3297
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3298
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created" }),
|
|
3299
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: new Date(detail.created_at).toLocaleDateString("en-US", {
|
|
3300
|
-
year: "numeric",
|
|
3301
|
-
month: "short",
|
|
3302
|
-
day: "numeric",
|
|
3303
|
-
hour: "numeric",
|
|
3304
|
-
minute: "2-digit",
|
|
3305
|
-
hour12: true
|
|
3306
|
-
}) })
|
|
3307
|
-
] })
|
|
2854
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2855
|
+
ui.Button,
|
|
2856
|
+
{
|
|
2857
|
+
variant: "secondary",
|
|
2858
|
+
onClick: () => loadReturns(0, true),
|
|
2859
|
+
children: "Try again"
|
|
2860
|
+
}
|
|
2861
|
+
) })
|
|
2862
|
+
] }) : null,
|
|
2863
|
+
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: [
|
|
2864
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No return orders yet" }),
|
|
2865
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Return orders created by customers will appear here." })
|
|
2866
|
+
] }) : /* @__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: [
|
|
2867
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
2868
|
+
/* @__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" }),
|
|
2869
|
+
/* @__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" }),
|
|
2870
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Customer" }),
|
|
2871
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
2872
|
+
/* @__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" }),
|
|
2873
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
2874
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
3308
2875
|
] }) }),
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
}
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
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
|
-
|
|
3346
|
-
setLoading(true);
|
|
3347
|
-
setError(null);
|
|
3348
|
-
fetch(`/admin/refunds/${id}`, { credentials: "include" }).then((res) => {
|
|
3349
|
-
if (!res.ok) throw new Error(res.statusText || "Failed to load");
|
|
3350
|
-
return res.json();
|
|
3351
|
-
}).then((data) => {
|
|
3352
|
-
if (!cancelled) setDetail(data);
|
|
3353
|
-
}).catch((e) => {
|
|
3354
|
-
if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
|
|
3355
|
-
}).finally(() => {
|
|
3356
|
-
if (!cancelled) setLoading(false);
|
|
3357
|
-
});
|
|
3358
|
-
return () => {
|
|
3359
|
-
cancelled = true;
|
|
3360
|
-
};
|
|
3361
|
-
}, [id]);
|
|
3362
|
-
const paymentStatus = ((_b = detail == null ? void 0 : detail.payment) == null ? void 0 : _b.status) ?? "—";
|
|
3363
|
-
const hasGatewayData = ((_c = detail == null ? void 0 : detail.payment) == null ? void 0 : _c.payment_data) && typeof detail.payment.payment_data === "object" && Object.keys(detail.payment.payment_data).length > 0;
|
|
3364
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-4xl flex-col gap-6 p-6", children: [
|
|
3365
|
-
/* @__PURE__ */ jsxRuntime.jsx("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3366
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => navigate("/refunds"), children: "← Refunds" }),
|
|
3367
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Refund details" }),
|
|
3368
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle font-mono", children: id ?? "—" })
|
|
3369
|
-
] }) }),
|
|
3370
|
-
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
3371
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
3372
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/refunds"), children: "Back to list" })
|
|
3373
|
-
] }) : loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading…" }) }) : detail ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
3374
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
3375
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Refund summary" }),
|
|
3376
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
3377
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3378
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund ID" }),
|
|
3379
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.id })
|
|
3380
|
-
] }),
|
|
3381
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3382
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
|
|
3383
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.refund.amount) })
|
|
3384
|
-
] }),
|
|
3385
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3386
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Note" }),
|
|
3387
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.refund.note ?? "—" })
|
|
3388
|
-
] }),
|
|
3389
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3390
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created at" }),
|
|
3391
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: new Date(detail.refund.created_at).toLocaleDateString("en-US", {
|
|
2876
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((returnOrder) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2877
|
+
"tr",
|
|
2878
|
+
{
|
|
2879
|
+
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
2880
|
+
onClick: () => navigate(`/returns/${returnOrder.id}`),
|
|
2881
|
+
children: [
|
|
2882
|
+
/* @__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 }) }) }),
|
|
2883
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.order_id }),
|
|
2884
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.customer_email || returnOrder.order_email || "—" }),
|
|
2885
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2886
|
+
ui.Badge,
|
|
2887
|
+
{
|
|
2888
|
+
size: "2xsmall",
|
|
2889
|
+
className: `uppercase ${getStatusBadgeClass$5(returnOrder.status)}`,
|
|
2890
|
+
children: returnOrder.status.replace(/_/g, " ")
|
|
2891
|
+
}
|
|
2892
|
+
) }),
|
|
2893
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
|
|
2894
|
+
const calc = returnOrder.refund;
|
|
2895
|
+
if (calc?.is_processed && calc.final_refund_amount != null) {
|
|
2896
|
+
return formatRefundCurrency(
|
|
2897
|
+
calc.final_refund_amount,
|
|
2898
|
+
calc.currency_code || returnOrder.currency_code
|
|
2899
|
+
);
|
|
2900
|
+
}
|
|
2901
|
+
if (calc) {
|
|
2902
|
+
return "Pending";
|
|
2903
|
+
}
|
|
2904
|
+
if (returnOrder.refund_amount == null) {
|
|
2905
|
+
return "—";
|
|
2906
|
+
}
|
|
2907
|
+
return formatRefundCurrency(
|
|
2908
|
+
Number(returnOrder.refund_amount),
|
|
2909
|
+
returnOrder.currency_code
|
|
2910
|
+
);
|
|
2911
|
+
})() }),
|
|
2912
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(returnOrder.created_at).toLocaleDateString("en-US", {
|
|
3392
2913
|
year: "numeric",
|
|
3393
2914
|
month: "short",
|
|
3394
2915
|
day: "numeric",
|
|
3395
2916
|
hour: "numeric",
|
|
3396
2917
|
minute: "2-digit",
|
|
3397
2918
|
hour12: true
|
|
3398
|
-
}) })
|
|
3399
|
-
|
|
3400
|
-
detail.refund.created_by ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3401
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created by" }),
|
|
3402
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.created_by })
|
|
3403
|
-
] }) : null
|
|
3404
|
-
] })
|
|
3405
|
-
] }),
|
|
3406
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
3407
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Payment summary" }),
|
|
3408
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
3409
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3410
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Payment amount" }),
|
|
3411
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.payment_amount) })
|
|
3412
|
-
] }),
|
|
3413
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3414
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Captured amount" }),
|
|
3415
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.captured_amount) })
|
|
3416
|
-
] }),
|
|
3417
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3418
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refunded amount" }),
|
|
3419
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.refunded_amount) })
|
|
3420
|
-
] }),
|
|
3421
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3422
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
|
|
3423
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.payment.provider_id || "—" })
|
|
3424
|
-
] }),
|
|
3425
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3426
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
|
|
3427
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3428
|
-
ui.Badge,
|
|
3429
|
-
{
|
|
3430
|
-
size: "2xsmall",
|
|
3431
|
-
className: `uppercase ${getStatusBadgeClass$2(paymentStatus)}`,
|
|
3432
|
-
children: paymentStatus !== "—" ? paymentStatus.replace(/_/g, " ") : "—"
|
|
3433
|
-
}
|
|
3434
|
-
) })
|
|
3435
|
-
] }),
|
|
3436
|
-
detail.computed ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3437
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3438
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Full refund" }),
|
|
3439
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.computed.is_full_refund ? "Yes" : "No" })
|
|
3440
|
-
] }),
|
|
3441
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3442
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Remaining refundable" }),
|
|
3443
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.computed.remaining_refundable_amount) })
|
|
3444
|
-
] }),
|
|
3445
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3446
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund %" }),
|
|
3447
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "mt-1 block", children: [
|
|
3448
|
-
detail.computed.refund_percentage.toFixed(1),
|
|
3449
|
-
"%"
|
|
3450
|
-
] })
|
|
3451
|
-
] })
|
|
3452
|
-
] }) : null
|
|
3453
|
-
] })
|
|
3454
|
-
] }),
|
|
3455
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
3456
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Order summary" }),
|
|
3457
|
-
detail.order ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
3458
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3459
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Order" }),
|
|
3460
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2919
|
+
}) }),
|
|
2920
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3461
2921
|
ui.Button,
|
|
3462
2922
|
{
|
|
3463
2923
|
variant: "transparent",
|
|
3464
2924
|
size: "small",
|
|
3465
|
-
onClick: () =>
|
|
3466
|
-
|
|
2925
|
+
onClick: (e) => {
|
|
2926
|
+
e.stopPropagation();
|
|
2927
|
+
navigate(`/app/orders/${returnOrder.order_id}`);
|
|
2928
|
+
},
|
|
2929
|
+
children: "Go to order"
|
|
3467
2930
|
}
|
|
3468
2931
|
) })
|
|
3469
|
-
]
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
2932
|
+
]
|
|
2933
|
+
},
|
|
2934
|
+
returnOrder.id
|
|
2935
|
+
)) })
|
|
2936
|
+
] }) }),
|
|
2937
|
+
hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2938
|
+
ui.Button,
|
|
2939
|
+
{
|
|
2940
|
+
variant: "secondary",
|
|
2941
|
+
isLoading: isFetchingMore,
|
|
2942
|
+
onClick: () => loadReturns(offset, false),
|
|
2943
|
+
children: "Load more"
|
|
2944
|
+
}
|
|
2945
|
+
) }) : null
|
|
2946
|
+
] }) });
|
|
2947
|
+
};
|
|
2948
|
+
const config$6 = adminSdk.defineRouteConfig({
|
|
2949
|
+
label: "Return Orders",
|
|
2950
|
+
icon: icons.ArrowPath
|
|
2951
|
+
});
|
|
2952
|
+
const useDebounce = (value, delay) => {
|
|
2953
|
+
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
2954
|
+
react.useEffect(() => {
|
|
2955
|
+
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
2956
|
+
return () => clearTimeout(handler);
|
|
2957
|
+
}, [value, delay]);
|
|
2958
|
+
return debouncedValue;
|
|
2959
|
+
};
|
|
2960
|
+
const getStatusBadgeClass$4 = (status) => {
|
|
2961
|
+
const statusLower = status.toLowerCase();
|
|
2962
|
+
if (statusLower === "requested") {
|
|
2963
|
+
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
2964
|
+
}
|
|
2965
|
+
if (statusLower === "approved") {
|
|
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
|
+
}
|
|
2977
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
2978
|
+
};
|
|
2979
|
+
const SwapsPage = () => {
|
|
2980
|
+
const navigate = reactRouterDom.useNavigate();
|
|
2981
|
+
const [items, setItems] = react.useState([]);
|
|
2982
|
+
const [statusFilter, setStatusFilter] = react.useState("all");
|
|
2983
|
+
const [createdByFilter, setCreatedByFilter] = react.useState("all");
|
|
2984
|
+
const [searchQuery, setSearchQuery] = react.useState("");
|
|
2985
|
+
const debouncedSearchQuery = useDebounce(searchQuery, 300);
|
|
2986
|
+
const [isLoading, setIsLoading] = react.useState(true);
|
|
2987
|
+
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
2988
|
+
const [error, setError] = react.useState(null);
|
|
2989
|
+
const [offset, setOffset] = react.useState(0);
|
|
2990
|
+
const [count, setCount] = react.useState(0);
|
|
2991
|
+
const limit = 50;
|
|
2992
|
+
const loadSwaps = react.useCallback(
|
|
2993
|
+
async (nextOffset, replace = false) => {
|
|
2994
|
+
try {
|
|
2995
|
+
if (replace) {
|
|
2996
|
+
setIsLoading(true);
|
|
2997
|
+
} else {
|
|
2998
|
+
setIsFetchingMore(true);
|
|
2999
|
+
}
|
|
3000
|
+
setError(null);
|
|
3001
|
+
const params = new URLSearchParams();
|
|
3002
|
+
params.set("limit", String(limit));
|
|
3003
|
+
params.set("offset", String(nextOffset));
|
|
3004
|
+
if (statusFilter !== "all") {
|
|
3005
|
+
params.set("status", statusFilter);
|
|
3006
|
+
}
|
|
3007
|
+
if (debouncedSearchQuery.trim()) {
|
|
3008
|
+
params.set("order_id", debouncedSearchQuery.trim());
|
|
3009
|
+
}
|
|
3010
|
+
if (createdByFilter !== "all") {
|
|
3011
|
+
params.set("created_by", createdByFilter);
|
|
3012
|
+
}
|
|
3013
|
+
const response = await fetch(
|
|
3014
|
+
`/admin/swaps?${params.toString()}`,
|
|
3015
|
+
{ credentials: "include" }
|
|
3016
|
+
);
|
|
3017
|
+
if (!response.ok) {
|
|
3018
|
+
const message = await response.text();
|
|
3019
|
+
throw new Error(message || "Unable to load swaps");
|
|
3020
|
+
}
|
|
3021
|
+
const payload = await response.json();
|
|
3022
|
+
setCount(payload.count ?? 0);
|
|
3023
|
+
setOffset(nextOffset + (payload.swaps?.length ?? 0));
|
|
3024
|
+
setItems(
|
|
3025
|
+
(prev) => replace ? payload.swaps ?? [] : [...prev, ...payload.swaps ?? []]
|
|
3026
|
+
);
|
|
3027
|
+
} catch (loadError) {
|
|
3028
|
+
const message = loadError instanceof Error ? loadError.message : "Unable to load swaps";
|
|
3029
|
+
setError(message);
|
|
3030
|
+
} finally {
|
|
3031
|
+
setIsLoading(false);
|
|
3032
|
+
setIsFetchingMore(false);
|
|
3033
|
+
}
|
|
3034
|
+
},
|
|
3035
|
+
[statusFilter, createdByFilter, debouncedSearchQuery]
|
|
3036
|
+
);
|
|
3037
|
+
react.useEffect(() => {
|
|
3038
|
+
void loadSwaps(0, true);
|
|
3039
|
+
}, [statusFilter, createdByFilter, debouncedSearchQuery, loadSwaps]);
|
|
3040
|
+
const hasMore = react.useMemo(() => offset < count, [offset, count]);
|
|
3041
|
+
const availableStatuses = react.useMemo(() => {
|
|
3042
|
+
const statuses = /* @__PURE__ */ new Set();
|
|
3043
|
+
items.forEach((item) => statuses.add(item.status));
|
|
3044
|
+
return Array.from(statuses).sort();
|
|
3045
|
+
}, [items]);
|
|
3046
|
+
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
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
3048
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3049
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Exchanges" }),
|
|
3050
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "View and manage all customer exchange requests" })
|
|
3487
3051
|
] }),
|
|
3488
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3052
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => loadSwaps(0, true), children: "Refresh" })
|
|
3053
|
+
] }),
|
|
3054
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
3055
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3056
|
+
ui.Input,
|
|
3057
|
+
{
|
|
3058
|
+
placeholder: "Search by swap ID or order ID",
|
|
3059
|
+
value: searchQuery,
|
|
3060
|
+
onChange: (event) => setSearchQuery(event.target.value),
|
|
3061
|
+
className: "md:max-w-sm"
|
|
3062
|
+
}
|
|
3063
|
+
),
|
|
3064
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
|
|
3489
3065
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3490
|
-
"
|
|
3066
|
+
"select",
|
|
3491
3067
|
{
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
"aria-expanded": gatewayExpanded,
|
|
3496
|
-
"aria-label": gatewayExpanded ? "Collapse gateway data" : "Expand gateway data",
|
|
3068
|
+
value: createdByFilter,
|
|
3069
|
+
onChange: (event) => setCreatedByFilter(event.target.value),
|
|
3070
|
+
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",
|
|
3497
3071
|
children: [
|
|
3498
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3499
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3072
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All (Created by)" }),
|
|
3073
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "customer", children: "Customer" }),
|
|
3074
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "admin", children: "Admin" })
|
|
3500
3075
|
]
|
|
3501
3076
|
}
|
|
3502
3077
|
),
|
|
3503
|
-
|
|
3078
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3079
|
+
"select",
|
|
3080
|
+
{
|
|
3081
|
+
value: statusFilter,
|
|
3082
|
+
onChange: (event) => setStatusFilter(event.target.value),
|
|
3083
|
+
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",
|
|
3084
|
+
children: [
|
|
3085
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All Statuses" }),
|
|
3086
|
+
availableStatuses.map((status) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
|
|
3087
|
+
]
|
|
3088
|
+
}
|
|
3089
|
+
)
|
|
3504
3090
|
] })
|
|
3505
|
-
] })
|
|
3506
|
-
|
|
3507
|
-
}
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3091
|
+
] }),
|
|
3092
|
+
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
3093
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
3094
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3095
|
+
ui.Button,
|
|
3096
|
+
{
|
|
3097
|
+
variant: "secondary",
|
|
3098
|
+
onClick: () => loadSwaps(0, true),
|
|
3099
|
+
children: "Try again"
|
|
3100
|
+
}
|
|
3101
|
+
) })
|
|
3102
|
+
] }) : null,
|
|
3103
|
+
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: [
|
|
3104
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No exchanges yet" }),
|
|
3105
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Exchange requests created by customers will appear here." })
|
|
3106
|
+
] }) : /* @__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: [
|
|
3107
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
3108
|
+
/* @__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" }),
|
|
3109
|
+
/* @__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" }),
|
|
3110
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
3111
|
+
/* @__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" }),
|
|
3112
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
3113
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
3114
|
+
] }) }),
|
|
3115
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((swap) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3116
|
+
"tr",
|
|
3117
|
+
{
|
|
3118
|
+
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
3119
|
+
onClick: () => navigate(`/swaps/${swap.id}`),
|
|
3120
|
+
children: [
|
|
3121
|
+
/* @__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 }) }) }),
|
|
3122
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: swap.order_id }),
|
|
3123
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3124
|
+
ui.Badge,
|
|
3125
|
+
{
|
|
3126
|
+
size: "2xsmall",
|
|
3127
|
+
className: `uppercase ${getStatusBadgeClass$4(swap.status)}`,
|
|
3128
|
+
children: swap.status.replace(/_/g, " ")
|
|
3129
|
+
}
|
|
3130
|
+
) }),
|
|
3131
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
|
|
3132
|
+
const amount = swap.difference_due;
|
|
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",
|
|
3143
|
+
month: "short",
|
|
3144
|
+
day: "numeric",
|
|
3145
|
+
hour: "numeric",
|
|
3146
|
+
minute: "2-digit",
|
|
3147
|
+
hour12: true
|
|
3148
|
+
}) }),
|
|
3149
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3150
|
+
ui.Button,
|
|
3151
|
+
{
|
|
3152
|
+
variant: "transparent",
|
|
3153
|
+
size: "small",
|
|
3154
|
+
onClick: (e) => {
|
|
3155
|
+
e.stopPropagation();
|
|
3156
|
+
navigate(`/app/orders/${swap.order_id}`);
|
|
3157
|
+
},
|
|
3158
|
+
children: "Go to order"
|
|
3159
|
+
}
|
|
3160
|
+
) })
|
|
3161
|
+
]
|
|
3162
|
+
},
|
|
3163
|
+
swap.id
|
|
3164
|
+
)) })
|
|
3165
|
+
] }) }),
|
|
3166
|
+
hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3167
|
+
ui.Button,
|
|
3168
|
+
{
|
|
3169
|
+
variant: "secondary",
|
|
3170
|
+
isLoading: isFetchingMore,
|
|
3171
|
+
onClick: () => loadSwaps(offset, false),
|
|
3172
|
+
children: "Load more"
|
|
3173
|
+
}
|
|
3174
|
+
) }) : null
|
|
3175
|
+
] }) });
|
|
3176
|
+
};
|
|
3177
|
+
const config$5 = adminSdk.defineRouteConfig({
|
|
3178
|
+
label: "Exchanges",
|
|
3179
|
+
icon: icons.ArrowPath
|
|
3180
|
+
});
|
|
3181
|
+
const MASKED_VALUE = "••••••••••••";
|
|
3182
|
+
const SENSITIVE_KEY_PATTERNS = [
|
|
3183
|
+
/password|passwd|passphrase/i,
|
|
3184
|
+
/secret/i,
|
|
3185
|
+
/token/i,
|
|
3186
|
+
/api_?key$/i,
|
|
3187
|
+
/private_?key/i,
|
|
3188
|
+
/access_?key/i,
|
|
3520
3189
|
/(^|_)hash(ed)?($|_)/i,
|
|
3521
3190
|
/(^|_)salt$/i,
|
|
3522
3191
|
/^cvv$|^cvc$|security_code/i,
|
|
@@ -3550,13 +3219,12 @@ function isSensitiveKey(key) {
|
|
|
3550
3219
|
const FULLY_SECRET_TABLES = /* @__PURE__ */ new Set(["auth_mfa_recovery_code", "auth_password_reset_token"]);
|
|
3551
3220
|
const ALWAYS_VISIBLE_KEYS = /* @__PURE__ */ new Set(["id", "created_at", "updated_at", "deleted_at", "expires_at", "used_at"]);
|
|
3552
3221
|
function maskValue(value, ctx, depth) {
|
|
3553
|
-
var _a;
|
|
3554
3222
|
if (Array.isArray(value)) return value.map((item) => maskValue(item, ctx, depth + 1));
|
|
3555
3223
|
if (value !== null && typeof value === "object") {
|
|
3556
3224
|
const out = {};
|
|
3557
3225
|
for (const [key, inner] of Object.entries(value)) {
|
|
3558
3226
|
const topLevel = depth === 0;
|
|
3559
|
-
const secret = inner !== null && inner !== void 0 && inner !== "" && (isSensitiveKey(key) || topLevel &&
|
|
3227
|
+
const secret = inner !== null && inner !== void 0 && inner !== "" && (isSensitiveKey(key) || topLevel && ctx.tableKeys?.has(key.toLowerCase()) === true || topLevel && ctx.maskAll && !ALWAYS_VISIBLE_KEYS.has(key) && !key.endsWith("_id"));
|
|
3560
3228
|
if (secret) {
|
|
3561
3229
|
ctx.count += 1;
|
|
3562
3230
|
out[key] = MASKED_VALUE;
|
|
@@ -4022,13 +3690,12 @@ function readLastListSearch() {
|
|
|
4022
3690
|
}
|
|
4023
3691
|
}
|
|
4024
3692
|
const DeletedRecordDetailPage = () => {
|
|
4025
|
-
var _a;
|
|
4026
3693
|
const navigate = reactRouterDom.useNavigate();
|
|
4027
3694
|
const location = reactRouterDom.useLocation();
|
|
4028
3695
|
const { id = "" } = reactRouterDom.useParams();
|
|
4029
3696
|
const [state, setState] = react.useState({ status: "loading" });
|
|
4030
3697
|
const [reloadToken, setReloadToken] = react.useState(0);
|
|
4031
|
-
const cameFromList =
|
|
3698
|
+
const cameFromList = location.state?.fromList === true;
|
|
4032
3699
|
const goBack = () => {
|
|
4033
3700
|
if (cameFromList) navigate(-1);
|
|
4034
3701
|
else navigate(`/deleted-records-audit${readLastListSearch()}`);
|
|
@@ -4163,96 +3830,405 @@ const DetailContent = ({ audit }) => {
|
|
|
4163
3830
|
" ",
|
|
4164
3831
|
"from this screen."
|
|
4165
3832
|
] }),
|
|
4166
|
-
/* @__PURE__ */ jsxRuntime.jsxs("ol", { className: "flex list-decimal flex-col gap-3 pl-5 text-sm text-ui-fg-subtle marker:text-ui-fg-muted", children: [
|
|
4167
|
-
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
4168
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: "Check whether this was expected." }),
|
|
4169
|
-
" ",
|
|
4170
|
-
audit.deleted_by || source.kind !== "unknown" ? "Confirm with the person or system shown above." : `Who deleted it wasn’t recorded—check with your team or integrations active around ${formatExactDateTime(audit.occurred_at)}.`,
|
|
4171
|
-
" ",
|
|
4172
|
-
guidance.headline
|
|
4173
|
-
] }),
|
|
4174
|
-
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
4175
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: "If it needs to come back:" }),
|
|
4176
|
-
" ",
|
|
4177
|
-
guidance.recreate
|
|
4178
|
-
] }),
|
|
4179
|
-
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
4180
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: "Need the details?" }),
|
|
4181
|
-
" Use “View full record” above to see or copy everything that was stored. Sensitive values stay hidden."
|
|
3833
|
+
/* @__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: [
|
|
3834
|
+
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
3835
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: "Check whether this was expected." }),
|
|
3836
|
+
" ",
|
|
3837
|
+
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)}.`,
|
|
3838
|
+
" ",
|
|
3839
|
+
guidance.headline
|
|
3840
|
+
] }),
|
|
3841
|
+
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
3842
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: "If it needs to come back:" }),
|
|
3843
|
+
" ",
|
|
3844
|
+
guidance.recreate
|
|
3845
|
+
] }),
|
|
3846
|
+
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
3847
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: "Need the details?" }),
|
|
3848
|
+
" Use “View full record” above to see or copy everything that was stored. Sensitive values stay hidden."
|
|
3849
|
+
] })
|
|
3850
|
+
] }),
|
|
3851
|
+
guidance.adminSection || related.length ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
3852
|
+
guidance.adminSection ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", size: "small", onClick: () => navigate(guidance.adminSection.path), children: guidance.adminSection.label }) : null,
|
|
3853
|
+
related.map((link) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3854
|
+
ui.Button,
|
|
3855
|
+
{
|
|
3856
|
+
variant: "transparent",
|
|
3857
|
+
size: "small",
|
|
3858
|
+
onClick: () => navigate(link.path),
|
|
3859
|
+
title: `Opens ${link.label.toLowerCase()} ${link.id} if it still exists`,
|
|
3860
|
+
children: [
|
|
3861
|
+
"Open related ",
|
|
3862
|
+
link.label.toLowerCase(),
|
|
3863
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRightMini, {})
|
|
3864
|
+
]
|
|
3865
|
+
},
|
|
3866
|
+
link.path
|
|
3867
|
+
))
|
|
3868
|
+
] }) : null,
|
|
3869
|
+
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
|
|
3870
|
+
] }) })
|
|
3871
|
+
] });
|
|
3872
|
+
};
|
|
3873
|
+
const Section = ({
|
|
3874
|
+
title,
|
|
3875
|
+
description,
|
|
3876
|
+
actions,
|
|
3877
|
+
children
|
|
3878
|
+
}) => /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "flex flex-col gap-4 rounded-lg border border-ui-border-base p-5", children: [
|
|
3879
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-2", children: [
|
|
3880
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
3881
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: title }),
|
|
3882
|
+
description ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: description }) : null
|
|
3883
|
+
] }),
|
|
3884
|
+
actions
|
|
3885
|
+
] }),
|
|
3886
|
+
children
|
|
3887
|
+
] });
|
|
3888
|
+
const Field = ({ label, children }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
|
|
3889
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-xs font-medium uppercase tracking-wide text-ui-fg-muted", children: label }),
|
|
3890
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { className: "min-w-0", children })
|
|
3891
|
+
] });
|
|
3892
|
+
const DetailSkeleton = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", "aria-busy": "true", children: [
|
|
3893
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
3894
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-5 w-24 rounded-full" }),
|
|
3895
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-8 w-64" }),
|
|
3896
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-4 w-48" })
|
|
3897
|
+
] }),
|
|
3898
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-14 w-full" }),
|
|
3899
|
+
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: [
|
|
3900
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-5 w-40" }),
|
|
3901
|
+
/* @__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: [
|
|
3902
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-3 w-20" }),
|
|
3903
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-4 w-36" })
|
|
3904
|
+
] }, j)) })
|
|
3905
|
+
] }, i))
|
|
3906
|
+
] });
|
|
3907
|
+
const DetailError = ({
|
|
3908
|
+
notFound,
|
|
3909
|
+
message,
|
|
3910
|
+
onRetry,
|
|
3911
|
+
onBack
|
|
3912
|
+
}) => /* @__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: [
|
|
3913
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ExclamationCircle, { className: ui.clx(notFound ? "text-ui-fg-muted" : "text-ui-fg-error") }),
|
|
3914
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: notFound ? "Audit entry not found" : "Unable to load this deleted record" }),
|
|
3915
|
+
/* @__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." }),
|
|
3916
|
+
!notFound ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "max-w-md font-mono text-ui-fg-muted", children: message }) : null,
|
|
3917
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex gap-2", children: [
|
|
3918
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", size: "small", onClick: onBack, children: "Back to Deleted Records" }),
|
|
3919
|
+
!notFound ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", size: "small", onClick: onRetry, children: "Try again" }) : null
|
|
3920
|
+
] })
|
|
3921
|
+
] });
|
|
3922
|
+
const config$4 = adminSdk.defineRouteConfig({});
|
|
3923
|
+
const getStatusBadgeClass$3 = (status) => {
|
|
3924
|
+
const s2 = status.toLowerCase();
|
|
3925
|
+
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
3926
|
+
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
3927
|
+
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
3928
|
+
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
3929
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
3930
|
+
};
|
|
3931
|
+
const PaymentDetailPage = () => {
|
|
3932
|
+
const navigate = reactRouterDom.useNavigate();
|
|
3933
|
+
const params = reactRouterDom.useParams();
|
|
3934
|
+
const id = params?.id?.trim();
|
|
3935
|
+
const [detail, setDetail] = react.useState(null);
|
|
3936
|
+
const [loading, setLoading] = react.useState(!!id);
|
|
3937
|
+
const [error, setError] = react.useState(null);
|
|
3938
|
+
react.useEffect(() => {
|
|
3939
|
+
if (!id) {
|
|
3940
|
+
setLoading(false);
|
|
3941
|
+
return;
|
|
3942
|
+
}
|
|
3943
|
+
let cancelled = false;
|
|
3944
|
+
setLoading(true);
|
|
3945
|
+
setError(null);
|
|
3946
|
+
fetch(`/admin/payment-transactions/${id}`, { credentials: "include" }).then((res) => {
|
|
3947
|
+
if (!res.ok) throw new Error(res.statusText || "Failed to load");
|
|
3948
|
+
return res.json();
|
|
3949
|
+
}).then((data) => {
|
|
3950
|
+
if (!cancelled) setDetail(data);
|
|
3951
|
+
}).catch((e) => {
|
|
3952
|
+
if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
|
|
3953
|
+
}).finally(() => {
|
|
3954
|
+
if (!cancelled) setLoading(false);
|
|
3955
|
+
});
|
|
3956
|
+
return () => {
|
|
3957
|
+
cancelled = true;
|
|
3958
|
+
};
|
|
3959
|
+
}, [id]);
|
|
3960
|
+
const displayStatus = detail ? (detail.payment_id != null && detail.payment_status != null && detail.payment_status !== "" ? detail.payment_status : detail.session_status ?? "") || "—" : "";
|
|
3961
|
+
const sessionStatusRaw = detail?.session_status ?? "—";
|
|
3962
|
+
const paymentStatusRaw = detail?.payment_id != null ? detail?.payment_status ?? "—" : "—";
|
|
3963
|
+
const displayAmount = detail ? `${(detail.currency_code ?? "USD").toUpperCase()} ${Number(detail.amount)}` : "";
|
|
3964
|
+
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: [
|
|
3965
|
+
/* @__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: [
|
|
3966
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => navigate("/payments"), children: "← Payments" }),
|
|
3967
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Payment session" }),
|
|
3968
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: id ?? "—" })
|
|
3969
|
+
] }) }),
|
|
3970
|
+
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
3971
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
3972
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/payments"), children: "Back to list" })
|
|
3973
|
+
] }) : 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: [
|
|
3974
|
+
/* @__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: [
|
|
3975
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3976
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Order ID" }),
|
|
3977
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: detail.order_id ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3978
|
+
ui.Button,
|
|
3979
|
+
{
|
|
3980
|
+
variant: "transparent",
|
|
3981
|
+
size: "small",
|
|
3982
|
+
onClick: () => navigate(`/orders/${detail.order_id}`),
|
|
3983
|
+
children: detail.order_id
|
|
3984
|
+
}
|
|
3985
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "—" }) })
|
|
3986
|
+
] }),
|
|
3987
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3988
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
|
|
3989
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: displayAmount })
|
|
3990
|
+
] }),
|
|
3991
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3992
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
|
|
3993
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.provider_id })
|
|
3994
|
+
] }),
|
|
3995
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3996
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
|
|
3997
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3998
|
+
ui.Badge,
|
|
3999
|
+
{
|
|
4000
|
+
size: "2xsmall",
|
|
4001
|
+
className: `uppercase ${getStatusBadgeClass$3(displayStatus)}`,
|
|
4002
|
+
children: displayStatus !== "—" ? displayStatus.replace(/_/g, " ") : "—"
|
|
4003
|
+
}
|
|
4004
|
+
) })
|
|
4005
|
+
] }),
|
|
4006
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4007
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Session status (DB)" }),
|
|
4008
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: sessionStatusRaw })
|
|
4009
|
+
] }),
|
|
4010
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4011
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Payment status (DB)" }),
|
|
4012
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: paymentStatusRaw })
|
|
4013
|
+
] }),
|
|
4014
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4015
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Finalized" }),
|
|
4016
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.payment_id != null ? "Yes" : "No" })
|
|
4017
|
+
] }),
|
|
4018
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4019
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created" }),
|
|
4020
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: new Date(detail.created_at).toLocaleDateString("en-US", {
|
|
4021
|
+
year: "numeric",
|
|
4022
|
+
month: "short",
|
|
4023
|
+
day: "numeric",
|
|
4024
|
+
hour: "numeric",
|
|
4025
|
+
minute: "2-digit",
|
|
4026
|
+
hour12: true
|
|
4027
|
+
}) })
|
|
4028
|
+
] })
|
|
4029
|
+
] }) }),
|
|
4030
|
+
Object.keys(detail.data ?? {}).length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4031
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Provider data" }),
|
|
4032
|
+
/* @__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) })
|
|
4033
|
+
] }) : /* @__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." }) })
|
|
4034
|
+
] }) : null
|
|
4035
|
+
] }) });
|
|
4036
|
+
};
|
|
4037
|
+
const config$3 = adminSdk.defineRouteConfig({
|
|
4038
|
+
label: "Payment details",
|
|
4039
|
+
icon: icons.CreditCard
|
|
4040
|
+
});
|
|
4041
|
+
const getStatusBadgeClass$2 = (status) => {
|
|
4042
|
+
const s2 = status.toLowerCase();
|
|
4043
|
+
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
4044
|
+
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
4045
|
+
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
4046
|
+
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
4047
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
4048
|
+
};
|
|
4049
|
+
const formatAmount = (value) => {
|
|
4050
|
+
return String(value);
|
|
4051
|
+
};
|
|
4052
|
+
const RefundDetailPage = () => {
|
|
4053
|
+
const navigate = reactRouterDom.useNavigate();
|
|
4054
|
+
const params = reactRouterDom.useParams();
|
|
4055
|
+
const id = params?.id?.trim();
|
|
4056
|
+
const [detail, setDetail] = react.useState(null);
|
|
4057
|
+
const [loading, setLoading] = react.useState(!!id);
|
|
4058
|
+
const [error, setError] = react.useState(null);
|
|
4059
|
+
const [gatewayExpanded, setGatewayExpanded] = react.useState(false);
|
|
4060
|
+
react.useEffect(() => {
|
|
4061
|
+
if (!id) {
|
|
4062
|
+
setLoading(false);
|
|
4063
|
+
return;
|
|
4064
|
+
}
|
|
4065
|
+
let cancelled = false;
|
|
4066
|
+
setLoading(true);
|
|
4067
|
+
setError(null);
|
|
4068
|
+
fetch(`/admin/refunds/${id}`, { credentials: "include" }).then((res) => {
|
|
4069
|
+
if (!res.ok) throw new Error(res.statusText || "Failed to load");
|
|
4070
|
+
return res.json();
|
|
4071
|
+
}).then((data) => {
|
|
4072
|
+
if (!cancelled) setDetail(data);
|
|
4073
|
+
}).catch((e) => {
|
|
4074
|
+
if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
|
|
4075
|
+
}).finally(() => {
|
|
4076
|
+
if (!cancelled) setLoading(false);
|
|
4077
|
+
});
|
|
4078
|
+
return () => {
|
|
4079
|
+
cancelled = true;
|
|
4080
|
+
};
|
|
4081
|
+
}, [id]);
|
|
4082
|
+
const paymentStatus = detail?.payment?.status ?? "—";
|
|
4083
|
+
const hasGatewayData = detail?.payment?.payment_data && typeof detail.payment.payment_data === "object" && Object.keys(detail.payment.payment_data).length > 0;
|
|
4084
|
+
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: [
|
|
4085
|
+
/* @__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: [
|
|
4086
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => navigate("/refunds"), children: "← Refunds" }),
|
|
4087
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Refund details" }),
|
|
4088
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle font-mono", children: id ?? "—" })
|
|
4089
|
+
] }) }),
|
|
4090
|
+
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
4091
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
4092
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/refunds"), children: "Back to list" })
|
|
4093
|
+
] }) : 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: [
|
|
4094
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4095
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Refund summary" }),
|
|
4096
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
4097
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4098
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund ID" }),
|
|
4099
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.id })
|
|
4100
|
+
] }),
|
|
4101
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4102
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
|
|
4103
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.refund.amount) })
|
|
4104
|
+
] }),
|
|
4105
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4106
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Note" }),
|
|
4107
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.refund.note ?? "—" })
|
|
4108
|
+
] }),
|
|
4109
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4110
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created at" }),
|
|
4111
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: new Date(detail.refund.created_at).toLocaleDateString("en-US", {
|
|
4112
|
+
year: "numeric",
|
|
4113
|
+
month: "short",
|
|
4114
|
+
day: "numeric",
|
|
4115
|
+
hour: "numeric",
|
|
4116
|
+
minute: "2-digit",
|
|
4117
|
+
hour12: true
|
|
4118
|
+
}) })
|
|
4119
|
+
] }),
|
|
4120
|
+
detail.refund.created_by ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4121
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created by" }),
|
|
4122
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.created_by })
|
|
4123
|
+
] }) : null
|
|
4124
|
+
] })
|
|
4125
|
+
] }),
|
|
4126
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4127
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Payment summary" }),
|
|
4128
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
4129
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4130
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Payment amount" }),
|
|
4131
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.payment_amount) })
|
|
4132
|
+
] }),
|
|
4133
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4134
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Captured amount" }),
|
|
4135
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.captured_amount) })
|
|
4136
|
+
] }),
|
|
4137
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4138
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refunded amount" }),
|
|
4139
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.refunded_amount) })
|
|
4140
|
+
] }),
|
|
4141
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4142
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
|
|
4143
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.payment.provider_id || "—" })
|
|
4144
|
+
] }),
|
|
4145
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4146
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
|
|
4147
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4148
|
+
ui.Badge,
|
|
4149
|
+
{
|
|
4150
|
+
size: "2xsmall",
|
|
4151
|
+
className: `uppercase ${getStatusBadgeClass$2(paymentStatus)}`,
|
|
4152
|
+
children: paymentStatus !== "—" ? paymentStatus.replace(/_/g, " ") : "—"
|
|
4153
|
+
}
|
|
4154
|
+
) })
|
|
4155
|
+
] }),
|
|
4156
|
+
detail.computed ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4157
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4158
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Full refund" }),
|
|
4159
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.computed.is_full_refund ? "Yes" : "No" })
|
|
4160
|
+
] }),
|
|
4161
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4162
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Remaining refundable" }),
|
|
4163
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.computed.remaining_refundable_amount) })
|
|
4164
|
+
] }),
|
|
4165
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4166
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund %" }),
|
|
4167
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "mt-1 block", children: [
|
|
4168
|
+
detail.computed.refund_percentage.toFixed(1),
|
|
4169
|
+
"%"
|
|
4170
|
+
] })
|
|
4171
|
+
] })
|
|
4172
|
+
] }) : null
|
|
4182
4173
|
] })
|
|
4183
4174
|
] }),
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4175
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4176
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Order summary" }),
|
|
4177
|
+
detail.order ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
4178
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4179
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Order" }),
|
|
4180
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4181
|
+
ui.Button,
|
|
4182
|
+
{
|
|
4183
|
+
variant: "transparent",
|
|
4184
|
+
size: "small",
|
|
4185
|
+
onClick: () => navigate(`/orders/${detail.order.order_id}`),
|
|
4186
|
+
children: detail.order.order_number ?? detail.order.order_id
|
|
4187
|
+
}
|
|
4188
|
+
) })
|
|
4189
|
+
] }),
|
|
4190
|
+
detail.order.total != null ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4191
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Total" }),
|
|
4192
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.order.total) })
|
|
4193
|
+
] }) : null,
|
|
4194
|
+
detail.order.customer_id ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4195
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Customer ID" }),
|
|
4196
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.order.customer_id })
|
|
4197
|
+
] }) : null,
|
|
4198
|
+
detail.order.region ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4199
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Region" }),
|
|
4200
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.region })
|
|
4201
|
+
] }) : null,
|
|
4202
|
+
detail.order.fulfillment_status ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4203
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Fulfillment status" }),
|
|
4204
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.fulfillment_status })
|
|
4205
|
+
] }) : null
|
|
4206
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No order linked to this refund." })
|
|
4207
|
+
] }),
|
|
4208
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4209
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4210
|
+
"button",
|
|
4188
4211
|
{
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
onClick: () =>
|
|
4192
|
-
|
|
4212
|
+
type: "button",
|
|
4213
|
+
className: "flex w-full items-center justify-between text-left",
|
|
4214
|
+
onClick: () => setGatewayExpanded((prev) => !prev),
|
|
4215
|
+
"aria-expanded": gatewayExpanded,
|
|
4216
|
+
"aria-label": gatewayExpanded ? "Collapse gateway data" : "Expand gateway data",
|
|
4193
4217
|
children: [
|
|
4194
|
-
"
|
|
4195
|
-
|
|
4196
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRightMini, {})
|
|
4218
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg", children: "Gateway data" }),
|
|
4219
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: gatewayExpanded ? "Collapse" : "Expand" })
|
|
4197
4220
|
]
|
|
4198
|
-
}
|
|
4199
|
-
|
|
4200
|
-
))
|
|
4201
|
-
] })
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
] });
|
|
4221
|
+
}
|
|
4222
|
+
),
|
|
4223
|
+
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." }) })
|
|
4224
|
+
] })
|
|
4225
|
+
] }) : null
|
|
4226
|
+
] }) });
|
|
4205
4227
|
};
|
|
4206
|
-
const
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
children
|
|
4211
|
-
}) => /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "flex flex-col gap-4 rounded-lg border border-ui-border-base p-5", children: [
|
|
4212
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-2", children: [
|
|
4213
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
4214
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: title }),
|
|
4215
|
-
description ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: description }) : null
|
|
4216
|
-
] }),
|
|
4217
|
-
actions
|
|
4218
|
-
] }),
|
|
4219
|
-
children
|
|
4220
|
-
] });
|
|
4221
|
-
const Field = ({ label, children }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
|
|
4222
|
-
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-xs font-medium uppercase tracking-wide text-ui-fg-muted", children: label }),
|
|
4223
|
-
/* @__PURE__ */ jsxRuntime.jsx("dd", { className: "min-w-0", children })
|
|
4224
|
-
] });
|
|
4225
|
-
const DetailSkeleton = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", "aria-busy": "true", children: [
|
|
4226
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
4227
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-5 w-24 rounded-full" }),
|
|
4228
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-8 w-64" }),
|
|
4229
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-4 w-48" })
|
|
4230
|
-
] }),
|
|
4231
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-14 w-full" }),
|
|
4232
|
-
Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 rounded-lg border border-ui-border-base p-5", children: [
|
|
4233
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-5 w-40" }),
|
|
4234
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: Array.from({ length: 4 }).map((__, j) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
4235
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-3 w-20" }),
|
|
4236
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-4 w-36" })
|
|
4237
|
-
] }, j)) })
|
|
4238
|
-
] }, i))
|
|
4239
|
-
] });
|
|
4240
|
-
const DetailError = ({
|
|
4241
|
-
notFound,
|
|
4242
|
-
message,
|
|
4243
|
-
onRetry,
|
|
4244
|
-
onBack
|
|
4245
|
-
}) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2 rounded-lg border border-ui-border-base px-6 py-12 text-center", children: [
|
|
4246
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ExclamationCircle, { className: ui.clx(notFound ? "text-ui-fg-muted" : "text-ui-fg-error") }),
|
|
4247
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: notFound ? "Audit entry not found" : "Unable to load this deleted record" }),
|
|
4248
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "max-w-md text-ui-fg-subtle", children: notFound ? "This audit entry doesn’t exist. The link may be incorrect." : "We couldn’t retrieve the audit entry right now. Check your connection and try again." }),
|
|
4249
|
-
!notFound ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "max-w-md font-mono text-ui-fg-muted", children: message }) : null,
|
|
4250
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex gap-2", children: [
|
|
4251
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", size: "small", onClick: onBack, children: "Back to Deleted Records" }),
|
|
4252
|
-
!notFound ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", size: "small", onClick: onRetry, children: "Try again" }) : null
|
|
4253
|
-
] })
|
|
4254
|
-
] });
|
|
4255
|
-
adminSdk.defineRouteConfig({});
|
|
4228
|
+
const config$2 = adminSdk.defineRouteConfig({
|
|
4229
|
+
label: "Refund details",
|
|
4230
|
+
icon: icons.Receipt
|
|
4231
|
+
});
|
|
4256
4232
|
const getStatusBadgeClass$1 = (status) => {
|
|
4257
4233
|
const statusLower = status.toLowerCase();
|
|
4258
4234
|
if (statusLower === "requested") {
|
|
@@ -4279,7 +4255,6 @@ const getStatusBadgeClass$1 = (status) => {
|
|
|
4279
4255
|
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
4280
4256
|
};
|
|
4281
4257
|
const ReturnDetailPage = () => {
|
|
4282
|
-
var _a, _b, _c;
|
|
4283
4258
|
const navigate = reactRouterDom.useNavigate();
|
|
4284
4259
|
const { id } = reactRouterDom.useParams();
|
|
4285
4260
|
const [returnOrder, setReturnOrder] = react.useState(null);
|
|
@@ -4362,7 +4337,7 @@ const ReturnDetailPage = () => {
|
|
|
4362
4337
|
/* @__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" }) })
|
|
4363
4338
|
] }) }) });
|
|
4364
4339
|
}
|
|
4365
|
-
const statusHistory =
|
|
4340
|
+
const statusHistory = returnOrder.metadata?.status_history || [];
|
|
4366
4341
|
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: [
|
|
4367
4342
|
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3", children: [
|
|
4368
4343
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -4498,11 +4473,11 @@ const ReturnDetailPage = () => {
|
|
|
4498
4473
|
] }),
|
|
4499
4474
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4500
4475
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Customer" }),
|
|
4501
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children:
|
|
4476
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.order.customer?.email || returnOrder.order.email || "—" })
|
|
4502
4477
|
] }),
|
|
4503
4478
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4504
4479
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Payment method" }),
|
|
4505
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children:
|
|
4480
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.order.order_payment?.label || "—" })
|
|
4506
4481
|
] }),
|
|
4507
4482
|
returnOrder.order.total && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4508
4483
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Total" }),
|
|
@@ -4559,13 +4534,12 @@ const getStatusBadgeClass = (status) => {
|
|
|
4559
4534
|
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
4560
4535
|
};
|
|
4561
4536
|
const SwapDetailPage = () => {
|
|
4562
|
-
var _a, _b, _c;
|
|
4563
4537
|
const navigate = reactRouterDom.useNavigate();
|
|
4564
4538
|
const { id } = reactRouterDom.useParams();
|
|
4565
4539
|
const [swap, setSwap] = react.useState(null);
|
|
4566
4540
|
const [order, setOrder] = react.useState(null);
|
|
4567
4541
|
const [isLoading, setIsLoading] = react.useState(true);
|
|
4568
|
-
react.useState(false);
|
|
4542
|
+
const [isRejecting, setIsRejecting] = react.useState(false);
|
|
4569
4543
|
const [isCancelling, setIsCancelling] = react.useState(false);
|
|
4570
4544
|
const [error, setError] = react.useState(null);
|
|
4571
4545
|
const [updateError, setUpdateError] = react.useState(null);
|
|
@@ -4636,9 +4610,9 @@ const SwapDetailPage = () => {
|
|
|
4636
4610
|
setIsCancelling(false);
|
|
4637
4611
|
}
|
|
4638
4612
|
};
|
|
4639
|
-
const isOrderExchange = Boolean(swap
|
|
4613
|
+
const isOrderExchange = Boolean(swap?.exchange_id);
|
|
4640
4614
|
const canCancelExchange = isOrderExchange && swap && !["cancelled", "canceled", "completed", "declined"].includes(
|
|
4641
|
-
|
|
4615
|
+
swap.status?.toLowerCase() ?? ""
|
|
4642
4616
|
);
|
|
4643
4617
|
if (isLoading) {
|
|
4644
4618
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading swap..." }) }) }) });
|
|
@@ -4649,7 +4623,7 @@ const SwapDetailPage = () => {
|
|
|
4649
4623
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => navigate("/swaps"), children: "Back to list" }) })
|
|
4650
4624
|
] }) }) });
|
|
4651
4625
|
}
|
|
4652
|
-
const statusHistory =
|
|
4626
|
+
const statusHistory = swap.metadata?.status_history || [];
|
|
4653
4627
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: [
|
|
4654
4628
|
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3", children: [
|
|
4655
4629
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -4770,7 +4744,7 @@ const SwapDetailPage = () => {
|
|
|
4770
4744
|
] }),
|
|
4771
4745
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4772
4746
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Customer" }),
|
|
4773
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children:
|
|
4747
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: order.customer?.email || order.email || "—" })
|
|
4774
4748
|
] }),
|
|
4775
4749
|
order.total && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4776
4750
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Total" }),
|
|
@@ -4819,112 +4793,142 @@ const i18nTranslations0 = {};
|
|
|
4819
4793
|
const widgetModule = { widgets: [
|
|
4820
4794
|
{
|
|
4821
4795
|
Component: OrderGiftItemsWidget,
|
|
4822
|
-
zone: ["order.details.side.after"]
|
|
4796
|
+
zone: ["order.details.side.after"],
|
|
4797
|
+
widgetId: "Widget-b753"
|
|
4823
4798
|
},
|
|
4824
4799
|
{
|
|
4825
4800
|
Component: OrderRefundContextWidget,
|
|
4826
|
-
zone: ["order.details.after"]
|
|
4801
|
+
zone: ["order.details.after"],
|
|
4802
|
+
widgetId: "Widget-0606"
|
|
4827
4803
|
}
|
|
4828
4804
|
] };
|
|
4829
4805
|
const routeModule = {
|
|
4830
4806
|
routes: [
|
|
4831
4807
|
{
|
|
4832
|
-
Component:
|
|
4833
|
-
path: "/
|
|
4808
|
+
Component: DeletedRecordsPage,
|
|
4809
|
+
path: "/deleted-records-audit",
|
|
4810
|
+
handle: { label: config$9.label, translationNs: config$9.translationNs }
|
|
4834
4811
|
},
|
|
4835
4812
|
{
|
|
4836
|
-
Component:
|
|
4837
|
-
path: "/
|
|
4813
|
+
Component: PaymentsPage,
|
|
4814
|
+
path: "/payments",
|
|
4815
|
+
handle: { label: config$8.label, translationNs: config$8.translationNs }
|
|
4838
4816
|
},
|
|
4839
4817
|
{
|
|
4840
|
-
Component:
|
|
4841
|
-
path: "/
|
|
4818
|
+
Component: RefundsPage,
|
|
4819
|
+
path: "/refunds",
|
|
4820
|
+
handle: { label: config$7.label, translationNs: config$7.translationNs }
|
|
4842
4821
|
},
|
|
4843
4822
|
{
|
|
4844
4823
|
Component: ReturnsPage,
|
|
4845
|
-
path: "/returns"
|
|
4824
|
+
path: "/returns",
|
|
4825
|
+
handle: { label: config$6.label, translationNs: config$6.translationNs }
|
|
4846
4826
|
},
|
|
4847
4827
|
{
|
|
4848
4828
|
Component: SwapsPage,
|
|
4849
|
-
path: "/swaps"
|
|
4829
|
+
path: "/swaps",
|
|
4830
|
+
handle: { label: config$5.label, translationNs: config$5.translationNs }
|
|
4850
4831
|
},
|
|
4851
4832
|
{
|
|
4852
|
-
Component:
|
|
4853
|
-
path: "/
|
|
4833
|
+
Component: DeletedRecordDetailPage,
|
|
4834
|
+
path: "/deleted-records-audit/:id",
|
|
4835
|
+
handle: { label: config$4.label, translationNs: config$4.translationNs }
|
|
4854
4836
|
},
|
|
4855
4837
|
{
|
|
4856
|
-
Component:
|
|
4857
|
-
path: "/
|
|
4838
|
+
Component: PaymentDetailPage,
|
|
4839
|
+
path: "/payments/:id",
|
|
4840
|
+
handle: { label: config$3.label, translationNs: config$3.translationNs }
|
|
4858
4841
|
},
|
|
4859
4842
|
{
|
|
4860
|
-
Component:
|
|
4861
|
-
path: "/
|
|
4843
|
+
Component: RefundDetailPage,
|
|
4844
|
+
path: "/refunds/:id",
|
|
4845
|
+
handle: { label: config$2.label, translationNs: config$2.translationNs }
|
|
4862
4846
|
},
|
|
4863
4847
|
{
|
|
4864
4848
|
Component: ReturnDetailPage,
|
|
4865
|
-
path: "/returns/:id"
|
|
4849
|
+
path: "/returns/:id",
|
|
4850
|
+
handle: { label: config$1.label, translationNs: config$1.translationNs }
|
|
4866
4851
|
},
|
|
4867
4852
|
{
|
|
4868
4853
|
Component: SwapDetailPage,
|
|
4869
|
-
path: "/swaps/:id"
|
|
4854
|
+
path: "/swaps/:id",
|
|
4855
|
+
handle: { label: config.label, translationNs: config.translationNs }
|
|
4870
4856
|
}
|
|
4871
4857
|
]
|
|
4872
4858
|
};
|
|
4873
4859
|
const menuItemModule = {
|
|
4874
4860
|
menuItems: [
|
|
4875
4861
|
{
|
|
4876
|
-
label: config$
|
|
4877
|
-
icon: config$
|
|
4878
|
-
path: "/
|
|
4879
|
-
nested: void 0
|
|
4862
|
+
label: config$9.label,
|
|
4863
|
+
icon: config$9.icon,
|
|
4864
|
+
path: "/deleted-records-audit",
|
|
4865
|
+
nested: void 0,
|
|
4866
|
+
rank: void 0,
|
|
4867
|
+
translationNs: void 0
|
|
4868
|
+
},
|
|
4869
|
+
{
|
|
4870
|
+
label: config$8.label,
|
|
4871
|
+
icon: config$8.icon,
|
|
4872
|
+
path: "/payments",
|
|
4873
|
+
nested: void 0,
|
|
4874
|
+
rank: void 0,
|
|
4875
|
+
translationNs: void 0
|
|
4880
4876
|
},
|
|
4881
4877
|
{
|
|
4882
4878
|
label: config$7.label,
|
|
4883
4879
|
icon: config$7.icon,
|
|
4884
4880
|
path: "/refunds",
|
|
4885
|
-
nested: void 0
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
label: config$4.label,
|
|
4889
|
-
icon: config$4.icon,
|
|
4890
|
-
path: "/swaps",
|
|
4891
|
-
nested: void 0
|
|
4881
|
+
nested: void 0,
|
|
4882
|
+
rank: void 0,
|
|
4883
|
+
translationNs: void 0
|
|
4892
4884
|
},
|
|
4893
4885
|
{
|
|
4894
4886
|
label: config$6.label,
|
|
4895
4887
|
icon: config$6.icon,
|
|
4896
|
-
path: "/
|
|
4897
|
-
nested: void 0
|
|
4888
|
+
path: "/returns",
|
|
4889
|
+
nested: void 0,
|
|
4890
|
+
rank: void 0,
|
|
4891
|
+
translationNs: void 0
|
|
4898
4892
|
},
|
|
4899
4893
|
{
|
|
4900
|
-
label: config$
|
|
4901
|
-
icon: config$
|
|
4902
|
-
path: "/
|
|
4903
|
-
nested: void 0
|
|
4894
|
+
label: config$5.label,
|
|
4895
|
+
icon: config$5.icon,
|
|
4896
|
+
path: "/swaps",
|
|
4897
|
+
nested: void 0,
|
|
4898
|
+
rank: void 0,
|
|
4899
|
+
translationNs: void 0
|
|
4904
4900
|
},
|
|
4905
4901
|
{
|
|
4906
|
-
label: config$
|
|
4907
|
-
icon: config$
|
|
4908
|
-
path: "/payments",
|
|
4909
|
-
nested: void 0
|
|
4902
|
+
label: config$3.label,
|
|
4903
|
+
icon: config$3.icon,
|
|
4904
|
+
path: "/payments/:id",
|
|
4905
|
+
nested: void 0,
|
|
4906
|
+
rank: void 0,
|
|
4907
|
+
translationNs: void 0
|
|
4910
4908
|
},
|
|
4911
4909
|
{
|
|
4912
4910
|
label: config$2.label,
|
|
4913
4911
|
icon: config$2.icon,
|
|
4914
4912
|
path: "/refunds/:id",
|
|
4915
|
-
nested: void 0
|
|
4913
|
+
nested: void 0,
|
|
4914
|
+
rank: void 0,
|
|
4915
|
+
translationNs: void 0
|
|
4916
|
+
},
|
|
4917
|
+
{
|
|
4918
|
+
label: config$1.label,
|
|
4919
|
+
icon: config$1.icon,
|
|
4920
|
+
path: "/returns/:id",
|
|
4921
|
+
nested: void 0,
|
|
4922
|
+
rank: void 0,
|
|
4923
|
+
translationNs: void 0
|
|
4916
4924
|
},
|
|
4917
4925
|
{
|
|
4918
4926
|
label: config.label,
|
|
4919
4927
|
icon: config.icon,
|
|
4920
4928
|
path: "/swaps/:id",
|
|
4921
|
-
nested: void 0
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
label: config$3.label,
|
|
4925
|
-
icon: config$3.icon,
|
|
4926
|
-
path: "/payments/:id",
|
|
4927
|
-
nested: void 0
|
|
4929
|
+
nested: void 0,
|
|
4930
|
+
rank: void 0,
|
|
4931
|
+
translationNs: void 0
|
|
4928
4932
|
}
|
|
4929
4933
|
]
|
|
4930
4934
|
};
|
|
@@ -4933,12 +4937,18 @@ const displayModule = {
|
|
|
4933
4937
|
displays: {}
|
|
4934
4938
|
};
|
|
4935
4939
|
const i18nModule = { resources: i18nTranslations0 };
|
|
4940
|
+
const cellRendererModule = {};
|
|
4941
|
+
const layoutModule = { layouts: [] };
|
|
4942
|
+
const searchEntityModule = {};
|
|
4936
4943
|
const plugin = {
|
|
4937
4944
|
widgetModule,
|
|
4938
4945
|
routeModule,
|
|
4939
4946
|
menuItemModule,
|
|
4940
4947
|
formModule,
|
|
4941
4948
|
displayModule,
|
|
4942
|
-
i18nModule
|
|
4949
|
+
i18nModule,
|
|
4950
|
+
cellRendererModule,
|
|
4951
|
+
layoutModule,
|
|
4952
|
+
searchEntityModule
|
|
4943
4953
|
};
|
|
4944
4954
|
module.exports = plugin;
|