order-management 0.0.96 → 0.0.98
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 +2863 -824
- package/.medusa/server/src/admin/index.mjs +2867 -828
- package/.medusa/server/src/api/admin/deleted-records-audit/[id]/route.js +30 -0
- package/.medusa/server/src/api/admin/deleted-records-audit/route.js +48 -0
- package/.medusa/server/src/api/admin/deleted-records-audit/stats/route.js +27 -0
- package/.medusa/server/src/api/admin/deleted-records-audit/validators.js +57 -0
- package/.medusa/server/src/modules/deleted-records-audit/audited-tables.js +257 -0
- package/.medusa/server/src/modules/deleted-records-audit/index.js +14 -0
- package/.medusa/server/src/modules/deleted-records-audit/migrations/Migration20261008120000.js +81 -0
- package/.medusa/server/src/modules/deleted-records-audit/models/deleted-records-audit.js +15 -0
- package/.medusa/server/src/modules/deleted-records-audit/service.js +164 -0
- package/.medusa/server/src/modules/deleted-records-audit/types.js +3 -0
- package/.medusa/server/src/utils/notification-handler.js +38 -11
- package/README.md +79 -1
- package/package.json +1 -1
|
@@ -1,4 +1,7 @@
|
|
|
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);
|
|
2
5
|
const jsxRuntime = require("react/jsx-runtime");
|
|
3
6
|
const adminSdk = require("@medusajs/admin-sdk");
|
|
4
7
|
const react = require("react");
|
|
@@ -375,14 +378,15 @@ const s = {
|
|
|
375
378
|
const OrderGiftItemsWidget = ({ data }) => {
|
|
376
379
|
const [fetchedItems, setFetchedItems] = react.useState(null);
|
|
377
380
|
react.useEffect(() => {
|
|
378
|
-
if (!data
|
|
381
|
+
if (!(data == null ? void 0 : data.id)) return;
|
|
379
382
|
fetch(
|
|
380
383
|
`/admin/orders/${data.id}?fields=*items,items.metadata`
|
|
381
|
-
).then((r) => r.json()).then(({ order }) => setFetchedItems(order
|
|
382
|
-
}, [data
|
|
383
|
-
const items = fetchedItems ?? data
|
|
384
|
+
).then((r) => r.json()).then(({ order }) => setFetchedItems((order == null ? void 0 : order.items) ?? [])).catch(() => setFetchedItems((data == null ? void 0 : data.items) ?? []));
|
|
385
|
+
}, [data == null ? void 0 : data.id]);
|
|
386
|
+
const items = fetchedItems ?? (data == null ? void 0 : data.items) ?? [];
|
|
384
387
|
const giftedItems = items.filter((i) => {
|
|
385
|
-
|
|
388
|
+
var _a;
|
|
389
|
+
const flag = (_a = i.metadata) == null ? void 0 : _a.is_gift;
|
|
386
390
|
return flag === "true" || flag === true;
|
|
387
391
|
});
|
|
388
392
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: s.widget, children: [
|
|
@@ -411,9 +415,9 @@ const OrderGiftItemsWidget = ({ data }) => {
|
|
|
411
415
|
),
|
|
412
416
|
giftedItems.map((item) => {
|
|
413
417
|
const meta = item.metadata;
|
|
414
|
-
const from = meta
|
|
415
|
-
const to = meta
|
|
416
|
-
const message = meta
|
|
418
|
+
const from = meta == null ? void 0 : meta.gift_from;
|
|
419
|
+
const to = meta == null ? void 0 : meta.gift_to;
|
|
420
|
+
const message = meta == null ? void 0 : meta.gift_message;
|
|
417
421
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: s.card, children: [
|
|
418
422
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: s.ribbon, children: [
|
|
419
423
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: s.bowCenter, children: "🎀" }),
|
|
@@ -477,7 +481,7 @@ function formatRefundCurrency(amount, currencyCode = "inr", options) {
|
|
|
477
481
|
minimumFractionDigits: 2,
|
|
478
482
|
maximumFractionDigits: 2
|
|
479
483
|
}).format(amount);
|
|
480
|
-
if (options
|
|
484
|
+
if ((options == null ? void 0 : options.signed) && amount > 0) {
|
|
481
485
|
return `−${formatted}`;
|
|
482
486
|
}
|
|
483
487
|
return formatted;
|
|
@@ -532,7 +536,8 @@ function getOrderIdFromPath() {
|
|
|
532
536
|
return m ? m[1] : void 0;
|
|
533
537
|
}
|
|
534
538
|
const OrderRefundContextWidget = (props) => {
|
|
535
|
-
|
|
539
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
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();
|
|
536
541
|
const [context, setContext] = react.useState(null);
|
|
537
542
|
const [loading, setLoading] = react.useState(!!orderId);
|
|
538
543
|
const [error, setError] = react.useState(null);
|
|
@@ -570,7 +575,7 @@ const OrderRefundContextWidget = (props) => {
|
|
|
570
575
|
};
|
|
571
576
|
}, [orderId]);
|
|
572
577
|
const handleMarkRefunded = async () => {
|
|
573
|
-
if (!context
|
|
578
|
+
if (!(context == null ? void 0 : context.return_id) || !(context == null ? void 0 : context.refund_mapping) || context.refund_mapping.is_refunded || !context.can_process_refund) {
|
|
574
579
|
return;
|
|
575
580
|
}
|
|
576
581
|
setMarking(true);
|
|
@@ -587,14 +592,17 @@ const OrderRefundContextWidget = (props) => {
|
|
|
587
592
|
}
|
|
588
593
|
const data = await res.json();
|
|
589
594
|
setContext(
|
|
590
|
-
(prev) =>
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
595
|
+
(prev) => {
|
|
596
|
+
var _a2;
|
|
597
|
+
return prev && prev.refund_mapping ? {
|
|
598
|
+
...prev,
|
|
599
|
+
can_process_refund: false,
|
|
600
|
+
refund_mapping: {
|
|
601
|
+
...prev.refund_mapping,
|
|
602
|
+
is_refunded: ((_a2 = data.refund_payment_mapping) == null ? void 0 : _a2.is_refunded) ?? true
|
|
603
|
+
}
|
|
604
|
+
} : prev;
|
|
605
|
+
}
|
|
598
606
|
);
|
|
599
607
|
} catch (e) {
|
|
600
608
|
setMarkError(e instanceof Error ? e.message : "Failed to mark refunded");
|
|
@@ -603,19 +611,20 @@ const OrderRefundContextWidget = (props) => {
|
|
|
603
611
|
}
|
|
604
612
|
};
|
|
605
613
|
const handleEditClick = () => {
|
|
606
|
-
const mapping = context
|
|
607
|
-
const mode = mapping
|
|
614
|
+
const mapping = context == null ? void 0 : context.refund_mapping;
|
|
615
|
+
const mode = mapping == null ? void 0 : mapping.refund_mode;
|
|
608
616
|
setEditRefundMode(
|
|
609
617
|
mode === "offline" || mode === "online" ? mode : ""
|
|
610
618
|
);
|
|
611
|
-
setEditDetails(mapping
|
|
612
|
-
setEditImageUrls(mapping
|
|
619
|
+
setEditDetails((mapping == null ? void 0 : mapping.details) ?? "");
|
|
620
|
+
setEditImageUrls((mapping == null ? void 0 : mapping.images) ?? []);
|
|
613
621
|
setSaveError(null);
|
|
614
622
|
setUploadError(null);
|
|
615
623
|
setEditing(true);
|
|
616
624
|
};
|
|
617
625
|
const handleUploadImage = async (e) => {
|
|
618
|
-
|
|
626
|
+
var _a2, _b2, _c2;
|
|
627
|
+
const file = (_a2 = e.target.files) == null ? void 0 : _a2[0];
|
|
619
628
|
if (!file) return;
|
|
620
629
|
setUploading(true);
|
|
621
630
|
setUploadError(null);
|
|
@@ -632,7 +641,7 @@ const OrderRefundContextWidget = (props) => {
|
|
|
632
641
|
throw new Error(data2.message || "Upload failed");
|
|
633
642
|
}
|
|
634
643
|
const data = await res.json();
|
|
635
|
-
const url = data.files
|
|
644
|
+
const url = (_c2 = (_b2 = data.files) == null ? void 0 : _b2[0]) == null ? void 0 : _c2.url;
|
|
636
645
|
if (url) setEditImageUrls((prev) => [...prev, url]);
|
|
637
646
|
} catch (err) {
|
|
638
647
|
setUploadError(err instanceof Error ? err.message : "Upload failed");
|
|
@@ -645,7 +654,7 @@ const OrderRefundContextWidget = (props) => {
|
|
|
645
654
|
setEditImageUrls((prev) => prev.filter((_, i) => i !== index));
|
|
646
655
|
};
|
|
647
656
|
const handleSaveAdminFields = async () => {
|
|
648
|
-
if (!context
|
|
657
|
+
if (!(context == null ? void 0 : context.return_id)) return;
|
|
649
658
|
setSaving(true);
|
|
650
659
|
setSaveError(null);
|
|
651
660
|
try {
|
|
@@ -682,14 +691,14 @@ const OrderRefundContextWidget = (props) => {
|
|
|
682
691
|
if (error) {
|
|
683
692
|
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 }) }) });
|
|
684
693
|
}
|
|
685
|
-
const hasReturn = !!context
|
|
686
|
-
const hasMapping = !!context
|
|
687
|
-
const canMarkRefunded = Boolean(context
|
|
688
|
-
const returnStatus = context
|
|
689
|
-
const showReceiveFirstHint = hasReturn && !context
|
|
690
|
-
const paymentDetail = context
|
|
691
|
-
const paymentDetails = context
|
|
692
|
-
const orderPayment = context
|
|
694
|
+
const hasReturn = !!(context == null ? void 0 : context.return_id);
|
|
695
|
+
const hasMapping = !!(context == null ? void 0 : context.refund_mapping);
|
|
696
|
+
const canMarkRefunded = Boolean(context == null ? void 0 : context.can_process_refund);
|
|
697
|
+
const returnStatus = (context == null ? void 0 : context.return_status) ?? null;
|
|
698
|
+
const showReceiveFirstHint = hasReturn && !((_d = context == null ? void 0 : context.refund_mapping) == null ? void 0 : _d.is_refunded) && returnStatus !== "received" && returnStatus !== "canceled";
|
|
699
|
+
const paymentDetail = context == null ? void 0 : context.payment_detail;
|
|
700
|
+
const paymentDetails = (context == null ? void 0 : context.payment_details) && context.payment_details.length > 0 ? context.payment_details : paymentDetail ? [paymentDetail] : [];
|
|
701
|
+
const orderPayment = context == null ? void 0 : context.order_payment;
|
|
693
702
|
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: [
|
|
694
703
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Heading, { level: "h2", className: "flex items-center gap-2", children: [
|
|
695
704
|
/* @__PURE__ */ jsxRuntime.jsx(icons.CashSolid, { className: "text-ui-fg-subtle" }),
|
|
@@ -701,7 +710,7 @@ const OrderRefundContextWidget = (props) => {
|
|
|
701
710
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
702
711
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", className: "text-ui-fg-subtle", children: "Return" }),
|
|
703
712
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: context.return_id }),
|
|
704
|
-
context.refund_mapping
|
|
713
|
+
((_e = context.refund_mapping) == null ? void 0 : _e.is_refunded) ? /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: "green", children: "Refunded" }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: "orange", children: "Not refunded" })
|
|
705
714
|
] }),
|
|
706
715
|
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,
|
|
707
716
|
orderPayment && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 space-y-2 border-t border-ui-border-base pt-3", children: [
|
|
@@ -715,17 +724,17 @@ const OrderRefundContextWidget = (props) => {
|
|
|
715
724
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 space-y-2 border-t border-ui-border-base pt-3", children: [
|
|
716
725
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
717
726
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", className: "text-ui-fg-subtle", children: "Payment method (refund destination)" }),
|
|
718
|
-
context.refund_mapping
|
|
727
|
+
((_f = context.refund_mapping) == null ? void 0 : _f.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
|
|
719
728
|
] }),
|
|
720
|
-
context.refund_mapping
|
|
721
|
-
!context.refund_mapping
|
|
722
|
-
!context.refund_mapping
|
|
729
|
+
((_g = context.refund_mapping) == null ? void 0 : _g.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." }) }),
|
|
730
|
+
!((_h = context.refund_mapping) == null ? void 0 : _h.payment_id) && (paymentDetail == null ? void 0 : 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." }) }),
|
|
731
|
+
!((_i = context.refund_mapping) == null ? void 0 : _i.payment_id) && !paymentDetail && orderPayment && !orderPayment.is_cod && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-ui-border-base bg-ui-bg-subtle px-3 py-2", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: [
|
|
723
732
|
"Refund will go to the original payment method (",
|
|
724
733
|
orderPayment.label,
|
|
725
734
|
")."
|
|
726
735
|
] }) }),
|
|
727
|
-
!context.refund_mapping
|
|
728
|
-
!context.refund_mapping
|
|
736
|
+
!((_j = context.refund_mapping) == null ? void 0 : _j.payment_id) && !paymentDetail && (context.is_cod || (orderPayment == null ? void 0 : 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." }) }),
|
|
737
|
+
!((_k = context.refund_mapping) == null ? void 0 : _k.payment_id) && !paymentDetail && !orderPayment && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-ui-border-base bg-ui-bg-subtle px-3 py-2", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: "No payment method found for this customer." }) }),
|
|
729
738
|
paymentDetails.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: paymentDetails.map((detail) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
730
739
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
731
740
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { children: detail.type.toUpperCase() }),
|
|
@@ -737,7 +746,7 @@ const OrderRefundContextWidget = (props) => {
|
|
|
737
746
|
] }, `${detail.id}-${k}`)) })
|
|
738
747
|
] }, detail.id)) })
|
|
739
748
|
] }),
|
|
740
|
-
context
|
|
749
|
+
(context == null ? void 0 : context.refund_mapping) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 space-y-3 border-t border-ui-border-base pt-3", children: [
|
|
741
750
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
742
751
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", className: "text-ui-fg-subtle", children: "Refund mode, details & images" }),
|
|
743
752
|
!editing ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -825,7 +834,10 @@ const OrderRefundContextWidget = (props) => {
|
|
|
825
834
|
variant: "secondary",
|
|
826
835
|
type: "button",
|
|
827
836
|
disabled: uploading,
|
|
828
|
-
onClick: () =>
|
|
837
|
+
onClick: () => {
|
|
838
|
+
var _a2;
|
|
839
|
+
return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
|
|
840
|
+
},
|
|
829
841
|
children: uploading ? "Uploading…" : "Upload image"
|
|
830
842
|
}
|
|
831
843
|
),
|
|
@@ -876,7 +888,7 @@ const OrderRefundContextWidget = (props) => {
|
|
|
876
888
|
] }),
|
|
877
889
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
878
890
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", weight: "plus", className: "text-ui-fg-muted", children: "Images" }),
|
|
879
|
-
context.refund_mapping.images
|
|
891
|
+
((_l = context.refund_mapping.images) == null ? void 0 : _l.length) ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 flex flex-wrap gap-2", children: context.refund_mapping.images.map((url, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
880
892
|
"a",
|
|
881
893
|
{
|
|
882
894
|
href: url,
|
|
@@ -906,10 +918,10 @@ const OrderRefundContextWidget = (props) => {
|
|
|
906
918
|
),
|
|
907
919
|
markError && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-error", children: markError })
|
|
908
920
|
] }),
|
|
909
|
-
hasMapping && !canMarkRefunded && !context.refund_mapping
|
|
921
|
+
hasMapping && !canMarkRefunded && !((_m = context.refund_mapping) == null ? void 0 : _m.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." })
|
|
910
922
|
] }),
|
|
911
923
|
hasReturn && !hasMapping && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-4", children: [
|
|
912
|
-
context
|
|
924
|
+
(context == null ? void 0 : context.refund) ? /* @__PURE__ */ jsxRuntime.jsx(RefundCalculationBlock, { refund: context.refund }) : null,
|
|
913
925
|
orderPayment && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-3 space-y-1", children: [
|
|
914
926
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", className: "text-ui-fg-subtle", children: "Order payment method" }),
|
|
915
927
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
@@ -924,6 +936,1301 @@ const OrderRefundContextWidget = (props) => {
|
|
|
924
936
|
adminSdk.defineWidgetConfig({
|
|
925
937
|
zone: "order.details.after"
|
|
926
938
|
});
|
|
939
|
+
const AUDITED_TABLE_NAMES = [
|
|
940
|
+
"account_deletion_request",
|
|
941
|
+
"account_holder",
|
|
942
|
+
"api_key",
|
|
943
|
+
"application_method_buy_rules",
|
|
944
|
+
"application_method_target_rules",
|
|
945
|
+
"auth_identity",
|
|
946
|
+
"auth_mfa_factor",
|
|
947
|
+
"auth_mfa_recovery_code",
|
|
948
|
+
"auth_password_reset_token",
|
|
949
|
+
"auth_verification",
|
|
950
|
+
"cancel_order_reason_mapping",
|
|
951
|
+
"capture",
|
|
952
|
+
"cart",
|
|
953
|
+
"cart_address",
|
|
954
|
+
"cart_line_item",
|
|
955
|
+
"cart_line_item_adjustment",
|
|
956
|
+
"cart_line_item_tax_line",
|
|
957
|
+
"cart_payment_collection",
|
|
958
|
+
"cart_promotion",
|
|
959
|
+
"cart_shipping_method",
|
|
960
|
+
"cart_shipping_method_adjustment",
|
|
961
|
+
"cart_shipping_method_tax_line",
|
|
962
|
+
"contact_email_subscription",
|
|
963
|
+
"contact_request",
|
|
964
|
+
"contact_request_comment",
|
|
965
|
+
"credit_line",
|
|
966
|
+
"currency",
|
|
967
|
+
"customer",
|
|
968
|
+
"customer_account_holder",
|
|
969
|
+
"customer_address",
|
|
970
|
+
"customer_group",
|
|
971
|
+
"customer_group_customer",
|
|
972
|
+
"dynamic_config_value",
|
|
973
|
+
"fulfillment",
|
|
974
|
+
"fulfillment_address",
|
|
975
|
+
"fulfillment_item",
|
|
976
|
+
"fulfillment_label",
|
|
977
|
+
"fulfillment_provider",
|
|
978
|
+
"fulfillment_set",
|
|
979
|
+
"geo_zone",
|
|
980
|
+
"image",
|
|
981
|
+
"inventory_count_item",
|
|
982
|
+
"inventory_count_session",
|
|
983
|
+
"inventory_item",
|
|
984
|
+
"inventory_level",
|
|
985
|
+
"inventory_movement",
|
|
986
|
+
"inventory_purchase",
|
|
987
|
+
"inventory_purchase_attachment",
|
|
988
|
+
"inventory_purchase_audit_event",
|
|
989
|
+
"inventory_purchase_batch",
|
|
990
|
+
"inventory_purchase_line_item",
|
|
991
|
+
"invite",
|
|
992
|
+
"invite_rbac_role",
|
|
993
|
+
"invoice",
|
|
994
|
+
"invoice_sequence",
|
|
995
|
+
"layout_configuration",
|
|
996
|
+
"link_module_migrations",
|
|
997
|
+
"location_fulfillment_provider",
|
|
998
|
+
"location_fulfillment_set",
|
|
999
|
+
"loyalty_gift_card",
|
|
1000
|
+
"mikro_orm_migrations",
|
|
1001
|
+
"notification",
|
|
1002
|
+
"notification_provider",
|
|
1003
|
+
"notification_tokens",
|
|
1004
|
+
"order",
|
|
1005
|
+
"order_address",
|
|
1006
|
+
"order_cart",
|
|
1007
|
+
"order_change",
|
|
1008
|
+
"order_change_action",
|
|
1009
|
+
"order_claim",
|
|
1010
|
+
"order_claim_item",
|
|
1011
|
+
"order_claim_item_image",
|
|
1012
|
+
"order_credit_line",
|
|
1013
|
+
"order_exchange",
|
|
1014
|
+
"order_exchange_item",
|
|
1015
|
+
"order_fulfillment",
|
|
1016
|
+
"order_item",
|
|
1017
|
+
"order_line_item",
|
|
1018
|
+
"order_line_item_adjustment",
|
|
1019
|
+
"order_line_item_tax_line",
|
|
1020
|
+
"order_payment_collection",
|
|
1021
|
+
"order_promotion",
|
|
1022
|
+
"order_shipping",
|
|
1023
|
+
"order_shipping_method",
|
|
1024
|
+
"order_shipping_method_adjustment",
|
|
1025
|
+
"order_shipping_method_tax_line",
|
|
1026
|
+
"order_summary",
|
|
1027
|
+
"order_transaction",
|
|
1028
|
+
"otp_verification",
|
|
1029
|
+
"payment",
|
|
1030
|
+
"payment_collection",
|
|
1031
|
+
"payment_collection_payment_providers",
|
|
1032
|
+
"payment_detail",
|
|
1033
|
+
"payment_provider",
|
|
1034
|
+
"payment_session",
|
|
1035
|
+
"payout_request",
|
|
1036
|
+
"price",
|
|
1037
|
+
"price_list",
|
|
1038
|
+
"price_list_rule",
|
|
1039
|
+
"price_preference",
|
|
1040
|
+
"price_rule",
|
|
1041
|
+
"price_set",
|
|
1042
|
+
"product",
|
|
1043
|
+
"product_category",
|
|
1044
|
+
"product_category_product",
|
|
1045
|
+
"product_collection",
|
|
1046
|
+
"product_display_priority",
|
|
1047
|
+
"product_option",
|
|
1048
|
+
"product_option_value",
|
|
1049
|
+
"product_product_option",
|
|
1050
|
+
"product_product_option_value",
|
|
1051
|
+
"product_sales_channel",
|
|
1052
|
+
"product_shipping_profile",
|
|
1053
|
+
"product_tag",
|
|
1054
|
+
"product_tags",
|
|
1055
|
+
"product_type",
|
|
1056
|
+
"product_variant",
|
|
1057
|
+
"product_variant_inventory_item",
|
|
1058
|
+
"product_variant_option",
|
|
1059
|
+
"product_variant_price_set",
|
|
1060
|
+
"product_variant_product_image",
|
|
1061
|
+
"product_view",
|
|
1062
|
+
"promotion",
|
|
1063
|
+
"promotion_application_method",
|
|
1064
|
+
"promotion_campaign",
|
|
1065
|
+
"promotion_campaign_budget",
|
|
1066
|
+
"promotion_campaign_budget_usage",
|
|
1067
|
+
"promotion_promotion_rule",
|
|
1068
|
+
"promotion_rule",
|
|
1069
|
+
"promotion_rule_value",
|
|
1070
|
+
"property_label",
|
|
1071
|
+
"provider_identity",
|
|
1072
|
+
"publishable_api_key_sales_channel",
|
|
1073
|
+
"purchase_supplier",
|
|
1074
|
+
"referral_link",
|
|
1075
|
+
"referral_reward",
|
|
1076
|
+
"refund",
|
|
1077
|
+
"refund_payment_mapping",
|
|
1078
|
+
"refund_reason",
|
|
1079
|
+
"region",
|
|
1080
|
+
"region_country",
|
|
1081
|
+
"region_payment_provider",
|
|
1082
|
+
"reservation_item",
|
|
1083
|
+
"return",
|
|
1084
|
+
"return_fulfillment",
|
|
1085
|
+
"return_item",
|
|
1086
|
+
"return_reason",
|
|
1087
|
+
"review",
|
|
1088
|
+
"sales_channel",
|
|
1089
|
+
"sales_channel_stock_location",
|
|
1090
|
+
"script_migrations",
|
|
1091
|
+
"search_index",
|
|
1092
|
+
"search_index_sync",
|
|
1093
|
+
"search_index_version",
|
|
1094
|
+
"search_postgres_index",
|
|
1095
|
+
"service_zone",
|
|
1096
|
+
"shipment_tracking_event",
|
|
1097
|
+
"shipping_option",
|
|
1098
|
+
"shipping_option_price_set",
|
|
1099
|
+
"shipping_option_rule",
|
|
1100
|
+
"shipping_option_type",
|
|
1101
|
+
"shipping_profile",
|
|
1102
|
+
"skip_merge_cart",
|
|
1103
|
+
"stock_location",
|
|
1104
|
+
"stock_location_address",
|
|
1105
|
+
"store",
|
|
1106
|
+
"store_credit_account",
|
|
1107
|
+
"store_credit_account_transaction",
|
|
1108
|
+
"store_currency",
|
|
1109
|
+
"store_locale",
|
|
1110
|
+
"tax_provider",
|
|
1111
|
+
"tax_rate",
|
|
1112
|
+
"tax_rate_rule",
|
|
1113
|
+
"tax_region",
|
|
1114
|
+
"telegram_config",
|
|
1115
|
+
"telegram_notification_log",
|
|
1116
|
+
"user",
|
|
1117
|
+
"user_preference",
|
|
1118
|
+
"user_rbac_role",
|
|
1119
|
+
"view_configuration",
|
|
1120
|
+
"wallet_account",
|
|
1121
|
+
"wallet_credit_lot",
|
|
1122
|
+
"wallet_gift_card",
|
|
1123
|
+
"wallet_hold",
|
|
1124
|
+
"wallet_ledger_entry",
|
|
1125
|
+
"wallet_rate_limit",
|
|
1126
|
+
"wallet_refund_intent",
|
|
1127
|
+
"wallet_top_up_request",
|
|
1128
|
+
"wishlist",
|
|
1129
|
+
"workflow_execution"
|
|
1130
|
+
];
|
|
1131
|
+
const ENTITY_CATEGORIES = [
|
|
1132
|
+
{ id: "orders", label: "Orders", description: "Orders, items, returns, exchanges and claims" },
|
|
1133
|
+
{ id: "carts", label: "Carts", description: "Shopping carts and checkout data" },
|
|
1134
|
+
{ id: "customers", label: "Customers", description: "Customers, addresses and groups" },
|
|
1135
|
+
{ id: "catalog", label: "Catalog", description: "Products, variants, categories and collections" },
|
|
1136
|
+
{ id: "pricing", label: "Pricing & Promotions", description: "Prices, price lists and promotions" },
|
|
1137
|
+
{ id: "payments", label: "Payments & Refunds", description: "Payments, sessions, captures and refunds" },
|
|
1138
|
+
{ id: "fulfillment", label: "Fulfillment & Shipping", description: "Fulfillments, shipping options and tracking" },
|
|
1139
|
+
{ id: "inventory", label: "Inventory & Purchasing", description: "Stock, locations, reservations and purchases" },
|
|
1140
|
+
{ id: "wallet", label: "Wallet & Credits", description: "Wallets, store credit and gift cards" },
|
|
1141
|
+
{ id: "access", label: "Users & Access", description: "Admin users, logins, roles and API keys" },
|
|
1142
|
+
{ id: "store", label: "Store & Regions", description: "Store, regions, currencies, taxes and sales channels" },
|
|
1143
|
+
{ id: "engagement", label: "Engagement", description: "Reviews, wishlists, referrals and contact requests" },
|
|
1144
|
+
{ id: "notifications", label: "Notifications", description: "Notifications and messaging" },
|
|
1145
|
+
{ id: "system", label: "System & Configuration", description: "Settings, search, workflows and migrations" }
|
|
1146
|
+
];
|
|
1147
|
+
const ENTITY_DEFINITIONS = {
|
|
1148
|
+
// Orders
|
|
1149
|
+
order: { label: "Order", category: "orders" },
|
|
1150
|
+
order_address: { label: "Order Address", category: "orders" },
|
|
1151
|
+
order_cart: { label: "Order–Cart Link", category: "orders" },
|
|
1152
|
+
order_change: { label: "Order Change", category: "orders" },
|
|
1153
|
+
order_change_action: { label: "Order Change Action", category: "orders" },
|
|
1154
|
+
order_claim: { label: "Claim", category: "orders" },
|
|
1155
|
+
order_claim_item: { label: "Claim Item", category: "orders" },
|
|
1156
|
+
order_claim_item_image: { label: "Claim Item Image", category: "orders" },
|
|
1157
|
+
order_credit_line: { label: "Order Credit Line", category: "orders" },
|
|
1158
|
+
order_exchange: { label: "Exchange", category: "orders" },
|
|
1159
|
+
order_exchange_item: { label: "Exchange Item", category: "orders" },
|
|
1160
|
+
order_fulfillment: { label: "Order–Fulfillment Link", category: "orders" },
|
|
1161
|
+
order_item: { label: "Order Item Quantity", category: "orders" },
|
|
1162
|
+
order_line_item: { label: "Order Item", category: "orders" },
|
|
1163
|
+
order_line_item_adjustment: { label: "Order Item Discount", category: "orders" },
|
|
1164
|
+
order_line_item_tax_line: { label: "Order Item Tax", category: "orders" },
|
|
1165
|
+
order_payment_collection: { label: "Order–Payment Link", category: "orders" },
|
|
1166
|
+
order_promotion: { label: "Order Promotion", category: "orders" },
|
|
1167
|
+
order_shipping: { label: "Order Shipping", category: "orders" },
|
|
1168
|
+
order_shipping_method: { label: "Order Shipping Method", category: "orders" },
|
|
1169
|
+
order_shipping_method_adjustment: { label: "Order Shipping Discount", category: "orders" },
|
|
1170
|
+
order_shipping_method_tax_line: { label: "Order Shipping Tax", category: "orders" },
|
|
1171
|
+
order_summary: { label: "Order Summary", category: "orders" },
|
|
1172
|
+
order_transaction: { label: "Order Transaction", category: "orders" },
|
|
1173
|
+
return: { label: "Return", category: "orders" },
|
|
1174
|
+
return_fulfillment: { label: "Return–Fulfillment Link", category: "orders" },
|
|
1175
|
+
return_item: { label: "Return Item", category: "orders" },
|
|
1176
|
+
return_reason: { label: "Return Reason", category: "orders" },
|
|
1177
|
+
cancel_order_reason_mapping: { label: "Order Cancellation Reason", category: "orders" },
|
|
1178
|
+
credit_line: { label: "Credit Line", category: "orders" },
|
|
1179
|
+
invoice: { label: "Invoice", category: "orders" },
|
|
1180
|
+
invoice_sequence: { label: "Invoice Number Sequence", category: "orders" },
|
|
1181
|
+
// Carts
|
|
1182
|
+
cart: { label: "Cart", category: "carts" },
|
|
1183
|
+
cart_address: { label: "Cart Address", category: "carts" },
|
|
1184
|
+
cart_line_item: { label: "Cart Item", category: "carts" },
|
|
1185
|
+
cart_line_item_adjustment: { label: "Cart Item Discount", category: "carts" },
|
|
1186
|
+
cart_line_item_tax_line: { label: "Cart Item Tax", category: "carts" },
|
|
1187
|
+
cart_payment_collection: { label: "Cart–Payment Link", category: "carts" },
|
|
1188
|
+
cart_promotion: { label: "Cart Promotion", category: "carts" },
|
|
1189
|
+
cart_shipping_method: { label: "Cart Shipping Method", category: "carts" },
|
|
1190
|
+
cart_shipping_method_adjustment: { label: "Cart Shipping Discount", category: "carts" },
|
|
1191
|
+
cart_shipping_method_tax_line: { label: "Cart Shipping Tax", category: "carts" },
|
|
1192
|
+
skip_merge_cart: { label: "Cart Merge Exclusion", category: "carts" },
|
|
1193
|
+
// Customers
|
|
1194
|
+
customer: { label: "Customer", category: "customers" },
|
|
1195
|
+
customer_address: { label: "Customer Address", category: "customers" },
|
|
1196
|
+
customer_group: { label: "Customer Group", category: "customers" },
|
|
1197
|
+
customer_group_customer: { label: "Customer Group Member", category: "customers" },
|
|
1198
|
+
customer_account_holder: { label: "Customer–Account Holder Link", category: "customers" },
|
|
1199
|
+
account_holder: { label: "Payment Account Holder", category: "customers" },
|
|
1200
|
+
account_deletion_request: { label: "Account Deletion Request", category: "customers" },
|
|
1201
|
+
payment_detail: { label: "Customer Refund Method", category: "customers" },
|
|
1202
|
+
otp_verification: { label: "OTP Verification", category: "customers" },
|
|
1203
|
+
// Catalog
|
|
1204
|
+
product: { label: "Product", category: "catalog" },
|
|
1205
|
+
product_variant: { label: "Product Variant", category: "catalog" },
|
|
1206
|
+
product_category: { label: "Product Category", category: "catalog" },
|
|
1207
|
+
product_category_product: { label: "Product–Category Link", category: "catalog" },
|
|
1208
|
+
product_collection: { label: "Collection", category: "catalog" },
|
|
1209
|
+
product_option: { label: "Product Option", category: "catalog" },
|
|
1210
|
+
product_option_value: { label: "Product Option Value", category: "catalog" },
|
|
1211
|
+
product_product_option: { label: "Product–Option Link", category: "catalog" },
|
|
1212
|
+
product_product_option_value: { label: "Product–Option Value Link", category: "catalog" },
|
|
1213
|
+
product_tag: { label: "Product Tag", category: "catalog" },
|
|
1214
|
+
product_tags: { label: "Product–Tag Link", category: "catalog" },
|
|
1215
|
+
product_type: { label: "Product Type", category: "catalog" },
|
|
1216
|
+
product_sales_channel: { label: "Product–Sales Channel Link", category: "catalog" },
|
|
1217
|
+
product_shipping_profile: { label: "Product–Shipping Profile Link", category: "catalog" },
|
|
1218
|
+
product_variant_inventory_item: { label: "Variant–Inventory Link", category: "catalog" },
|
|
1219
|
+
product_variant_option: { label: "Variant Option", category: "catalog" },
|
|
1220
|
+
product_variant_price_set: { label: "Variant–Price Link", category: "catalog" },
|
|
1221
|
+
product_variant_product_image: { label: "Variant Image", category: "catalog" },
|
|
1222
|
+
product_display_priority: { label: "Product Display Priority", category: "catalog" },
|
|
1223
|
+
product_view: { label: "Product View", category: "catalog" },
|
|
1224
|
+
image: { label: "Product Image", category: "catalog" },
|
|
1225
|
+
property_label: { label: "Property Label", category: "catalog" },
|
|
1226
|
+
// Pricing & promotions
|
|
1227
|
+
price: { label: "Price", category: "pricing" },
|
|
1228
|
+
price_list: { label: "Price List", category: "pricing" },
|
|
1229
|
+
price_list_rule: { label: "Price List Rule", category: "pricing" },
|
|
1230
|
+
price_preference: { label: "Price Preference", category: "pricing" },
|
|
1231
|
+
price_rule: { label: "Price Rule", category: "pricing" },
|
|
1232
|
+
price_set: { label: "Price Set", category: "pricing" },
|
|
1233
|
+
promotion: { label: "Promotion", category: "pricing" },
|
|
1234
|
+
promotion_application_method: { label: "Promotion Application Method", category: "pricing" },
|
|
1235
|
+
promotion_campaign: { label: "Campaign", category: "pricing" },
|
|
1236
|
+
promotion_campaign_budget: { label: "Campaign Budget", category: "pricing" },
|
|
1237
|
+
promotion_campaign_budget_usage: { label: "Campaign Budget Usage", category: "pricing" },
|
|
1238
|
+
promotion_promotion_rule: { label: "Promotion–Rule Link", category: "pricing" },
|
|
1239
|
+
promotion_rule: { label: "Promotion Rule", category: "pricing" },
|
|
1240
|
+
promotion_rule_value: { label: "Promotion Rule Value", category: "pricing" },
|
|
1241
|
+
application_method_buy_rules: { label: "Promotion Buy Rule", category: "pricing" },
|
|
1242
|
+
application_method_target_rules: { label: "Promotion Target Rule", category: "pricing" },
|
|
1243
|
+
// Payments
|
|
1244
|
+
payment: { label: "Payment", category: "payments" },
|
|
1245
|
+
payment_collection: { label: "Payment Collection", category: "payments" },
|
|
1246
|
+
payment_collection_payment_providers: { label: "Payment Collection–Provider Link", category: "payments" },
|
|
1247
|
+
payment_provider: { label: "Payment Provider", category: "payments" },
|
|
1248
|
+
payment_session: { label: "Payment Session", category: "payments" },
|
|
1249
|
+
capture: { label: "Payment Capture", category: "payments" },
|
|
1250
|
+
refund: { label: "Refund", category: "payments" },
|
|
1251
|
+
refund_reason: { label: "Refund Reason", category: "payments" },
|
|
1252
|
+
refund_payment_mapping: { label: "Return Refund Mapping", category: "payments" },
|
|
1253
|
+
payout_request: { label: "Payout Request", category: "payments" },
|
|
1254
|
+
// Fulfillment
|
|
1255
|
+
fulfillment: { label: "Fulfillment", category: "fulfillment" },
|
|
1256
|
+
fulfillment_address: { label: "Fulfillment Address", category: "fulfillment" },
|
|
1257
|
+
fulfillment_item: { label: "Fulfillment Item", category: "fulfillment" },
|
|
1258
|
+
fulfillment_label: { label: "Shipping Label", category: "fulfillment" },
|
|
1259
|
+
fulfillment_provider: { label: "Fulfillment Provider", category: "fulfillment" },
|
|
1260
|
+
fulfillment_set: { label: "Fulfillment Set", category: "fulfillment" },
|
|
1261
|
+
geo_zone: { label: "Geo Zone", category: "fulfillment" },
|
|
1262
|
+
service_zone: { label: "Service Zone", category: "fulfillment" },
|
|
1263
|
+
shipping_option: { label: "Shipping Option", category: "fulfillment" },
|
|
1264
|
+
shipping_option_price_set: { label: "Shipping Option–Price Link", category: "fulfillment" },
|
|
1265
|
+
shipping_option_rule: { label: "Shipping Option Rule", category: "fulfillment" },
|
|
1266
|
+
shipping_option_type: { label: "Shipping Option Type", category: "fulfillment" },
|
|
1267
|
+
shipping_profile: { label: "Shipping Profile", category: "fulfillment" },
|
|
1268
|
+
shipment_tracking_event: { label: "Shipment Tracking Event", category: "fulfillment" },
|
|
1269
|
+
location_fulfillment_provider: { label: "Location–Fulfillment Provider Link", category: "fulfillment" },
|
|
1270
|
+
location_fulfillment_set: { label: "Location–Fulfillment Set Link", category: "fulfillment" },
|
|
1271
|
+
// Inventory
|
|
1272
|
+
inventory_item: { label: "Inventory Item", category: "inventory" },
|
|
1273
|
+
inventory_level: { label: "Inventory Level", category: "inventory" },
|
|
1274
|
+
inventory_movement: { label: "Inventory Movement", category: "inventory" },
|
|
1275
|
+
inventory_count_item: { label: "Stock Count Item", category: "inventory" },
|
|
1276
|
+
inventory_count_session: { label: "Stock Count Session", category: "inventory" },
|
|
1277
|
+
inventory_purchase: { label: "Purchase", category: "inventory" },
|
|
1278
|
+
inventory_purchase_attachment: { label: "Purchase Attachment", category: "inventory" },
|
|
1279
|
+
inventory_purchase_audit_event: { label: "Purchase Audit Event", category: "inventory" },
|
|
1280
|
+
inventory_purchase_batch: { label: "Purchase Batch", category: "inventory" },
|
|
1281
|
+
inventory_purchase_line_item: { label: "Purchase Item", category: "inventory" },
|
|
1282
|
+
purchase_supplier: { label: "Supplier", category: "inventory" },
|
|
1283
|
+
reservation_item: { label: "Stock Reservation", category: "inventory" },
|
|
1284
|
+
stock_location: { label: "Stock Location", category: "inventory" },
|
|
1285
|
+
stock_location_address: { label: "Stock Location Address", category: "inventory" },
|
|
1286
|
+
sales_channel_stock_location: { label: "Sales Channel–Location Link", category: "inventory" },
|
|
1287
|
+
// Wallet
|
|
1288
|
+
wallet_account: { label: "Wallet Account", category: "wallet" },
|
|
1289
|
+
wallet_credit_lot: { label: "Wallet Credit Lot", category: "wallet" },
|
|
1290
|
+
wallet_gift_card: { label: "Wallet Gift Card", category: "wallet" },
|
|
1291
|
+
wallet_hold: { label: "Wallet Hold", category: "wallet" },
|
|
1292
|
+
wallet_ledger_entry: { label: "Wallet Ledger Entry", category: "wallet" },
|
|
1293
|
+
wallet_rate_limit: { label: "Wallet Rate Limit", category: "wallet" },
|
|
1294
|
+
wallet_refund_intent: { label: "Wallet Refund", category: "wallet" },
|
|
1295
|
+
wallet_top_up_request: { label: "Wallet Top-up Request", category: "wallet" },
|
|
1296
|
+
store_credit_account: { label: "Store Credit Account", category: "wallet" },
|
|
1297
|
+
store_credit_account_transaction: { label: "Store Credit Transaction", category: "wallet" },
|
|
1298
|
+
loyalty_gift_card: { label: "Loyalty Gift Card", category: "wallet" },
|
|
1299
|
+
// Users & access
|
|
1300
|
+
user: { label: "Admin User", category: "access" },
|
|
1301
|
+
user_preference: { label: "User Preference", category: "access" },
|
|
1302
|
+
user_rbac_role: { label: "User Role", category: "access" },
|
|
1303
|
+
invite: { label: "Admin Invite", category: "access" },
|
|
1304
|
+
invite_rbac_role: { label: "Invite Role", category: "access" },
|
|
1305
|
+
api_key: { label: "API Key", category: "access" },
|
|
1306
|
+
publishable_api_key_sales_channel: { label: "API Key–Sales Channel Link", category: "access" },
|
|
1307
|
+
auth_identity: { label: "Login Identity", category: "access" },
|
|
1308
|
+
auth_mfa_factor: { label: "MFA Factor", category: "access" },
|
|
1309
|
+
auth_mfa_recovery_code: { label: "MFA Recovery Code", category: "access" },
|
|
1310
|
+
auth_password_reset_token: { label: "Password Reset Token", category: "access" },
|
|
1311
|
+
auth_verification: { label: "Auth Verification", category: "access" },
|
|
1312
|
+
provider_identity: { label: "Login Provider Identity", category: "access" },
|
|
1313
|
+
// Store & regions
|
|
1314
|
+
store: { label: "Store", category: "store" },
|
|
1315
|
+
store_currency: { label: "Store Currency", category: "store" },
|
|
1316
|
+
store_locale: { label: "Store Locale", category: "store" },
|
|
1317
|
+
currency: { label: "Currency", category: "store" },
|
|
1318
|
+
region: { label: "Region", category: "store" },
|
|
1319
|
+
region_country: { label: "Region Country", category: "store" },
|
|
1320
|
+
region_payment_provider: { label: "Region–Payment Provider Link", category: "store" },
|
|
1321
|
+
sales_channel: { label: "Sales Channel", category: "store" },
|
|
1322
|
+
tax_provider: { label: "Tax Provider", category: "store" },
|
|
1323
|
+
tax_rate: { label: "Tax Rate", category: "store" },
|
|
1324
|
+
tax_rate_rule: { label: "Tax Rate Rule", category: "store" },
|
|
1325
|
+
tax_region: { label: "Tax Region", category: "store" },
|
|
1326
|
+
// Engagement
|
|
1327
|
+
review: { label: "Review", category: "engagement" },
|
|
1328
|
+
wishlist: { label: "Wishlist", category: "engagement" },
|
|
1329
|
+
referral_link: { label: "Referral Link", category: "engagement" },
|
|
1330
|
+
referral_reward: { label: "Referral Reward", category: "engagement" },
|
|
1331
|
+
contact_request: { label: "Contact Request", category: "engagement" },
|
|
1332
|
+
contact_request_comment: { label: "Contact Request Comment", category: "engagement" },
|
|
1333
|
+
contact_email_subscription: { label: "Email Subscription", category: "engagement" },
|
|
1334
|
+
// Notifications
|
|
1335
|
+
notification: { label: "Notification", category: "notifications" },
|
|
1336
|
+
notification_provider: { label: "Notification Provider", category: "notifications" },
|
|
1337
|
+
notification_tokens: { label: "Push Notification Token", category: "notifications" },
|
|
1338
|
+
telegram_config: { label: "Telegram Settings", category: "notifications" },
|
|
1339
|
+
telegram_notification_log: { label: "Telegram Notification Log", category: "notifications" },
|
|
1340
|
+
// System
|
|
1341
|
+
dynamic_config_value: { label: "Plugin Setting", category: "system" },
|
|
1342
|
+
layout_configuration: { label: "Layout Configuration", category: "system" },
|
|
1343
|
+
view_configuration: { label: "View Configuration", category: "system" },
|
|
1344
|
+
workflow_execution: { label: "Workflow Execution", category: "system" },
|
|
1345
|
+
search_index: { label: "Search Index", category: "system" },
|
|
1346
|
+
search_index_sync: { label: "Search Index Sync", category: "system" },
|
|
1347
|
+
search_index_version: { label: "Search Index Version", category: "system" },
|
|
1348
|
+
search_postgres_index: { label: "Search Index Entry", category: "system" },
|
|
1349
|
+
link_module_migrations: { label: "Link Migration Record", category: "system" },
|
|
1350
|
+
mikro_orm_migrations: { label: "Database Migration Record", category: "system" },
|
|
1351
|
+
script_migrations: { label: "Script Migration Record", category: "system" }
|
|
1352
|
+
};
|
|
1353
|
+
const CATEGORY_BY_ID = new Map(ENTITY_CATEGORIES.map((c) => [c.id, c]));
|
|
1354
|
+
const SYSTEM_CATEGORY = CATEGORY_BY_ID.get("system");
|
|
1355
|
+
function humanizeTableName(tableName) {
|
|
1356
|
+
return tableName.split("_").filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
1357
|
+
}
|
|
1358
|
+
function getEntityInfo(tableName) {
|
|
1359
|
+
const def = ENTITY_DEFINITIONS[tableName];
|
|
1360
|
+
return {
|
|
1361
|
+
tableName,
|
|
1362
|
+
label: (def == null ? void 0 : def.label) ?? humanizeTableName(tableName),
|
|
1363
|
+
category: def && CATEGORY_BY_ID.get(def.category) || SYSTEM_CATEGORY
|
|
1364
|
+
};
|
|
1365
|
+
}
|
|
1366
|
+
function getEntitiesByCategory() {
|
|
1367
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1368
|
+
for (const table of AUDITED_TABLE_NAMES) {
|
|
1369
|
+
const info = getEntityInfo(table);
|
|
1370
|
+
const list = groups.get(info.category.id) ?? [];
|
|
1371
|
+
list.push(info);
|
|
1372
|
+
groups.set(info.category.id, list);
|
|
1373
|
+
}
|
|
1374
|
+
return ENTITY_CATEGORIES.filter((category) => groups.has(category.id)).map((category) => ({
|
|
1375
|
+
category,
|
|
1376
|
+
entities: (groups.get(category.id) ?? []).sort((a, b) => a.label.localeCompare(b.label))
|
|
1377
|
+
}));
|
|
1378
|
+
}
|
|
1379
|
+
function getCategory(id) {
|
|
1380
|
+
return CATEGORY_BY_ID.get(id);
|
|
1381
|
+
}
|
|
1382
|
+
function getTablesForCategory(id) {
|
|
1383
|
+
return AUDITED_TABLE_NAMES.filter((table) => getEntityInfo(table).category.id === id);
|
|
1384
|
+
}
|
|
1385
|
+
const GROUPS = getEntitiesByCategory();
|
|
1386
|
+
function triggerLabel(entity, category) {
|
|
1387
|
+
var _a;
|
|
1388
|
+
if (entity) return getEntityInfo(entity).label;
|
|
1389
|
+
if (category) return `All ${((_a = getCategory(category)) == null ? void 0 : _a.label) ?? category}`;
|
|
1390
|
+
return "All entities";
|
|
1391
|
+
}
|
|
1392
|
+
const EntityPicker = ({ entity, category, onChange }) => {
|
|
1393
|
+
var _a;
|
|
1394
|
+
const [open, setOpen] = react.useState(false);
|
|
1395
|
+
const [search, setSearch] = react.useState("");
|
|
1396
|
+
const searchRef = react.useRef(null);
|
|
1397
|
+
const filteredGroups = react.useMemo(() => {
|
|
1398
|
+
const term = search.trim().toLowerCase();
|
|
1399
|
+
if (!term) return GROUPS;
|
|
1400
|
+
return GROUPS.map((group) => {
|
|
1401
|
+
const categoryMatches = group.category.label.toLowerCase().includes(term);
|
|
1402
|
+
const entities = categoryMatches ? group.entities : group.entities.filter(
|
|
1403
|
+
(e) => e.label.toLowerCase().includes(term) || e.tableName.includes(term.replace(/\s+/g, "_"))
|
|
1404
|
+
);
|
|
1405
|
+
return { ...group, entities };
|
|
1406
|
+
}).filter((group) => group.entities.length > 0);
|
|
1407
|
+
}, [search]);
|
|
1408
|
+
const select = (next) => {
|
|
1409
|
+
onChange(next);
|
|
1410
|
+
setOpen(false);
|
|
1411
|
+
setSearch("");
|
|
1412
|
+
};
|
|
1413
|
+
const firstMatch = (_a = filteredGroups[0]) == null ? void 0 : _a.entities[0];
|
|
1414
|
+
const isAll = !entity && !category;
|
|
1415
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1416
|
+
ui.Popover,
|
|
1417
|
+
{
|
|
1418
|
+
open,
|
|
1419
|
+
onOpenChange: (next) => {
|
|
1420
|
+
setOpen(next);
|
|
1421
|
+
if (!next) setSearch("");
|
|
1422
|
+
},
|
|
1423
|
+
children: [
|
|
1424
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1425
|
+
"button",
|
|
1426
|
+
{
|
|
1427
|
+
type: "button",
|
|
1428
|
+
"aria-label": "Filter by entity",
|
|
1429
|
+
className: ui.clx(
|
|
1430
|
+
"txt-compact-small flex h-7 w-full min-w-[200px] items-center justify-between gap-2 rounded-md bg-ui-bg-field px-2 text-left shadow-borders-base outline-none transition-fg",
|
|
1431
|
+
"hover:bg-ui-bg-field-hover focus-visible:shadow-borders-interactive-with-active md:w-auto",
|
|
1432
|
+
isAll ? "text-ui-fg-muted" : "text-ui-fg-base"
|
|
1433
|
+
),
|
|
1434
|
+
children: [
|
|
1435
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: triggerLabel(entity, category) }),
|
|
1436
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDownMini, { className: "shrink-0 text-ui-fg-muted" })
|
|
1437
|
+
]
|
|
1438
|
+
}
|
|
1439
|
+
) }),
|
|
1440
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1441
|
+
ui.Popover.Content,
|
|
1442
|
+
{
|
|
1443
|
+
align: "start",
|
|
1444
|
+
className: "w-[min(360px,calc(100vw-2rem))] p-0",
|
|
1445
|
+
onOpenAutoFocus: (event) => {
|
|
1446
|
+
var _a2;
|
|
1447
|
+
event.preventDefault();
|
|
1448
|
+
(_a2 = searchRef.current) == null ? void 0 : _a2.focus();
|
|
1449
|
+
},
|
|
1450
|
+
children: [
|
|
1451
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-ui-border-base p-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1452
|
+
ui.Input,
|
|
1453
|
+
{
|
|
1454
|
+
ref: searchRef,
|
|
1455
|
+
size: "small",
|
|
1456
|
+
type: "search",
|
|
1457
|
+
placeholder: "Search entities, e.g. order, wallet…",
|
|
1458
|
+
value: search,
|
|
1459
|
+
onChange: (e) => setSearch(e.target.value),
|
|
1460
|
+
onKeyDown: (e) => {
|
|
1461
|
+
if (e.key === "Enter" && firstMatch) {
|
|
1462
|
+
e.preventDefault();
|
|
1463
|
+
select({ entity: firstMatch.tableName, category: "" });
|
|
1464
|
+
}
|
|
1465
|
+
},
|
|
1466
|
+
"aria-label": "Search entities"
|
|
1467
|
+
}
|
|
1468
|
+
) }),
|
|
1469
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-h-[360px] overflow-y-auto p-1", role: "listbox", "aria-label": "Entities", children: [
|
|
1470
|
+
!search.trim() ? /* @__PURE__ */ jsxRuntime.jsx(PickerOption, { selected: isAll, onSelect: () => select({ entity: "", category: "" }), children: "All entities" }) : null,
|
|
1471
|
+
filteredGroups.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "px-3 py-6 text-center text-ui-fg-muted", children: [
|
|
1472
|
+
"No entities match “",
|
|
1473
|
+
search.trim(),
|
|
1474
|
+
"”"
|
|
1475
|
+
] }) : null,
|
|
1476
|
+
filteredGroups.map((group) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1", children: [
|
|
1477
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 pb-1 pt-2 text-xs font-medium uppercase tracking-wide text-ui-fg-muted", children: group.category.label }),
|
|
1478
|
+
!search.trim() ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1479
|
+
PickerOption,
|
|
1480
|
+
{
|
|
1481
|
+
selected: !entity && category === group.category.id,
|
|
1482
|
+
onSelect: () => select({ entity: "", category: group.category.id }),
|
|
1483
|
+
secondary: group.category.description,
|
|
1484
|
+
children: [
|
|
1485
|
+
"All ",
|
|
1486
|
+
group.category.label
|
|
1487
|
+
]
|
|
1488
|
+
}
|
|
1489
|
+
) : null,
|
|
1490
|
+
group.entities.map((info) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1491
|
+
PickerOption,
|
|
1492
|
+
{
|
|
1493
|
+
selected: entity === info.tableName,
|
|
1494
|
+
onSelect: () => select({ entity: info.tableName, category: "" }),
|
|
1495
|
+
secondary: info.tableName,
|
|
1496
|
+
secondaryMono: true,
|
|
1497
|
+
indent: !search.trim(),
|
|
1498
|
+
children: info.label
|
|
1499
|
+
},
|
|
1500
|
+
info.tableName
|
|
1501
|
+
))
|
|
1502
|
+
] }, group.category.id))
|
|
1503
|
+
] })
|
|
1504
|
+
]
|
|
1505
|
+
}
|
|
1506
|
+
)
|
|
1507
|
+
]
|
|
1508
|
+
}
|
|
1509
|
+
);
|
|
1510
|
+
};
|
|
1511
|
+
const PickerOption = ({ selected, onSelect, children, secondary, secondaryMono, indent }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1512
|
+
"button",
|
|
1513
|
+
{
|
|
1514
|
+
type: "button",
|
|
1515
|
+
role: "option",
|
|
1516
|
+
"aria-selected": selected,
|
|
1517
|
+
onClick: onSelect,
|
|
1518
|
+
className: ui.clx(
|
|
1519
|
+
"flex w-full items-start gap-2 rounded-md px-2 py-1.5 text-left outline-none transition-fg",
|
|
1520
|
+
"hover:bg-ui-bg-base-hover focus-visible:bg-ui-bg-base-hover",
|
|
1521
|
+
indent && "pl-4"
|
|
1522
|
+
),
|
|
1523
|
+
children: [
|
|
1524
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-0.5 flex size-4 shrink-0 items-center justify-center text-ui-fg-interactive", children: selected ? /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}) : null }),
|
|
1525
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-col", children: [
|
|
1526
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm text-ui-fg-base", children }),
|
|
1527
|
+
secondary ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: ui.clx("truncate text-xs text-ui-fg-muted", secondaryMono && "font-mono"), children: secondary }) : null
|
|
1528
|
+
] })
|
|
1529
|
+
]
|
|
1530
|
+
}
|
|
1531
|
+
);
|
|
1532
|
+
const CopyableId = ({ value, emptyLabel = "No ID", className }) => {
|
|
1533
|
+
if (!value) {
|
|
1534
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "italic text-ui-fg-muted", children: emptyLabel });
|
|
1535
|
+
}
|
|
1536
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: ui.clx("inline-flex min-w-0 max-w-full items-center gap-1", className), children: [
|
|
1537
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-mono text-xs text-ui-fg-base", title: value, children: value }),
|
|
1538
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { onClick: (e) => e.stopPropagation(), className: "inline-flex shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Copy, { content: value, variant: "mini", className: "text-ui-fg-muted", "aria-label": `Copy ${value}` }) })
|
|
1539
|
+
] });
|
|
1540
|
+
};
|
|
1541
|
+
const RELATIVE_UNITS = [
|
|
1542
|
+
{ unit: "year", seconds: 60 * 60 * 24 * 365 },
|
|
1543
|
+
{ unit: "month", seconds: 60 * 60 * 24 * 30 },
|
|
1544
|
+
{ unit: "week", seconds: 60 * 60 * 24 * 7 },
|
|
1545
|
+
{ unit: "day", seconds: 60 * 60 * 24 },
|
|
1546
|
+
{ unit: "hour", seconds: 60 * 60 },
|
|
1547
|
+
{ unit: "minute", seconds: 60 }
|
|
1548
|
+
];
|
|
1549
|
+
function toDate(value) {
|
|
1550
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
1551
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
1552
|
+
}
|
|
1553
|
+
function formatRelativeTime(value, now = /* @__PURE__ */ new Date()) {
|
|
1554
|
+
const date = toDate(value);
|
|
1555
|
+
if (!date) return "—";
|
|
1556
|
+
const diffSeconds = Math.round((date.getTime() - now.getTime()) / 1e3);
|
|
1557
|
+
if (Math.abs(diffSeconds) < 45) return "just now";
|
|
1558
|
+
const rtf = new Intl.RelativeTimeFormat(void 0, { numeric: "auto" });
|
|
1559
|
+
for (const { unit, seconds } of RELATIVE_UNITS) {
|
|
1560
|
+
if (Math.abs(diffSeconds) >= seconds) {
|
|
1561
|
+
return rtf.format(Math.round(diffSeconds / seconds), unit);
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
return rtf.format(Math.round(diffSeconds / 60), "minute");
|
|
1565
|
+
}
|
|
1566
|
+
function formatExactDateTime(value) {
|
|
1567
|
+
const date = toDate(value);
|
|
1568
|
+
if (!date) return "—";
|
|
1569
|
+
return new Intl.DateTimeFormat(void 0, {
|
|
1570
|
+
day: "2-digit",
|
|
1571
|
+
month: "short",
|
|
1572
|
+
year: "numeric",
|
|
1573
|
+
hour: "2-digit",
|
|
1574
|
+
minute: "2-digit",
|
|
1575
|
+
second: "2-digit",
|
|
1576
|
+
timeZoneName: "short"
|
|
1577
|
+
}).format(date);
|
|
1578
|
+
}
|
|
1579
|
+
function formatDate(value) {
|
|
1580
|
+
const date = toDate(value);
|
|
1581
|
+
if (!date) return "—";
|
|
1582
|
+
return new Intl.DateTimeFormat(void 0, { day: "2-digit", month: "short", year: "numeric" }).format(date);
|
|
1583
|
+
}
|
|
1584
|
+
function formatNumber(value) {
|
|
1585
|
+
return new Intl.NumberFormat().format(value);
|
|
1586
|
+
}
|
|
1587
|
+
function formatMoney(amount, currencyCode) {
|
|
1588
|
+
const code = currencyCode == null ? void 0 : currencyCode.trim().toUpperCase();
|
|
1589
|
+
if (code && /^[A-Z]{3}$/.test(code)) {
|
|
1590
|
+
try {
|
|
1591
|
+
return new Intl.NumberFormat(void 0, { style: "currency", currency: code }).format(amount);
|
|
1592
|
+
} catch {
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
return code ? `${code} ${formatNumber(amount)}` : formatNumber(amount);
|
|
1596
|
+
}
|
|
1597
|
+
const SOURCE_ALIASES = {
|
|
1598
|
+
admin: { kind: "admin", label: "Admin Panel" },
|
|
1599
|
+
admin_panel: { kind: "admin", label: "Admin Panel" },
|
|
1600
|
+
dashboard: { kind: "admin", label: "Admin Panel" },
|
|
1601
|
+
api: { kind: "api", label: "API" },
|
|
1602
|
+
store_api: { kind: "api", label: "Storefront API" },
|
|
1603
|
+
admin_api: { kind: "api", label: "Admin API" },
|
|
1604
|
+
system: { kind: "system", label: "System" },
|
|
1605
|
+
job: { kind: "job", label: "Background Job" },
|
|
1606
|
+
background_job: { kind: "job", label: "Background Job" },
|
|
1607
|
+
scheduled_job: { kind: "job", label: "Background Job" },
|
|
1608
|
+
cron: { kind: "job", label: "Background Job" },
|
|
1609
|
+
workflow: { kind: "workflow", label: "Workflow" },
|
|
1610
|
+
migration: { kind: "system", label: "Migration" }
|
|
1611
|
+
};
|
|
1612
|
+
function describeSource(source) {
|
|
1613
|
+
if (!source || !source.trim()) return { kind: "unknown", label: "Unknown" };
|
|
1614
|
+
const key = source.trim().toLowerCase().replace(/[\s-]+/g, "_");
|
|
1615
|
+
return SOURCE_ALIASES[key] ?? { kind: "other", label: source.trim() };
|
|
1616
|
+
}
|
|
1617
|
+
function sourceBadgeColor(kind) {
|
|
1618
|
+
switch (kind) {
|
|
1619
|
+
case "admin":
|
|
1620
|
+
return "blue";
|
|
1621
|
+
case "api":
|
|
1622
|
+
return "purple";
|
|
1623
|
+
case "job":
|
|
1624
|
+
case "workflow":
|
|
1625
|
+
return "orange";
|
|
1626
|
+
case "system":
|
|
1627
|
+
return "green";
|
|
1628
|
+
default:
|
|
1629
|
+
return "grey";
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
const CARDS = [
|
|
1633
|
+
{ key: "total", label: "Total deleted", hint: "All records captured since auditing began" },
|
|
1634
|
+
{ key: "today", label: "Today", hint: "Deleted since midnight (your time)" },
|
|
1635
|
+
{ key: "last_7_days", label: "Last 7 days", hint: "Including today" },
|
|
1636
|
+
{ key: "tables_affected", label: "Entity types affected", hint: "Distinct kinds of records deleted" }
|
|
1637
|
+
];
|
|
1638
|
+
const SummaryCards = ({ stats, loading, failed }) => {
|
|
1639
|
+
if (failed && !stats) return null;
|
|
1640
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-3 lg:grid-cols-4", children: CARDS.map((card) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1641
|
+
"div",
|
|
1642
|
+
{
|
|
1643
|
+
className: "flex flex-col gap-1 rounded-lg border border-ui-border-base bg-ui-bg-subtle px-4 py-3",
|
|
1644
|
+
title: card.hint,
|
|
1645
|
+
children: [
|
|
1646
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: card.label }),
|
|
1647
|
+
loading || !stats ? /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-7 w-16" }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-2xl font-semibold leading-8 text-ui-fg-base", children: formatNumber(stats[card.key]) })
|
|
1648
|
+
]
|
|
1649
|
+
},
|
|
1650
|
+
card.key
|
|
1651
|
+
)) });
|
|
1652
|
+
};
|
|
1653
|
+
const BASE = "/admin/deleted-records-audit";
|
|
1654
|
+
class AuditApiError extends Error {
|
|
1655
|
+
constructor(message, status) {
|
|
1656
|
+
super(message);
|
|
1657
|
+
__publicField(this, "status");
|
|
1658
|
+
this.status = status;
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
async function getJson(url, signal) {
|
|
1662
|
+
const response = await fetch(url, { credentials: "include", signal });
|
|
1663
|
+
if (!response.ok) {
|
|
1664
|
+
let message = response.statusText || "Request failed";
|
|
1665
|
+
try {
|
|
1666
|
+
const body = await response.json();
|
|
1667
|
+
if (body && typeof body === "object" && "message" in body && typeof body.message === "string") {
|
|
1668
|
+
message = body.message;
|
|
1669
|
+
}
|
|
1670
|
+
} catch {
|
|
1671
|
+
}
|
|
1672
|
+
throw new AuditApiError(message, response.status);
|
|
1673
|
+
}
|
|
1674
|
+
return await response.json();
|
|
1675
|
+
}
|
|
1676
|
+
function fetchAuditList(params, signal) {
|
|
1677
|
+
return getJson(`${BASE}?${params.toString()}`, signal);
|
|
1678
|
+
}
|
|
1679
|
+
async function fetchAuditStats(signal) {
|
|
1680
|
+
const todayStart = /* @__PURE__ */ new Date();
|
|
1681
|
+
todayStart.setHours(0, 0, 0, 0);
|
|
1682
|
+
const params = new URLSearchParams({ today_start: todayStart.toISOString() });
|
|
1683
|
+
const body = await getJson(`${BASE}/stats?${params.toString()}`, signal);
|
|
1684
|
+
return body.stats;
|
|
1685
|
+
}
|
|
1686
|
+
async function fetchAuditDetail(id, signal) {
|
|
1687
|
+
const body = await getJson(`${BASE}/${encodeURIComponent(id)}`, signal);
|
|
1688
|
+
return body.audit;
|
|
1689
|
+
}
|
|
1690
|
+
const LAST_LIST_URL_KEY = "om.deleted-records-audit.last-list-search";
|
|
1691
|
+
const DATE_PRESETS = [
|
|
1692
|
+
{ value: "any", label: "Any time" },
|
|
1693
|
+
{ value: "today", label: "Today" },
|
|
1694
|
+
{ value: "yesterday", label: "Yesterday" },
|
|
1695
|
+
{ value: "7d", label: "Last 7 days" },
|
|
1696
|
+
{ value: "30d", label: "Last 30 days" },
|
|
1697
|
+
{ value: "custom", label: "Custom range" }
|
|
1698
|
+
];
|
|
1699
|
+
const EMPTY_FILTERS = {
|
|
1700
|
+
q: "",
|
|
1701
|
+
entity: "",
|
|
1702
|
+
category: "",
|
|
1703
|
+
date: "any",
|
|
1704
|
+
from: "",
|
|
1705
|
+
to: "",
|
|
1706
|
+
source: "",
|
|
1707
|
+
deletedBy: ""
|
|
1708
|
+
};
|
|
1709
|
+
const URL_KEYS = {
|
|
1710
|
+
q: "q",
|
|
1711
|
+
entity: "entity",
|
|
1712
|
+
category: "category",
|
|
1713
|
+
date: "date",
|
|
1714
|
+
from: "from",
|
|
1715
|
+
to: "to",
|
|
1716
|
+
source: "source",
|
|
1717
|
+
deletedBy: "deleted_by"
|
|
1718
|
+
};
|
|
1719
|
+
const DATE_PRESET_VALUES = new Set(DATE_PRESETS.map((p) => p.value));
|
|
1720
|
+
const DAY_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
1721
|
+
function filtersFromSearchParams(params) {
|
|
1722
|
+
const read = (key) => {
|
|
1723
|
+
var _a;
|
|
1724
|
+
return ((_a = params.get(URL_KEYS[key])) == null ? void 0 : _a.trim()) ?? "";
|
|
1725
|
+
};
|
|
1726
|
+
const date = read("date");
|
|
1727
|
+
const from = read("from");
|
|
1728
|
+
const to = read("to");
|
|
1729
|
+
return {
|
|
1730
|
+
q: read("q"),
|
|
1731
|
+
entity: read("entity"),
|
|
1732
|
+
category: read("category"),
|
|
1733
|
+
date: DATE_PRESET_VALUES.has(date) ? date : "any",
|
|
1734
|
+
from: DAY_PATTERN.test(from) ? from : "",
|
|
1735
|
+
to: DAY_PATTERN.test(to) ? to : "",
|
|
1736
|
+
source: read("source"),
|
|
1737
|
+
deletedBy: read("deletedBy")
|
|
1738
|
+
};
|
|
1739
|
+
}
|
|
1740
|
+
function filtersToSearchParams(filters) {
|
|
1741
|
+
const params = new URLSearchParams();
|
|
1742
|
+
for (const key of Object.keys(URL_KEYS)) {
|
|
1743
|
+
const value = filters[key];
|
|
1744
|
+
if (!value || value === EMPTY_FILTERS[key]) continue;
|
|
1745
|
+
if ((key === "from" || key === "to") && filters.date !== "custom") continue;
|
|
1746
|
+
params.set(URL_KEYS[key], value);
|
|
1747
|
+
}
|
|
1748
|
+
return params;
|
|
1749
|
+
}
|
|
1750
|
+
function hasActiveFilters(filters) {
|
|
1751
|
+
return filtersToSearchParams(filters).toString() !== "";
|
|
1752
|
+
}
|
|
1753
|
+
function startOfDay(date) {
|
|
1754
|
+
const d = new Date(date);
|
|
1755
|
+
d.setHours(0, 0, 0, 0);
|
|
1756
|
+
return d;
|
|
1757
|
+
}
|
|
1758
|
+
function endOfDay(date) {
|
|
1759
|
+
const d = new Date(date);
|
|
1760
|
+
d.setHours(23, 59, 59, 999);
|
|
1761
|
+
return d;
|
|
1762
|
+
}
|
|
1763
|
+
function parseDay(day) {
|
|
1764
|
+
if (!DAY_PATTERN.test(day)) return null;
|
|
1765
|
+
const [y, m, d] = day.split("-").map(Number);
|
|
1766
|
+
const date = new Date(y, m - 1, d);
|
|
1767
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
1768
|
+
}
|
|
1769
|
+
function resolveDateRange(filters, now = /* @__PURE__ */ new Date()) {
|
|
1770
|
+
const today = startOfDay(now);
|
|
1771
|
+
switch (filters.date) {
|
|
1772
|
+
case "today":
|
|
1773
|
+
return { from: today };
|
|
1774
|
+
case "yesterday": {
|
|
1775
|
+
const y = new Date(today);
|
|
1776
|
+
y.setDate(y.getDate() - 1);
|
|
1777
|
+
return { from: y, to: endOfDay(y) };
|
|
1778
|
+
}
|
|
1779
|
+
case "7d": {
|
|
1780
|
+
const from = new Date(today);
|
|
1781
|
+
from.setDate(from.getDate() - 6);
|
|
1782
|
+
return { from };
|
|
1783
|
+
}
|
|
1784
|
+
case "30d": {
|
|
1785
|
+
const from = new Date(today);
|
|
1786
|
+
from.setDate(from.getDate() - 29);
|
|
1787
|
+
return { from };
|
|
1788
|
+
}
|
|
1789
|
+
case "custom": {
|
|
1790
|
+
const from = parseDay(filters.from);
|
|
1791
|
+
const to = parseDay(filters.to);
|
|
1792
|
+
return { from: from ?? void 0, to: to ? endOfDay(to) : void 0 };
|
|
1793
|
+
}
|
|
1794
|
+
default:
|
|
1795
|
+
return {};
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
function filtersToApiParams(filters, page, now = /* @__PURE__ */ new Date()) {
|
|
1799
|
+
const params = new URLSearchParams();
|
|
1800
|
+
params.set("limit", String(page.limit));
|
|
1801
|
+
params.set("offset", String(page.offset));
|
|
1802
|
+
if (filters.q) params.set("q", filters.q);
|
|
1803
|
+
if (filters.entity) {
|
|
1804
|
+
params.set("table_name", filters.entity);
|
|
1805
|
+
} else if (filters.category) {
|
|
1806
|
+
const tables = getTablesForCategory(filters.category);
|
|
1807
|
+
if (tables.length) params.set("table_names", tables.join(","));
|
|
1808
|
+
}
|
|
1809
|
+
const range = resolveDateRange(filters, now);
|
|
1810
|
+
if (range.from) params.set("date_from", range.from.toISOString());
|
|
1811
|
+
if (range.to) params.set("date_to", range.to.toISOString());
|
|
1812
|
+
if (filters.source) params.set("source", filters.source);
|
|
1813
|
+
if (filters.deletedBy) params.set("deleted_by", filters.deletedBy);
|
|
1814
|
+
return params;
|
|
1815
|
+
}
|
|
1816
|
+
const PAGE_SIZE = 50;
|
|
1817
|
+
const RESTORE_PAGE_SIZE = 100;
|
|
1818
|
+
const MAX_RESTORE_ROWS = 500;
|
|
1819
|
+
const ALL = "__all__";
|
|
1820
|
+
const UNKNOWN_SOURCE = "unknown";
|
|
1821
|
+
const LOADED_COUNT_KEY_PREFIX = "om.deleted-records-audit.loaded:";
|
|
1822
|
+
const LAST_VIEWED_KEY = "om.deleted-records-audit.last-viewed";
|
|
1823
|
+
function readSession(key) {
|
|
1824
|
+
try {
|
|
1825
|
+
return window.sessionStorage.getItem(key);
|
|
1826
|
+
} catch {
|
|
1827
|
+
return null;
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
function writeSession(key, value) {
|
|
1831
|
+
try {
|
|
1832
|
+
window.sessionStorage.setItem(key, value);
|
|
1833
|
+
} catch {
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
const DeletedRecordsPage = () => {
|
|
1837
|
+
const navigate = reactRouterDom.useNavigate();
|
|
1838
|
+
const location = reactRouterDom.useLocation();
|
|
1839
|
+
const [searchParams, setSearchParams] = reactRouterDom.useSearchParams();
|
|
1840
|
+
const filters = react.useMemo(() => filtersFromSearchParams(searchParams), [searchParams]);
|
|
1841
|
+
const filterKey = filtersToSearchParams(filters).toString();
|
|
1842
|
+
const filtersActive = hasActiveFilters(filters);
|
|
1843
|
+
const [searchText, setSearchText] = react.useState(filters.q);
|
|
1844
|
+
const [items, setItems] = react.useState([]);
|
|
1845
|
+
const [count, setCount] = react.useState(0);
|
|
1846
|
+
const [isLoading, setIsLoading] = react.useState(true);
|
|
1847
|
+
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
1848
|
+
const [error, setError] = react.useState(null);
|
|
1849
|
+
const [stats, setStats] = react.useState(null);
|
|
1850
|
+
const [statsLoading, setStatsLoading] = react.useState(true);
|
|
1851
|
+
const [statsFailed, setStatsFailed] = react.useState(false);
|
|
1852
|
+
const [reloadToken, setReloadToken] = react.useState(0);
|
|
1853
|
+
const [highlightId, setHighlightId] = react.useState(null);
|
|
1854
|
+
const restoredScrollRef = react.useRef(false);
|
|
1855
|
+
const updateFilters = react.useCallback(
|
|
1856
|
+
(patch) => {
|
|
1857
|
+
const next = { ...filters, ...patch };
|
|
1858
|
+
setSearchParams(filtersToSearchParams(next), { replace: true });
|
|
1859
|
+
},
|
|
1860
|
+
[filters, setSearchParams]
|
|
1861
|
+
);
|
|
1862
|
+
react.useEffect(() => {
|
|
1863
|
+
if (searchText.trim() === filters.q) return;
|
|
1864
|
+
const handle = setTimeout(() => updateFilters({ q: searchText.trim() }), 300);
|
|
1865
|
+
return () => clearTimeout(handle);
|
|
1866
|
+
}, [searchText, filters.q, updateFilters]);
|
|
1867
|
+
react.useEffect(() => {
|
|
1868
|
+
setSearchText((current) => current.trim() === filters.q ? current : filters.q);
|
|
1869
|
+
}, [filters.q]);
|
|
1870
|
+
react.useEffect(() => {
|
|
1871
|
+
writeSession(LAST_LIST_URL_KEY, location.search);
|
|
1872
|
+
}, [location.search]);
|
|
1873
|
+
const loadStats = react.useCallback(async (signal) => {
|
|
1874
|
+
setStatsLoading(true);
|
|
1875
|
+
setStatsFailed(false);
|
|
1876
|
+
try {
|
|
1877
|
+
setStats(await fetchAuditStats(signal));
|
|
1878
|
+
} catch (e) {
|
|
1879
|
+
if (!(signal == null ? void 0 : signal.aborted)) setStatsFailed(true);
|
|
1880
|
+
} finally {
|
|
1881
|
+
if (!(signal == null ? void 0 : signal.aborted)) setStatsLoading(false);
|
|
1882
|
+
}
|
|
1883
|
+
}, []);
|
|
1884
|
+
react.useEffect(() => {
|
|
1885
|
+
const controller = new AbortController();
|
|
1886
|
+
void loadStats(controller.signal);
|
|
1887
|
+
return () => controller.abort();
|
|
1888
|
+
}, [loadStats, reloadToken]);
|
|
1889
|
+
react.useEffect(() => {
|
|
1890
|
+
const controller = new AbortController();
|
|
1891
|
+
const restoreTarget = Math.min(
|
|
1892
|
+
MAX_RESTORE_ROWS,
|
|
1893
|
+
Math.max(PAGE_SIZE, Number(readSession(LOADED_COUNT_KEY_PREFIX + filterKey)) || 0)
|
|
1894
|
+
);
|
|
1895
|
+
setIsLoading(true);
|
|
1896
|
+
setError(null);
|
|
1897
|
+
(async () => {
|
|
1898
|
+
try {
|
|
1899
|
+
const collected = [];
|
|
1900
|
+
let total = 0;
|
|
1901
|
+
while (collected.length < restoreTarget) {
|
|
1902
|
+
const limit = restoreTarget > PAGE_SIZE ? RESTORE_PAGE_SIZE : PAGE_SIZE;
|
|
1903
|
+
const page = await fetchAuditList(
|
|
1904
|
+
filtersToApiParams(filters, { limit, offset: collected.length }),
|
|
1905
|
+
controller.signal
|
|
1906
|
+
);
|
|
1907
|
+
total = page.count;
|
|
1908
|
+
collected.push(...page.audits);
|
|
1909
|
+
if (page.audits.length < limit || collected.length >= total) break;
|
|
1910
|
+
}
|
|
1911
|
+
if (controller.signal.aborted) return;
|
|
1912
|
+
setItems(collected.slice(0, restoreTarget));
|
|
1913
|
+
setCount(total);
|
|
1914
|
+
} catch (e) {
|
|
1915
|
+
if (controller.signal.aborted) return;
|
|
1916
|
+
setItems([]);
|
|
1917
|
+
setCount(0);
|
|
1918
|
+
setError(e instanceof Error ? e.message : "Unknown error");
|
|
1919
|
+
} finally {
|
|
1920
|
+
if (!controller.signal.aborted) setIsLoading(false);
|
|
1921
|
+
}
|
|
1922
|
+
})();
|
|
1923
|
+
return () => controller.abort();
|
|
1924
|
+
}, [filterKey, reloadToken]);
|
|
1925
|
+
react.useEffect(() => {
|
|
1926
|
+
if (!isLoading) writeSession(LOADED_COUNT_KEY_PREFIX + filterKey, String(items.length));
|
|
1927
|
+
}, [items.length, isLoading, filterKey]);
|
|
1928
|
+
react.useEffect(() => {
|
|
1929
|
+
if (isLoading || restoredScrollRef.current) return;
|
|
1930
|
+
restoredScrollRef.current = true;
|
|
1931
|
+
const lastViewed = readSession(LAST_VIEWED_KEY);
|
|
1932
|
+
if (!lastViewed || !items.some((item) => item.id === lastViewed)) return;
|
|
1933
|
+
setHighlightId(lastViewed);
|
|
1934
|
+
requestAnimationFrame(() => {
|
|
1935
|
+
const visible = Array.from(document.querySelectorAll(`[data-audit-row="${lastViewed}"]`)).find(
|
|
1936
|
+
(el) => el.offsetParent !== null
|
|
1937
|
+
);
|
|
1938
|
+
visible == null ? void 0 : visible.scrollIntoView({ block: "center" });
|
|
1939
|
+
});
|
|
1940
|
+
const handle = setTimeout(() => setHighlightId(null), 2500);
|
|
1941
|
+
return () => clearTimeout(handle);
|
|
1942
|
+
}, [isLoading, items]);
|
|
1943
|
+
const loadMore = async () => {
|
|
1944
|
+
setIsFetchingMore(true);
|
|
1945
|
+
try {
|
|
1946
|
+
const page = await fetchAuditList(filtersToApiParams(filters, { limit: PAGE_SIZE, offset: items.length }));
|
|
1947
|
+
setItems((prev) => [...prev, ...page.audits]);
|
|
1948
|
+
setCount(page.count);
|
|
1949
|
+
} catch (e) {
|
|
1950
|
+
setError(e instanceof Error ? e.message : "Unknown error");
|
|
1951
|
+
} finally {
|
|
1952
|
+
setIsFetchingMore(false);
|
|
1953
|
+
}
|
|
1954
|
+
};
|
|
1955
|
+
const openDetail = (id) => {
|
|
1956
|
+
writeSession(LAST_VIEWED_KEY, id);
|
|
1957
|
+
navigate(`/deleted-records-audit/${id}`, { state: { fromList: true } });
|
|
1958
|
+
};
|
|
1959
|
+
const clearFilters = () => {
|
|
1960
|
+
setSearchText("");
|
|
1961
|
+
setSearchParams(filtersToSearchParams(EMPTY_FILTERS), { replace: true });
|
|
1962
|
+
};
|
|
1963
|
+
const refresh = () => setReloadToken((t) => t + 1);
|
|
1964
|
+
const hasMore = items.length < count;
|
|
1965
|
+
const knownSources = (stats == null ? void 0 : stats.sources) ?? [];
|
|
1966
|
+
const knownDeletedBy = (stats == null ? void 0 : stats.deleted_by) ?? [];
|
|
1967
|
+
const attributionMissing = !!stats && stats.total > 0 && knownSources.length === 0 && knownDeletedBy.length === 0;
|
|
1968
|
+
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: [
|
|
1969
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-start md:justify-between", children: [
|
|
1970
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1971
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Deleted Records" }),
|
|
1972
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Review records that were permanently deleted from the system." })
|
|
1973
|
+
] }),
|
|
1974
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: "secondary", size: "small", onClick: refresh, isLoading: isLoading && items.length > 0, children: [
|
|
1975
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowPath, {}),
|
|
1976
|
+
"Refresh"
|
|
1977
|
+
] })
|
|
1978
|
+
] }),
|
|
1979
|
+
/* @__PURE__ */ jsxRuntime.jsx(SummaryCards, { stats, loading: statsLoading, failed: statsFailed }),
|
|
1980
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "flex flex-col gap-3", "aria-label": "Search and filters", children: [
|
|
1981
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1982
|
+
ui.Input,
|
|
1983
|
+
{
|
|
1984
|
+
type: "search",
|
|
1985
|
+
size: "base",
|
|
1986
|
+
placeholder: "Search by record ID, e.g. order_01J…, prod_…, cus_…",
|
|
1987
|
+
value: searchText,
|
|
1988
|
+
onChange: (e) => setSearchText(e.target.value),
|
|
1989
|
+
"aria-label": "Search by record ID",
|
|
1990
|
+
className: "w-full"
|
|
1991
|
+
}
|
|
1992
|
+
),
|
|
1993
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 md:flex-row md:flex-wrap md:items-center", children: [
|
|
1994
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1995
|
+
EntityPicker,
|
|
1996
|
+
{
|
|
1997
|
+
entity: filters.entity,
|
|
1998
|
+
category: filters.category,
|
|
1999
|
+
onChange: (next) => updateFilters(next)
|
|
2000
|
+
}
|
|
2001
|
+
),
|
|
2002
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "md:w-[160px]", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2003
|
+
ui.Select,
|
|
2004
|
+
{
|
|
2005
|
+
size: "small",
|
|
2006
|
+
value: filters.date,
|
|
2007
|
+
onValueChange: (value) => updateFilters({ date: value }),
|
|
2008
|
+
children: [
|
|
2009
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { "aria-label": "Filter by date", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, {}) }),
|
|
2010
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: DATE_PRESETS.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: preset.value, children: preset.label }, preset.value)) })
|
|
2011
|
+
]
|
|
2012
|
+
}
|
|
2013
|
+
) }),
|
|
2014
|
+
filters.date === "custom" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2015
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2016
|
+
ui.Input,
|
|
2017
|
+
{
|
|
2018
|
+
type: "date",
|
|
2019
|
+
size: "small",
|
|
2020
|
+
value: filters.from,
|
|
2021
|
+
max: filters.to || void 0,
|
|
2022
|
+
onChange: (e) => updateFilters({ from: e.target.value }),
|
|
2023
|
+
"aria-label": "From date"
|
|
2024
|
+
}
|
|
2025
|
+
),
|
|
2026
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "to" }),
|
|
2027
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2028
|
+
ui.Input,
|
|
2029
|
+
{
|
|
2030
|
+
type: "date",
|
|
2031
|
+
size: "small",
|
|
2032
|
+
value: filters.to,
|
|
2033
|
+
min: filters.from || void 0,
|
|
2034
|
+
onChange: (e) => updateFilters({ to: e.target.value }),
|
|
2035
|
+
"aria-label": "To date"
|
|
2036
|
+
}
|
|
2037
|
+
)
|
|
2038
|
+
] }) : null,
|
|
2039
|
+
knownSources.length > 0 || filters.source ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "md:w-[170px]", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2040
|
+
ui.Select,
|
|
2041
|
+
{
|
|
2042
|
+
size: "small",
|
|
2043
|
+
value: filters.source || ALL,
|
|
2044
|
+
onValueChange: (value) => updateFilters({ source: value === ALL ? "" : value }),
|
|
2045
|
+
children: [
|
|
2046
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { "aria-label": "Filter by source", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, {}) }),
|
|
2047
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Select.Content, { children: [
|
|
2048
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: ALL, children: "All sources" }),
|
|
2049
|
+
knownSources.map((source) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: source, children: describeSource(source).label }, source)),
|
|
2050
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: UNKNOWN_SOURCE, children: "Unknown" })
|
|
2051
|
+
] })
|
|
2052
|
+
]
|
|
2053
|
+
}
|
|
2054
|
+
) }) : null,
|
|
2055
|
+
knownDeletedBy.length > 0 || filters.deletedBy ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md:w-[200px]", children: [
|
|
2056
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2057
|
+
ui.Input,
|
|
2058
|
+
{
|
|
2059
|
+
size: "small",
|
|
2060
|
+
list: "deleted-records-audit-deleted-by",
|
|
2061
|
+
placeholder: "Deleted by (all users)",
|
|
2062
|
+
defaultValue: filters.deletedBy,
|
|
2063
|
+
onBlur: (e) => updateFilters({ deletedBy: e.target.value.trim() }),
|
|
2064
|
+
onKeyDown: (e) => {
|
|
2065
|
+
if (e.key === "Enter") updateFilters({ deletedBy: e.currentTarget.value.trim() });
|
|
2066
|
+
},
|
|
2067
|
+
"aria-label": "Filter by who deleted the record"
|
|
2068
|
+
},
|
|
2069
|
+
filters.deletedBy
|
|
2070
|
+
),
|
|
2071
|
+
/* @__PURE__ */ jsxRuntime.jsx("datalist", { id: "deleted-records-audit-deleted-by", children: knownDeletedBy.map((value) => /* @__PURE__ */ jsxRuntime.jsx("option", { value }, value)) })
|
|
2072
|
+
] }) : null,
|
|
2073
|
+
filtersActive ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: clearFilters, children: "Clear filters" }) : null
|
|
2074
|
+
] })
|
|
2075
|
+
] }),
|
|
2076
|
+
attributionMissing ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 rounded-lg border border-ui-border-base bg-ui-bg-subtle px-3 py-2", children: [
|
|
2077
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.InformationCircle, { className: "mt-0.5 shrink-0 text-ui-fg-muted" }),
|
|
2078
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Who deleted a record and where the deletion came from are not being recorded yet, so those columns show “Unknown”. Every deleted record is still captured in full." })
|
|
2079
|
+
] }) : null,
|
|
2080
|
+
!isLoading && !error && items.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", "aria-live": "polite", children: [
|
|
2081
|
+
"Showing ",
|
|
2082
|
+
formatNumber(items.length),
|
|
2083
|
+
" of ",
|
|
2084
|
+
formatNumber(count),
|
|
2085
|
+
" ",
|
|
2086
|
+
count === 1 ? "record" : "records",
|
|
2087
|
+
filtersActive ? " matching your filters" : ""
|
|
2088
|
+
] }) : null,
|
|
2089
|
+
error ? /* @__PURE__ */ jsxRuntime.jsx(ErrorState, { onRetry: refresh, detail: error }) : isLoading ? /* @__PURE__ */ jsxRuntime.jsx(ListSkeleton, {}) : items.length === 0 ? filtersActive ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2090
|
+
EmptyState,
|
|
2091
|
+
{
|
|
2092
|
+
title: "No deleted records found",
|
|
2093
|
+
body: "There are no audit records matching your current filters.",
|
|
2094
|
+
action: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", size: "small", onClick: clearFilters, children: "Clear filters" })
|
|
2095
|
+
}
|
|
2096
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2097
|
+
EmptyState,
|
|
2098
|
+
{
|
|
2099
|
+
title: "No deleted records yet",
|
|
2100
|
+
body: "Hard-deleted records will appear here automatically when a monitored database record is permanently deleted."
|
|
2101
|
+
}
|
|
2102
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2103
|
+
/* @__PURE__ */ jsxRuntime.jsx(AuditTable, { items, highlightId, onOpen: openDetail }),
|
|
2104
|
+
/* @__PURE__ */ jsxRuntime.jsx(AuditCards, { items, highlightId, onOpen: openDetail })
|
|
2105
|
+
] }),
|
|
2106
|
+
!error && !isLoading && hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", isLoading: isFetchingMore, onClick: loadMore, children: "Load more" }) }) : null
|
|
2107
|
+
] }) });
|
|
2108
|
+
};
|
|
2109
|
+
const HEADER_CELL = "px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted";
|
|
2110
|
+
const DeletedWhen = ({ occurredAt }) => /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { content: formatExactDateTime(occurredAt), children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cursor-default text-sm text-ui-fg-base", children: formatRelativeTime(occurredAt) }) });
|
|
2111
|
+
const SourceBadge = ({ source }) => {
|
|
2112
|
+
const info = describeSource(source);
|
|
2113
|
+
if (info.kind === "unknown") {
|
|
2114
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Unknown" });
|
|
2115
|
+
}
|
|
2116
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", color: sourceBadgeColor(info.kind), className: "shrink-0 whitespace-nowrap", children: info.label });
|
|
2117
|
+
};
|
|
2118
|
+
const AuditTable = ({ items, highlightId, onOpen }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden w-full overflow-hidden rounded-xl border border-ui-border-base md:block", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full table-fixed divide-y divide-ui-border-base", children: [
|
|
2119
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
2120
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[22%]"), children: "Entity" }),
|
|
2121
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[24%]"), children: "Record" }),
|
|
2122
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[13%]"), children: "Deleted" }),
|
|
2123
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[13%]"), children: "Deleted by" }),
|
|
2124
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[11%]"), children: "Source" }),
|
|
2125
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[8%]"), children: "Status" }),
|
|
2126
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[9%]"), children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Action" }) })
|
|
2127
|
+
] }) }),
|
|
2128
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((item) => {
|
|
2129
|
+
const entity = getEntityInfo(item.table_name);
|
|
2130
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2131
|
+
"tr",
|
|
2132
|
+
{
|
|
2133
|
+
"data-audit-row": item.id,
|
|
2134
|
+
tabIndex: 0,
|
|
2135
|
+
onClick: () => onOpen(item.id),
|
|
2136
|
+
onKeyDown: (e) => {
|
|
2137
|
+
if (e.key === "Enter") onOpen(item.id);
|
|
2138
|
+
},
|
|
2139
|
+
className: ui.clx(
|
|
2140
|
+
"cursor-pointer outline-none transition-colors hover:bg-ui-bg-subtle/60 focus-visible:bg-ui-bg-subtle",
|
|
2141
|
+
highlightId === item.id && "bg-ui-bg-highlight"
|
|
2142
|
+
),
|
|
2143
|
+
children: [
|
|
2144
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col", children: [
|
|
2145
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm font-medium text-ui-fg-base", title: entity.label, children: entity.label }),
|
|
2146
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-xs text-ui-fg-muted", children: entity.category.label })
|
|
2147
|
+
] }) }),
|
|
2148
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(CopyableId, { value: item.record_id }) }),
|
|
2149
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(DeletedWhen, { occurredAt: item.occurred_at }) }),
|
|
2150
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-sm", title: item.deleted_by ?? void 0, children: item.deleted_by ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-base", children: item.deleted_by }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: "Unknown" }) }),
|
|
2151
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(SourceBadge, { source: item.source }) }),
|
|
2152
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", color: "red", children: "Deleted" }) }),
|
|
2153
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-3 text-right", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-0.5 whitespace-nowrap text-sm font-medium text-ui-fg-interactive", children: [
|
|
2154
|
+
"View",
|
|
2155
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRightMini, {})
|
|
2156
|
+
] }) })
|
|
2157
|
+
]
|
|
2158
|
+
},
|
|
2159
|
+
item.id
|
|
2160
|
+
);
|
|
2161
|
+
}) })
|
|
2162
|
+
] }) });
|
|
2163
|
+
const AuditCards = ({ items, highlightId, onOpen }) => /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-col gap-2 md:hidden", children: items.map((item) => {
|
|
2164
|
+
const entity = getEntityInfo(item.table_name);
|
|
2165
|
+
return /* @__PURE__ */ jsxRuntime.jsx("li", { "data-audit-row": item.id, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2166
|
+
"div",
|
|
2167
|
+
{
|
|
2168
|
+
role: "button",
|
|
2169
|
+
tabIndex: 0,
|
|
2170
|
+
onClick: () => onOpen(item.id),
|
|
2171
|
+
onKeyDown: (e) => {
|
|
2172
|
+
if (e.key === "Enter") onOpen(item.id);
|
|
2173
|
+
},
|
|
2174
|
+
className: ui.clx(
|
|
2175
|
+
"flex w-full flex-col gap-2 rounded-lg border border-ui-border-base p-3 text-left outline-none hover:bg-ui-bg-subtle/60 focus-visible:bg-ui-bg-subtle",
|
|
2176
|
+
highlightId === item.id && "bg-ui-bg-highlight"
|
|
2177
|
+
),
|
|
2178
|
+
children: [
|
|
2179
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
2180
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col", children: [
|
|
2181
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm font-medium text-ui-fg-base", children: entity.label }),
|
|
2182
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-ui-fg-muted", children: entity.category.label })
|
|
2183
|
+
] }),
|
|
2184
|
+
/* @__PURE__ */ jsxRuntime.jsx(DeletedWhen, { occurredAt: item.occurred_at })
|
|
2185
|
+
] }),
|
|
2186
|
+
/* @__PURE__ */ jsxRuntime.jsx(CopyableId, { value: item.record_id }),
|
|
2187
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
2188
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
2189
|
+
/* @__PURE__ */ jsxRuntime.jsx(SourceBadge, { source: item.source }),
|
|
2190
|
+
item.deleted_by ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "truncate text-xs text-ui-fg-subtle", children: [
|
|
2191
|
+
"by ",
|
|
2192
|
+
item.deleted_by
|
|
2193
|
+
] }) : null
|
|
2194
|
+
] }),
|
|
2195
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex shrink-0 items-center whitespace-nowrap text-sm font-medium text-ui-fg-interactive", children: [
|
|
2196
|
+
"View details",
|
|
2197
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRightMini, {})
|
|
2198
|
+
] })
|
|
2199
|
+
] })
|
|
2200
|
+
]
|
|
2201
|
+
}
|
|
2202
|
+
) }, item.id);
|
|
2203
|
+
}) });
|
|
2204
|
+
const ListSkeleton = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0 overflow-hidden rounded-xl border border-ui-border-base", "aria-busy": "true", children: [
|
|
2205
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-ui-bg-subtle px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-3 w-40" }) }),
|
|
2206
|
+
Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 border-t border-ui-border-subtle px-3 py-4", children: [
|
|
2207
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-[22%] flex-col gap-1.5", children: [
|
|
2208
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-3.5 w-28" }),
|
|
2209
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-3 w-16" })
|
|
2210
|
+
] }),
|
|
2211
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-3.5 w-[20%]" }),
|
|
2212
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-3.5 w-[10%]" }),
|
|
2213
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "hidden h-3.5 w-[10%] md:block" }),
|
|
2214
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "hidden h-5 w-14 rounded-full md:block" })
|
|
2215
|
+
] }, i))
|
|
2216
|
+
] });
|
|
2217
|
+
const EmptyState = ({ title, body, action }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2 rounded-lg border border-dashed border-ui-border-strong px-6 py-12 text-center", children: [
|
|
2218
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.MagnifierAlert, { className: "text-ui-fg-muted" }),
|
|
2219
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: title }),
|
|
2220
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "max-w-md text-ui-fg-subtle", children: body }),
|
|
2221
|
+
action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2", children: action }) : null
|
|
2222
|
+
] });
|
|
2223
|
+
const ErrorState = ({ onRetry, detail }) => /* @__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: [
|
|
2224
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ExclamationCircle, { className: "text-ui-fg-error" }),
|
|
2225
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: "Unable to load deleted records" }),
|
|
2226
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "max-w-md text-ui-fg-subtle", children: "We couldn’t retrieve the audit records right now. Check your connection and try again." }),
|
|
2227
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "max-w-md font-mono text-ui-fg-muted", children: detail }),
|
|
2228
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", size: "small", className: "mt-2", onClick: onRetry, children: "Try again" })
|
|
2229
|
+
] });
|
|
2230
|
+
const config$8 = adminSdk.defineRouteConfig({
|
|
2231
|
+
label: "Deleted Records",
|
|
2232
|
+
icon: icons.Trash
|
|
2233
|
+
});
|
|
927
2234
|
const useDebounce$3 = (value, delay) => {
|
|
928
2235
|
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
929
2236
|
react.useEffect(() => {
|
|
@@ -940,19 +2247,27 @@ const getStatusBadgeClass$7 = (status) => {
|
|
|
940
2247
|
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
941
2248
|
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
942
2249
|
};
|
|
943
|
-
const
|
|
2250
|
+
const RefundsPage = () => {
|
|
944
2251
|
const navigate = reactRouterDom.useNavigate();
|
|
945
2252
|
const [items, setItems] = react.useState([]);
|
|
946
|
-
const [statusFilter, setStatusFilter] = react.useState("all");
|
|
947
2253
|
const [orderIdSearch, setOrderIdSearch] = react.useState("");
|
|
948
2254
|
const debouncedOrderId = useDebounce$3(orderIdSearch, 300);
|
|
2255
|
+
const [paymentStatusFilter, setPaymentStatusFilter] = react.useState("all");
|
|
2256
|
+
const [providerSearch, setProviderSearch] = react.useState("");
|
|
2257
|
+
const debouncedProvider = useDebounce$3(providerSearch, 300);
|
|
2258
|
+
const [currencySearch, setCurrencySearch] = react.useState("");
|
|
2259
|
+
const debouncedCurrency = useDebounce$3(currencySearch, 300);
|
|
2260
|
+
const [dateFrom, setDateFrom] = react.useState("");
|
|
2261
|
+
const [dateTo, setDateTo] = react.useState("");
|
|
2262
|
+
const [amountMin, setAmountMin] = react.useState("");
|
|
2263
|
+
const [amountMax, setAmountMax] = react.useState("");
|
|
949
2264
|
const [isLoading, setIsLoading] = react.useState(true);
|
|
950
2265
|
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
951
2266
|
const [error, setError] = react.useState(null);
|
|
952
2267
|
const [offset, setOffset] = react.useState(0);
|
|
953
2268
|
const [count, setCount] = react.useState(0);
|
|
954
2269
|
const limit = 50;
|
|
955
|
-
const
|
|
2270
|
+
const loadRefunds = react.useCallback(
|
|
956
2271
|
async (nextOffset, replace) => {
|
|
957
2272
|
try {
|
|
958
2273
|
if (replace) setIsLoading(true);
|
|
@@ -961,18 +2276,25 @@ const PaymentsPage = () => {
|
|
|
961
2276
|
const params = new URLSearchParams();
|
|
962
2277
|
params.set("limit", String(limit));
|
|
963
2278
|
params.set("offset", String(nextOffset));
|
|
964
|
-
if (statusFilter !== "all") params.set("status", statusFilter);
|
|
965
2279
|
if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
);
|
|
2280
|
+
if (paymentStatusFilter !== "all") params.set("payment_status", paymentStatusFilter);
|
|
2281
|
+
if (debouncedProvider.trim()) params.set("provider_id", debouncedProvider.trim());
|
|
2282
|
+
if (debouncedCurrency.trim()) params.set("currency_code", debouncedCurrency.trim());
|
|
2283
|
+
if (dateFrom.trim()) params.set("date_from", dateFrom.trim());
|
|
2284
|
+
if (dateTo.trim()) params.set("date_to", dateTo.trim());
|
|
2285
|
+
const min = amountMin.trim() ? Number(amountMin) : void 0;
|
|
2286
|
+
const max = amountMax.trim() ? Number(amountMax) : void 0;
|
|
2287
|
+
if (min != null && !Number.isNaN(min)) params.set("amount_min", String(min));
|
|
2288
|
+
if (max != null && !Number.isNaN(max)) params.set("amount_max", String(max));
|
|
2289
|
+
const response = await fetch(`/admin/refunds?${params.toString()}`, {
|
|
2290
|
+
credentials: "include"
|
|
2291
|
+
});
|
|
970
2292
|
if (!response.ok) {
|
|
971
2293
|
const text = await response.text();
|
|
972
|
-
throw new Error(text || "Failed to load
|
|
2294
|
+
throw new Error(text || "Failed to load refunds");
|
|
973
2295
|
}
|
|
974
2296
|
const payload = await response.json();
|
|
975
|
-
const list = payload.
|
|
2297
|
+
const list = payload.refunds ?? [];
|
|
976
2298
|
setCount(payload.count ?? 0);
|
|
977
2299
|
setOffset(nextOffset + list.length);
|
|
978
2300
|
setItems((prev) => replace ? list : [...prev, ...list]);
|
|
@@ -983,235 +2305,20 @@ const PaymentsPage = () => {
|
|
|
983
2305
|
setIsFetchingMore(false);
|
|
984
2306
|
}
|
|
985
2307
|
},
|
|
986
|
-
[
|
|
2308
|
+
[
|
|
2309
|
+
debouncedOrderId,
|
|
2310
|
+
paymentStatusFilter,
|
|
2311
|
+
debouncedProvider,
|
|
2312
|
+
debouncedCurrency,
|
|
2313
|
+
dateFrom,
|
|
2314
|
+
dateTo,
|
|
2315
|
+
amountMin,
|
|
2316
|
+
amountMax
|
|
2317
|
+
]
|
|
987
2318
|
);
|
|
988
2319
|
react.useEffect(() => {
|
|
989
|
-
void
|
|
990
|
-
}, [
|
|
991
|
-
const hasMore = react.useMemo(() => offset < count, [offset, count]);
|
|
992
|
-
const displayStatus = (t) => {
|
|
993
|
-
const s2 = t.payment_id != null && t.payment_status != null && t.payment_status !== "" ? t.payment_status : t.session_status ?? "";
|
|
994
|
-
return s2 !== "" ? s2 : "—";
|
|
995
|
-
};
|
|
996
|
-
const displayAmount = (t) => {
|
|
997
|
-
const code = (t.currency_code ?? "USD").toUpperCase();
|
|
998
|
-
return `${code} ${Number(t.amount)}`;
|
|
999
|
-
};
|
|
1000
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
|
|
1001
|
-
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
1002
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1003
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Payments" }),
|
|
1004
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "All payment attempts — completed, pending, failed, requires action" })
|
|
1005
|
-
] }),
|
|
1006
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => loadTransactions(0, true), children: "Refresh" })
|
|
1007
|
-
] }),
|
|
1008
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
1009
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1010
|
-
ui.Input,
|
|
1011
|
-
{
|
|
1012
|
-
placeholder: "Search by Order ID",
|
|
1013
|
-
value: orderIdSearch,
|
|
1014
|
-
onChange: (e) => setOrderIdSearch(e.target.value),
|
|
1015
|
-
className: "md:max-w-sm",
|
|
1016
|
-
"aria-label": "Search by order ID"
|
|
1017
|
-
}
|
|
1018
|
-
),
|
|
1019
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1020
|
-
"select",
|
|
1021
|
-
{
|
|
1022
|
-
value: statusFilter,
|
|
1023
|
-
onChange: (e) => setStatusFilter(e.target.value),
|
|
1024
|
-
className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-xs",
|
|
1025
|
-
"aria-label": "Filter by status",
|
|
1026
|
-
children: [
|
|
1027
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All statuses" }),
|
|
1028
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "pending", children: "Pending" }),
|
|
1029
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "requires_more", children: "Requires more" }),
|
|
1030
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "error", children: "Error" }),
|
|
1031
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "canceled", children: "Canceled" }),
|
|
1032
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "authorized", children: "Authorized" }),
|
|
1033
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "captured", children: "Captured" })
|
|
1034
|
-
]
|
|
1035
|
-
}
|
|
1036
|
-
) })
|
|
1037
|
-
] }),
|
|
1038
|
-
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
1039
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
1040
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => loadTransactions(0, true), children: "Try again" }) })
|
|
1041
|
-
] }) : null,
|
|
1042
|
-
isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading payments…" }) }) : items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
1043
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No payment transactions yet" }),
|
|
1044
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Payment attempts will appear here." })
|
|
1045
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
1046
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
1047
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
1048
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Amount" }),
|
|
1049
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Provider" }),
|
|
1050
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
1051
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Finalized" }),
|
|
1052
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
1053
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
1054
|
-
] }) }),
|
|
1055
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((t) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1056
|
-
"tr",
|
|
1057
|
-
{
|
|
1058
|
-
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
1059
|
-
onClick: () => navigate(`/payments/${t.payment_session_id}`),
|
|
1060
|
-
children: [
|
|
1061
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: t.order_id ?? "—" }),
|
|
1062
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: displayAmount(t) }),
|
|
1063
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.provider_id }),
|
|
1064
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1065
|
-
ui.Badge,
|
|
1066
|
-
{
|
|
1067
|
-
size: "2xsmall",
|
|
1068
|
-
className: `uppercase ${getStatusBadgeClass$7(displayStatus(t))}`,
|
|
1069
|
-
children: displayStatus(t) !== "—" ? displayStatus(t).replace(/_/g, " ") : "—"
|
|
1070
|
-
}
|
|
1071
|
-
) }),
|
|
1072
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.payment_id != null ? "Yes" : "No" }),
|
|
1073
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(t.created_at).toLocaleDateString("en-US", {
|
|
1074
|
-
year: "numeric",
|
|
1075
|
-
month: "short",
|
|
1076
|
-
day: "numeric",
|
|
1077
|
-
hour: "numeric",
|
|
1078
|
-
minute: "2-digit",
|
|
1079
|
-
hour12: true
|
|
1080
|
-
}) }),
|
|
1081
|
-
/* @__PURE__ */ jsxRuntime.jsxs("td", { className: "px-4 py-4", children: [
|
|
1082
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1083
|
-
ui.Button,
|
|
1084
|
-
{
|
|
1085
|
-
variant: "transparent",
|
|
1086
|
-
size: "small",
|
|
1087
|
-
onClick: (e) => {
|
|
1088
|
-
e.stopPropagation();
|
|
1089
|
-
navigate(`/payments/${t.payment_session_id}`);
|
|
1090
|
-
},
|
|
1091
|
-
children: "View details"
|
|
1092
|
-
}
|
|
1093
|
-
),
|
|
1094
|
-
t.order_id ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1095
|
-
ui.Button,
|
|
1096
|
-
{
|
|
1097
|
-
variant: "transparent",
|
|
1098
|
-
size: "small",
|
|
1099
|
-
onClick: (e) => {
|
|
1100
|
-
e.stopPropagation();
|
|
1101
|
-
navigate(`/orders/${t.order_id}`);
|
|
1102
|
-
},
|
|
1103
|
-
children: "Order"
|
|
1104
|
-
}
|
|
1105
|
-
) : null
|
|
1106
|
-
] })
|
|
1107
|
-
]
|
|
1108
|
-
},
|
|
1109
|
-
t.payment_session_id
|
|
1110
|
-
)) })
|
|
1111
|
-
] }) }),
|
|
1112
|
-
hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1113
|
-
ui.Button,
|
|
1114
|
-
{
|
|
1115
|
-
variant: "secondary",
|
|
1116
|
-
isLoading: isFetchingMore,
|
|
1117
|
-
onClick: () => loadTransactions(offset, false),
|
|
1118
|
-
children: "Load more"
|
|
1119
|
-
}
|
|
1120
|
-
) }) : null
|
|
1121
|
-
] }) });
|
|
1122
|
-
};
|
|
1123
|
-
const config$7 = adminSdk.defineRouteConfig({
|
|
1124
|
-
label: "Payments",
|
|
1125
|
-
icon: icons.CreditCard
|
|
1126
|
-
});
|
|
1127
|
-
const useDebounce$2 = (value, delay) => {
|
|
1128
|
-
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
1129
|
-
react.useEffect(() => {
|
|
1130
|
-
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
1131
|
-
return () => clearTimeout(handler);
|
|
1132
|
-
}, [value, delay]);
|
|
1133
|
-
return debouncedValue;
|
|
1134
|
-
};
|
|
1135
|
-
const getStatusBadgeClass$6 = (status) => {
|
|
1136
|
-
const s2 = status.toLowerCase();
|
|
1137
|
-
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
1138
|
-
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
1139
|
-
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
1140
|
-
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
1141
|
-
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
1142
|
-
};
|
|
1143
|
-
const RefundsPage = () => {
|
|
1144
|
-
const navigate = reactRouterDom.useNavigate();
|
|
1145
|
-
const [items, setItems] = react.useState([]);
|
|
1146
|
-
const [orderIdSearch, setOrderIdSearch] = react.useState("");
|
|
1147
|
-
const debouncedOrderId = useDebounce$2(orderIdSearch, 300);
|
|
1148
|
-
const [paymentStatusFilter, setPaymentStatusFilter] = react.useState("all");
|
|
1149
|
-
const [providerSearch, setProviderSearch] = react.useState("");
|
|
1150
|
-
const debouncedProvider = useDebounce$2(providerSearch, 300);
|
|
1151
|
-
const [currencySearch, setCurrencySearch] = react.useState("");
|
|
1152
|
-
const debouncedCurrency = useDebounce$2(currencySearch, 300);
|
|
1153
|
-
const [dateFrom, setDateFrom] = react.useState("");
|
|
1154
|
-
const [dateTo, setDateTo] = react.useState("");
|
|
1155
|
-
const [amountMin, setAmountMin] = react.useState("");
|
|
1156
|
-
const [amountMax, setAmountMax] = react.useState("");
|
|
1157
|
-
const [isLoading, setIsLoading] = react.useState(true);
|
|
1158
|
-
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
1159
|
-
const [error, setError] = react.useState(null);
|
|
1160
|
-
const [offset, setOffset] = react.useState(0);
|
|
1161
|
-
const [count, setCount] = react.useState(0);
|
|
1162
|
-
const limit = 50;
|
|
1163
|
-
const loadRefunds = react.useCallback(
|
|
1164
|
-
async (nextOffset, replace) => {
|
|
1165
|
-
try {
|
|
1166
|
-
if (replace) setIsLoading(true);
|
|
1167
|
-
else setIsFetchingMore(true);
|
|
1168
|
-
setError(null);
|
|
1169
|
-
const params = new URLSearchParams();
|
|
1170
|
-
params.set("limit", String(limit));
|
|
1171
|
-
params.set("offset", String(nextOffset));
|
|
1172
|
-
if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
|
|
1173
|
-
if (paymentStatusFilter !== "all") params.set("payment_status", paymentStatusFilter);
|
|
1174
|
-
if (debouncedProvider.trim()) params.set("provider_id", debouncedProvider.trim());
|
|
1175
|
-
if (debouncedCurrency.trim()) params.set("currency_code", debouncedCurrency.trim());
|
|
1176
|
-
if (dateFrom.trim()) params.set("date_from", dateFrom.trim());
|
|
1177
|
-
if (dateTo.trim()) params.set("date_to", dateTo.trim());
|
|
1178
|
-
const min = amountMin.trim() ? Number(amountMin) : void 0;
|
|
1179
|
-
const max = amountMax.trim() ? Number(amountMax) : void 0;
|
|
1180
|
-
if (min != null && !Number.isNaN(min)) params.set("amount_min", String(min));
|
|
1181
|
-
if (max != null && !Number.isNaN(max)) params.set("amount_max", String(max));
|
|
1182
|
-
const response = await fetch(`/admin/refunds?${params.toString()}`, {
|
|
1183
|
-
credentials: "include"
|
|
1184
|
-
});
|
|
1185
|
-
if (!response.ok) {
|
|
1186
|
-
const text = await response.text();
|
|
1187
|
-
throw new Error(text || "Failed to load refunds");
|
|
1188
|
-
}
|
|
1189
|
-
const payload = await response.json();
|
|
1190
|
-
const list = payload.refunds ?? [];
|
|
1191
|
-
setCount(payload.count ?? 0);
|
|
1192
|
-
setOffset(nextOffset + list.length);
|
|
1193
|
-
setItems((prev) => replace ? list : [...prev, ...list]);
|
|
1194
|
-
} catch (e) {
|
|
1195
|
-
setError(e instanceof Error ? e.message : "Failed to load");
|
|
1196
|
-
} finally {
|
|
1197
|
-
setIsLoading(false);
|
|
1198
|
-
setIsFetchingMore(false);
|
|
1199
|
-
}
|
|
1200
|
-
},
|
|
1201
|
-
[
|
|
1202
|
-
debouncedOrderId,
|
|
1203
|
-
paymentStatusFilter,
|
|
1204
|
-
debouncedProvider,
|
|
1205
|
-
debouncedCurrency,
|
|
1206
|
-
dateFrom,
|
|
1207
|
-
dateTo,
|
|
1208
|
-
amountMin,
|
|
1209
|
-
amountMax
|
|
1210
|
-
]
|
|
1211
|
-
);
|
|
1212
|
-
react.useEffect(() => {
|
|
1213
|
-
void loadRefunds(0, true);
|
|
1214
|
-
}, [loadRefunds]);
|
|
2320
|
+
void loadRefunds(0, true);
|
|
2321
|
+
}, [loadRefunds]);
|
|
1215
2322
|
const hasMore = react.useMemo(() => offset < count, [offset, count]);
|
|
1216
2323
|
const displayAmount = (r) => {
|
|
1217
2324
|
const code = (r.currency_code ?? "USD").toUpperCase();
|
|
@@ -1361,7 +2468,7 @@ const RefundsPage = () => {
|
|
|
1361
2468
|
ui.Badge,
|
|
1362
2469
|
{
|
|
1363
2470
|
size: "2xsmall",
|
|
1364
|
-
className: `uppercase ${getStatusBadgeClass$
|
|
2471
|
+
className: `uppercase ${getStatusBadgeClass$7(displayStatus(r))}`,
|
|
1365
2472
|
children: displayStatus(r) !== "—" ? displayStatus(r).replace(/_/g, " ") : "—"
|
|
1366
2473
|
}
|
|
1367
2474
|
) }),
|
|
@@ -1415,11 +2522,11 @@ const RefundsPage = () => {
|
|
|
1415
2522
|
) }) : null
|
|
1416
2523
|
] }) });
|
|
1417
2524
|
};
|
|
1418
|
-
const config$
|
|
2525
|
+
const config$7 = adminSdk.defineRouteConfig({
|
|
1419
2526
|
label: "Refunds",
|
|
1420
2527
|
icon: icons.Receipt
|
|
1421
2528
|
});
|
|
1422
|
-
const useDebounce$
|
|
2529
|
+
const useDebounce$2 = (value, delay) => {
|
|
1423
2530
|
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
1424
2531
|
react.useEffect(() => {
|
|
1425
2532
|
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
@@ -1427,43 +2534,244 @@ const useDebounce$1 = (value, delay) => {
|
|
|
1427
2534
|
}, [value, delay]);
|
|
1428
2535
|
return debouncedValue;
|
|
1429
2536
|
};
|
|
1430
|
-
const getStatusBadgeClass$
|
|
1431
|
-
const
|
|
1432
|
-
if (
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
if (
|
|
1436
|
-
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
1437
|
-
}
|
|
1438
|
-
if (statusLower === "requires_action") {
|
|
1439
|
-
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
1440
|
-
}
|
|
1441
|
-
if (statusLower === "completed") {
|
|
1442
|
-
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
1443
|
-
}
|
|
1444
|
-
if (statusLower === "canceled") {
|
|
1445
|
-
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
1446
|
-
}
|
|
2537
|
+
const getStatusBadgeClass$6 = (status) => {
|
|
2538
|
+
const s2 = status.toLowerCase();
|
|
2539
|
+
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
2540
|
+
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
2541
|
+
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
2542
|
+
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
1447
2543
|
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
1448
2544
|
};
|
|
1449
|
-
const
|
|
2545
|
+
const PaymentsPage = () => {
|
|
1450
2546
|
const navigate = reactRouterDom.useNavigate();
|
|
1451
2547
|
const [items, setItems] = react.useState([]);
|
|
1452
2548
|
const [statusFilter, setStatusFilter] = react.useState("all");
|
|
1453
|
-
const [
|
|
1454
|
-
const
|
|
1455
|
-
const debouncedSearchQuery = useDebounce$1(searchQuery, 300);
|
|
2549
|
+
const [orderIdSearch, setOrderIdSearch] = react.useState("");
|
|
2550
|
+
const debouncedOrderId = useDebounce$2(orderIdSearch, 300);
|
|
1456
2551
|
const [isLoading, setIsLoading] = react.useState(true);
|
|
1457
2552
|
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
1458
2553
|
const [error, setError] = react.useState(null);
|
|
1459
2554
|
const [offset, setOffset] = react.useState(0);
|
|
1460
2555
|
const [count, setCount] = react.useState(0);
|
|
1461
2556
|
const limit = 50;
|
|
1462
|
-
const
|
|
1463
|
-
async (nextOffset, replace
|
|
2557
|
+
const loadTransactions = react.useCallback(
|
|
2558
|
+
async (nextOffset, replace) => {
|
|
1464
2559
|
try {
|
|
1465
|
-
if (replace)
|
|
1466
|
-
|
|
2560
|
+
if (replace) setIsLoading(true);
|
|
2561
|
+
else setIsFetchingMore(true);
|
|
2562
|
+
setError(null);
|
|
2563
|
+
const params = new URLSearchParams();
|
|
2564
|
+
params.set("limit", String(limit));
|
|
2565
|
+
params.set("offset", String(nextOffset));
|
|
2566
|
+
if (statusFilter !== "all") params.set("status", statusFilter);
|
|
2567
|
+
if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
|
|
2568
|
+
const response = await fetch(
|
|
2569
|
+
`/admin/payment-transactions?${params.toString()}`,
|
|
2570
|
+
{ credentials: "include" }
|
|
2571
|
+
);
|
|
2572
|
+
if (!response.ok) {
|
|
2573
|
+
const text = await response.text();
|
|
2574
|
+
throw new Error(text || "Failed to load payment transactions");
|
|
2575
|
+
}
|
|
2576
|
+
const payload = await response.json();
|
|
2577
|
+
const list = payload.transactions ?? [];
|
|
2578
|
+
setCount(payload.count ?? 0);
|
|
2579
|
+
setOffset(nextOffset + list.length);
|
|
2580
|
+
setItems((prev) => replace ? list : [...prev, ...list]);
|
|
2581
|
+
} catch (e) {
|
|
2582
|
+
setError(e instanceof Error ? e.message : "Failed to load");
|
|
2583
|
+
} finally {
|
|
2584
|
+
setIsLoading(false);
|
|
2585
|
+
setIsFetchingMore(false);
|
|
2586
|
+
}
|
|
2587
|
+
},
|
|
2588
|
+
[statusFilter, debouncedOrderId]
|
|
2589
|
+
);
|
|
2590
|
+
react.useEffect(() => {
|
|
2591
|
+
void loadTransactions(0, true);
|
|
2592
|
+
}, [loadTransactions]);
|
|
2593
|
+
const hasMore = react.useMemo(() => offset < count, [offset, count]);
|
|
2594
|
+
const displayStatus = (t) => {
|
|
2595
|
+
const s2 = t.payment_id != null && t.payment_status != null && t.payment_status !== "" ? t.payment_status : t.session_status ?? "";
|
|
2596
|
+
return s2 !== "" ? s2 : "—";
|
|
2597
|
+
};
|
|
2598
|
+
const displayAmount = (t) => {
|
|
2599
|
+
const code = (t.currency_code ?? "USD").toUpperCase();
|
|
2600
|
+
return `${code} ${Number(t.amount)}`;
|
|
2601
|
+
};
|
|
2602
|
+
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: [
|
|
2603
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
2604
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
2605
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Payments" }),
|
|
2606
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "All payment attempts — completed, pending, failed, requires action" })
|
|
2607
|
+
] }),
|
|
2608
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => loadTransactions(0, true), children: "Refresh" })
|
|
2609
|
+
] }),
|
|
2610
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
2611
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2612
|
+
ui.Input,
|
|
2613
|
+
{
|
|
2614
|
+
placeholder: "Search by Order ID",
|
|
2615
|
+
value: orderIdSearch,
|
|
2616
|
+
onChange: (e) => setOrderIdSearch(e.target.value),
|
|
2617
|
+
className: "md:max-w-sm",
|
|
2618
|
+
"aria-label": "Search by order ID"
|
|
2619
|
+
}
|
|
2620
|
+
),
|
|
2621
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2622
|
+
"select",
|
|
2623
|
+
{
|
|
2624
|
+
value: statusFilter,
|
|
2625
|
+
onChange: (e) => setStatusFilter(e.target.value),
|
|
2626
|
+
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",
|
|
2627
|
+
"aria-label": "Filter by status",
|
|
2628
|
+
children: [
|
|
2629
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All statuses" }),
|
|
2630
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "pending", children: "Pending" }),
|
|
2631
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "requires_more", children: "Requires more" }),
|
|
2632
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "error", children: "Error" }),
|
|
2633
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "canceled", children: "Canceled" }),
|
|
2634
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "authorized", children: "Authorized" }),
|
|
2635
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "captured", children: "Captured" })
|
|
2636
|
+
]
|
|
2637
|
+
}
|
|
2638
|
+
) })
|
|
2639
|
+
] }),
|
|
2640
|
+
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
2641
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
2642
|
+
/* @__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" }) })
|
|
2643
|
+
] }) : null,
|
|
2644
|
+
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: [
|
|
2645
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No payment transactions yet" }),
|
|
2646
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Payment attempts will appear here." })
|
|
2647
|
+
] }) : /* @__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: [
|
|
2648
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
2649
|
+
/* @__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" }),
|
|
2650
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Amount" }),
|
|
2651
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Provider" }),
|
|
2652
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
2653
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Finalized" }),
|
|
2654
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
2655
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
2656
|
+
] }) }),
|
|
2657
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((t) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2658
|
+
"tr",
|
|
2659
|
+
{
|
|
2660
|
+
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
2661
|
+
onClick: () => navigate(`/payments/${t.payment_session_id}`),
|
|
2662
|
+
children: [
|
|
2663
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: t.order_id ?? "—" }),
|
|
2664
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: displayAmount(t) }),
|
|
2665
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.provider_id }),
|
|
2666
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2667
|
+
ui.Badge,
|
|
2668
|
+
{
|
|
2669
|
+
size: "2xsmall",
|
|
2670
|
+
className: `uppercase ${getStatusBadgeClass$6(displayStatus(t))}`,
|
|
2671
|
+
children: displayStatus(t) !== "—" ? displayStatus(t).replace(/_/g, " ") : "—"
|
|
2672
|
+
}
|
|
2673
|
+
) }),
|
|
2674
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.payment_id != null ? "Yes" : "No" }),
|
|
2675
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(t.created_at).toLocaleDateString("en-US", {
|
|
2676
|
+
year: "numeric",
|
|
2677
|
+
month: "short",
|
|
2678
|
+
day: "numeric",
|
|
2679
|
+
hour: "numeric",
|
|
2680
|
+
minute: "2-digit",
|
|
2681
|
+
hour12: true
|
|
2682
|
+
}) }),
|
|
2683
|
+
/* @__PURE__ */ jsxRuntime.jsxs("td", { className: "px-4 py-4", children: [
|
|
2684
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2685
|
+
ui.Button,
|
|
2686
|
+
{
|
|
2687
|
+
variant: "transparent",
|
|
2688
|
+
size: "small",
|
|
2689
|
+
onClick: (e) => {
|
|
2690
|
+
e.stopPropagation();
|
|
2691
|
+
navigate(`/payments/${t.payment_session_id}`);
|
|
2692
|
+
},
|
|
2693
|
+
children: "View details"
|
|
2694
|
+
}
|
|
2695
|
+
),
|
|
2696
|
+
t.order_id ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2697
|
+
ui.Button,
|
|
2698
|
+
{
|
|
2699
|
+
variant: "transparent",
|
|
2700
|
+
size: "small",
|
|
2701
|
+
onClick: (e) => {
|
|
2702
|
+
e.stopPropagation();
|
|
2703
|
+
navigate(`/orders/${t.order_id}`);
|
|
2704
|
+
},
|
|
2705
|
+
children: "Order"
|
|
2706
|
+
}
|
|
2707
|
+
) : null
|
|
2708
|
+
] })
|
|
2709
|
+
]
|
|
2710
|
+
},
|
|
2711
|
+
t.payment_session_id
|
|
2712
|
+
)) })
|
|
2713
|
+
] }) }),
|
|
2714
|
+
hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2715
|
+
ui.Button,
|
|
2716
|
+
{
|
|
2717
|
+
variant: "secondary",
|
|
2718
|
+
isLoading: isFetchingMore,
|
|
2719
|
+
onClick: () => loadTransactions(offset, false),
|
|
2720
|
+
children: "Load more"
|
|
2721
|
+
}
|
|
2722
|
+
) }) : null
|
|
2723
|
+
] }) });
|
|
2724
|
+
};
|
|
2725
|
+
const config$6 = adminSdk.defineRouteConfig({
|
|
2726
|
+
label: "Payments",
|
|
2727
|
+
icon: icons.CreditCard
|
|
2728
|
+
});
|
|
2729
|
+
const useDebounce$1 = (value, delay) => {
|
|
2730
|
+
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
2731
|
+
react.useEffect(() => {
|
|
2732
|
+
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
2733
|
+
return () => clearTimeout(handler);
|
|
2734
|
+
}, [value, delay]);
|
|
2735
|
+
return debouncedValue;
|
|
2736
|
+
};
|
|
2737
|
+
const getStatusBadgeClass$5 = (status) => {
|
|
2738
|
+
const statusLower = status.toLowerCase();
|
|
2739
|
+
if (statusLower === "requested") {
|
|
2740
|
+
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
2741
|
+
}
|
|
2742
|
+
if (statusLower === "received") {
|
|
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
|
+
}
|
|
2754
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
2755
|
+
};
|
|
2756
|
+
const ReturnsPage = () => {
|
|
2757
|
+
const navigate = reactRouterDom.useNavigate();
|
|
2758
|
+
const [items, setItems] = react.useState([]);
|
|
2759
|
+
const [statusFilter, setStatusFilter] = react.useState("all");
|
|
2760
|
+
const [createdByFilter, setCreatedByFilter] = react.useState("all");
|
|
2761
|
+
const [searchQuery, setSearchQuery] = react.useState("");
|
|
2762
|
+
const debouncedSearchQuery = useDebounce$1(searchQuery, 300);
|
|
2763
|
+
const [isLoading, setIsLoading] = react.useState(true);
|
|
2764
|
+
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
2765
|
+
const [error, setError] = react.useState(null);
|
|
2766
|
+
const [offset, setOffset] = react.useState(0);
|
|
2767
|
+
const [count, setCount] = react.useState(0);
|
|
2768
|
+
const limit = 50;
|
|
2769
|
+
const loadReturns = react.useCallback(
|
|
2770
|
+
async (nextOffset, replace = false) => {
|
|
2771
|
+
var _a;
|
|
2772
|
+
try {
|
|
2773
|
+
if (replace) {
|
|
2774
|
+
setIsLoading(true);
|
|
1467
2775
|
} else {
|
|
1468
2776
|
setIsFetchingMore(true);
|
|
1469
2777
|
}
|
|
@@ -1491,7 +2799,7 @@ const ReturnsPage = () => {
|
|
|
1491
2799
|
}
|
|
1492
2800
|
const payload = await response.json();
|
|
1493
2801
|
setCount(payload.count ?? 0);
|
|
1494
|
-
setOffset(nextOffset + (payload.returns
|
|
2802
|
+
setOffset(nextOffset + (((_a = payload.returns) == null ? void 0 : _a.length) ?? 0));
|
|
1495
2803
|
setItems(
|
|
1496
2804
|
(prev) => replace ? payload.returns ?? [] : [...prev, ...payload.returns ?? []]
|
|
1497
2805
|
);
|
|
@@ -1603,7 +2911,7 @@ const ReturnsPage = () => {
|
|
|
1603
2911
|
) }),
|
|
1604
2912
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
|
|
1605
2913
|
const calc = returnOrder.refund;
|
|
1606
|
-
if (calc
|
|
2914
|
+
if ((calc == null ? void 0 : calc.is_processed) && calc.final_refund_amount != null) {
|
|
1607
2915
|
return formatRefundCurrency(
|
|
1608
2916
|
calc.final_refund_amount,
|
|
1609
2917
|
calc.currency_code || returnOrder.currency_code
|
|
@@ -1702,6 +3010,7 @@ const SwapsPage = () => {
|
|
|
1702
3010
|
const limit = 50;
|
|
1703
3011
|
const loadSwaps = react.useCallback(
|
|
1704
3012
|
async (nextOffset, replace = false) => {
|
|
3013
|
+
var _a;
|
|
1705
3014
|
try {
|
|
1706
3015
|
if (replace) {
|
|
1707
3016
|
setIsLoading(true);
|
|
@@ -1731,7 +3040,7 @@ const SwapsPage = () => {
|
|
|
1731
3040
|
}
|
|
1732
3041
|
const payload = await response.json();
|
|
1733
3042
|
setCount(payload.count ?? 0);
|
|
1734
|
-
setOffset(nextOffset + (payload.swaps
|
|
3043
|
+
setOffset(nextOffset + (((_a = payload.swaps) == null ? void 0 : _a.length) ?? 0));
|
|
1735
3044
|
setItems(
|
|
1736
3045
|
(prev) => replace ? payload.swaps ?? [] : [...prev, ...payload.swaps ?? []]
|
|
1737
3046
|
);
|
|
@@ -1889,52 +3198,989 @@ const config$4 = adminSdk.defineRouteConfig({
|
|
|
1889
3198
|
label: "Exchanges",
|
|
1890
3199
|
icon: icons.ArrowPath
|
|
1891
3200
|
});
|
|
1892
|
-
const
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
3201
|
+
const MASKED_VALUE = "••••••••••••";
|
|
3202
|
+
const SENSITIVE_KEY_PATTERNS = [
|
|
3203
|
+
/password|passwd|passphrase/i,
|
|
3204
|
+
/secret/i,
|
|
3205
|
+
/token/i,
|
|
3206
|
+
/api_?key$/i,
|
|
3207
|
+
/private_?key/i,
|
|
3208
|
+
/access_?key/i,
|
|
3209
|
+
/(^|_)hash(ed)?($|_)/i,
|
|
3210
|
+
/(^|_)salt$/i,
|
|
3211
|
+
/^cvv$|^cvc$|security_code/i,
|
|
3212
|
+
/card_?number/i,
|
|
3213
|
+
/account_?number/i,
|
|
3214
|
+
/credential/i,
|
|
3215
|
+
/authorization/i,
|
|
3216
|
+
/recovery_?code/i,
|
|
3217
|
+
/(^|_)otp($|_)/i,
|
|
3218
|
+
/verification_?code/i,
|
|
3219
|
+
/^code_hash$/i,
|
|
3220
|
+
/webhook_?signature/i
|
|
3221
|
+
];
|
|
3222
|
+
const TABLE_SENSITIVE_KEYS = {
|
|
3223
|
+
otp_verification: /* @__PURE__ */ new Set(["code", "value"]),
|
|
3224
|
+
auth_verification: /* @__PURE__ */ new Set(["code", "value"]),
|
|
3225
|
+
auth_mfa_factor: /* @__PURE__ */ new Set(["value", "config"])
|
|
1899
3226
|
};
|
|
1900
|
-
const
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
3227
|
+
const SAFE_KEYS = /* @__PURE__ */ new Set([
|
|
3228
|
+
"token_type",
|
|
3229
|
+
"redacted",
|
|
3230
|
+
"api_key_id",
|
|
3231
|
+
"token_id",
|
|
3232
|
+
"notification_token_id"
|
|
3233
|
+
]);
|
|
3234
|
+
function isSensitiveKey(key) {
|
|
3235
|
+
const normalized = key.trim().toLowerCase();
|
|
3236
|
+
if (SAFE_KEYS.has(normalized)) return false;
|
|
3237
|
+
return SENSITIVE_KEY_PATTERNS.some((pattern) => pattern.test(normalized));
|
|
3238
|
+
}
|
|
3239
|
+
const FULLY_SECRET_TABLES = /* @__PURE__ */ new Set(["auth_mfa_recovery_code", "auth_password_reset_token"]);
|
|
3240
|
+
const ALWAYS_VISIBLE_KEYS = /* @__PURE__ */ new Set(["id", "created_at", "updated_at", "deleted_at", "expires_at", "used_at"]);
|
|
3241
|
+
function maskValue(value, ctx, depth) {
|
|
3242
|
+
var _a;
|
|
3243
|
+
if (Array.isArray(value)) return value.map((item) => maskValue(item, ctx, depth + 1));
|
|
3244
|
+
if (value !== null && typeof value === "object") {
|
|
3245
|
+
const out = {};
|
|
3246
|
+
for (const [key, inner] of Object.entries(value)) {
|
|
3247
|
+
const topLevel = depth === 0;
|
|
3248
|
+
const secret = inner !== null && inner !== void 0 && inner !== "" && (isSensitiveKey(key) || topLevel && ((_a = ctx.tableKeys) == null ? void 0 : _a.has(key.toLowerCase())) === true || topLevel && ctx.maskAll && !ALWAYS_VISIBLE_KEYS.has(key) && !key.endsWith("_id"));
|
|
3249
|
+
if (secret) {
|
|
3250
|
+
ctx.count += 1;
|
|
3251
|
+
out[key] = MASKED_VALUE;
|
|
3252
|
+
} else {
|
|
3253
|
+
out[key] = maskValue(inner, ctx, depth + 1);
|
|
3254
|
+
}
|
|
1911
3255
|
}
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
const
|
|
1930
|
-
const
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.
|
|
1937
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.
|
|
3256
|
+
return out;
|
|
3257
|
+
}
|
|
3258
|
+
return value;
|
|
3259
|
+
}
|
|
3260
|
+
function maskSensitiveData(data, tableName) {
|
|
3261
|
+
const ctx = {
|
|
3262
|
+
count: 0,
|
|
3263
|
+
maskAll: tableName ? FULLY_SECRET_TABLES.has(tableName) : false,
|
|
3264
|
+
tableKeys: tableName ? TABLE_SENSITIVE_KEYS[tableName] : void 0
|
|
3265
|
+
};
|
|
3266
|
+
const value = maskValue(data, ctx, 0);
|
|
3267
|
+
return { value, maskedCount: ctx.count };
|
|
3268
|
+
}
|
|
3269
|
+
const AUTO_EXPAND_DEPTH = 1;
|
|
3270
|
+
const LONG_STRING = 200;
|
|
3271
|
+
const JsonViewer = ({ data }) => {
|
|
3272
|
+
const [generation, setGeneration] = react.useState(0);
|
|
3273
|
+
const [expandAll, setExpandAll] = react.useState(null);
|
|
3274
|
+
const setAll = (value) => {
|
|
3275
|
+
setExpandAll(value);
|
|
3276
|
+
setGeneration((g) => g + 1);
|
|
3277
|
+
};
|
|
3278
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
3279
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
3280
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => setAll(true), children: "Expand all" }),
|
|
3281
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => setAll(false), children: "Collapse all" })
|
|
3282
|
+
] }),
|
|
3283
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-[560px] overflow-auto rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 font-mono text-xs leading-5", children: /* @__PURE__ */ jsxRuntime.jsx(JsonNode, { value: data, depth: 0, forceExpand: expandAll }, generation) })
|
|
3284
|
+
] });
|
|
3285
|
+
};
|
|
3286
|
+
const JsonNode = ({ name, value, depth, forceExpand }) => {
|
|
3287
|
+
const isContainer = value !== null && typeof value === "object";
|
|
3288
|
+
const [open, setOpen] = react.useState(forceExpand ?? depth < AUTO_EXPAND_DEPTH);
|
|
3289
|
+
const label = name !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-fg-subtle", children: [
|
|
3290
|
+
name,
|
|
3291
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: ": " })
|
|
3292
|
+
] }) : null;
|
|
3293
|
+
if (!isContainer) {
|
|
3294
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-start", style: { paddingLeft: depth ? 16 : 0 }, children: [
|
|
3295
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-4 shrink-0" }),
|
|
3296
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 break-words [overflow-wrap:anywhere]", children: [
|
|
3297
|
+
label,
|
|
3298
|
+
/* @__PURE__ */ jsxRuntime.jsx(Primitive, { value })
|
|
3299
|
+
] })
|
|
3300
|
+
] });
|
|
3301
|
+
}
|
|
3302
|
+
const entries = Array.isArray(value) ? value.map((v, i) => [String(i), v]) : Object.entries(value);
|
|
3303
|
+
const [openBracket, closeBracket] = Array.isArray(value) ? ["[", "]"] : ["{", "}"];
|
|
3304
|
+
const summary = Array.isArray(value) ? `${entries.length} items` : `${entries.length} keys`;
|
|
3305
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { paddingLeft: depth ? 16 : 0 }, children: [
|
|
3306
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3307
|
+
"button",
|
|
3308
|
+
{
|
|
3309
|
+
type: "button",
|
|
3310
|
+
onClick: () => setOpen((o) => !o),
|
|
3311
|
+
className: "flex items-start text-left hover:bg-ui-bg-base-hover",
|
|
3312
|
+
"aria-expanded": open,
|
|
3313
|
+
children: [
|
|
3314
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex w-4 shrink-0 items-center pt-0.5 text-ui-fg-muted", children: entries.length ? open ? /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDownMini, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRightMini, {}) : null }),
|
|
3315
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
3316
|
+
label,
|
|
3317
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: openBracket }),
|
|
3318
|
+
!open || entries.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3319
|
+
entries.length ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-1 italic text-ui-fg-muted", children: summary }) : null,
|
|
3320
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: closeBracket })
|
|
3321
|
+
] }) : null
|
|
3322
|
+
] })
|
|
3323
|
+
]
|
|
3324
|
+
}
|
|
3325
|
+
),
|
|
3326
|
+
open && entries.length ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3327
|
+
entries.map(([key, child]) => /* @__PURE__ */ jsxRuntime.jsx(JsonNode, { name: key, value: child, depth: depth + 1, forceExpand }, key)),
|
|
3328
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { paddingLeft: 16 }, className: "text-ui-fg-muted", children: closeBracket })
|
|
3329
|
+
] }) : null
|
|
3330
|
+
] });
|
|
3331
|
+
};
|
|
3332
|
+
const Primitive = ({ value }) => {
|
|
3333
|
+
const [showFull, setShowFull] = react.useState(false);
|
|
3334
|
+
if (value === MASKED_VALUE) {
|
|
3335
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded bg-ui-tag-orange-bg px-1 text-ui-tag-orange-text", title: "Hidden for security", children: MASKED_VALUE });
|
|
3336
|
+
}
|
|
3337
|
+
if (value === null || value === void 0) return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: "null" });
|
|
3338
|
+
if (typeof value === "boolean") return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-tag-purple-text", children: String(value) });
|
|
3339
|
+
if (typeof value === "number") return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-tag-blue-text", children: value });
|
|
3340
|
+
const text = String(value);
|
|
3341
|
+
const truncated = !showFull && text.length > LONG_STRING;
|
|
3342
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: ui.clx("text-ui-tag-green-text"), children: [
|
|
3343
|
+
'"',
|
|
3344
|
+
truncated ? `${text.slice(0, LONG_STRING)}…` : text,
|
|
3345
|
+
'"',
|
|
3346
|
+
text.length > LONG_STRING ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3347
|
+
"button",
|
|
3348
|
+
{
|
|
3349
|
+
type: "button",
|
|
3350
|
+
onClick: () => setShowFull((s2) => !s2),
|
|
3351
|
+
className: "ml-1 font-sans text-ui-fg-interactive hover:underline",
|
|
3352
|
+
children: showFull ? "show less" : `show all (${text.length} chars)`
|
|
3353
|
+
}
|
|
3354
|
+
) : null
|
|
3355
|
+
] });
|
|
3356
|
+
};
|
|
3357
|
+
const GUIDANCE = {
|
|
3358
|
+
orders: {
|
|
3359
|
+
headline: "Order data affects customers, payments and reports.",
|
|
3360
|
+
recreate: "Orders can’t be recreated identically from the admin. If this deletion was not intended, ask a developer to restore it from a database backup using the snapshot on this page.",
|
|
3361
|
+
adminSection: { label: "Go to Orders", path: "/orders" }
|
|
3362
|
+
},
|
|
3363
|
+
carts: {
|
|
3364
|
+
headline: "Carts are usually cleaned up automatically.",
|
|
3365
|
+
recreate: "No action is normally needed. Customers can simply add items to a new cart."
|
|
3366
|
+
},
|
|
3367
|
+
customers: {
|
|
3368
|
+
headline: "Customer data may be needed for orders, support and compliance.",
|
|
3369
|
+
recreate: "If it was deleted by mistake, recreate it from Customers using the values shown above. A recreated customer gets a new ID and must reset their password.",
|
|
3370
|
+
adminSection: { label: "Go to Customers", path: "/customers" }
|
|
3371
|
+
},
|
|
3372
|
+
catalog: {
|
|
3373
|
+
headline: "Catalog changes affect what customers can see and buy.",
|
|
3374
|
+
recreate: "If it was deleted by mistake, recreate it from Products using the values shown above. It will get a new ID.",
|
|
3375
|
+
adminSection: { label: "Go to Products", path: "/products" }
|
|
3376
|
+
},
|
|
3377
|
+
pricing: {
|
|
3378
|
+
headline: "Pricing and promotions affect what customers pay.",
|
|
3379
|
+
recreate: "If it was deleted by mistake, recreate it from Promotions or Price Lists using the values shown above.",
|
|
3380
|
+
adminSection: { label: "Go to Promotions", path: "/promotions" }
|
|
3381
|
+
},
|
|
3382
|
+
payments: {
|
|
3383
|
+
headline: "Payment records are financial data.",
|
|
3384
|
+
recreate: "Do not recreate payment records by hand—this can make balances inconsistent. If this deletion was not expected, escalate to a developer or your finance team."
|
|
3385
|
+
},
|
|
3386
|
+
fulfillment: {
|
|
3387
|
+
headline: "Shipping and fulfillment settings affect checkout and delivery.",
|
|
3388
|
+
recreate: "If it was deleted by mistake, recreate it from Settings → Locations & Shipping using the values shown above.",
|
|
3389
|
+
adminSection: { label: "Go to Settings", path: "/settings" }
|
|
3390
|
+
},
|
|
3391
|
+
inventory: {
|
|
3392
|
+
headline: "Inventory changes can affect stock levels and availability.",
|
|
3393
|
+
recreate: "If it was deleted by mistake, recreate it from Inventory using the values shown above and re-check stock quantities.",
|
|
3394
|
+
adminSection: { label: "Go to Inventory", path: "/inventory" }
|
|
3395
|
+
},
|
|
3396
|
+
wallet: {
|
|
3397
|
+
headline: "Wallet and credit records are financial data.",
|
|
3398
|
+
recreate: "Do not recreate balances by hand. If this deletion was not expected, escalate to a developer or your finance team so balances can be verified."
|
|
3399
|
+
},
|
|
3400
|
+
access: {
|
|
3401
|
+
headline: "Access records control who can sign in.",
|
|
3402
|
+
recreate: "Secrets such as passwords and keys can’t be restored. Re-invite the user or create a new API key if access is still needed.",
|
|
3403
|
+
adminSection: { label: "Go to Settings", path: "/settings" }
|
|
3404
|
+
},
|
|
3405
|
+
store: {
|
|
3406
|
+
headline: "Store settings affect regions, currencies and taxes.",
|
|
3407
|
+
recreate: "If it was deleted by mistake, recreate it from Settings using the values shown above.",
|
|
3408
|
+
adminSection: { label: "Go to Settings", path: "/settings" }
|
|
3409
|
+
},
|
|
3410
|
+
engagement: {
|
|
3411
|
+
headline: "Customer-generated content.",
|
|
3412
|
+
recreate: "These usually can’t be recreated on the customer’s behalf. Keep the snapshot on this page if you need a record of it."
|
|
3413
|
+
},
|
|
3414
|
+
notifications: {
|
|
3415
|
+
headline: "Notification records are usually cleaned up automatically.",
|
|
3416
|
+
recreate: "No action is normally needed."
|
|
3417
|
+
},
|
|
3418
|
+
system: {
|
|
3419
|
+
headline: "Internal system data, usually removed automatically by the platform.",
|
|
3420
|
+
recreate: "No action is normally needed. If you suspect a problem, share this page with a developer."
|
|
3421
|
+
}
|
|
3422
|
+
};
|
|
3423
|
+
function getNextSteps(category) {
|
|
3424
|
+
return GUIDANCE[category];
|
|
3425
|
+
}
|
|
3426
|
+
const RELATED_LINKS = [
|
|
3427
|
+
{ key: "order_id", label: "Order", path: (id) => `/orders/${id}`, selfTables: ["order"] },
|
|
3428
|
+
{ key: "customer_id", label: "Customer", path: (id) => `/customers/${id}`, selfTables: ["customer"] },
|
|
3429
|
+
{ key: "product_id", label: "Product", path: (id) => `/products/${id}`, selfTables: ["product"] }
|
|
3430
|
+
];
|
|
3431
|
+
function getRelatedLinks(tableName, oldData) {
|
|
3432
|
+
if (!oldData) return [];
|
|
3433
|
+
return RELATED_LINKS.flatMap((link) => {
|
|
3434
|
+
const id = oldData[link.key];
|
|
3435
|
+
if (link.selfTables.includes(tableName) || typeof id !== "string" || !id.trim()) return [];
|
|
3436
|
+
return [{ label: link.label, id, path: link.path(id) }];
|
|
3437
|
+
});
|
|
3438
|
+
}
|
|
3439
|
+
const fullName = (row) => {
|
|
3440
|
+
const parts = [row.first_name, row.last_name].filter(
|
|
3441
|
+
(part) => typeof part === "string" && part.trim() !== ""
|
|
3442
|
+
);
|
|
3443
|
+
return parts.length ? parts.join(" ") : void 0;
|
|
3444
|
+
};
|
|
3445
|
+
const addressLine = (row) => {
|
|
3446
|
+
const parts = [row.address_1, row.address_2, row.city, row.province, row.postal_code, row.country_code].filter((part) => typeof part === "string" && part.trim() !== "").map((part) => part.trim());
|
|
3447
|
+
return parts.length ? parts.join(", ") : void 0;
|
|
3448
|
+
};
|
|
3449
|
+
const NAME = { key: "name", label: "Name", derive: fullName };
|
|
3450
|
+
const ADDRESS = { key: "address", label: "Address", derive: addressLine };
|
|
3451
|
+
const CREATED = { key: "created_at", label: "Created", kind: "date" };
|
|
3452
|
+
const ENTITY_FIELDS = {
|
|
3453
|
+
order: [
|
|
3454
|
+
{ key: "display_id", label: "Order number" },
|
|
3455
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
3456
|
+
{ key: "email", label: "Customer email" },
|
|
3457
|
+
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
3458
|
+
{ key: "currency_code", label: "Currency" },
|
|
3459
|
+
{ key: "region_id", label: "Region ID", kind: "id" },
|
|
3460
|
+
{ key: "sales_channel_id", label: "Sales channel ID", kind: "id" },
|
|
3461
|
+
{ key: "canceled_at", label: "Canceled", kind: "date" },
|
|
3462
|
+
CREATED
|
|
3463
|
+
],
|
|
3464
|
+
order_line_item: [
|
|
3465
|
+
{ key: "title", label: "Item" },
|
|
3466
|
+
{ key: "variant_title", label: "Variant" },
|
|
3467
|
+
{ key: "variant_sku", label: "SKU" },
|
|
3468
|
+
{ key: "unit_price", label: "Unit price", kind: "money" },
|
|
3469
|
+
{ key: "product_id", label: "Product ID", kind: "id" },
|
|
3470
|
+
{ key: "variant_id", label: "Variant ID", kind: "id" },
|
|
3471
|
+
CREATED
|
|
3472
|
+
],
|
|
3473
|
+
cart_line_item: [
|
|
3474
|
+
{ key: "title", label: "Item" },
|
|
3475
|
+
{ key: "variant_sku", label: "SKU" },
|
|
3476
|
+
{ key: "quantity", label: "Quantity", kind: "number" },
|
|
3477
|
+
{ key: "unit_price", label: "Unit price", kind: "money" },
|
|
3478
|
+
{ key: "cart_id", label: "Cart ID", kind: "id" },
|
|
3479
|
+
{ key: "variant_id", label: "Variant ID", kind: "id" },
|
|
3480
|
+
CREATED
|
|
3481
|
+
],
|
|
3482
|
+
cart: [
|
|
3483
|
+
{ key: "email", label: "Email" },
|
|
3484
|
+
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
3485
|
+
{ key: "currency_code", label: "Currency" },
|
|
3486
|
+
{ key: "region_id", label: "Region ID", kind: "id" },
|
|
3487
|
+
{ key: "completed_at", label: "Completed", kind: "date" },
|
|
3488
|
+
CREATED
|
|
3489
|
+
],
|
|
3490
|
+
customer: [
|
|
3491
|
+
NAME,
|
|
3492
|
+
{ key: "email", label: "Email" },
|
|
3493
|
+
{ key: "phone", label: "Phone" },
|
|
3494
|
+
{ key: "company_name", label: "Company" },
|
|
3495
|
+
{ key: "has_account", label: "Registered account", kind: "boolean" },
|
|
3496
|
+
CREATED
|
|
3497
|
+
],
|
|
3498
|
+
customer_address: [
|
|
3499
|
+
{ key: "address_name", label: "Label" },
|
|
3500
|
+
NAME,
|
|
3501
|
+
ADDRESS,
|
|
3502
|
+
{ key: "phone", label: "Phone" },
|
|
3503
|
+
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
3504
|
+
{ key: "is_default_shipping", label: "Default shipping", kind: "boolean" },
|
|
3505
|
+
CREATED
|
|
3506
|
+
],
|
|
3507
|
+
order_address: [NAME, ADDRESS, { key: "phone", label: "Phone" }, CREATED],
|
|
3508
|
+
cart_address: [NAME, ADDRESS, { key: "phone", label: "Phone" }, CREATED],
|
|
3509
|
+
product: [
|
|
3510
|
+
{ key: "title", label: "Title" },
|
|
3511
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
3512
|
+
{ key: "handle", label: "Handle" },
|
|
3513
|
+
{ key: "subtitle", label: "Subtitle" },
|
|
3514
|
+
{ key: "collection_id", label: "Collection ID", kind: "id" },
|
|
3515
|
+
{ key: "is_giftcard", label: "Gift card", kind: "boolean" },
|
|
3516
|
+
CREATED
|
|
3517
|
+
],
|
|
3518
|
+
product_variant: [
|
|
3519
|
+
{ key: "title", label: "Title" },
|
|
3520
|
+
{ key: "sku", label: "SKU" },
|
|
3521
|
+
{ key: "barcode", label: "Barcode" },
|
|
3522
|
+
{ key: "product_id", label: "Product ID", kind: "id" },
|
|
3523
|
+
{ key: "manage_inventory", label: "Manages inventory", kind: "boolean" },
|
|
3524
|
+
CREATED
|
|
3525
|
+
],
|
|
3526
|
+
product_category: [
|
|
3527
|
+
{ key: "name", label: "Name" },
|
|
3528
|
+
{ key: "handle", label: "Handle" },
|
|
3529
|
+
{ key: "is_active", label: "Active", kind: "boolean" },
|
|
3530
|
+
{ key: "parent_category_id", label: "Parent category ID", kind: "id" },
|
|
3531
|
+
CREATED
|
|
3532
|
+
],
|
|
3533
|
+
product_collection: [{ key: "title", label: "Title" }, { key: "handle", label: "Handle" }, CREATED],
|
|
3534
|
+
payment: [
|
|
3535
|
+
{ key: "amount", label: "Amount", kind: "money" },
|
|
3536
|
+
{ key: "currency_code", label: "Currency" },
|
|
3537
|
+
{ key: "provider_id", label: "Provider" },
|
|
3538
|
+
{ key: "captured_at", label: "Captured", kind: "date" },
|
|
3539
|
+
{ key: "canceled_at", label: "Canceled", kind: "date" },
|
|
3540
|
+
{ key: "payment_collection_id", label: "Payment collection ID", kind: "id" },
|
|
3541
|
+
CREATED
|
|
3542
|
+
],
|
|
3543
|
+
payment_session: [
|
|
3544
|
+
{ key: "amount", label: "Amount", kind: "money" },
|
|
3545
|
+
{ key: "currency_code", label: "Currency" },
|
|
3546
|
+
{ key: "provider_id", label: "Provider" },
|
|
3547
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
3548
|
+
{ key: "payment_collection_id", label: "Payment collection ID", kind: "id" },
|
|
3549
|
+
CREATED
|
|
3550
|
+
],
|
|
3551
|
+
payment_collection: [
|
|
3552
|
+
{ key: "amount", label: "Amount", kind: "money" },
|
|
3553
|
+
{ key: "currency_code", label: "Currency" },
|
|
3554
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
3555
|
+
CREATED
|
|
3556
|
+
],
|
|
3557
|
+
refund: [
|
|
3558
|
+
{ key: "amount", label: "Amount", kind: "money" },
|
|
3559
|
+
{ key: "payment_id", label: "Payment ID", kind: "id" },
|
|
3560
|
+
{ key: "refund_reason_id", label: "Refund reason ID", kind: "id" },
|
|
3561
|
+
{ key: "note", label: "Note" },
|
|
3562
|
+
{ key: "created_by", label: "Created by" },
|
|
3563
|
+
CREATED
|
|
3564
|
+
],
|
|
3565
|
+
return: [
|
|
3566
|
+
{ key: "display_id", label: "Return number" },
|
|
3567
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
3568
|
+
{ key: "order_id", label: "Order ID", kind: "id" },
|
|
3569
|
+
{ key: "refund_amount", label: "Refund amount", kind: "money" },
|
|
3570
|
+
{ key: "received_at", label: "Received", kind: "date" },
|
|
3571
|
+
CREATED
|
|
3572
|
+
],
|
|
3573
|
+
payment_detail: [
|
|
3574
|
+
{ key: "type", label: "Method type" },
|
|
3575
|
+
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
3576
|
+
{ key: "is_default", label: "Default method", kind: "boolean" },
|
|
3577
|
+
CREATED
|
|
3578
|
+
],
|
|
3579
|
+
user: [NAME, { key: "email", label: "Email" }, CREATED],
|
|
3580
|
+
invite: [
|
|
3581
|
+
{ key: "email", label: "Email" },
|
|
3582
|
+
{ key: "accepted", label: "Accepted", kind: "boolean" },
|
|
3583
|
+
{ key: "expires_at", label: "Expires", kind: "date" },
|
|
3584
|
+
CREATED
|
|
3585
|
+
],
|
|
3586
|
+
api_key: [
|
|
3587
|
+
{ key: "title", label: "Title" },
|
|
3588
|
+
{ key: "type", label: "Type" },
|
|
3589
|
+
{ key: "redacted", label: "Key (redacted)" },
|
|
3590
|
+
{ key: "revoked_at", label: "Revoked", kind: "date" },
|
|
3591
|
+
CREATED
|
|
3592
|
+
],
|
|
3593
|
+
promotion: [
|
|
3594
|
+
{ key: "code", label: "Promotion code" },
|
|
3595
|
+
{ key: "type", label: "Type" },
|
|
3596
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
3597
|
+
{ key: "is_automatic", label: "Automatic", kind: "boolean" },
|
|
3598
|
+
CREATED
|
|
3599
|
+
],
|
|
3600
|
+
fulfillment: [
|
|
3601
|
+
{ key: "provider_id", label: "Provider" },
|
|
3602
|
+
{ key: "location_id", label: "Location ID", kind: "id" },
|
|
3603
|
+
{ key: "shipped_at", label: "Shipped", kind: "date" },
|
|
3604
|
+
{ key: "delivered_at", label: "Delivered", kind: "date" },
|
|
3605
|
+
{ key: "canceled_at", label: "Canceled", kind: "date" },
|
|
3606
|
+
CREATED
|
|
3607
|
+
],
|
|
3608
|
+
inventory_item: [
|
|
3609
|
+
{ key: "sku", label: "SKU" },
|
|
3610
|
+
{ key: "title", label: "Title" },
|
|
3611
|
+
{ key: "requires_shipping", label: "Requires shipping", kind: "boolean" },
|
|
3612
|
+
CREATED
|
|
3613
|
+
],
|
|
3614
|
+
inventory_level: [
|
|
3615
|
+
{ key: "inventory_item_id", label: "Inventory item ID", kind: "id" },
|
|
3616
|
+
{ key: "location_id", label: "Location ID", kind: "id" },
|
|
3617
|
+
{ key: "stocked_quantity", label: "Stocked", kind: "number" },
|
|
3618
|
+
{ key: "reserved_quantity", label: "Reserved", kind: "number" },
|
|
3619
|
+
CREATED
|
|
3620
|
+
],
|
|
3621
|
+
review: [
|
|
3622
|
+
{ key: "title", label: "Title" },
|
|
3623
|
+
{ key: "rating", label: "Rating", kind: "number" },
|
|
3624
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
3625
|
+
{ key: "product_id", label: "Product ID", kind: "id" },
|
|
3626
|
+
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
3627
|
+
CREATED
|
|
3628
|
+
]
|
|
3629
|
+
};
|
|
3630
|
+
const GENERIC_FIELDS = [
|
|
3631
|
+
{ key: "display_id", label: "Number" },
|
|
3632
|
+
{ key: "title", label: "Title" },
|
|
3633
|
+
{ key: "name", label: "Name" },
|
|
3634
|
+
NAME,
|
|
3635
|
+
{ key: "email", label: "Email" },
|
|
3636
|
+
{ key: "phone", label: "Phone" },
|
|
3637
|
+
{ key: "handle", label: "Handle" },
|
|
3638
|
+
{ key: "sku", label: "SKU" },
|
|
3639
|
+
{ key: "code", label: "Code" },
|
|
3640
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
3641
|
+
{ key: "type", label: "Type" },
|
|
3642
|
+
{ key: "amount", label: "Amount", kind: "money" },
|
|
3643
|
+
{ key: "quantity", label: "Quantity", kind: "number" },
|
|
3644
|
+
{ key: "currency_code", label: "Currency" },
|
|
3645
|
+
{ key: "order_id", label: "Order ID", kind: "id" },
|
|
3646
|
+
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
3647
|
+
{ key: "product_id", label: "Product ID", kind: "id" },
|
|
3648
|
+
{ key: "payment_id", label: "Payment ID", kind: "id" },
|
|
3649
|
+
{ key: "provider_id", label: "Provider" },
|
|
3650
|
+
CREATED,
|
|
3651
|
+
{ key: "updated_at", label: "Last updated", kind: "date" }
|
|
3652
|
+
];
|
|
3653
|
+
const MAX_GENERIC_FIELDS = 8;
|
|
3654
|
+
function amountOf(value) {
|
|
3655
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
3656
|
+
if (typeof value === "string" && value.trim() !== "" && Number.isFinite(Number(value))) return Number(value);
|
|
3657
|
+
if (value !== null && typeof value === "object" && "value" in value) {
|
|
3658
|
+
return amountOf(value.value);
|
|
3659
|
+
}
|
|
3660
|
+
return null;
|
|
3661
|
+
}
|
|
3662
|
+
function formatValue(raw, kind, row) {
|
|
3663
|
+
if (raw === null || raw === void 0 || raw === "") return null;
|
|
3664
|
+
if (raw === MASKED_VALUE) return { value: MASKED_VALUE, kind: "masked" };
|
|
3665
|
+
switch (kind) {
|
|
3666
|
+
case "money": {
|
|
3667
|
+
const amount = amountOf(raw);
|
|
3668
|
+
if (amount === null) return null;
|
|
3669
|
+
const currency = typeof row.currency_code === "string" ? row.currency_code : null;
|
|
3670
|
+
return { value: formatMoney(amount, currency), kind };
|
|
3671
|
+
}
|
|
3672
|
+
case "date":
|
|
3673
|
+
return typeof raw === "string" || raw instanceof Date ? { value: formatDate(raw), kind } : null;
|
|
3674
|
+
case "boolean":
|
|
3675
|
+
return { value: raw === true || raw === "true" ? "Yes" : "No", kind };
|
|
3676
|
+
case "number": {
|
|
3677
|
+
const n = amountOf(raw);
|
|
3678
|
+
return n === null ? null : { value: formatNumber(n), kind };
|
|
3679
|
+
}
|
|
3680
|
+
case "status":
|
|
3681
|
+
return { value: String(raw).replace(/_/g, " "), kind };
|
|
3682
|
+
default:
|
|
3683
|
+
if (typeof raw === "object") return null;
|
|
3684
|
+
if (typeof raw === "string" && raw.length > 160) return { value: `${raw.slice(0, 157)}…`, kind };
|
|
3685
|
+
return { value: String(raw), kind };
|
|
3686
|
+
}
|
|
3687
|
+
}
|
|
3688
|
+
function summarizeOldData(tableName, oldData) {
|
|
3689
|
+
if (!oldData) return [];
|
|
3690
|
+
const { value: row } = maskSensitiveData(oldData, tableName);
|
|
3691
|
+
const specific = ENTITY_FIELDS[tableName];
|
|
3692
|
+
const specs = specific ?? GENERIC_FIELDS;
|
|
3693
|
+
const fields = [];
|
|
3694
|
+
const seenLabels = /* @__PURE__ */ new Set();
|
|
3695
|
+
for (const spec of specs) {
|
|
3696
|
+
const raw = spec.derive ? spec.derive(row) : row[spec.key];
|
|
3697
|
+
const formatted = formatValue(raw, spec.kind ?? "text", row);
|
|
3698
|
+
if (!formatted || seenLabels.has(spec.label)) continue;
|
|
3699
|
+
seenLabels.add(spec.label);
|
|
3700
|
+
const value = spec.key === "currency_code" ? formatted.value.toUpperCase() : formatted.value;
|
|
3701
|
+
fields.push({ key: spec.key, label: spec.label, value, kind: formatted.kind });
|
|
3702
|
+
if (!specific && fields.length >= MAX_GENERIC_FIELDS) break;
|
|
3703
|
+
}
|
|
3704
|
+
return fields;
|
|
3705
|
+
}
|
|
3706
|
+
function readLastListSearch() {
|
|
3707
|
+
try {
|
|
3708
|
+
return window.sessionStorage.getItem(LAST_LIST_URL_KEY) ?? "";
|
|
3709
|
+
} catch {
|
|
3710
|
+
return "";
|
|
3711
|
+
}
|
|
3712
|
+
}
|
|
3713
|
+
const DeletedRecordDetailPage = () => {
|
|
3714
|
+
var _a;
|
|
3715
|
+
const navigate = reactRouterDom.useNavigate();
|
|
3716
|
+
const location = reactRouterDom.useLocation();
|
|
3717
|
+
const { id = "" } = reactRouterDom.useParams();
|
|
3718
|
+
const [state, setState] = react.useState({ status: "loading" });
|
|
3719
|
+
const [reloadToken, setReloadToken] = react.useState(0);
|
|
3720
|
+
const cameFromList = ((_a = location.state) == null ? void 0 : _a.fromList) === true;
|
|
3721
|
+
const goBack = () => {
|
|
3722
|
+
if (cameFromList) navigate(-1);
|
|
3723
|
+
else navigate(`/deleted-records-audit${readLastListSearch()}`);
|
|
3724
|
+
};
|
|
3725
|
+
react.useEffect(() => {
|
|
3726
|
+
const controller = new AbortController();
|
|
3727
|
+
setState({ status: "loading" });
|
|
3728
|
+
fetchAuditDetail(id, controller.signal).then((audit) => setState({ status: "ready", audit })).catch((e) => {
|
|
3729
|
+
if (controller.signal.aborted) return;
|
|
3730
|
+
setState({
|
|
3731
|
+
status: "error",
|
|
3732
|
+
message: e instanceof Error ? e.message : "Unknown error",
|
|
3733
|
+
notFound: e instanceof AuditApiError && e.status === 404
|
|
3734
|
+
});
|
|
3735
|
+
});
|
|
3736
|
+
return () => controller.abort();
|
|
3737
|
+
}, [id, reloadToken]);
|
|
3738
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-3 md:p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-4 md:p-6", children: [
|
|
3739
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: "transparent", size: "small", onClick: goBack, className: "-ml-2", children: [
|
|
3740
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, {}),
|
|
3741
|
+
"Back to Deleted Records"
|
|
3742
|
+
] }) }),
|
|
3743
|
+
state.status === "loading" ? /* @__PURE__ */ jsxRuntime.jsx(DetailSkeleton, {}) : state.status === "error" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3744
|
+
DetailError,
|
|
3745
|
+
{
|
|
3746
|
+
notFound: state.notFound,
|
|
3747
|
+
message: state.message,
|
|
3748
|
+
onRetry: () => setReloadToken((t) => t + 1),
|
|
3749
|
+
onBack: goBack
|
|
3750
|
+
}
|
|
3751
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(DetailContent, { audit: state.audit })
|
|
3752
|
+
] }) });
|
|
3753
|
+
};
|
|
3754
|
+
const DetailContent = ({ audit }) => {
|
|
3755
|
+
const navigate = reactRouterDom.useNavigate();
|
|
3756
|
+
const entity = getEntityInfo(audit.table_name);
|
|
3757
|
+
const source = describeSource(audit.source);
|
|
3758
|
+
const summary = react.useMemo(() => summarizeOldData(audit.table_name, audit.old_data), [audit]);
|
|
3759
|
+
const masked = react.useMemo(() => maskSensitiveData(audit.old_data, audit.table_name), [audit]);
|
|
3760
|
+
const guidance = getNextSteps(entity.category.id);
|
|
3761
|
+
const related = getRelatedLinks(audit.table_name, audit.old_data);
|
|
3762
|
+
const [showRaw, setShowRaw] = react.useState(false);
|
|
3763
|
+
const copyJson = async () => {
|
|
3764
|
+
try {
|
|
3765
|
+
await navigator.clipboard.writeText(JSON.stringify(masked.value, null, 2));
|
|
3766
|
+
ui.toast.success("Record data copied", {
|
|
3767
|
+
description: masked.maskedCount ? "Sensitive values were left hidden." : void 0
|
|
3768
|
+
});
|
|
3769
|
+
} catch {
|
|
3770
|
+
ui.toast.error("Couldn’t copy to clipboard");
|
|
3771
|
+
}
|
|
3772
|
+
};
|
|
3773
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3774
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3", children: [
|
|
3775
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
3776
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Badge, { size: "small", color: "red", children: [
|
|
3777
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.Trash, {}),
|
|
3778
|
+
"Deleted"
|
|
3779
|
+
] }),
|
|
3780
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: entity.category.label })
|
|
3781
|
+
] }),
|
|
3782
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Heading, { level: "h1", children: [
|
|
3783
|
+
"Deleted ",
|
|
3784
|
+
entity.label
|
|
3785
|
+
] }),
|
|
3786
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3787
|
+
/* @__PURE__ */ jsxRuntime.jsx(CopyableId, { value: audit.record_id, emptyLabel: "This record type has no ID column", className: "text-sm" }),
|
|
3788
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: [
|
|
3789
|
+
"Database table: ",
|
|
3790
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: audit.table_name })
|
|
3791
|
+
] })
|
|
3792
|
+
] })
|
|
3793
|
+
] }),
|
|
3794
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 rounded-lg border border-ui-tag-orange-border bg-ui-tag-orange-bg px-4 py-3", children: [
|
|
3795
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.InformationCircle, { className: "mt-0.5 shrink-0 text-ui-tag-orange-icon" }),
|
|
3796
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-tag-orange-text", children: [
|
|
3797
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "This is a historical snapshot" }),
|
|
3798
|
+
" captured immediately before deletion. The record no longer exists in the database, so changes elsewhere in the admin are not reflected here."
|
|
3799
|
+
] })
|
|
3800
|
+
] }),
|
|
3801
|
+
/* @__PURE__ */ jsxRuntime.jsx(Section, { title: "Deletion information", children: /* @__PURE__ */ jsxRuntime.jsxs("dl", { className: "grid grid-cols-1 gap-x-6 gap-y-4 sm:grid-cols-2", children: [
|
|
3802
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Deleted", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
|
|
3803
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: formatExactDateTime(audit.occurred_at) }),
|
|
3804
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1 text-xs text-ui-fg-muted", children: [
|
|
3805
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ClockSolid, { className: "size-3" }),
|
|
3806
|
+
formatRelativeTime(audit.occurred_at)
|
|
3807
|
+
] })
|
|
3808
|
+
] }) }),
|
|
3809
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Deleted by", children: audit.deleted_by ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "break-all text-sm text-ui-fg-base", children: audit.deleted_by }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-muted", children: "Not recorded" }) }),
|
|
3810
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Source", children: source.kind === "unknown" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-muted", children: "Unknown" }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "small", color: sourceBadgeColor(source.kind), children: source.label }) }),
|
|
3811
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Action", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Permanently deleted" }) })
|
|
3812
|
+
] }) }),
|
|
3813
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3814
|
+
Section,
|
|
3815
|
+
{
|
|
3816
|
+
title: "Record summary",
|
|
3817
|
+
description: `Key details of this ${entity.label.toLowerCase()} at the moment it was deleted.`,
|
|
3818
|
+
children: summary.length ? /* @__PURE__ */ jsxRuntime.jsx("dl", { className: "grid grid-cols-1 gap-x-6 gap-y-4 sm:grid-cols-2", children: summary.map((field) => /* @__PURE__ */ jsxRuntime.jsx(Field, { label: field.label, children: field.kind === "id" ? /* @__PURE__ */ jsxRuntime.jsx(CopyableId, { value: field.value }) : field.kind === "status" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", color: "grey", className: "capitalize", children: field.value }) : field.kind === "masked" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-muted", children: "Hidden for security" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "break-words text-sm text-ui-fg-base", children: field.value }) }, field.label)) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "No key details could be extracted for this record type. See the original record data below." })
|
|
3819
|
+
}
|
|
3820
|
+
),
|
|
3821
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3822
|
+
Section,
|
|
3823
|
+
{
|
|
3824
|
+
title: "Original record data",
|
|
3825
|
+
description: "The complete data captured before deletion.",
|
|
3826
|
+
actions: showRaw && audit.old_data ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: "secondary", size: "small", onClick: copyJson, children: [
|
|
3827
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.SquareTwoStack, {}),
|
|
3828
|
+
"Copy JSON"
|
|
3829
|
+
] }) : null,
|
|
3830
|
+
children: audit.old_data ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
3831
|
+
masked.maskedCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3832
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ShieldCheck, { className: "shrink-0 text-ui-fg-muted" }),
|
|
3833
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
3834
|
+
masked.maskedCount,
|
|
3835
|
+
" sensitive ",
|
|
3836
|
+
masked.maskedCount === 1 ? "value is" : "values are",
|
|
3837
|
+
" hidden for security (passwords, tokens, card or account numbers)."
|
|
3838
|
+
] })
|
|
3839
|
+
] }) : null,
|
|
3840
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: "secondary", size: "small", onClick: () => setShowRaw((s2) => !s2), "aria-expanded": showRaw, children: [
|
|
3841
|
+
showRaw ? /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDownMini, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRightMini, {}),
|
|
3842
|
+
showRaw ? "Hide full record" : "View full record"
|
|
3843
|
+
] }) }),
|
|
3844
|
+
showRaw ? /* @__PURE__ */ jsxRuntime.jsx(JsonViewer, { data: masked.value }) : null
|
|
3845
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "No data was captured for this deletion." })
|
|
3846
|
+
}
|
|
3847
|
+
),
|
|
3848
|
+
/* @__PURE__ */ jsxRuntime.jsx(Section, { title: "What you can do now", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
3849
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-base", children: [
|
|
3850
|
+
"This record was permanently deleted. ",
|
|
3851
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Automatic restoration is not available" }),
|
|
3852
|
+
" ",
|
|
3853
|
+
"from this screen."
|
|
3854
|
+
] }),
|
|
3855
|
+
/* @__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: [
|
|
3856
|
+
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
3857
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: "Check whether this was expected." }),
|
|
3858
|
+
" ",
|
|
3859
|
+
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)}.`,
|
|
3860
|
+
" ",
|
|
3861
|
+
guidance.headline
|
|
3862
|
+
] }),
|
|
3863
|
+
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
3864
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: "If it needs to come back:" }),
|
|
3865
|
+
" ",
|
|
3866
|
+
guidance.recreate
|
|
3867
|
+
] }),
|
|
3868
|
+
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
3869
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: "Need the details?" }),
|
|
3870
|
+
" Use “View full record” above to see or copy everything that was stored. Sensitive values stay hidden."
|
|
3871
|
+
] })
|
|
3872
|
+
] }),
|
|
3873
|
+
guidance.adminSection || related.length ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
3874
|
+
guidance.adminSection ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", size: "small", onClick: () => navigate(guidance.adminSection.path), children: guidance.adminSection.label }) : null,
|
|
3875
|
+
related.map((link) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3876
|
+
ui.Button,
|
|
3877
|
+
{
|
|
3878
|
+
variant: "transparent",
|
|
3879
|
+
size: "small",
|
|
3880
|
+
onClick: () => navigate(link.path),
|
|
3881
|
+
title: `Opens ${link.label.toLowerCase()} ${link.id} if it still exists`,
|
|
3882
|
+
children: [
|
|
3883
|
+
"Open related ",
|
|
3884
|
+
link.label.toLowerCase(),
|
|
3885
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRightMini, {})
|
|
3886
|
+
]
|
|
3887
|
+
},
|
|
3888
|
+
link.path
|
|
3889
|
+
))
|
|
3890
|
+
] }) : null,
|
|
3891
|
+
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
|
|
3892
|
+
] }) })
|
|
3893
|
+
] });
|
|
3894
|
+
};
|
|
3895
|
+
const Section = ({
|
|
3896
|
+
title,
|
|
3897
|
+
description,
|
|
3898
|
+
actions,
|
|
3899
|
+
children
|
|
3900
|
+
}) => /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "flex flex-col gap-4 rounded-lg border border-ui-border-base p-5", children: [
|
|
3901
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-2", children: [
|
|
3902
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
3903
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: title }),
|
|
3904
|
+
description ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: description }) : null
|
|
3905
|
+
] }),
|
|
3906
|
+
actions
|
|
3907
|
+
] }),
|
|
3908
|
+
children
|
|
3909
|
+
] });
|
|
3910
|
+
const Field = ({ label, children }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
|
|
3911
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-xs font-medium uppercase tracking-wide text-ui-fg-muted", children: label }),
|
|
3912
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { className: "min-w-0", children })
|
|
3913
|
+
] });
|
|
3914
|
+
const DetailSkeleton = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", "aria-busy": "true", children: [
|
|
3915
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
3916
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-5 w-24 rounded-full" }),
|
|
3917
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-8 w-64" }),
|
|
3918
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-4 w-48" })
|
|
3919
|
+
] }),
|
|
3920
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-14 w-full" }),
|
|
3921
|
+
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: [
|
|
3922
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-5 w-40" }),
|
|
3923
|
+
/* @__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: [
|
|
3924
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-3 w-20" }),
|
|
3925
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-4 w-36" })
|
|
3926
|
+
] }, j)) })
|
|
3927
|
+
] }, i))
|
|
3928
|
+
] });
|
|
3929
|
+
const DetailError = ({
|
|
3930
|
+
notFound,
|
|
3931
|
+
message,
|
|
3932
|
+
onRetry,
|
|
3933
|
+
onBack
|
|
3934
|
+
}) => /* @__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: [
|
|
3935
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ExclamationCircle, { className: ui.clx(notFound ? "text-ui-fg-muted" : "text-ui-fg-error") }),
|
|
3936
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: notFound ? "Audit entry not found" : "Unable to load this deleted record" }),
|
|
3937
|
+
/* @__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." }),
|
|
3938
|
+
!notFound ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "max-w-md font-mono text-ui-fg-muted", children: message }) : null,
|
|
3939
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex gap-2", children: [
|
|
3940
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", size: "small", onClick: onBack, children: "Back to Deleted Records" }),
|
|
3941
|
+
!notFound ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", size: "small", onClick: onRetry, children: "Try again" }) : null
|
|
3942
|
+
] })
|
|
3943
|
+
] });
|
|
3944
|
+
adminSdk.defineRouteConfig({});
|
|
3945
|
+
const getStatusBadgeClass$3 = (status) => {
|
|
3946
|
+
const s2 = status.toLowerCase();
|
|
3947
|
+
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
3948
|
+
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
3949
|
+
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
3950
|
+
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
3951
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
3952
|
+
};
|
|
3953
|
+
const formatAmount = (value) => {
|
|
3954
|
+
return String(value);
|
|
3955
|
+
};
|
|
3956
|
+
const RefundDetailPage = () => {
|
|
3957
|
+
var _a, _b, _c;
|
|
3958
|
+
const navigate = reactRouterDom.useNavigate();
|
|
3959
|
+
const params = reactRouterDom.useParams();
|
|
3960
|
+
const id = (_a = params == null ? void 0 : params.id) == null ? void 0 : _a.trim();
|
|
3961
|
+
const [detail, setDetail] = react.useState(null);
|
|
3962
|
+
const [loading, setLoading] = react.useState(!!id);
|
|
3963
|
+
const [error, setError] = react.useState(null);
|
|
3964
|
+
const [gatewayExpanded, setGatewayExpanded] = react.useState(false);
|
|
3965
|
+
react.useEffect(() => {
|
|
3966
|
+
if (!id) {
|
|
3967
|
+
setLoading(false);
|
|
3968
|
+
return;
|
|
3969
|
+
}
|
|
3970
|
+
let cancelled = false;
|
|
3971
|
+
setLoading(true);
|
|
3972
|
+
setError(null);
|
|
3973
|
+
fetch(`/admin/refunds/${id}`, { credentials: "include" }).then((res) => {
|
|
3974
|
+
if (!res.ok) throw new Error(res.statusText || "Failed to load");
|
|
3975
|
+
return res.json();
|
|
3976
|
+
}).then((data) => {
|
|
3977
|
+
if (!cancelled) setDetail(data);
|
|
3978
|
+
}).catch((e) => {
|
|
3979
|
+
if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
|
|
3980
|
+
}).finally(() => {
|
|
3981
|
+
if (!cancelled) setLoading(false);
|
|
3982
|
+
});
|
|
3983
|
+
return () => {
|
|
3984
|
+
cancelled = true;
|
|
3985
|
+
};
|
|
3986
|
+
}, [id]);
|
|
3987
|
+
const paymentStatus = ((_b = detail == null ? void 0 : detail.payment) == null ? void 0 : _b.status) ?? "—";
|
|
3988
|
+
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;
|
|
3989
|
+
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: [
|
|
3990
|
+
/* @__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: [
|
|
3991
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => navigate("/refunds"), children: "← Refunds" }),
|
|
3992
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Refund details" }),
|
|
3993
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle font-mono", children: id ?? "—" })
|
|
3994
|
+
] }) }),
|
|
3995
|
+
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
3996
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
3997
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/refunds"), children: "Back to list" })
|
|
3998
|
+
] }) : 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: [
|
|
3999
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4000
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Refund summary" }),
|
|
4001
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
4002
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4003
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund ID" }),
|
|
4004
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.id })
|
|
4005
|
+
] }),
|
|
4006
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4007
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
|
|
4008
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.refund.amount) })
|
|
4009
|
+
] }),
|
|
4010
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4011
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Note" }),
|
|
4012
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.refund.note ?? "—" })
|
|
4013
|
+
] }),
|
|
4014
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4015
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created at" }),
|
|
4016
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: new Date(detail.refund.created_at).toLocaleDateString("en-US", {
|
|
4017
|
+
year: "numeric",
|
|
4018
|
+
month: "short",
|
|
4019
|
+
day: "numeric",
|
|
4020
|
+
hour: "numeric",
|
|
4021
|
+
minute: "2-digit",
|
|
4022
|
+
hour12: true
|
|
4023
|
+
}) })
|
|
4024
|
+
] }),
|
|
4025
|
+
detail.refund.created_by ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4026
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created by" }),
|
|
4027
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.created_by })
|
|
4028
|
+
] }) : null
|
|
4029
|
+
] })
|
|
4030
|
+
] }),
|
|
4031
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4032
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Payment summary" }),
|
|
4033
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
4034
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4035
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Payment amount" }),
|
|
4036
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.payment_amount) })
|
|
4037
|
+
] }),
|
|
4038
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4039
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Captured amount" }),
|
|
4040
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.captured_amount) })
|
|
4041
|
+
] }),
|
|
4042
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4043
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refunded amount" }),
|
|
4044
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.refunded_amount) })
|
|
4045
|
+
] }),
|
|
4046
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4047
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
|
|
4048
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.payment.provider_id || "—" })
|
|
4049
|
+
] }),
|
|
4050
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4051
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
|
|
4052
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4053
|
+
ui.Badge,
|
|
4054
|
+
{
|
|
4055
|
+
size: "2xsmall",
|
|
4056
|
+
className: `uppercase ${getStatusBadgeClass$3(paymentStatus)}`,
|
|
4057
|
+
children: paymentStatus !== "—" ? paymentStatus.replace(/_/g, " ") : "—"
|
|
4058
|
+
}
|
|
4059
|
+
) })
|
|
4060
|
+
] }),
|
|
4061
|
+
detail.computed ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4062
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4063
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Full refund" }),
|
|
4064
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.computed.is_full_refund ? "Yes" : "No" })
|
|
4065
|
+
] }),
|
|
4066
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4067
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Remaining refundable" }),
|
|
4068
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.computed.remaining_refundable_amount) })
|
|
4069
|
+
] }),
|
|
4070
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4071
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund %" }),
|
|
4072
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "mt-1 block", children: [
|
|
4073
|
+
detail.computed.refund_percentage.toFixed(1),
|
|
4074
|
+
"%"
|
|
4075
|
+
] })
|
|
4076
|
+
] })
|
|
4077
|
+
] }) : null
|
|
4078
|
+
] })
|
|
4079
|
+
] }),
|
|
4080
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4081
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Order summary" }),
|
|
4082
|
+
detail.order ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
4083
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4084
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Order" }),
|
|
4085
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4086
|
+
ui.Button,
|
|
4087
|
+
{
|
|
4088
|
+
variant: "transparent",
|
|
4089
|
+
size: "small",
|
|
4090
|
+
onClick: () => navigate(`/orders/${detail.order.order_id}`),
|
|
4091
|
+
children: detail.order.order_number ?? detail.order.order_id
|
|
4092
|
+
}
|
|
4093
|
+
) })
|
|
4094
|
+
] }),
|
|
4095
|
+
detail.order.total != null ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4096
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Total" }),
|
|
4097
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.order.total) })
|
|
4098
|
+
] }) : null,
|
|
4099
|
+
detail.order.customer_id ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4100
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Customer ID" }),
|
|
4101
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.order.customer_id })
|
|
4102
|
+
] }) : null,
|
|
4103
|
+
detail.order.region ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4104
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Region" }),
|
|
4105
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.region })
|
|
4106
|
+
] }) : null,
|
|
4107
|
+
detail.order.fulfillment_status ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4108
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Fulfillment status" }),
|
|
4109
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.fulfillment_status })
|
|
4110
|
+
] }) : null
|
|
4111
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No order linked to this refund." })
|
|
4112
|
+
] }),
|
|
4113
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4114
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4115
|
+
"button",
|
|
4116
|
+
{
|
|
4117
|
+
type: "button",
|
|
4118
|
+
className: "flex w-full items-center justify-between text-left",
|
|
4119
|
+
onClick: () => setGatewayExpanded((prev) => !prev),
|
|
4120
|
+
"aria-expanded": gatewayExpanded,
|
|
4121
|
+
"aria-label": gatewayExpanded ? "Collapse gateway data" : "Expand gateway data",
|
|
4122
|
+
children: [
|
|
4123
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg", children: "Gateway data" }),
|
|
4124
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: gatewayExpanded ? "Collapse" : "Expand" })
|
|
4125
|
+
]
|
|
4126
|
+
}
|
|
4127
|
+
),
|
|
4128
|
+
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." }) })
|
|
4129
|
+
] })
|
|
4130
|
+
] }) : null
|
|
4131
|
+
] }) });
|
|
4132
|
+
};
|
|
4133
|
+
const config$3 = adminSdk.defineRouteConfig({
|
|
4134
|
+
label: "Refund details",
|
|
4135
|
+
icon: icons.Receipt
|
|
4136
|
+
});
|
|
4137
|
+
const getStatusBadgeClass$2 = (status) => {
|
|
4138
|
+
const s2 = status.toLowerCase();
|
|
4139
|
+
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
4140
|
+
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
4141
|
+
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
4142
|
+
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
4143
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
4144
|
+
};
|
|
4145
|
+
const PaymentDetailPage = () => {
|
|
4146
|
+
var _a;
|
|
4147
|
+
const navigate = reactRouterDom.useNavigate();
|
|
4148
|
+
const params = reactRouterDom.useParams();
|
|
4149
|
+
const id = (_a = params == null ? void 0 : params.id) == null ? void 0 : _a.trim();
|
|
4150
|
+
const [detail, setDetail] = react.useState(null);
|
|
4151
|
+
const [loading, setLoading] = react.useState(!!id);
|
|
4152
|
+
const [error, setError] = react.useState(null);
|
|
4153
|
+
react.useEffect(() => {
|
|
4154
|
+
if (!id) {
|
|
4155
|
+
setLoading(false);
|
|
4156
|
+
return;
|
|
4157
|
+
}
|
|
4158
|
+
let cancelled = false;
|
|
4159
|
+
setLoading(true);
|
|
4160
|
+
setError(null);
|
|
4161
|
+
fetch(`/admin/payment-transactions/${id}`, { credentials: "include" }).then((res) => {
|
|
4162
|
+
if (!res.ok) throw new Error(res.statusText || "Failed to load");
|
|
4163
|
+
return res.json();
|
|
4164
|
+
}).then((data) => {
|
|
4165
|
+
if (!cancelled) setDetail(data);
|
|
4166
|
+
}).catch((e) => {
|
|
4167
|
+
if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
|
|
4168
|
+
}).finally(() => {
|
|
4169
|
+
if (!cancelled) setLoading(false);
|
|
4170
|
+
});
|
|
4171
|
+
return () => {
|
|
4172
|
+
cancelled = true;
|
|
4173
|
+
};
|
|
4174
|
+
}, [id]);
|
|
4175
|
+
const displayStatus = detail ? (detail.payment_id != null && detail.payment_status != null && detail.payment_status !== "" ? detail.payment_status : detail.session_status ?? "") || "—" : "";
|
|
4176
|
+
const sessionStatusRaw = (detail == null ? void 0 : detail.session_status) ?? "—";
|
|
4177
|
+
const paymentStatusRaw = (detail == null ? void 0 : detail.payment_id) != null ? (detail == null ? void 0 : detail.payment_status) ?? "—" : "—";
|
|
4178
|
+
const displayAmount = detail ? `${(detail.currency_code ?? "USD").toUpperCase()} ${Number(detail.amount)}` : "";
|
|
4179
|
+
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: [
|
|
4180
|
+
/* @__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: [
|
|
4181
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => navigate("/payments"), children: "← Payments" }),
|
|
4182
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Payment session" }),
|
|
4183
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: id ?? "—" })
|
|
1938
4184
|
] }) }),
|
|
1939
4185
|
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
1940
4186
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
@@ -1967,7 +4213,7 @@ const PaymentDetailPage = () => {
|
|
|
1967
4213
|
ui.Badge,
|
|
1968
4214
|
{
|
|
1969
4215
|
size: "2xsmall",
|
|
1970
|
-
className: `uppercase ${getStatusBadgeClass$
|
|
4216
|
+
className: `uppercase ${getStatusBadgeClass$2(displayStatus)}`,
|
|
1971
4217
|
children: displayStatus !== "—" ? displayStatus.replace(/_/g, " ") : "—"
|
|
1972
4218
|
}
|
|
1973
4219
|
) })
|
|
@@ -2003,11 +4249,11 @@ const PaymentDetailPage = () => {
|
|
|
2003
4249
|
] }) : null
|
|
2004
4250
|
] }) });
|
|
2005
4251
|
};
|
|
2006
|
-
const config$
|
|
4252
|
+
const config$2 = adminSdk.defineRouteConfig({
|
|
2007
4253
|
label: "Payment details",
|
|
2008
4254
|
icon: icons.CreditCard
|
|
2009
4255
|
});
|
|
2010
|
-
const getStatusBadgeClass$
|
|
4256
|
+
const getStatusBadgeClass$1 = (status) => {
|
|
2011
4257
|
const statusLower = status.toLowerCase();
|
|
2012
4258
|
if (statusLower === "requested") {
|
|
2013
4259
|
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
@@ -2018,104 +4264,109 @@ const getStatusBadgeClass$2 = (status) => {
|
|
|
2018
4264
|
if (statusLower === "rejected") {
|
|
2019
4265
|
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
2020
4266
|
}
|
|
2021
|
-
if (statusLower === "received") {
|
|
2022
|
-
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
2023
|
-
}
|
|
2024
|
-
if (statusLower === "refunded") {
|
|
2025
|
-
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
2026
|
-
}
|
|
2027
4267
|
if (statusLower === "completed") {
|
|
2028
4268
|
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
2029
4269
|
}
|
|
2030
|
-
if (statusLower === "cancelled") {
|
|
4270
|
+
if (statusLower === "cancelled" || statusLower === "canceled") {
|
|
2031
4271
|
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
2032
4272
|
}
|
|
4273
|
+
if (statusLower === "pending") {
|
|
4274
|
+
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
4275
|
+
}
|
|
2033
4276
|
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
2034
4277
|
};
|
|
2035
|
-
const
|
|
4278
|
+
const SwapDetailPage = () => {
|
|
4279
|
+
var _a, _b, _c;
|
|
2036
4280
|
const navigate = reactRouterDom.useNavigate();
|
|
2037
4281
|
const { id } = reactRouterDom.useParams();
|
|
2038
|
-
const [
|
|
4282
|
+
const [swap, setSwap] = react.useState(null);
|
|
4283
|
+
const [order, setOrder] = react.useState(null);
|
|
2039
4284
|
const [isLoading, setIsLoading] = react.useState(true);
|
|
2040
|
-
|
|
4285
|
+
react.useState(false);
|
|
4286
|
+
const [isCancelling, setIsCancelling] = react.useState(false);
|
|
2041
4287
|
const [error, setError] = react.useState(null);
|
|
2042
4288
|
const [updateError, setUpdateError] = react.useState(null);
|
|
2043
4289
|
const [updateSuccess, setUpdateSuccess] = react.useState(false);
|
|
2044
4290
|
react.useEffect(() => {
|
|
2045
4291
|
if (!id) {
|
|
2046
|
-
navigate("/
|
|
4292
|
+
navigate("/swaps");
|
|
2047
4293
|
return;
|
|
2048
4294
|
}
|
|
2049
|
-
const
|
|
4295
|
+
const loadSwap = async () => {
|
|
2050
4296
|
try {
|
|
2051
4297
|
setIsLoading(true);
|
|
2052
4298
|
setError(null);
|
|
2053
|
-
const response = await fetch(`/admin/
|
|
4299
|
+
const response = await fetch(`/admin/swaps/${id}`, {
|
|
2054
4300
|
credentials: "include"
|
|
2055
4301
|
});
|
|
2056
4302
|
if (!response.ok) {
|
|
2057
4303
|
const message = await response.text();
|
|
2058
|
-
throw new Error(message || "Unable to load
|
|
4304
|
+
throw new Error(message || "Unable to load swap");
|
|
2059
4305
|
}
|
|
2060
4306
|
const payload = await response.json();
|
|
2061
|
-
|
|
4307
|
+
setSwap(payload.swap);
|
|
4308
|
+
setOrder(payload.order || null);
|
|
2062
4309
|
} catch (loadError) {
|
|
2063
|
-
const message = loadError instanceof Error ? loadError.message : "Unable to load
|
|
4310
|
+
const message = loadError instanceof Error ? loadError.message : "Unable to load swap";
|
|
2064
4311
|
setError(message);
|
|
2065
4312
|
} finally {
|
|
2066
4313
|
setIsLoading(false);
|
|
2067
4314
|
}
|
|
2068
4315
|
};
|
|
2069
|
-
void
|
|
4316
|
+
void loadSwap();
|
|
2070
4317
|
}, [id, navigate]);
|
|
2071
|
-
const
|
|
4318
|
+
const handleCancelExchange = async () => {
|
|
2072
4319
|
if (!id) {
|
|
2073
4320
|
return;
|
|
2074
4321
|
}
|
|
2075
4322
|
try {
|
|
2076
|
-
|
|
4323
|
+
setIsCancelling(true);
|
|
2077
4324
|
setUpdateError(null);
|
|
2078
4325
|
setUpdateSuccess(false);
|
|
2079
|
-
const response = await fetch(`/admin/
|
|
4326
|
+
const response = await fetch(`/admin/swaps/${id}/cancel`, {
|
|
2080
4327
|
method: "POST",
|
|
2081
4328
|
headers: {
|
|
2082
4329
|
"Content-Type": "application/json"
|
|
2083
4330
|
},
|
|
2084
|
-
credentials: "include"
|
|
2085
|
-
body: JSON.stringify({ reason: "Rejected by admin" })
|
|
4331
|
+
credentials: "include"
|
|
2086
4332
|
});
|
|
2087
4333
|
if (!response.ok) {
|
|
2088
4334
|
const message = await response.text();
|
|
2089
|
-
throw new Error(message || "Unable to
|
|
4335
|
+
throw new Error(message || "Unable to cancel exchange");
|
|
2090
4336
|
}
|
|
2091
4337
|
const payload = await response.json();
|
|
2092
|
-
|
|
4338
|
+
setSwap(payload.swap);
|
|
2093
4339
|
setUpdateSuccess(true);
|
|
2094
4340
|
setTimeout(() => setUpdateSuccess(false), 3e3);
|
|
2095
|
-
const detailResponse = await fetch(`/admin/
|
|
4341
|
+
const detailResponse = await fetch(`/admin/swaps/${id}`, {
|
|
2096
4342
|
credentials: "include"
|
|
2097
4343
|
});
|
|
2098
4344
|
if (detailResponse.ok) {
|
|
2099
4345
|
const detailPayload = await detailResponse.json();
|
|
2100
|
-
|
|
4346
|
+
setSwap(detailPayload.swap);
|
|
4347
|
+
setOrder(detailPayload.order || null);
|
|
2101
4348
|
}
|
|
2102
|
-
} catch (
|
|
2103
|
-
const message =
|
|
4349
|
+
} catch (cancelErr) {
|
|
4350
|
+
const message = cancelErr instanceof Error ? cancelErr.message : "Unable to cancel exchange";
|
|
2104
4351
|
setUpdateError(message);
|
|
2105
4352
|
} finally {
|
|
2106
|
-
|
|
4353
|
+
setIsCancelling(false);
|
|
2107
4354
|
}
|
|
2108
4355
|
};
|
|
4356
|
+
const isOrderExchange = Boolean(swap == null ? void 0 : swap.exchange_id);
|
|
4357
|
+
const canCancelExchange = isOrderExchange && swap && !["cancelled", "canceled", "completed", "declined"].includes(
|
|
4358
|
+
((_a = swap.status) == null ? void 0 : _a.toLowerCase()) ?? ""
|
|
4359
|
+
);
|
|
2109
4360
|
if (isLoading) {
|
|
2110
|
-
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
|
|
4361
|
+
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..." }) }) }) });
|
|
2111
4362
|
}
|
|
2112
|
-
if (error || !
|
|
4363
|
+
if (error || !swap) {
|
|
2113
4364
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
2114
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error || "
|
|
2115
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => navigate("/
|
|
4365
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error || "Swap not found" }),
|
|
4366
|
+
/* @__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" }) })
|
|
2116
4367
|
] }) }) });
|
|
2117
4368
|
}
|
|
2118
|
-
const statusHistory =
|
|
4369
|
+
const statusHistory = ((_b = swap.metadata) == null ? void 0 : _b.status_history) || [];
|
|
2119
4370
|
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: [
|
|
2120
4371
|
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3", children: [
|
|
2121
4372
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -2123,7 +4374,7 @@ const ReturnDetailPage = () => {
|
|
|
2123
4374
|
{
|
|
2124
4375
|
variant: "transparent",
|
|
2125
4376
|
size: "small",
|
|
2126
|
-
onClick: () => navigate("/
|
|
4377
|
+
onClick: () => navigate("/swaps"),
|
|
2127
4378
|
className: "w-fit",
|
|
2128
4379
|
children: [
|
|
2129
4380
|
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, { className: "mr-2" }),
|
|
@@ -2133,82 +4384,67 @@ const ReturnDetailPage = () => {
|
|
|
2133
4384
|
),
|
|
2134
4385
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 md:flex-row md:items-center md:justify-between", children: [
|
|
2135
4386
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
2136
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "
|
|
2137
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children:
|
|
4387
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Exchange Details" }),
|
|
4388
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: swap.id })
|
|
2138
4389
|
] }),
|
|
2139
4390
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2140
4391
|
ui.Badge,
|
|
2141
4392
|
{
|
|
2142
4393
|
size: "small",
|
|
2143
|
-
className: `uppercase ${getStatusBadgeClass$
|
|
2144
|
-
children:
|
|
4394
|
+
className: `uppercase ${getStatusBadgeClass$1(swap.status)}`,
|
|
4395
|
+
children: swap.status.replace(/_/g, " ")
|
|
2145
4396
|
}
|
|
2146
4397
|
)
|
|
2147
4398
|
] })
|
|
2148
4399
|
] }),
|
|
2149
|
-
|
|
4400
|
+
canCancelExchange && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
2150
4401
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2151
|
-
ui.Button,
|
|
2152
|
-
{
|
|
2153
|
-
variant: "danger",
|
|
2154
|
-
onClick:
|
|
2155
|
-
disabled:
|
|
2156
|
-
isLoading:
|
|
2157
|
-
children: "
|
|
2158
|
-
}
|
|
2159
|
-
) }),
|
|
2160
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children:
|
|
2161
|
-
] }),
|
|
2162
|
-
returnOrder.refund ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: /* @__PURE__ */ jsxRuntime.jsx(RefundCalculationBlock, { refund: returnOrder.refund }) }) : null,
|
|
2163
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
2164
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Information" }),
|
|
2165
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
2166
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2167
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Return ID" }),
|
|
2168
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.id })
|
|
2169
|
-
] }),
|
|
2170
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2171
|
-
ui.Button,
|
|
2172
|
-
{
|
|
2173
|
-
variant: "secondary",
|
|
2174
|
-
onClick: () => {
|
|
2175
|
-
window.open(
|
|
2176
|
-
`/app/orders/${returnOrder.order_id}`,
|
|
2177
|
-
"_blank"
|
|
2178
|
-
);
|
|
2179
|
-
},
|
|
2180
|
-
children: "View order"
|
|
2181
|
-
}
|
|
2182
|
-
) })
|
|
2183
|
-
] })
|
|
4402
|
+
ui.Button,
|
|
4403
|
+
{
|
|
4404
|
+
variant: "danger",
|
|
4405
|
+
onClick: handleCancelExchange,
|
|
4406
|
+
disabled: isCancelling,
|
|
4407
|
+
isLoading: isCancelling,
|
|
4408
|
+
children: "Cancel Exchange"
|
|
4409
|
+
}
|
|
4410
|
+
) }),
|
|
4411
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "This will cancel the exchange request. The order will remain unchanged." })
|
|
2184
4412
|
] }),
|
|
2185
4413
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-6 md:grid-cols-2", children: [
|
|
2186
4414
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
2187
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "
|
|
4415
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Exchange Information" }),
|
|
2188
4416
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
2189
4417
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2190
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "
|
|
2191
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children:
|
|
4418
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Exchange ID" }),
|
|
4419
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.id })
|
|
2192
4420
|
] }),
|
|
2193
4421
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2194
4422
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Status" }),
|
|
2195
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children:
|
|
4423
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.status })
|
|
2196
4424
|
] }),
|
|
2197
|
-
|
|
4425
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4426
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Difference Due" }),
|
|
4427
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.difference_due != null ? `${swap.currency_code || "$"}${(Number(swap.difference_due) / 100).toFixed(2)}` : "—" })
|
|
4428
|
+
] }),
|
|
4429
|
+
swap.reason && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2198
4430
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Reason" }),
|
|
2199
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children:
|
|
4431
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.reason })
|
|
2200
4432
|
] }),
|
|
2201
|
-
|
|
4433
|
+
swap.note && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2202
4434
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Note" }),
|
|
2203
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children:
|
|
4435
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.note })
|
|
2204
4436
|
] }),
|
|
2205
4437
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2206
4438
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Created" }),
|
|
2207
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(
|
|
4439
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(swap.created_at).toLocaleString() })
|
|
2208
4440
|
] }),
|
|
2209
4441
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2210
4442
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Last Updated" }),
|
|
2211
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(
|
|
4443
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(swap.updated_at).toLocaleString() })
|
|
4444
|
+
] }),
|
|
4445
|
+
swap.exchange_id && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4446
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Exchange ID" }),
|
|
4447
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.exchange_id })
|
|
2212
4448
|
] })
|
|
2213
4449
|
] })
|
|
2214
4450
|
] }),
|
|
@@ -2223,7 +4459,7 @@ const ReturnDetailPage = () => {
|
|
|
2223
4459
|
ui.Badge,
|
|
2224
4460
|
{
|
|
2225
4461
|
size: "2xsmall",
|
|
2226
|
-
className: `uppercase ${getStatusBadgeClass$
|
|
4462
|
+
className: `uppercase ${getStatusBadgeClass$1(entry.status)}`,
|
|
2227
4463
|
children: entry.status.replace(/_/g, " ")
|
|
2228
4464
|
}
|
|
2229
4465
|
) }),
|
|
@@ -2238,247 +4474,63 @@ const ReturnDetailPage = () => {
|
|
|
2238
4474
|
)) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "No status history available" })
|
|
2239
4475
|
] })
|
|
2240
4476
|
] }),
|
|
2241
|
-
|
|
4477
|
+
order && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
2242
4478
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Related Order Information" }),
|
|
2243
4479
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
2244
4480
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2245
4481
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order ID" }),
|
|
2246
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children:
|
|
4482
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: order.id })
|
|
2247
4483
|
] }),
|
|
2248
4484
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2249
4485
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Status" }),
|
|
2250
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children:
|
|
4486
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: order.status || "—" })
|
|
2251
4487
|
] }),
|
|
2252
4488
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2253
4489
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Customer" }),
|
|
2254
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children:
|
|
4490
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: ((_c = order.customer) == null ? void 0 : _c.email) || order.email || "—" })
|
|
2255
4491
|
] }),
|
|
2256
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2257
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Payment method" }),
|
|
2258
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.order.order_payment?.label || "—" })
|
|
2259
|
-
] }),
|
|
2260
|
-
returnOrder.order.total && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4492
|
+
order.total && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2261
4493
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Total" }),
|
|
2262
4494
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "font-medium", children: [
|
|
2263
|
-
|
|
2264
|
-
(Number(
|
|
4495
|
+
order.currency_code || "$",
|
|
4496
|
+
(Number(order.total) / 100).toFixed(2)
|
|
2265
4497
|
] })
|
|
2266
4498
|
] })
|
|
2267
4499
|
] })
|
|
2268
4500
|
] }),
|
|
2269
|
-
|
|
4501
|
+
swap.return_items && swap.return_items.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
2270
4502
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Items" }),
|
|
2271
4503
|
/* @__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: [
|
|
2272
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
2273
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Item ID" }),
|
|
2274
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Quantity" }),
|
|
2275
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Reason" })
|
|
2276
|
-
] }) }),
|
|
2277
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children:
|
|
2278
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: item.id }),
|
|
2279
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.quantity }),
|
|
2280
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.reason || "—" })
|
|
2281
|
-
] }, item.id || index)) })
|
|
2282
|
-
] }) })
|
|
2283
|
-
] }),
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
2298
|
-
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
2299
|
-
};
|
|
2300
|
-
const formatAmount = (value) => {
|
|
2301
|
-
return String(value);
|
|
2302
|
-
};
|
|
2303
|
-
const RefundDetailPage = () => {
|
|
2304
|
-
const navigate = reactRouterDom.useNavigate();
|
|
2305
|
-
const params = reactRouterDom.useParams();
|
|
2306
|
-
const id = params?.id?.trim();
|
|
2307
|
-
const [detail, setDetail] = react.useState(null);
|
|
2308
|
-
const [loading, setLoading] = react.useState(!!id);
|
|
2309
|
-
const [error, setError] = react.useState(null);
|
|
2310
|
-
const [gatewayExpanded, setGatewayExpanded] = react.useState(false);
|
|
2311
|
-
react.useEffect(() => {
|
|
2312
|
-
if (!id) {
|
|
2313
|
-
setLoading(false);
|
|
2314
|
-
return;
|
|
2315
|
-
}
|
|
2316
|
-
let cancelled = false;
|
|
2317
|
-
setLoading(true);
|
|
2318
|
-
setError(null);
|
|
2319
|
-
fetch(`/admin/refunds/${id}`, { credentials: "include" }).then((res) => {
|
|
2320
|
-
if (!res.ok) throw new Error(res.statusText || "Failed to load");
|
|
2321
|
-
return res.json();
|
|
2322
|
-
}).then((data) => {
|
|
2323
|
-
if (!cancelled) setDetail(data);
|
|
2324
|
-
}).catch((e) => {
|
|
2325
|
-
if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
|
|
2326
|
-
}).finally(() => {
|
|
2327
|
-
if (!cancelled) setLoading(false);
|
|
2328
|
-
});
|
|
2329
|
-
return () => {
|
|
2330
|
-
cancelled = true;
|
|
2331
|
-
};
|
|
2332
|
-
}, [id]);
|
|
2333
|
-
const paymentStatus = detail?.payment?.status ?? "—";
|
|
2334
|
-
const hasGatewayData = detail?.payment?.payment_data && typeof detail.payment.payment_data === "object" && Object.keys(detail.payment.payment_data).length > 0;
|
|
2335
|
-
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: [
|
|
2336
|
-
/* @__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: [
|
|
2337
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => navigate("/refunds"), children: "← Refunds" }),
|
|
2338
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Refund details" }),
|
|
2339
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle font-mono", children: id ?? "—" })
|
|
2340
|
-
] }) }),
|
|
2341
|
-
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
2342
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
2343
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/refunds"), children: "Back to list" })
|
|
2344
|
-
] }) : 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: [
|
|
2345
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
2346
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Refund summary" }),
|
|
2347
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
2348
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2349
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund ID" }),
|
|
2350
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.id })
|
|
2351
|
-
] }),
|
|
2352
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2353
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
|
|
2354
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.refund.amount) })
|
|
2355
|
-
] }),
|
|
2356
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2357
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Note" }),
|
|
2358
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.refund.note ?? "—" })
|
|
2359
|
-
] }),
|
|
2360
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2361
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created at" }),
|
|
2362
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: new Date(detail.refund.created_at).toLocaleDateString("en-US", {
|
|
2363
|
-
year: "numeric",
|
|
2364
|
-
month: "short",
|
|
2365
|
-
day: "numeric",
|
|
2366
|
-
hour: "numeric",
|
|
2367
|
-
minute: "2-digit",
|
|
2368
|
-
hour12: true
|
|
2369
|
-
}) })
|
|
2370
|
-
] }),
|
|
2371
|
-
detail.refund.created_by ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2372
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created by" }),
|
|
2373
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.created_by })
|
|
2374
|
-
] }) : null
|
|
2375
|
-
] })
|
|
2376
|
-
] }),
|
|
2377
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
2378
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Payment summary" }),
|
|
2379
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
2380
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2381
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Payment amount" }),
|
|
2382
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.payment_amount) })
|
|
2383
|
-
] }),
|
|
2384
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2385
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Captured amount" }),
|
|
2386
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.captured_amount) })
|
|
2387
|
-
] }),
|
|
2388
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2389
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refunded amount" }),
|
|
2390
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.refunded_amount) })
|
|
2391
|
-
] }),
|
|
2392
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2393
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
|
|
2394
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.payment.provider_id || "—" })
|
|
2395
|
-
] }),
|
|
2396
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2397
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
|
|
2398
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2399
|
-
ui.Badge,
|
|
2400
|
-
{
|
|
2401
|
-
size: "2xsmall",
|
|
2402
|
-
className: `uppercase ${getStatusBadgeClass$1(paymentStatus)}`,
|
|
2403
|
-
children: paymentStatus !== "—" ? paymentStatus.replace(/_/g, " ") : "—"
|
|
2404
|
-
}
|
|
2405
|
-
) })
|
|
2406
|
-
] }),
|
|
2407
|
-
detail.computed ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2408
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2409
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Full refund" }),
|
|
2410
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.computed.is_full_refund ? "Yes" : "No" })
|
|
2411
|
-
] }),
|
|
2412
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2413
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Remaining refundable" }),
|
|
2414
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.computed.remaining_refundable_amount) })
|
|
2415
|
-
] }),
|
|
2416
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2417
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund %" }),
|
|
2418
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "mt-1 block", children: [
|
|
2419
|
-
detail.computed.refund_percentage.toFixed(1),
|
|
2420
|
-
"%"
|
|
2421
|
-
] })
|
|
2422
|
-
] })
|
|
2423
|
-
] }) : null
|
|
2424
|
-
] })
|
|
2425
|
-
] }),
|
|
2426
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
2427
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Order summary" }),
|
|
2428
|
-
detail.order ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
2429
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2430
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Order" }),
|
|
2431
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2432
|
-
ui.Button,
|
|
2433
|
-
{
|
|
2434
|
-
variant: "transparent",
|
|
2435
|
-
size: "small",
|
|
2436
|
-
onClick: () => navigate(`/orders/${detail.order.order_id}`),
|
|
2437
|
-
children: detail.order.order_number ?? detail.order.order_id
|
|
2438
|
-
}
|
|
2439
|
-
) })
|
|
2440
|
-
] }),
|
|
2441
|
-
detail.order.total != null ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2442
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Total" }),
|
|
2443
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.order.total) })
|
|
2444
|
-
] }) : null,
|
|
2445
|
-
detail.order.customer_id ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2446
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Customer ID" }),
|
|
2447
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.order.customer_id })
|
|
2448
|
-
] }) : null,
|
|
2449
|
-
detail.order.region ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2450
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Region" }),
|
|
2451
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.region })
|
|
2452
|
-
] }) : null,
|
|
2453
|
-
detail.order.fulfillment_status ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2454
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Fulfillment status" }),
|
|
2455
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.fulfillment_status })
|
|
2456
|
-
] }) : null
|
|
2457
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No order linked to this refund." })
|
|
2458
|
-
] }),
|
|
2459
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
2460
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2461
|
-
"button",
|
|
2462
|
-
{
|
|
2463
|
-
type: "button",
|
|
2464
|
-
className: "flex w-full items-center justify-between text-left",
|
|
2465
|
-
onClick: () => setGatewayExpanded((prev) => !prev),
|
|
2466
|
-
"aria-expanded": gatewayExpanded,
|
|
2467
|
-
"aria-label": gatewayExpanded ? "Collapse gateway data" : "Expand gateway data",
|
|
2468
|
-
children: [
|
|
2469
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg", children: "Gateway data" }),
|
|
2470
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: gatewayExpanded ? "Collapse" : "Expand" })
|
|
2471
|
-
]
|
|
2472
|
-
}
|
|
2473
|
-
),
|
|
2474
|
-
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." }) })
|
|
2475
|
-
] })
|
|
2476
|
-
] }) : null
|
|
4504
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
4505
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Item ID" }),
|
|
4506
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Quantity" }),
|
|
4507
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Reason" })
|
|
4508
|
+
] }) }),
|
|
4509
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: swap.return_items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
4510
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: item.id }),
|
|
4511
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.quantity }),
|
|
4512
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.reason || "—" })
|
|
4513
|
+
] }, item.id || index)) })
|
|
4514
|
+
] }) })
|
|
4515
|
+
] }),
|
|
4516
|
+
swap.new_items && swap.new_items.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4517
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "New Items" }),
|
|
4518
|
+
/* @__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: [
|
|
4519
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
4520
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Variant ID" }),
|
|
4521
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Quantity" })
|
|
4522
|
+
] }) }),
|
|
4523
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: swap.new_items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
4524
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: item.variant_id }),
|
|
4525
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.quantity })
|
|
4526
|
+
] }, item.variant_id || index)) })
|
|
4527
|
+
] }) })
|
|
4528
|
+
] })
|
|
2477
4529
|
] }) });
|
|
2478
4530
|
};
|
|
2479
4531
|
const config$1 = adminSdk.defineRouteConfig({
|
|
2480
|
-
label: "
|
|
2481
|
-
icon: icons.
|
|
4532
|
+
label: "Swap Details",
|
|
4533
|
+
icon: icons.ArrowPath
|
|
2482
4534
|
});
|
|
2483
4535
|
const getStatusBadgeClass = (status) => {
|
|
2484
4536
|
const statusLower = status.toLowerCase();
|
|
@@ -2491,108 +4543,105 @@ const getStatusBadgeClass = (status) => {
|
|
|
2491
4543
|
if (statusLower === "rejected") {
|
|
2492
4544
|
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
2493
4545
|
}
|
|
4546
|
+
if (statusLower === "received") {
|
|
4547
|
+
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
4548
|
+
}
|
|
4549
|
+
if (statusLower === "refunded") {
|
|
4550
|
+
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
4551
|
+
}
|
|
2494
4552
|
if (statusLower === "completed") {
|
|
2495
4553
|
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
2496
4554
|
}
|
|
2497
|
-
if (statusLower === "cancelled"
|
|
4555
|
+
if (statusLower === "cancelled") {
|
|
2498
4556
|
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
2499
4557
|
}
|
|
2500
|
-
if (statusLower === "pending") {
|
|
2501
|
-
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
2502
|
-
}
|
|
2503
4558
|
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
2504
4559
|
};
|
|
2505
|
-
const
|
|
4560
|
+
const ReturnDetailPage = () => {
|
|
4561
|
+
var _a, _b, _c;
|
|
2506
4562
|
const navigate = reactRouterDom.useNavigate();
|
|
2507
4563
|
const { id } = reactRouterDom.useParams();
|
|
2508
|
-
const [
|
|
2509
|
-
const [order, setOrder] = react.useState(null);
|
|
4564
|
+
const [returnOrder, setReturnOrder] = react.useState(null);
|
|
2510
4565
|
const [isLoading, setIsLoading] = react.useState(true);
|
|
2511
4566
|
const [isRejecting, setIsRejecting] = react.useState(false);
|
|
2512
|
-
const [isCancelling, setIsCancelling] = react.useState(false);
|
|
2513
4567
|
const [error, setError] = react.useState(null);
|
|
2514
4568
|
const [updateError, setUpdateError] = react.useState(null);
|
|
2515
4569
|
const [updateSuccess, setUpdateSuccess] = react.useState(false);
|
|
2516
4570
|
react.useEffect(() => {
|
|
2517
4571
|
if (!id) {
|
|
2518
|
-
navigate("/
|
|
4572
|
+
navigate("/returns");
|
|
2519
4573
|
return;
|
|
2520
4574
|
}
|
|
2521
|
-
const
|
|
4575
|
+
const loadReturn = async () => {
|
|
2522
4576
|
try {
|
|
2523
4577
|
setIsLoading(true);
|
|
2524
4578
|
setError(null);
|
|
2525
|
-
const response = await fetch(`/admin/
|
|
4579
|
+
const response = await fetch(`/admin/return/${id}`, {
|
|
2526
4580
|
credentials: "include"
|
|
2527
4581
|
});
|
|
2528
4582
|
if (!response.ok) {
|
|
2529
4583
|
const message = await response.text();
|
|
2530
|
-
throw new Error(message || "Unable to load
|
|
4584
|
+
throw new Error(message || "Unable to load return order");
|
|
2531
4585
|
}
|
|
2532
4586
|
const payload = await response.json();
|
|
2533
|
-
|
|
2534
|
-
setOrder(payload.order || null);
|
|
4587
|
+
setReturnOrder(payload.return);
|
|
2535
4588
|
} catch (loadError) {
|
|
2536
|
-
const message = loadError instanceof Error ? loadError.message : "Unable to load
|
|
4589
|
+
const message = loadError instanceof Error ? loadError.message : "Unable to load return order";
|
|
2537
4590
|
setError(message);
|
|
2538
4591
|
} finally {
|
|
2539
4592
|
setIsLoading(false);
|
|
2540
4593
|
}
|
|
2541
4594
|
};
|
|
2542
|
-
void
|
|
4595
|
+
void loadReturn();
|
|
2543
4596
|
}, [id, navigate]);
|
|
2544
|
-
const
|
|
4597
|
+
const handleReject = async () => {
|
|
2545
4598
|
if (!id) {
|
|
2546
4599
|
return;
|
|
2547
4600
|
}
|
|
2548
4601
|
try {
|
|
2549
|
-
|
|
4602
|
+
setIsRejecting(true);
|
|
2550
4603
|
setUpdateError(null);
|
|
2551
4604
|
setUpdateSuccess(false);
|
|
2552
|
-
const response = await fetch(`/admin/
|
|
4605
|
+
const response = await fetch(`/admin/return/${id}/reject`, {
|
|
2553
4606
|
method: "POST",
|
|
2554
4607
|
headers: {
|
|
2555
4608
|
"Content-Type": "application/json"
|
|
2556
4609
|
},
|
|
2557
|
-
credentials: "include"
|
|
4610
|
+
credentials: "include",
|
|
4611
|
+
body: JSON.stringify({ reason: "Rejected by admin" })
|
|
2558
4612
|
});
|
|
2559
4613
|
if (!response.ok) {
|
|
2560
4614
|
const message = await response.text();
|
|
2561
|
-
throw new Error(message || "Unable to
|
|
4615
|
+
throw new Error(message || "Unable to reject return");
|
|
2562
4616
|
}
|
|
2563
4617
|
const payload = await response.json();
|
|
2564
|
-
|
|
4618
|
+
setReturnOrder(payload.return);
|
|
2565
4619
|
setUpdateSuccess(true);
|
|
2566
4620
|
setTimeout(() => setUpdateSuccess(false), 3e3);
|
|
2567
|
-
const detailResponse = await fetch(`/admin/
|
|
4621
|
+
const detailResponse = await fetch(`/admin/return/${id}`, {
|
|
2568
4622
|
credentials: "include"
|
|
2569
4623
|
});
|
|
2570
4624
|
if (detailResponse.ok) {
|
|
2571
4625
|
const detailPayload = await detailResponse.json();
|
|
2572
|
-
|
|
2573
|
-
setOrder(detailPayload.order || null);
|
|
4626
|
+
setReturnOrder(detailPayload.return);
|
|
2574
4627
|
}
|
|
2575
|
-
} catch (
|
|
2576
|
-
const message =
|
|
4628
|
+
} catch (updateErr) {
|
|
4629
|
+
const message = updateErr instanceof Error ? updateErr.message : "Unable to reject return";
|
|
2577
4630
|
setUpdateError(message);
|
|
2578
4631
|
} finally {
|
|
2579
|
-
|
|
4632
|
+
setIsRejecting(false);
|
|
2580
4633
|
}
|
|
2581
4634
|
};
|
|
2582
|
-
const isOrderExchange = Boolean(swap?.exchange_id);
|
|
2583
|
-
const canCancelExchange = isOrderExchange && swap && !["cancelled", "canceled", "completed", "declined"].includes(
|
|
2584
|
-
swap.status?.toLowerCase() ?? ""
|
|
2585
|
-
);
|
|
2586
4635
|
if (isLoading) {
|
|
2587
|
-
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
|
|
4636
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading return order..." }) }) }) });
|
|
2588
4637
|
}
|
|
2589
|
-
if (error || !
|
|
4638
|
+
if (error || !returnOrder) {
|
|
2590
4639
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
2591
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error || "
|
|
2592
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => navigate("/
|
|
4640
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error || "Return order not found" }),
|
|
4641
|
+
/* @__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" }) })
|
|
2593
4642
|
] }) }) });
|
|
2594
4643
|
}
|
|
2595
|
-
const statusHistory =
|
|
4644
|
+
const statusHistory = ((_a = returnOrder.metadata) == null ? void 0 : _a.status_history) || [];
|
|
2596
4645
|
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: [
|
|
2597
4646
|
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3", children: [
|
|
2598
4647
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -2600,7 +4649,7 @@ const SwapDetailPage = () => {
|
|
|
2600
4649
|
{
|
|
2601
4650
|
variant: "transparent",
|
|
2602
4651
|
size: "small",
|
|
2603
|
-
onClick: () => navigate("/
|
|
4652
|
+
onClick: () => navigate("/returns"),
|
|
2604
4653
|
className: "w-fit",
|
|
2605
4654
|
children: [
|
|
2606
4655
|
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, { className: "mr-2" }),
|
|
@@ -2610,67 +4659,82 @@ const SwapDetailPage = () => {
|
|
|
2610
4659
|
),
|
|
2611
4660
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 md:flex-row md:items-center md:justify-between", children: [
|
|
2612
4661
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
2613
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "
|
|
2614
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children:
|
|
4662
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Return Order Details" }),
|
|
4663
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: returnOrder.id })
|
|
2615
4664
|
] }),
|
|
2616
4665
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2617
4666
|
ui.Badge,
|
|
2618
4667
|
{
|
|
2619
4668
|
size: "small",
|
|
2620
|
-
className: `uppercase ${getStatusBadgeClass(
|
|
2621
|
-
children:
|
|
4669
|
+
className: `uppercase ${getStatusBadgeClass(returnOrder.status)}`,
|
|
4670
|
+
children: returnOrder.status.replace(/_/g, " ")
|
|
2622
4671
|
}
|
|
2623
4672
|
)
|
|
2624
4673
|
] })
|
|
2625
4674
|
] }),
|
|
2626
|
-
|
|
4675
|
+
returnOrder.status === "requested" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
2627
4676
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2628
4677
|
ui.Button,
|
|
2629
4678
|
{
|
|
2630
4679
|
variant: "danger",
|
|
2631
|
-
onClick:
|
|
2632
|
-
disabled:
|
|
2633
|
-
isLoading:
|
|
2634
|
-
children: "Cancel
|
|
4680
|
+
onClick: handleReject,
|
|
4681
|
+
disabled: isRejecting,
|
|
4682
|
+
isLoading: isRejecting,
|
|
4683
|
+
children: "Reject (Cancel) Return"
|
|
2635
4684
|
}
|
|
2636
4685
|
) }),
|
|
2637
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children:
|
|
4686
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: 'Cancel this return request. Use "Mark as received" when items are received.' })
|
|
4687
|
+
] }),
|
|
4688
|
+
returnOrder.refund ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: /* @__PURE__ */ jsxRuntime.jsx(RefundCalculationBlock, { refund: returnOrder.refund }) }) : null,
|
|
4689
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4690
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Information" }),
|
|
4691
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
4692
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4693
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Return ID" }),
|
|
4694
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.id })
|
|
4695
|
+
] }),
|
|
4696
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4697
|
+
ui.Button,
|
|
4698
|
+
{
|
|
4699
|
+
variant: "secondary",
|
|
4700
|
+
onClick: () => {
|
|
4701
|
+
window.open(
|
|
4702
|
+
`/app/orders/${returnOrder.order_id}`,
|
|
4703
|
+
"_blank"
|
|
4704
|
+
);
|
|
4705
|
+
},
|
|
4706
|
+
children: "View order"
|
|
4707
|
+
}
|
|
4708
|
+
) })
|
|
4709
|
+
] })
|
|
2638
4710
|
] }),
|
|
2639
4711
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-6 md:grid-cols-2", children: [
|
|
2640
4712
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
2641
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "
|
|
4713
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Details" }),
|
|
2642
4714
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
2643
4715
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2644
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "
|
|
2645
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children:
|
|
4716
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Return ID" }),
|
|
4717
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.id })
|
|
2646
4718
|
] }),
|
|
2647
4719
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2648
4720
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Status" }),
|
|
2649
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children:
|
|
2650
|
-
] }),
|
|
2651
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2652
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Difference Due" }),
|
|
2653
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.difference_due != null ? `${swap.currency_code || "$"}${(Number(swap.difference_due) / 100).toFixed(2)}` : "—" })
|
|
4721
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.status })
|
|
2654
4722
|
] }),
|
|
2655
|
-
|
|
4723
|
+
returnOrder.reason && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2656
4724
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Reason" }),
|
|
2657
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children:
|
|
4725
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.reason })
|
|
2658
4726
|
] }),
|
|
2659
|
-
|
|
4727
|
+
returnOrder.note && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2660
4728
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Note" }),
|
|
2661
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children:
|
|
4729
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.note })
|
|
2662
4730
|
] }),
|
|
2663
4731
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2664
4732
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Created" }),
|
|
2665
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(
|
|
4733
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(returnOrder.created_at).toLocaleString() })
|
|
2666
4734
|
] }),
|
|
2667
4735
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2668
4736
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Last Updated" }),
|
|
2669
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(
|
|
2670
|
-
] }),
|
|
2671
|
-
swap.exchange_id && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2672
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Exchange ID" }),
|
|
2673
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: swap.exchange_id })
|
|
4737
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(returnOrder.updated_at).toLocaleString() })
|
|
2674
4738
|
] })
|
|
2675
4739
|
] })
|
|
2676
4740
|
] }),
|
|
@@ -2700,31 +4764,35 @@ const SwapDetailPage = () => {
|
|
|
2700
4764
|
)) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "No status history available" })
|
|
2701
4765
|
] })
|
|
2702
4766
|
] }),
|
|
2703
|
-
order && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4767
|
+
returnOrder.order && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
2704
4768
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Related Order Information" }),
|
|
2705
4769
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
2706
4770
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2707
4771
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order ID" }),
|
|
2708
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: order.id })
|
|
4772
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.order.id })
|
|
2709
4773
|
] }),
|
|
2710
4774
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2711
4775
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Status" }),
|
|
2712
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: order.status || "—" })
|
|
4776
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.order.status || "—" })
|
|
2713
4777
|
] }),
|
|
2714
4778
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2715
4779
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Customer" }),
|
|
2716
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: order.customer
|
|
4780
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: ((_b = returnOrder.order.customer) == null ? void 0 : _b.email) || returnOrder.order.email || "—" })
|
|
2717
4781
|
] }),
|
|
2718
|
-
|
|
4782
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4783
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Payment method" }),
|
|
4784
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: ((_c = returnOrder.order.order_payment) == null ? void 0 : _c.label) || "—" })
|
|
4785
|
+
] }),
|
|
4786
|
+
returnOrder.order.total && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2719
4787
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Total" }),
|
|
2720
4788
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "font-medium", children: [
|
|
2721
|
-
order.currency_code || "$",
|
|
2722
|
-
(Number(order.total) / 100).toFixed(2)
|
|
4789
|
+
returnOrder.order.currency_code || "$",
|
|
4790
|
+
(Number(returnOrder.order.total) / 100).toFixed(2)
|
|
2723
4791
|
] })
|
|
2724
4792
|
] })
|
|
2725
4793
|
] })
|
|
2726
4794
|
] }),
|
|
2727
|
-
|
|
4795
|
+
returnOrder.return_items && returnOrder.return_items.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
2728
4796
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Items" }),
|
|
2729
4797
|
/* @__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: [
|
|
2730
4798
|
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
@@ -2732,86 +4800,73 @@ const SwapDetailPage = () => {
|
|
|
2732
4800
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Quantity" }),
|
|
2733
4801
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Reason" })
|
|
2734
4802
|
] }) }),
|
|
2735
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children:
|
|
4803
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: returnOrder.return_items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
2736
4804
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: item.id }),
|
|
2737
4805
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.quantity }),
|
|
2738
4806
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.reason || "—" })
|
|
2739
4807
|
] }, item.id || index)) })
|
|
2740
4808
|
] }) })
|
|
2741
4809
|
] }),
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
/* @__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: [
|
|
2745
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
2746
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Variant ID" }),
|
|
2747
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Quantity" })
|
|
2748
|
-
] }) }),
|
|
2749
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: swap.new_items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
2750
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: item.variant_id }),
|
|
2751
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.quantity })
|
|
2752
|
-
] }, item.variant_id || index)) })
|
|
2753
|
-
] }) })
|
|
2754
|
-
] })
|
|
4810
|
+
updateError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-ui-border-error bg-ui-bg-error-subtle p-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-error", children: updateError }) }),
|
|
4811
|
+
updateSuccess && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-ui-border-success bg-ui-bg-success-subtle p-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-success", children: "Action completed successfully" }) })
|
|
2755
4812
|
] }) });
|
|
2756
4813
|
};
|
|
2757
4814
|
const config = adminSdk.defineRouteConfig({
|
|
2758
|
-
label: "
|
|
2759
|
-
icon: icons.
|
|
4815
|
+
label: "Return Order Details",
|
|
4816
|
+
icon: icons.CheckCircle
|
|
2760
4817
|
});
|
|
2761
4818
|
const i18nTranslations0 = {};
|
|
2762
4819
|
const widgetModule = { widgets: [
|
|
2763
4820
|
{
|
|
2764
4821
|
Component: OrderGiftItemsWidget,
|
|
2765
|
-
zone: ["order.details.side.after"]
|
|
2766
|
-
widgetId: "Widget-b753"
|
|
4822
|
+
zone: ["order.details.side.after"]
|
|
2767
4823
|
},
|
|
2768
4824
|
{
|
|
2769
4825
|
Component: OrderRefundContextWidget,
|
|
2770
|
-
zone: ["order.details.after"]
|
|
2771
|
-
widgetId: "Widget-0606"
|
|
4826
|
+
zone: ["order.details.after"]
|
|
2772
4827
|
}
|
|
2773
4828
|
] };
|
|
2774
4829
|
const routeModule = {
|
|
2775
4830
|
routes: [
|
|
2776
4831
|
{
|
|
2777
|
-
Component:
|
|
2778
|
-
path: "/
|
|
2779
|
-
handle: { label: config$7.label, translationNs: config$7.translationNs }
|
|
4832
|
+
Component: DeletedRecordsPage,
|
|
4833
|
+
path: "/deleted-records-audit"
|
|
2780
4834
|
},
|
|
2781
4835
|
{
|
|
2782
4836
|
Component: RefundsPage,
|
|
2783
|
-
path: "/refunds"
|
|
2784
|
-
|
|
4837
|
+
path: "/refunds"
|
|
4838
|
+
},
|
|
4839
|
+
{
|
|
4840
|
+
Component: PaymentsPage,
|
|
4841
|
+
path: "/payments"
|
|
2785
4842
|
},
|
|
2786
4843
|
{
|
|
2787
4844
|
Component: ReturnsPage,
|
|
2788
|
-
path: "/returns"
|
|
2789
|
-
handle: { label: config$5.label, translationNs: config$5.translationNs }
|
|
4845
|
+
path: "/returns"
|
|
2790
4846
|
},
|
|
2791
4847
|
{
|
|
2792
4848
|
Component: SwapsPage,
|
|
2793
|
-
path: "/swaps"
|
|
2794
|
-
handle: { label: config$4.label, translationNs: config$4.translationNs }
|
|
4849
|
+
path: "/swaps"
|
|
2795
4850
|
},
|
|
2796
4851
|
{
|
|
2797
|
-
Component:
|
|
2798
|
-
path: "/
|
|
2799
|
-
handle: { label: config$3.label, translationNs: config$3.translationNs }
|
|
4852
|
+
Component: DeletedRecordDetailPage,
|
|
4853
|
+
path: "/deleted-records-audit/:id"
|
|
2800
4854
|
},
|
|
2801
4855
|
{
|
|
2802
|
-
Component:
|
|
2803
|
-
path: "/
|
|
2804
|
-
handle: { label: config$2.label, translationNs: config$2.translationNs }
|
|
4856
|
+
Component: RefundDetailPage,
|
|
4857
|
+
path: "/refunds/:id"
|
|
2805
4858
|
},
|
|
2806
4859
|
{
|
|
2807
|
-
Component:
|
|
2808
|
-
path: "/
|
|
2809
|
-
handle: { label: config$1.label, translationNs: config$1.translationNs }
|
|
4860
|
+
Component: PaymentDetailPage,
|
|
4861
|
+
path: "/payments/:id"
|
|
2810
4862
|
},
|
|
2811
4863
|
{
|
|
2812
4864
|
Component: SwapDetailPage,
|
|
2813
|
-
path: "/swaps/:id"
|
|
2814
|
-
|
|
4865
|
+
path: "/swaps/:id"
|
|
4866
|
+
},
|
|
4867
|
+
{
|
|
4868
|
+
Component: ReturnDetailPage,
|
|
4869
|
+
path: "/returns/:id"
|
|
2815
4870
|
}
|
|
2816
4871
|
]
|
|
2817
4872
|
};
|
|
@@ -2820,66 +4875,56 @@ const menuItemModule = {
|
|
|
2820
4875
|
{
|
|
2821
4876
|
label: config$6.label,
|
|
2822
4877
|
icon: config$6.icon,
|
|
2823
|
-
path: "/
|
|
2824
|
-
nested: void 0
|
|
2825
|
-
rank: void 0,
|
|
2826
|
-
translationNs: void 0
|
|
4878
|
+
path: "/payments",
|
|
4879
|
+
nested: void 0
|
|
2827
4880
|
},
|
|
2828
4881
|
{
|
|
2829
|
-
label: config$
|
|
2830
|
-
icon: config$
|
|
2831
|
-
path: "/
|
|
2832
|
-
nested: void 0
|
|
2833
|
-
rank: void 0,
|
|
2834
|
-
translationNs: void 0
|
|
4882
|
+
label: config$8.label,
|
|
4883
|
+
icon: config$8.icon,
|
|
4884
|
+
path: "/deleted-records-audit",
|
|
4885
|
+
nested: void 0
|
|
2835
4886
|
},
|
|
2836
4887
|
{
|
|
2837
4888
|
label: config$5.label,
|
|
2838
4889
|
icon: config$5.icon,
|
|
2839
4890
|
path: "/returns",
|
|
2840
|
-
nested: void 0
|
|
2841
|
-
|
|
2842
|
-
|
|
4891
|
+
nested: void 0
|
|
4892
|
+
},
|
|
4893
|
+
{
|
|
4894
|
+
label: config$7.label,
|
|
4895
|
+
icon: config$7.icon,
|
|
4896
|
+
path: "/refunds",
|
|
4897
|
+
nested: void 0
|
|
2843
4898
|
},
|
|
2844
4899
|
{
|
|
2845
4900
|
label: config$4.label,
|
|
2846
4901
|
icon: config$4.icon,
|
|
2847
4902
|
path: "/swaps",
|
|
2848
|
-
nested: void 0
|
|
2849
|
-
rank: void 0,
|
|
2850
|
-
translationNs: void 0
|
|
2851
|
-
},
|
|
2852
|
-
{
|
|
2853
|
-
label: config$1.label,
|
|
2854
|
-
icon: config$1.icon,
|
|
2855
|
-
path: "/refunds/:id",
|
|
2856
|
-
nested: void 0,
|
|
2857
|
-
rank: void 0,
|
|
2858
|
-
translationNs: void 0
|
|
2859
|
-
},
|
|
2860
|
-
{
|
|
2861
|
-
label: config$3.label,
|
|
2862
|
-
icon: config$3.icon,
|
|
2863
|
-
path: "/payments/:id",
|
|
2864
|
-
nested: void 0,
|
|
2865
|
-
rank: void 0,
|
|
2866
|
-
translationNs: void 0
|
|
4903
|
+
nested: void 0
|
|
2867
4904
|
},
|
|
2868
4905
|
{
|
|
2869
4906
|
label: config$2.label,
|
|
2870
4907
|
icon: config$2.icon,
|
|
2871
|
-
path: "/
|
|
2872
|
-
nested: void 0
|
|
2873
|
-
rank: void 0,
|
|
2874
|
-
translationNs: void 0
|
|
4908
|
+
path: "/payments/:id",
|
|
4909
|
+
nested: void 0
|
|
2875
4910
|
},
|
|
2876
4911
|
{
|
|
2877
4912
|
label: config.label,
|
|
2878
4913
|
icon: config.icon,
|
|
4914
|
+
path: "/returns/:id",
|
|
4915
|
+
nested: void 0
|
|
4916
|
+
},
|
|
4917
|
+
{
|
|
4918
|
+
label: config$3.label,
|
|
4919
|
+
icon: config$3.icon,
|
|
4920
|
+
path: "/refunds/:id",
|
|
4921
|
+
nested: void 0
|
|
4922
|
+
},
|
|
4923
|
+
{
|
|
4924
|
+
label: config$1.label,
|
|
4925
|
+
icon: config$1.icon,
|
|
2879
4926
|
path: "/swaps/:id",
|
|
2880
|
-
nested: void 0
|
|
2881
|
-
rank: void 0,
|
|
2882
|
-
translationNs: void 0
|
|
4927
|
+
nested: void 0
|
|
2883
4928
|
}
|
|
2884
4929
|
]
|
|
2885
4930
|
};
|
|
@@ -2888,18 +4933,12 @@ const displayModule = {
|
|
|
2888
4933
|
displays: {}
|
|
2889
4934
|
};
|
|
2890
4935
|
const i18nModule = { resources: i18nTranslations0 };
|
|
2891
|
-
const cellRendererModule = {};
|
|
2892
|
-
const layoutModule = { layouts: [] };
|
|
2893
|
-
const searchEntityModule = {};
|
|
2894
4936
|
const plugin = {
|
|
2895
4937
|
widgetModule,
|
|
2896
4938
|
routeModule,
|
|
2897
4939
|
menuItemModule,
|
|
2898
4940
|
formModule,
|
|
2899
4941
|
displayModule,
|
|
2900
|
-
i18nModule
|
|
2901
|
-
cellRendererModule,
|
|
2902
|
-
layoutModule,
|
|
2903
|
-
searchEntityModule
|
|
4942
|
+
i18nModule
|
|
2904
4943
|
};
|
|
2905
4944
|
module.exports = plugin;
|