order-management 0.0.105 → 0.0.107
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 +999 -999
- package/.medusa/server/src/admin/index.mjs +1000 -1000
- package/.medusa/server/src/api/store/returns/route.js +4 -19
- package/.medusa/server/src/modules/order-rma-gate/migrations/{Migration20260724100000.js → Migration20260724100001.js} +4 -4
- package/.medusa/server/src/modules/order-rma-gate/migrations/Migration20261027120000.js +36 -0
- package/package.json +1 -1
|
@@ -3487,1030 +3487,1030 @@ const config$3 = adminSdk.defineRouteConfig({
|
|
|
3487
3487
|
label: "Refund details",
|
|
3488
3488
|
icon: icons.Receipt
|
|
3489
3489
|
});
|
|
3490
|
-
const
|
|
3491
|
-
const
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
auth_mfa_factor: /* @__PURE__ */ new Set(["value", "config"])
|
|
3490
|
+
const getStatusBadgeClass$1 = (status) => {
|
|
3491
|
+
const statusLower = status.toLowerCase();
|
|
3492
|
+
if (statusLower === "requested") {
|
|
3493
|
+
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
3494
|
+
}
|
|
3495
|
+
if (statusLower === "approved") {
|
|
3496
|
+
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
3497
|
+
}
|
|
3498
|
+
if (statusLower === "rejected") {
|
|
3499
|
+
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
3500
|
+
}
|
|
3501
|
+
if (statusLower === "received") {
|
|
3502
|
+
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
3503
|
+
}
|
|
3504
|
+
if (statusLower === "refunded") {
|
|
3505
|
+
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
3506
|
+
}
|
|
3507
|
+
if (statusLower === "completed") {
|
|
3508
|
+
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
3509
|
+
}
|
|
3510
|
+
if (statusLower === "cancelled") {
|
|
3511
|
+
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
3512
|
+
}
|
|
3513
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
3515
3514
|
};
|
|
3516
|
-
const
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
]);
|
|
3523
|
-
|
|
3524
|
-
const
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3515
|
+
const ReturnDetailPage = () => {
|
|
3516
|
+
const navigate = reactRouterDom.useNavigate();
|
|
3517
|
+
const { id } = reactRouterDom.useParams();
|
|
3518
|
+
const [returnOrder, setReturnOrder] = react.useState(null);
|
|
3519
|
+
const [isLoading, setIsLoading] = react.useState(true);
|
|
3520
|
+
const [isRejecting, setIsRejecting] = react.useState(false);
|
|
3521
|
+
const [error, setError] = react.useState(null);
|
|
3522
|
+
const [updateError, setUpdateError] = react.useState(null);
|
|
3523
|
+
const [updateSuccess, setUpdateSuccess] = react.useState(false);
|
|
3524
|
+
react.useEffect(() => {
|
|
3525
|
+
if (!id) {
|
|
3526
|
+
navigate("/returns");
|
|
3527
|
+
return;
|
|
3528
|
+
}
|
|
3529
|
+
const loadReturn = async () => {
|
|
3530
|
+
try {
|
|
3531
|
+
setIsLoading(true);
|
|
3532
|
+
setError(null);
|
|
3533
|
+
const response = await fetch(`/admin/return/${id}`, {
|
|
3534
|
+
credentials: "include"
|
|
3535
|
+
});
|
|
3536
|
+
if (!response.ok) {
|
|
3537
|
+
const message = await response.text();
|
|
3538
|
+
throw new Error(message || "Unable to load return order");
|
|
3539
|
+
}
|
|
3540
|
+
const payload = await response.json();
|
|
3541
|
+
setReturnOrder(payload.return);
|
|
3542
|
+
} catch (loadError) {
|
|
3543
|
+
const message = loadError instanceof Error ? loadError.message : "Unable to load return order";
|
|
3544
|
+
setError(message);
|
|
3545
|
+
} finally {
|
|
3546
|
+
setIsLoading(false);
|
|
3542
3547
|
}
|
|
3548
|
+
};
|
|
3549
|
+
void loadReturn();
|
|
3550
|
+
}, [id, navigate]);
|
|
3551
|
+
const handleReject = async () => {
|
|
3552
|
+
if (!id) {
|
|
3553
|
+
return;
|
|
3554
|
+
}
|
|
3555
|
+
try {
|
|
3556
|
+
setIsRejecting(true);
|
|
3557
|
+
setUpdateError(null);
|
|
3558
|
+
setUpdateSuccess(false);
|
|
3559
|
+
const response = await fetch(`/admin/return/${id}/reject`, {
|
|
3560
|
+
method: "POST",
|
|
3561
|
+
headers: {
|
|
3562
|
+
"Content-Type": "application/json"
|
|
3563
|
+
},
|
|
3564
|
+
credentials: "include",
|
|
3565
|
+
body: JSON.stringify({ reason: "Rejected by admin" })
|
|
3566
|
+
});
|
|
3567
|
+
if (!response.ok) {
|
|
3568
|
+
const message = await response.text();
|
|
3569
|
+
throw new Error(message || "Unable to reject return");
|
|
3570
|
+
}
|
|
3571
|
+
const payload = await response.json();
|
|
3572
|
+
setReturnOrder(payload.return);
|
|
3573
|
+
setUpdateSuccess(true);
|
|
3574
|
+
setTimeout(() => setUpdateSuccess(false), 3e3);
|
|
3575
|
+
const detailResponse = await fetch(`/admin/return/${id}`, {
|
|
3576
|
+
credentials: "include"
|
|
3577
|
+
});
|
|
3578
|
+
if (detailResponse.ok) {
|
|
3579
|
+
const detailPayload = await detailResponse.json();
|
|
3580
|
+
setReturnOrder(detailPayload.return);
|
|
3581
|
+
}
|
|
3582
|
+
} catch (updateErr) {
|
|
3583
|
+
const message = updateErr instanceof Error ? updateErr.message : "Unable to reject return";
|
|
3584
|
+
setUpdateError(message);
|
|
3585
|
+
} finally {
|
|
3586
|
+
setIsRejecting(false);
|
|
3543
3587
|
}
|
|
3544
|
-
return out;
|
|
3545
|
-
}
|
|
3546
|
-
return value;
|
|
3547
|
-
}
|
|
3548
|
-
function maskSensitiveData(data, tableName) {
|
|
3549
|
-
const ctx = {
|
|
3550
|
-
count: 0,
|
|
3551
|
-
maskAll: tableName ? FULLY_SECRET_TABLES.has(tableName) : false,
|
|
3552
|
-
tableKeys: tableName ? TABLE_SENSITIVE_KEYS[tableName] : void 0
|
|
3553
|
-
};
|
|
3554
|
-
const value = maskValue(data, ctx, 0);
|
|
3555
|
-
return { value, maskedCount: ctx.count };
|
|
3556
|
-
}
|
|
3557
|
-
const AUTO_EXPAND_DEPTH = 1;
|
|
3558
|
-
const LONG_STRING = 200;
|
|
3559
|
-
const JsonViewer = ({ data }) => {
|
|
3560
|
-
const [generation, setGeneration] = react.useState(0);
|
|
3561
|
-
const [expandAll, setExpandAll] = react.useState(null);
|
|
3562
|
-
const setAll = (value) => {
|
|
3563
|
-
setExpandAll(value);
|
|
3564
|
-
setGeneration((g) => g + 1);
|
|
3565
3588
|
};
|
|
3566
|
-
|
|
3567
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3568
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => setAll(true), children: "Expand all" }),
|
|
3569
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => setAll(false), children: "Collapse all" })
|
|
3570
|
-
] }),
|
|
3571
|
-
/* @__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) })
|
|
3572
|
-
] });
|
|
3573
|
-
};
|
|
3574
|
-
const JsonNode = ({ name, value, depth, forceExpand }) => {
|
|
3575
|
-
const isContainer = value !== null && typeof value === "object";
|
|
3576
|
-
const [open, setOpen] = react.useState(forceExpand ?? depth < AUTO_EXPAND_DEPTH);
|
|
3577
|
-
const label = name !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-fg-subtle", children: [
|
|
3578
|
-
name,
|
|
3579
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: ": " })
|
|
3580
|
-
] }) : null;
|
|
3581
|
-
if (!isContainer) {
|
|
3582
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-start", style: { paddingLeft: depth ? 16 : 0 }, children: [
|
|
3583
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-4 shrink-0" }),
|
|
3584
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 break-words [overflow-wrap:anywhere]", children: [
|
|
3585
|
-
label,
|
|
3586
|
-
/* @__PURE__ */ jsxRuntime.jsx(Primitive, { value })
|
|
3587
|
-
] })
|
|
3588
|
-
] });
|
|
3589
|
+
if (isLoading) {
|
|
3590
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading return order..." }) }) }) });
|
|
3589
3591
|
}
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
"button",
|
|
3596
|
-
{
|
|
3597
|
-
type: "button",
|
|
3598
|
-
onClick: () => setOpen((o) => !o),
|
|
3599
|
-
className: "flex items-start text-left hover:bg-ui-bg-base-hover",
|
|
3600
|
-
"aria-expanded": open,
|
|
3601
|
-
children: [
|
|
3602
|
-
/* @__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 }),
|
|
3603
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
3604
|
-
label,
|
|
3605
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: openBracket }),
|
|
3606
|
-
!open || entries.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3607
|
-
entries.length ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-1 italic text-ui-fg-muted", children: summary }) : null,
|
|
3608
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: closeBracket })
|
|
3609
|
-
] }) : null
|
|
3610
|
-
] })
|
|
3611
|
-
]
|
|
3612
|
-
}
|
|
3613
|
-
),
|
|
3614
|
-
open && entries.length ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3615
|
-
entries.map(([key, child]) => /* @__PURE__ */ jsxRuntime.jsx(JsonNode, { name: key, value: child, depth: depth + 1, forceExpand }, key)),
|
|
3616
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { paddingLeft: 16 }, className: "text-ui-fg-muted", children: closeBracket })
|
|
3617
|
-
] }) : null
|
|
3618
|
-
] });
|
|
3619
|
-
};
|
|
3620
|
-
const Primitive = ({ value }) => {
|
|
3621
|
-
const [showFull, setShowFull] = react.useState(false);
|
|
3622
|
-
if (value === MASKED_VALUE) {
|
|
3623
|
-
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 });
|
|
3592
|
+
if (error || !returnOrder) {
|
|
3593
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
3594
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error || "Return order not found" }),
|
|
3595
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => navigate("/returns"), children: "Back to list" }) })
|
|
3596
|
+
] }) }) });
|
|
3624
3597
|
}
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
}
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
}
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
}
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
}
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
{
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
CREATED
|
|
3820
|
-
],
|
|
3821
|
-
product_collection: [{ key: "title", label: "Title" }, { key: "handle", label: "Handle" }, CREATED],
|
|
3822
|
-
payment: [
|
|
3823
|
-
{ key: "amount", label: "Amount", kind: "money" },
|
|
3824
|
-
{ key: "currency_code", label: "Currency" },
|
|
3825
|
-
{ key: "provider_id", label: "Provider" },
|
|
3826
|
-
{ key: "captured_at", label: "Captured", kind: "date" },
|
|
3827
|
-
{ key: "canceled_at", label: "Canceled", kind: "date" },
|
|
3828
|
-
{ key: "payment_collection_id", label: "Payment collection ID", kind: "id" },
|
|
3829
|
-
CREATED
|
|
3830
|
-
],
|
|
3831
|
-
payment_session: [
|
|
3832
|
-
{ key: "amount", label: "Amount", kind: "money" },
|
|
3833
|
-
{ key: "currency_code", label: "Currency" },
|
|
3834
|
-
{ key: "provider_id", label: "Provider" },
|
|
3835
|
-
{ key: "status", label: "Status", kind: "status" },
|
|
3836
|
-
{ key: "payment_collection_id", label: "Payment collection ID", kind: "id" },
|
|
3837
|
-
CREATED
|
|
3838
|
-
],
|
|
3839
|
-
payment_collection: [
|
|
3840
|
-
{ key: "amount", label: "Amount", kind: "money" },
|
|
3841
|
-
{ key: "currency_code", label: "Currency" },
|
|
3842
|
-
{ key: "status", label: "Status", kind: "status" },
|
|
3843
|
-
CREATED
|
|
3844
|
-
],
|
|
3845
|
-
refund: [
|
|
3846
|
-
{ key: "amount", label: "Amount", kind: "money" },
|
|
3847
|
-
{ key: "payment_id", label: "Payment ID", kind: "id" },
|
|
3848
|
-
{ key: "refund_reason_id", label: "Refund reason ID", kind: "id" },
|
|
3849
|
-
{ key: "note", label: "Note" },
|
|
3850
|
-
{ key: "created_by", label: "Created by" },
|
|
3851
|
-
CREATED
|
|
3852
|
-
],
|
|
3853
|
-
return: [
|
|
3854
|
-
{ key: "display_id", label: "Return number" },
|
|
3855
|
-
{ key: "status", label: "Status", kind: "status" },
|
|
3856
|
-
{ key: "order_id", label: "Order ID", kind: "id" },
|
|
3857
|
-
{ key: "refund_amount", label: "Refund amount", kind: "money" },
|
|
3858
|
-
{ key: "received_at", label: "Received", kind: "date" },
|
|
3859
|
-
CREATED
|
|
3860
|
-
],
|
|
3861
|
-
payment_detail: [
|
|
3862
|
-
{ key: "type", label: "Method type" },
|
|
3863
|
-
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
3864
|
-
{ key: "is_default", label: "Default method", kind: "boolean" },
|
|
3865
|
-
CREATED
|
|
3866
|
-
],
|
|
3867
|
-
user: [NAME, { key: "email", label: "Email" }, CREATED],
|
|
3868
|
-
invite: [
|
|
3869
|
-
{ key: "email", label: "Email" },
|
|
3870
|
-
{ key: "accepted", label: "Accepted", kind: "boolean" },
|
|
3871
|
-
{ key: "expires_at", label: "Expires", kind: "date" },
|
|
3872
|
-
CREATED
|
|
3873
|
-
],
|
|
3874
|
-
api_key: [
|
|
3875
|
-
{ key: "title", label: "Title" },
|
|
3876
|
-
{ key: "type", label: "Type" },
|
|
3877
|
-
{ key: "redacted", label: "Key (redacted)" },
|
|
3878
|
-
{ key: "revoked_at", label: "Revoked", kind: "date" },
|
|
3879
|
-
CREATED
|
|
3880
|
-
],
|
|
3881
|
-
promotion: [
|
|
3882
|
-
{ key: "code", label: "Promotion code" },
|
|
3883
|
-
{ key: "type", label: "Type" },
|
|
3884
|
-
{ key: "status", label: "Status", kind: "status" },
|
|
3885
|
-
{ key: "is_automatic", label: "Automatic", kind: "boolean" },
|
|
3886
|
-
CREATED
|
|
3887
|
-
],
|
|
3888
|
-
fulfillment: [
|
|
3889
|
-
{ key: "provider_id", label: "Provider" },
|
|
3890
|
-
{ key: "location_id", label: "Location ID", kind: "id" },
|
|
3891
|
-
{ key: "shipped_at", label: "Shipped", kind: "date" },
|
|
3892
|
-
{ key: "delivered_at", label: "Delivered", kind: "date" },
|
|
3893
|
-
{ key: "canceled_at", label: "Canceled", kind: "date" },
|
|
3894
|
-
CREATED
|
|
3895
|
-
],
|
|
3896
|
-
inventory_item: [
|
|
3897
|
-
{ key: "sku", label: "SKU" },
|
|
3898
|
-
{ key: "title", label: "Title" },
|
|
3899
|
-
{ key: "requires_shipping", label: "Requires shipping", kind: "boolean" },
|
|
3900
|
-
CREATED
|
|
3901
|
-
],
|
|
3902
|
-
inventory_level: [
|
|
3903
|
-
{ key: "inventory_item_id", label: "Inventory item ID", kind: "id" },
|
|
3904
|
-
{ key: "location_id", label: "Location ID", kind: "id" },
|
|
3905
|
-
{ key: "stocked_quantity", label: "Stocked", kind: "number" },
|
|
3906
|
-
{ key: "reserved_quantity", label: "Reserved", kind: "number" },
|
|
3907
|
-
CREATED
|
|
3908
|
-
],
|
|
3909
|
-
review: [
|
|
3910
|
-
{ key: "title", label: "Title" },
|
|
3911
|
-
{ key: "rating", label: "Rating", kind: "number" },
|
|
3912
|
-
{ key: "status", label: "Status", kind: "status" },
|
|
3913
|
-
{ key: "product_id", label: "Product ID", kind: "id" },
|
|
3914
|
-
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
3915
|
-
CREATED
|
|
3916
|
-
]
|
|
3917
|
-
};
|
|
3918
|
-
const GENERIC_FIELDS = [
|
|
3919
|
-
{ key: "display_id", label: "Number" },
|
|
3920
|
-
{ key: "title", label: "Title" },
|
|
3921
|
-
{ key: "name", label: "Name" },
|
|
3922
|
-
NAME,
|
|
3923
|
-
{ key: "email", label: "Email" },
|
|
3924
|
-
{ key: "phone", label: "Phone" },
|
|
3925
|
-
{ key: "handle", label: "Handle" },
|
|
3926
|
-
{ key: "sku", label: "SKU" },
|
|
3927
|
-
{ key: "code", label: "Code" },
|
|
3928
|
-
{ key: "status", label: "Status", kind: "status" },
|
|
3929
|
-
{ key: "type", label: "Type" },
|
|
3930
|
-
{ key: "amount", label: "Amount", kind: "money" },
|
|
3931
|
-
{ key: "quantity", label: "Quantity", kind: "number" },
|
|
3932
|
-
{ key: "currency_code", label: "Currency" },
|
|
3933
|
-
{ key: "order_id", label: "Order ID", kind: "id" },
|
|
3934
|
-
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
3935
|
-
{ key: "product_id", label: "Product ID", kind: "id" },
|
|
3936
|
-
{ key: "payment_id", label: "Payment ID", kind: "id" },
|
|
3937
|
-
{ key: "provider_id", label: "Provider" },
|
|
3938
|
-
CREATED,
|
|
3939
|
-
{ key: "updated_at", label: "Last updated", kind: "date" }
|
|
3598
|
+
const statusHistory = returnOrder.metadata?.status_history || [];
|
|
3599
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: [
|
|
3600
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3", children: [
|
|
3601
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3602
|
+
ui.Button,
|
|
3603
|
+
{
|
|
3604
|
+
variant: "transparent",
|
|
3605
|
+
size: "small",
|
|
3606
|
+
onClick: () => navigate("/returns"),
|
|
3607
|
+
className: "w-fit",
|
|
3608
|
+
children: [
|
|
3609
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, { className: "mr-2" }),
|
|
3610
|
+
"Back to list"
|
|
3611
|
+
]
|
|
3612
|
+
}
|
|
3613
|
+
),
|
|
3614
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 md:flex-row md:items-center md:justify-between", children: [
|
|
3615
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3616
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Return Order Details" }),
|
|
3617
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: returnOrder.id })
|
|
3618
|
+
] }),
|
|
3619
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3620
|
+
ui.Badge,
|
|
3621
|
+
{
|
|
3622
|
+
size: "small",
|
|
3623
|
+
className: `uppercase ${getStatusBadgeClass$1(returnOrder.status)}`,
|
|
3624
|
+
children: returnOrder.status.replace(/_/g, " ")
|
|
3625
|
+
}
|
|
3626
|
+
)
|
|
3627
|
+
] })
|
|
3628
|
+
] }),
|
|
3629
|
+
returnOrder.status === "requested" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
3630
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3631
|
+
ui.Button,
|
|
3632
|
+
{
|
|
3633
|
+
variant: "danger",
|
|
3634
|
+
onClick: handleReject,
|
|
3635
|
+
disabled: isRejecting,
|
|
3636
|
+
isLoading: isRejecting,
|
|
3637
|
+
children: "Reject (Cancel) Return"
|
|
3638
|
+
}
|
|
3639
|
+
) }),
|
|
3640
|
+
/* @__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.' })
|
|
3641
|
+
] }),
|
|
3642
|
+
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,
|
|
3643
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
3644
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Information" }),
|
|
3645
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
3646
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3647
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Return ID" }),
|
|
3648
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.id })
|
|
3649
|
+
] }),
|
|
3650
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3651
|
+
ui.Button,
|
|
3652
|
+
{
|
|
3653
|
+
variant: "secondary",
|
|
3654
|
+
onClick: () => {
|
|
3655
|
+
window.open(
|
|
3656
|
+
`/app/orders/${returnOrder.order_id}`,
|
|
3657
|
+
"_blank"
|
|
3658
|
+
);
|
|
3659
|
+
},
|
|
3660
|
+
children: "View order"
|
|
3661
|
+
}
|
|
3662
|
+
) })
|
|
3663
|
+
] })
|
|
3664
|
+
] }),
|
|
3665
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-6 md:grid-cols-2", children: [
|
|
3666
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
3667
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Details" }),
|
|
3668
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
3669
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3670
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Return ID" }),
|
|
3671
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.id })
|
|
3672
|
+
] }),
|
|
3673
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3674
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Status" }),
|
|
3675
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.status })
|
|
3676
|
+
] }),
|
|
3677
|
+
returnOrder.reason && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3678
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Reason" }),
|
|
3679
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.reason })
|
|
3680
|
+
] }),
|
|
3681
|
+
returnOrder.note && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3682
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Note" }),
|
|
3683
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.note })
|
|
3684
|
+
] }),
|
|
3685
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3686
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Created" }),
|
|
3687
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(returnOrder.created_at).toLocaleString() })
|
|
3688
|
+
] }),
|
|
3689
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3690
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Last Updated" }),
|
|
3691
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(returnOrder.updated_at).toLocaleString() })
|
|
3692
|
+
] })
|
|
3693
|
+
] })
|
|
3694
|
+
] }),
|
|
3695
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
3696
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Status History" }),
|
|
3697
|
+
statusHistory.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: statusHistory.map((entry, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3698
|
+
"div",
|
|
3699
|
+
{
|
|
3700
|
+
className: "flex items-center justify-between border-b border-ui-border-subtle pb-2 last:border-0",
|
|
3701
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3702
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3703
|
+
ui.Badge,
|
|
3704
|
+
{
|
|
3705
|
+
size: "2xsmall",
|
|
3706
|
+
className: `uppercase ${getStatusBadgeClass$1(entry.status)}`,
|
|
3707
|
+
children: entry.status.replace(/_/g, " ")
|
|
3708
|
+
}
|
|
3709
|
+
) }),
|
|
3710
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
3711
|
+
new Date(entry.timestamp).toLocaleString(),
|
|
3712
|
+
entry.admin_id && ` by ${entry.admin_id}`,
|
|
3713
|
+
entry.reason && ` - ${entry.reason}`
|
|
3714
|
+
] })
|
|
3715
|
+
] })
|
|
3716
|
+
},
|
|
3717
|
+
index
|
|
3718
|
+
)) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "No status history available" })
|
|
3719
|
+
] })
|
|
3720
|
+
] }),
|
|
3721
|
+
returnOrder.order && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
3722
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Related Order Information" }),
|
|
3723
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
3724
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3725
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order ID" }),
|
|
3726
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.order.id })
|
|
3727
|
+
] }),
|
|
3728
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3729
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Status" }),
|
|
3730
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.order.status || "—" })
|
|
3731
|
+
] }),
|
|
3732
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3733
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Customer" }),
|
|
3734
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.order.customer?.email || returnOrder.order.email || "—" })
|
|
3735
|
+
] }),
|
|
3736
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3737
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Payment method" }),
|
|
3738
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.order.order_payment?.label || "—" })
|
|
3739
|
+
] }),
|
|
3740
|
+
returnOrder.order.total && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3741
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Order Total" }),
|
|
3742
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "font-medium", children: [
|
|
3743
|
+
returnOrder.order.currency_code || "$",
|
|
3744
|
+
(Number(returnOrder.order.total) / 100).toFixed(2)
|
|
3745
|
+
] })
|
|
3746
|
+
] })
|
|
3747
|
+
] })
|
|
3748
|
+
] }),
|
|
3749
|
+
returnOrder.return_items && returnOrder.return_items.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
3750
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Items" }),
|
|
3751
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
3752
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
3753
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Item ID" }),
|
|
3754
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Quantity" }),
|
|
3755
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Reason" })
|
|
3756
|
+
] }) }),
|
|
3757
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: returnOrder.return_items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
3758
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: item.id }),
|
|
3759
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.quantity }),
|
|
3760
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: item.reason || "—" })
|
|
3761
|
+
] }, item.id || index)) })
|
|
3762
|
+
] }) })
|
|
3763
|
+
] }),
|
|
3764
|
+
updateError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-ui-border-error bg-ui-bg-error-subtle p-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-error", children: updateError }) }),
|
|
3765
|
+
updateSuccess && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-ui-border-success bg-ui-bg-success-subtle p-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-success", children: "Action completed successfully" }) })
|
|
3766
|
+
] }) });
|
|
3767
|
+
};
|
|
3768
|
+
const config$2 = adminSdk.defineRouteConfig({
|
|
3769
|
+
label: "Return Order Details",
|
|
3770
|
+
icon: icons.CheckCircle
|
|
3771
|
+
});
|
|
3772
|
+
const MASKED_VALUE = "••••••••••••";
|
|
3773
|
+
const SENSITIVE_KEY_PATTERNS = [
|
|
3774
|
+
/password|passwd|passphrase/i,
|
|
3775
|
+
/secret/i,
|
|
3776
|
+
/token/i,
|
|
3777
|
+
/api_?key$/i,
|
|
3778
|
+
/private_?key/i,
|
|
3779
|
+
/access_?key/i,
|
|
3780
|
+
/(^|_)hash(ed)?($|_)/i,
|
|
3781
|
+
/(^|_)salt$/i,
|
|
3782
|
+
/^cvv$|^cvc$|security_code/i,
|
|
3783
|
+
/card_?number/i,
|
|
3784
|
+
/account_?number/i,
|
|
3785
|
+
/credential/i,
|
|
3786
|
+
/authorization/i,
|
|
3787
|
+
/recovery_?code/i,
|
|
3788
|
+
/(^|_)otp($|_)/i,
|
|
3789
|
+
/verification_?code/i,
|
|
3790
|
+
/^code_hash$/i,
|
|
3791
|
+
/webhook_?signature/i
|
|
3940
3792
|
];
|
|
3941
|
-
const
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3793
|
+
const TABLE_SENSITIVE_KEYS = {
|
|
3794
|
+
otp_verification: /* @__PURE__ */ new Set(["code", "value"]),
|
|
3795
|
+
auth_verification: /* @__PURE__ */ new Set(["code", "value"]),
|
|
3796
|
+
auth_mfa_factor: /* @__PURE__ */ new Set(["value", "config"])
|
|
3797
|
+
};
|
|
3798
|
+
const SAFE_KEYS = /* @__PURE__ */ new Set([
|
|
3799
|
+
"token_type",
|
|
3800
|
+
"redacted",
|
|
3801
|
+
"api_key_id",
|
|
3802
|
+
"token_id",
|
|
3803
|
+
"notification_token_id"
|
|
3804
|
+
]);
|
|
3805
|
+
function isSensitiveKey(key) {
|
|
3806
|
+
const normalized = key.trim().toLowerCase();
|
|
3807
|
+
if (SAFE_KEYS.has(normalized)) return false;
|
|
3808
|
+
return SENSITIVE_KEY_PATTERNS.some((pattern) => pattern.test(normalized));
|
|
3949
3809
|
}
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
const
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
const n = amountOf(raw);
|
|
3966
|
-
return n === null ? null : { value: formatNumber(n), kind };
|
|
3810
|
+
const FULLY_SECRET_TABLES = /* @__PURE__ */ new Set(["auth_mfa_recovery_code", "auth_password_reset_token"]);
|
|
3811
|
+
const ALWAYS_VISIBLE_KEYS = /* @__PURE__ */ new Set(["id", "created_at", "updated_at", "deleted_at", "expires_at", "used_at"]);
|
|
3812
|
+
function maskValue(value, ctx, depth) {
|
|
3813
|
+
if (Array.isArray(value)) return value.map((item) => maskValue(item, ctx, depth + 1));
|
|
3814
|
+
if (value !== null && typeof value === "object") {
|
|
3815
|
+
const out = {};
|
|
3816
|
+
for (const [key, inner] of Object.entries(value)) {
|
|
3817
|
+
const topLevel = depth === 0;
|
|
3818
|
+
const secret = inner !== null && inner !== void 0 && inner !== "" && (isSensitiveKey(key) || topLevel && ctx.tableKeys?.has(key.toLowerCase()) === true || topLevel && ctx.maskAll && !ALWAYS_VISIBLE_KEYS.has(key) && !key.endsWith("_id"));
|
|
3819
|
+
if (secret) {
|
|
3820
|
+
ctx.count += 1;
|
|
3821
|
+
out[key] = MASKED_VALUE;
|
|
3822
|
+
} else {
|
|
3823
|
+
out[key] = maskValue(inner, ctx, depth + 1);
|
|
3824
|
+
}
|
|
3967
3825
|
}
|
|
3968
|
-
|
|
3969
|
-
return { value: String(raw).replace(/_/g, " "), kind };
|
|
3970
|
-
default:
|
|
3971
|
-
if (typeof raw === "object") return null;
|
|
3972
|
-
if (typeof raw === "string" && raw.length > 160) return { value: `${raw.slice(0, 157)}…`, kind };
|
|
3973
|
-
return { value: String(raw), kind };
|
|
3974
|
-
}
|
|
3975
|
-
}
|
|
3976
|
-
function summarizeOldData(tableName, oldData) {
|
|
3977
|
-
if (!oldData) return [];
|
|
3978
|
-
const { value: row } = maskSensitiveData(oldData, tableName);
|
|
3979
|
-
const specific = ENTITY_FIELDS[tableName];
|
|
3980
|
-
const specs = specific ?? GENERIC_FIELDS;
|
|
3981
|
-
const fields = [];
|
|
3982
|
-
const seenLabels = /* @__PURE__ */ new Set();
|
|
3983
|
-
for (const spec of specs) {
|
|
3984
|
-
const raw = spec.derive ? spec.derive(row) : row[spec.key];
|
|
3985
|
-
const formatted = formatValue(raw, spec.kind ?? "text", row);
|
|
3986
|
-
if (!formatted || seenLabels.has(spec.label)) continue;
|
|
3987
|
-
seenLabels.add(spec.label);
|
|
3988
|
-
const value = spec.key === "currency_code" ? formatted.value.toUpperCase() : formatted.value;
|
|
3989
|
-
fields.push({ key: spec.key, label: spec.label, value, kind: formatted.kind });
|
|
3990
|
-
if (!specific && fields.length >= MAX_GENERIC_FIELDS) break;
|
|
3991
|
-
}
|
|
3992
|
-
return fields;
|
|
3993
|
-
}
|
|
3994
|
-
function readLastListSearch() {
|
|
3995
|
-
try {
|
|
3996
|
-
return window.sessionStorage.getItem(LAST_LIST_URL_KEY) ?? "";
|
|
3997
|
-
} catch {
|
|
3998
|
-
return "";
|
|
3826
|
+
return out;
|
|
3999
3827
|
}
|
|
3828
|
+
return value;
|
|
4000
3829
|
}
|
|
4001
|
-
|
|
4002
|
-
const
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
const [reloadToken, setReloadToken] = react.useState(0);
|
|
4007
|
-
const cameFromList = location.state?.fromList === true;
|
|
4008
|
-
const goBack = () => {
|
|
4009
|
-
if (cameFromList) navigate(-1);
|
|
4010
|
-
else navigate(`/deleted-records-audit${readLastListSearch()}`);
|
|
3830
|
+
function maskSensitiveData(data, tableName) {
|
|
3831
|
+
const ctx = {
|
|
3832
|
+
count: 0,
|
|
3833
|
+
maskAll: tableName ? FULLY_SECRET_TABLES.has(tableName) : false,
|
|
3834
|
+
tableKeys: tableName ? TABLE_SENSITIVE_KEYS[tableName] : void 0
|
|
4011
3835
|
};
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
return () => controller.abort();
|
|
4024
|
-
}, [id, reloadToken]);
|
|
4025
|
-
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: [
|
|
4026
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: "transparent", size: "small", onClick: goBack, className: "-ml-2", children: [
|
|
4027
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, {}),
|
|
4028
|
-
"Back to Deleted Records"
|
|
4029
|
-
] }) }),
|
|
4030
|
-
state.status === "loading" ? /* @__PURE__ */ jsxRuntime.jsx(DetailSkeleton, {}) : state.status === "error" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4031
|
-
DetailError,
|
|
4032
|
-
{
|
|
4033
|
-
notFound: state.notFound,
|
|
4034
|
-
message: state.message,
|
|
4035
|
-
onRetry: () => setReloadToken((t) => t + 1),
|
|
4036
|
-
onBack: goBack
|
|
4037
|
-
}
|
|
4038
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(DetailContent, { audit: state.audit })
|
|
4039
|
-
] }) });
|
|
4040
|
-
};
|
|
4041
|
-
const DetailContent = ({ audit }) => {
|
|
4042
|
-
const navigate = reactRouterDom.useNavigate();
|
|
4043
|
-
const entity = getEntityInfo(audit.table_name);
|
|
4044
|
-
const source = describeSource(audit.source);
|
|
4045
|
-
const summary = react.useMemo(() => summarizeOldData(audit.table_name, audit.old_data), [audit]);
|
|
4046
|
-
const masked = react.useMemo(() => maskSensitiveData(audit.old_data, audit.table_name), [audit]);
|
|
4047
|
-
const guidance = getNextSteps(entity.category.id);
|
|
4048
|
-
const related = getRelatedLinks(audit.table_name, audit.old_data);
|
|
4049
|
-
const [showRaw, setShowRaw] = react.useState(false);
|
|
4050
|
-
const copyJson = async () => {
|
|
4051
|
-
try {
|
|
4052
|
-
await navigator.clipboard.writeText(JSON.stringify(masked.value, null, 2));
|
|
4053
|
-
ui.toast.success("Record data copied", {
|
|
4054
|
-
description: masked.maskedCount ? "Sensitive values were left hidden." : void 0
|
|
4055
|
-
});
|
|
4056
|
-
} catch {
|
|
4057
|
-
ui.toast.error("Couldn’t copy to clipboard");
|
|
4058
|
-
}
|
|
3836
|
+
const value = maskValue(data, ctx, 0);
|
|
3837
|
+
return { value, maskedCount: ctx.count };
|
|
3838
|
+
}
|
|
3839
|
+
const AUTO_EXPAND_DEPTH = 1;
|
|
3840
|
+
const LONG_STRING = 200;
|
|
3841
|
+
const JsonViewer = ({ data }) => {
|
|
3842
|
+
const [generation, setGeneration] = react.useState(0);
|
|
3843
|
+
const [expandAll, setExpandAll] = react.useState(null);
|
|
3844
|
+
const setAll = (value) => {
|
|
3845
|
+
setExpandAll(value);
|
|
3846
|
+
setGeneration((g) => g + 1);
|
|
4059
3847
|
};
|
|
4060
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4061
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
4062
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4063
|
-
|
|
4064
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.Trash, {}),
|
|
4065
|
-
"Deleted"
|
|
4066
|
-
] }),
|
|
4067
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: entity.category.label })
|
|
4068
|
-
] }),
|
|
4069
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Heading, { level: "h1", children: [
|
|
4070
|
-
"Deleted ",
|
|
4071
|
-
entity.label
|
|
4072
|
-
] }),
|
|
4073
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
4074
|
-
/* @__PURE__ */ jsxRuntime.jsx(CopyableId, { value: audit.record_id, emptyLabel: "This record type has no ID column", className: "text-sm" }),
|
|
4075
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: [
|
|
4076
|
-
"Database table: ",
|
|
4077
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: audit.table_name })
|
|
4078
|
-
] })
|
|
4079
|
-
] })
|
|
3848
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
3849
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
3850
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => setAll(true), children: "Expand all" }),
|
|
3851
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => setAll(false), children: "Collapse all" })
|
|
4080
3852
|
] }),
|
|
4081
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
3853
|
+
/* @__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) })
|
|
3854
|
+
] });
|
|
3855
|
+
};
|
|
3856
|
+
const JsonNode = ({ name, value, depth, forceExpand }) => {
|
|
3857
|
+
const isContainer = value !== null && typeof value === "object";
|
|
3858
|
+
const [open, setOpen] = react.useState(forceExpand ?? depth < AUTO_EXPAND_DEPTH);
|
|
3859
|
+
const label = name !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-fg-subtle", children: [
|
|
3860
|
+
name,
|
|
3861
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: ": " })
|
|
3862
|
+
] }) : null;
|
|
3863
|
+
if (!isContainer) {
|
|
3864
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-start", style: { paddingLeft: depth ? 16 : 0 }, children: [
|
|
3865
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-4 shrink-0" }),
|
|
3866
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 break-words [overflow-wrap:anywhere]", children: [
|
|
3867
|
+
label,
|
|
3868
|
+
/* @__PURE__ */ jsxRuntime.jsx(Primitive, { value })
|
|
4086
3869
|
] })
|
|
4087
|
-
] })
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
] }) }),
|
|
4096
|
-
/* @__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" }) }),
|
|
4097
|
-
/* @__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 }) }),
|
|
4098
|
-
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Action", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Permanently deleted" }) })
|
|
4099
|
-
] }) }),
|
|
4100
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4101
|
-
Section,
|
|
3870
|
+
] });
|
|
3871
|
+
}
|
|
3872
|
+
const entries = Array.isArray(value) ? value.map((v, i) => [String(i), v]) : Object.entries(value);
|
|
3873
|
+
const [openBracket, closeBracket] = Array.isArray(value) ? ["[", "]"] : ["{", "}"];
|
|
3874
|
+
const summary = Array.isArray(value) ? `${entries.length} items` : `${entries.length} keys`;
|
|
3875
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { paddingLeft: depth ? 16 : 0 }, children: [
|
|
3876
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3877
|
+
"button",
|
|
4102
3878
|
{
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
3879
|
+
type: "button",
|
|
3880
|
+
onClick: () => setOpen((o) => !o),
|
|
3881
|
+
className: "flex items-start text-left hover:bg-ui-bg-base-hover",
|
|
3882
|
+
"aria-expanded": open,
|
|
3883
|
+
children: [
|
|
3884
|
+
/* @__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 }),
|
|
3885
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
3886
|
+
label,
|
|
3887
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: openBracket }),
|
|
3888
|
+
!open || entries.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3889
|
+
entries.length ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-1 italic text-ui-fg-muted", children: summary }) : null,
|
|
3890
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: closeBracket })
|
|
3891
|
+
] }) : null
|
|
3892
|
+
] })
|
|
3893
|
+
]
|
|
4106
3894
|
}
|
|
4107
3895
|
),
|
|
4108
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4109
|
-
|
|
3896
|
+
open && entries.length ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3897
|
+
entries.map(([key, child]) => /* @__PURE__ */ jsxRuntime.jsx(JsonNode, { name: key, value: child, depth: depth + 1, forceExpand }, key)),
|
|
3898
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { paddingLeft: 16 }, className: "text-ui-fg-muted", children: closeBracket })
|
|
3899
|
+
] }) : null
|
|
3900
|
+
] });
|
|
3901
|
+
};
|
|
3902
|
+
const Primitive = ({ value }) => {
|
|
3903
|
+
const [showFull, setShowFull] = react.useState(false);
|
|
3904
|
+
if (value === MASKED_VALUE) {
|
|
3905
|
+
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 });
|
|
3906
|
+
}
|
|
3907
|
+
if (value === null || value === void 0) return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: "null" });
|
|
3908
|
+
if (typeof value === "boolean") return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-tag-purple-text", children: String(value) });
|
|
3909
|
+
if (typeof value === "number") return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-tag-blue-text", children: value });
|
|
3910
|
+
const text = String(value);
|
|
3911
|
+
const truncated = !showFull && text.length > LONG_STRING;
|
|
3912
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: ui.clx("text-ui-tag-green-text"), children: [
|
|
3913
|
+
'"',
|
|
3914
|
+
truncated ? `${text.slice(0, LONG_STRING)}…` : text,
|
|
3915
|
+
'"',
|
|
3916
|
+
text.length > LONG_STRING ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3917
|
+
"button",
|
|
4110
3918
|
{
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
"Copy JSON"
|
|
4116
|
-
] }) : null,
|
|
4117
|
-
children: audit.old_data ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
4118
|
-
masked.maskedCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
4119
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ShieldCheck, { className: "shrink-0 text-ui-fg-muted" }),
|
|
4120
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
4121
|
-
masked.maskedCount,
|
|
4122
|
-
" sensitive ",
|
|
4123
|
-
masked.maskedCount === 1 ? "value is" : "values are",
|
|
4124
|
-
" hidden for security (passwords, tokens, card or account numbers)."
|
|
4125
|
-
] })
|
|
4126
|
-
] }) : null,
|
|
4127
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: "secondary", size: "small", onClick: () => setShowRaw((s2) => !s2), "aria-expanded": showRaw, children: [
|
|
4128
|
-
showRaw ? /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDownMini, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRightMini, {}),
|
|
4129
|
-
showRaw ? "Hide full record" : "View full record"
|
|
4130
|
-
] }) }),
|
|
4131
|
-
showRaw ? /* @__PURE__ */ jsxRuntime.jsx(JsonViewer, { data: masked.value }) : null
|
|
4132
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "No data was captured for this deletion." })
|
|
3919
|
+
type: "button",
|
|
3920
|
+
onClick: () => setShowFull((s2) => !s2),
|
|
3921
|
+
className: "ml-1 font-sans text-ui-fg-interactive hover:underline",
|
|
3922
|
+
children: showFull ? "show less" : `show all (${text.length} chars)`
|
|
4133
3923
|
}
|
|
4134
|
-
)
|
|
4135
|
-
/* @__PURE__ */ jsxRuntime.jsx(Section, { title: "What you can do now", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
4136
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-base", children: [
|
|
4137
|
-
"This record was permanently deleted. ",
|
|
4138
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Automatic restoration is not available" }),
|
|
4139
|
-
" ",
|
|
4140
|
-
"from this screen."
|
|
4141
|
-
] }),
|
|
4142
|
-
/* @__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: [
|
|
4143
|
-
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
4144
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: "Check whether this was expected." }),
|
|
4145
|
-
" ",
|
|
4146
|
-
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)}.`,
|
|
4147
|
-
" ",
|
|
4148
|
-
guidance.headline
|
|
4149
|
-
] }),
|
|
4150
|
-
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
4151
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: "If it needs to come back:" }),
|
|
4152
|
-
" ",
|
|
4153
|
-
guidance.recreate
|
|
4154
|
-
] }),
|
|
4155
|
-
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
4156
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: "Need the details?" }),
|
|
4157
|
-
" Use “View full record” above to see or copy everything that was stored. Sensitive values stay hidden."
|
|
4158
|
-
] })
|
|
4159
|
-
] }),
|
|
4160
|
-
guidance.adminSection || related.length ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
4161
|
-
guidance.adminSection ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", size: "small", onClick: () => navigate(guidance.adminSection.path), children: guidance.adminSection.label }) : null,
|
|
4162
|
-
related.map((link) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4163
|
-
ui.Button,
|
|
4164
|
-
{
|
|
4165
|
-
variant: "transparent",
|
|
4166
|
-
size: "small",
|
|
4167
|
-
onClick: () => navigate(link.path),
|
|
4168
|
-
title: `Opens ${link.label.toLowerCase()} ${link.id} if it still exists`,
|
|
4169
|
-
children: [
|
|
4170
|
-
"Open related ",
|
|
4171
|
-
link.label.toLowerCase(),
|
|
4172
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRightMini, {})
|
|
4173
|
-
]
|
|
4174
|
-
},
|
|
4175
|
-
link.path
|
|
4176
|
-
))
|
|
4177
|
-
] }) : null,
|
|
4178
|
-
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
|
|
4179
|
-
] }) })
|
|
3924
|
+
) : null
|
|
4180
3925
|
] });
|
|
4181
3926
|
};
|
|
4182
|
-
const
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
}
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
}
|
|
4243
|
-
|
|
4244
|
-
|
|
3927
|
+
const GUIDANCE = {
|
|
3928
|
+
orders: {
|
|
3929
|
+
headline: "Order data affects customers, payments and reports.",
|
|
3930
|
+
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.",
|
|
3931
|
+
adminSection: { label: "Go to Orders", path: "/orders" }
|
|
3932
|
+
},
|
|
3933
|
+
carts: {
|
|
3934
|
+
headline: "Carts are usually cleaned up automatically.",
|
|
3935
|
+
recreate: "No action is normally needed. Customers can simply add items to a new cart."
|
|
3936
|
+
},
|
|
3937
|
+
customers: {
|
|
3938
|
+
headline: "Customer data may be needed for orders, support and compliance.",
|
|
3939
|
+
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.",
|
|
3940
|
+
adminSection: { label: "Go to Customers", path: "/customers" }
|
|
3941
|
+
},
|
|
3942
|
+
catalog: {
|
|
3943
|
+
headline: "Catalog changes affect what customers can see and buy.",
|
|
3944
|
+
recreate: "If it was deleted by mistake, recreate it from Products using the values shown above. It will get a new ID.",
|
|
3945
|
+
adminSection: { label: "Go to Products", path: "/products" }
|
|
3946
|
+
},
|
|
3947
|
+
pricing: {
|
|
3948
|
+
headline: "Pricing and promotions affect what customers pay.",
|
|
3949
|
+
recreate: "If it was deleted by mistake, recreate it from Promotions or Price Lists using the values shown above.",
|
|
3950
|
+
adminSection: { label: "Go to Promotions", path: "/promotions" }
|
|
3951
|
+
},
|
|
3952
|
+
payments: {
|
|
3953
|
+
headline: "Payment records are financial data.",
|
|
3954
|
+
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."
|
|
3955
|
+
},
|
|
3956
|
+
fulfillment: {
|
|
3957
|
+
headline: "Shipping and fulfillment settings affect checkout and delivery.",
|
|
3958
|
+
recreate: "If it was deleted by mistake, recreate it from Settings → Locations & Shipping using the values shown above.",
|
|
3959
|
+
adminSection: { label: "Go to Settings", path: "/settings" }
|
|
3960
|
+
},
|
|
3961
|
+
inventory: {
|
|
3962
|
+
headline: "Inventory changes can affect stock levels and availability.",
|
|
3963
|
+
recreate: "If it was deleted by mistake, recreate it from Inventory using the values shown above and re-check stock quantities.",
|
|
3964
|
+
adminSection: { label: "Go to Inventory", path: "/inventory" }
|
|
3965
|
+
},
|
|
3966
|
+
wallet: {
|
|
3967
|
+
headline: "Wallet and credit records are financial data.",
|
|
3968
|
+
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."
|
|
3969
|
+
},
|
|
3970
|
+
access: {
|
|
3971
|
+
headline: "Access records control who can sign in.",
|
|
3972
|
+
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.",
|
|
3973
|
+
adminSection: { label: "Go to Settings", path: "/settings" }
|
|
3974
|
+
},
|
|
3975
|
+
store: {
|
|
3976
|
+
headline: "Store settings affect regions, currencies and taxes.",
|
|
3977
|
+
recreate: "If it was deleted by mistake, recreate it from Settings using the values shown above.",
|
|
3978
|
+
adminSection: { label: "Go to Settings", path: "/settings" }
|
|
3979
|
+
},
|
|
3980
|
+
engagement: {
|
|
3981
|
+
headline: "Customer-generated content.",
|
|
3982
|
+
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."
|
|
3983
|
+
},
|
|
3984
|
+
notifications: {
|
|
3985
|
+
headline: "Notification records are usually cleaned up automatically.",
|
|
3986
|
+
recreate: "No action is normally needed."
|
|
3987
|
+
},
|
|
3988
|
+
system: {
|
|
3989
|
+
headline: "Internal system data, usually removed automatically by the platform.",
|
|
3990
|
+
recreate: "No action is normally needed. If you suspect a problem, share this page with a developer."
|
|
3991
|
+
}
|
|
3992
|
+
};
|
|
3993
|
+
function getNextSteps(category) {
|
|
3994
|
+
return GUIDANCE[category];
|
|
3995
|
+
}
|
|
3996
|
+
const RELATED_LINKS = [
|
|
3997
|
+
{ key: "order_id", label: "Order", path: (id) => `/orders/${id}`, selfTables: ["order"] },
|
|
3998
|
+
{ key: "customer_id", label: "Customer", path: (id) => `/customers/${id}`, selfTables: ["customer"] },
|
|
3999
|
+
{ key: "product_id", label: "Product", path: (id) => `/products/${id}`, selfTables: ["product"] }
|
|
4000
|
+
];
|
|
4001
|
+
function getRelatedLinks(tableName, oldData) {
|
|
4002
|
+
if (!oldData) return [];
|
|
4003
|
+
return RELATED_LINKS.flatMap((link) => {
|
|
4004
|
+
const id = oldData[link.key];
|
|
4005
|
+
if (link.selfTables.includes(tableName) || typeof id !== "string" || !id.trim()) return [];
|
|
4006
|
+
return [{ label: link.label, id, path: link.path(id) }];
|
|
4007
|
+
});
|
|
4008
|
+
}
|
|
4009
|
+
const fullName = (row) => {
|
|
4010
|
+
const parts = [row.first_name, row.last_name].filter(
|
|
4011
|
+
(part) => typeof part === "string" && part.trim() !== ""
|
|
4012
|
+
);
|
|
4013
|
+
return parts.length ? parts.join(" ") : void 0;
|
|
4014
|
+
};
|
|
4015
|
+
const addressLine = (row) => {
|
|
4016
|
+
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());
|
|
4017
|
+
return parts.length ? parts.join(", ") : void 0;
|
|
4018
|
+
};
|
|
4019
|
+
const NAME = { key: "name", label: "Name", derive: fullName };
|
|
4020
|
+
const ADDRESS = { key: "address", label: "Address", derive: addressLine };
|
|
4021
|
+
const CREATED = { key: "created_at", label: "Created", kind: "date" };
|
|
4022
|
+
const ENTITY_FIELDS = {
|
|
4023
|
+
order: [
|
|
4024
|
+
{ key: "display_id", label: "Order number" },
|
|
4025
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
4026
|
+
{ key: "email", label: "Customer email" },
|
|
4027
|
+
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
4028
|
+
{ key: "currency_code", label: "Currency" },
|
|
4029
|
+
{ key: "region_id", label: "Region ID", kind: "id" },
|
|
4030
|
+
{ key: "sales_channel_id", label: "Sales channel ID", kind: "id" },
|
|
4031
|
+
{ key: "canceled_at", label: "Canceled", kind: "date" },
|
|
4032
|
+
CREATED
|
|
4033
|
+
],
|
|
4034
|
+
order_line_item: [
|
|
4035
|
+
{ key: "title", label: "Item" },
|
|
4036
|
+
{ key: "variant_title", label: "Variant" },
|
|
4037
|
+
{ key: "variant_sku", label: "SKU" },
|
|
4038
|
+
{ key: "unit_price", label: "Unit price", kind: "money" },
|
|
4039
|
+
{ key: "product_id", label: "Product ID", kind: "id" },
|
|
4040
|
+
{ key: "variant_id", label: "Variant ID", kind: "id" },
|
|
4041
|
+
CREATED
|
|
4042
|
+
],
|
|
4043
|
+
cart_line_item: [
|
|
4044
|
+
{ key: "title", label: "Item" },
|
|
4045
|
+
{ key: "variant_sku", label: "SKU" },
|
|
4046
|
+
{ key: "quantity", label: "Quantity", kind: "number" },
|
|
4047
|
+
{ key: "unit_price", label: "Unit price", kind: "money" },
|
|
4048
|
+
{ key: "cart_id", label: "Cart ID", kind: "id" },
|
|
4049
|
+
{ key: "variant_id", label: "Variant ID", kind: "id" },
|
|
4050
|
+
CREATED
|
|
4051
|
+
],
|
|
4052
|
+
cart: [
|
|
4053
|
+
{ key: "email", label: "Email" },
|
|
4054
|
+
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
4055
|
+
{ key: "currency_code", label: "Currency" },
|
|
4056
|
+
{ key: "region_id", label: "Region ID", kind: "id" },
|
|
4057
|
+
{ key: "completed_at", label: "Completed", kind: "date" },
|
|
4058
|
+
CREATED
|
|
4059
|
+
],
|
|
4060
|
+
customer: [
|
|
4061
|
+
NAME,
|
|
4062
|
+
{ key: "email", label: "Email" },
|
|
4063
|
+
{ key: "phone", label: "Phone" },
|
|
4064
|
+
{ key: "company_name", label: "Company" },
|
|
4065
|
+
{ key: "has_account", label: "Registered account", kind: "boolean" },
|
|
4066
|
+
CREATED
|
|
4067
|
+
],
|
|
4068
|
+
customer_address: [
|
|
4069
|
+
{ key: "address_name", label: "Label" },
|
|
4070
|
+
NAME,
|
|
4071
|
+
ADDRESS,
|
|
4072
|
+
{ key: "phone", label: "Phone" },
|
|
4073
|
+
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
4074
|
+
{ key: "is_default_shipping", label: "Default shipping", kind: "boolean" },
|
|
4075
|
+
CREATED
|
|
4076
|
+
],
|
|
4077
|
+
order_address: [NAME, ADDRESS, { key: "phone", label: "Phone" }, CREATED],
|
|
4078
|
+
cart_address: [NAME, ADDRESS, { key: "phone", label: "Phone" }, CREATED],
|
|
4079
|
+
product: [
|
|
4080
|
+
{ key: "title", label: "Title" },
|
|
4081
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
4082
|
+
{ key: "handle", label: "Handle" },
|
|
4083
|
+
{ key: "subtitle", label: "Subtitle" },
|
|
4084
|
+
{ key: "collection_id", label: "Collection ID", kind: "id" },
|
|
4085
|
+
{ key: "is_giftcard", label: "Gift card", kind: "boolean" },
|
|
4086
|
+
CREATED
|
|
4087
|
+
],
|
|
4088
|
+
product_variant: [
|
|
4089
|
+
{ key: "title", label: "Title" },
|
|
4090
|
+
{ key: "sku", label: "SKU" },
|
|
4091
|
+
{ key: "barcode", label: "Barcode" },
|
|
4092
|
+
{ key: "product_id", label: "Product ID", kind: "id" },
|
|
4093
|
+
{ key: "manage_inventory", label: "Manages inventory", kind: "boolean" },
|
|
4094
|
+
CREATED
|
|
4095
|
+
],
|
|
4096
|
+
product_category: [
|
|
4097
|
+
{ key: "name", label: "Name" },
|
|
4098
|
+
{ key: "handle", label: "Handle" },
|
|
4099
|
+
{ key: "is_active", label: "Active", kind: "boolean" },
|
|
4100
|
+
{ key: "parent_category_id", label: "Parent category ID", kind: "id" },
|
|
4101
|
+
CREATED
|
|
4102
|
+
],
|
|
4103
|
+
product_collection: [{ key: "title", label: "Title" }, { key: "handle", label: "Handle" }, CREATED],
|
|
4104
|
+
payment: [
|
|
4105
|
+
{ key: "amount", label: "Amount", kind: "money" },
|
|
4106
|
+
{ key: "currency_code", label: "Currency" },
|
|
4107
|
+
{ key: "provider_id", label: "Provider" },
|
|
4108
|
+
{ key: "captured_at", label: "Captured", kind: "date" },
|
|
4109
|
+
{ key: "canceled_at", label: "Canceled", kind: "date" },
|
|
4110
|
+
{ key: "payment_collection_id", label: "Payment collection ID", kind: "id" },
|
|
4111
|
+
CREATED
|
|
4112
|
+
],
|
|
4113
|
+
payment_session: [
|
|
4114
|
+
{ key: "amount", label: "Amount", kind: "money" },
|
|
4115
|
+
{ key: "currency_code", label: "Currency" },
|
|
4116
|
+
{ key: "provider_id", label: "Provider" },
|
|
4117
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
4118
|
+
{ key: "payment_collection_id", label: "Payment collection ID", kind: "id" },
|
|
4119
|
+
CREATED
|
|
4120
|
+
],
|
|
4121
|
+
payment_collection: [
|
|
4122
|
+
{ key: "amount", label: "Amount", kind: "money" },
|
|
4123
|
+
{ key: "currency_code", label: "Currency" },
|
|
4124
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
4125
|
+
CREATED
|
|
4126
|
+
],
|
|
4127
|
+
refund: [
|
|
4128
|
+
{ key: "amount", label: "Amount", kind: "money" },
|
|
4129
|
+
{ key: "payment_id", label: "Payment ID", kind: "id" },
|
|
4130
|
+
{ key: "refund_reason_id", label: "Refund reason ID", kind: "id" },
|
|
4131
|
+
{ key: "note", label: "Note" },
|
|
4132
|
+
{ key: "created_by", label: "Created by" },
|
|
4133
|
+
CREATED
|
|
4134
|
+
],
|
|
4135
|
+
return: [
|
|
4136
|
+
{ key: "display_id", label: "Return number" },
|
|
4137
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
4138
|
+
{ key: "order_id", label: "Order ID", kind: "id" },
|
|
4139
|
+
{ key: "refund_amount", label: "Refund amount", kind: "money" },
|
|
4140
|
+
{ key: "received_at", label: "Received", kind: "date" },
|
|
4141
|
+
CREATED
|
|
4142
|
+
],
|
|
4143
|
+
payment_detail: [
|
|
4144
|
+
{ key: "type", label: "Method type" },
|
|
4145
|
+
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
4146
|
+
{ key: "is_default", label: "Default method", kind: "boolean" },
|
|
4147
|
+
CREATED
|
|
4148
|
+
],
|
|
4149
|
+
user: [NAME, { key: "email", label: "Email" }, CREATED],
|
|
4150
|
+
invite: [
|
|
4151
|
+
{ key: "email", label: "Email" },
|
|
4152
|
+
{ key: "accepted", label: "Accepted", kind: "boolean" },
|
|
4153
|
+
{ key: "expires_at", label: "Expires", kind: "date" },
|
|
4154
|
+
CREATED
|
|
4155
|
+
],
|
|
4156
|
+
api_key: [
|
|
4157
|
+
{ key: "title", label: "Title" },
|
|
4158
|
+
{ key: "type", label: "Type" },
|
|
4159
|
+
{ key: "redacted", label: "Key (redacted)" },
|
|
4160
|
+
{ key: "revoked_at", label: "Revoked", kind: "date" },
|
|
4161
|
+
CREATED
|
|
4162
|
+
],
|
|
4163
|
+
promotion: [
|
|
4164
|
+
{ key: "code", label: "Promotion code" },
|
|
4165
|
+
{ key: "type", label: "Type" },
|
|
4166
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
4167
|
+
{ key: "is_automatic", label: "Automatic", kind: "boolean" },
|
|
4168
|
+
CREATED
|
|
4169
|
+
],
|
|
4170
|
+
fulfillment: [
|
|
4171
|
+
{ key: "provider_id", label: "Provider" },
|
|
4172
|
+
{ key: "location_id", label: "Location ID", kind: "id" },
|
|
4173
|
+
{ key: "shipped_at", label: "Shipped", kind: "date" },
|
|
4174
|
+
{ key: "delivered_at", label: "Delivered", kind: "date" },
|
|
4175
|
+
{ key: "canceled_at", label: "Canceled", kind: "date" },
|
|
4176
|
+
CREATED
|
|
4177
|
+
],
|
|
4178
|
+
inventory_item: [
|
|
4179
|
+
{ key: "sku", label: "SKU" },
|
|
4180
|
+
{ key: "title", label: "Title" },
|
|
4181
|
+
{ key: "requires_shipping", label: "Requires shipping", kind: "boolean" },
|
|
4182
|
+
CREATED
|
|
4183
|
+
],
|
|
4184
|
+
inventory_level: [
|
|
4185
|
+
{ key: "inventory_item_id", label: "Inventory item ID", kind: "id" },
|
|
4186
|
+
{ key: "location_id", label: "Location ID", kind: "id" },
|
|
4187
|
+
{ key: "stocked_quantity", label: "Stocked", kind: "number" },
|
|
4188
|
+
{ key: "reserved_quantity", label: "Reserved", kind: "number" },
|
|
4189
|
+
CREATED
|
|
4190
|
+
],
|
|
4191
|
+
review: [
|
|
4192
|
+
{ key: "title", label: "Title" },
|
|
4193
|
+
{ key: "rating", label: "Rating", kind: "number" },
|
|
4194
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
4195
|
+
{ key: "product_id", label: "Product ID", kind: "id" },
|
|
4196
|
+
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
4197
|
+
CREATED
|
|
4198
|
+
]
|
|
4199
|
+
};
|
|
4200
|
+
const GENERIC_FIELDS = [
|
|
4201
|
+
{ key: "display_id", label: "Number" },
|
|
4202
|
+
{ key: "title", label: "Title" },
|
|
4203
|
+
{ key: "name", label: "Name" },
|
|
4204
|
+
NAME,
|
|
4205
|
+
{ key: "email", label: "Email" },
|
|
4206
|
+
{ key: "phone", label: "Phone" },
|
|
4207
|
+
{ key: "handle", label: "Handle" },
|
|
4208
|
+
{ key: "sku", label: "SKU" },
|
|
4209
|
+
{ key: "code", label: "Code" },
|
|
4210
|
+
{ key: "status", label: "Status", kind: "status" },
|
|
4211
|
+
{ key: "type", label: "Type" },
|
|
4212
|
+
{ key: "amount", label: "Amount", kind: "money" },
|
|
4213
|
+
{ key: "quantity", label: "Quantity", kind: "number" },
|
|
4214
|
+
{ key: "currency_code", label: "Currency" },
|
|
4215
|
+
{ key: "order_id", label: "Order ID", kind: "id" },
|
|
4216
|
+
{ key: "customer_id", label: "Customer ID", kind: "id" },
|
|
4217
|
+
{ key: "product_id", label: "Product ID", kind: "id" },
|
|
4218
|
+
{ key: "payment_id", label: "Payment ID", kind: "id" },
|
|
4219
|
+
{ key: "provider_id", label: "Provider" },
|
|
4220
|
+
CREATED,
|
|
4221
|
+
{ key: "updated_at", label: "Last updated", kind: "date" }
|
|
4222
|
+
];
|
|
4223
|
+
const MAX_GENERIC_FIELDS = 8;
|
|
4224
|
+
function amountOf(value) {
|
|
4225
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
4226
|
+
if (typeof value === "string" && value.trim() !== "" && Number.isFinite(Number(value))) return Number(value);
|
|
4227
|
+
if (value !== null && typeof value === "object" && "value" in value) {
|
|
4228
|
+
return amountOf(value.value);
|
|
4245
4229
|
}
|
|
4246
|
-
|
|
4247
|
-
|
|
4230
|
+
return null;
|
|
4231
|
+
}
|
|
4232
|
+
function formatValue(raw, kind, row) {
|
|
4233
|
+
if (raw === null || raw === void 0 || raw === "") return null;
|
|
4234
|
+
if (raw === MASKED_VALUE) return { value: MASKED_VALUE, kind: "masked" };
|
|
4235
|
+
switch (kind) {
|
|
4236
|
+
case "money": {
|
|
4237
|
+
const amount = amountOf(raw);
|
|
4238
|
+
if (amount === null) return null;
|
|
4239
|
+
const currency = typeof row.currency_code === "string" ? row.currency_code : null;
|
|
4240
|
+
return { value: formatMoney(amount, currency), kind };
|
|
4241
|
+
}
|
|
4242
|
+
case "date":
|
|
4243
|
+
return typeof raw === "string" || raw instanceof Date ? { value: formatDate(raw), kind } : null;
|
|
4244
|
+
case "boolean":
|
|
4245
|
+
return { value: raw === true || raw === "true" ? "Yes" : "No", kind };
|
|
4246
|
+
case "number": {
|
|
4247
|
+
const n = amountOf(raw);
|
|
4248
|
+
return n === null ? null : { value: formatNumber(n), kind };
|
|
4249
|
+
}
|
|
4250
|
+
case "status":
|
|
4251
|
+
return { value: String(raw).replace(/_/g, " "), kind };
|
|
4252
|
+
default:
|
|
4253
|
+
if (typeof raw === "object") return null;
|
|
4254
|
+
if (typeof raw === "string" && raw.length > 160) return { value: `${raw.slice(0, 157)}…`, kind };
|
|
4255
|
+
return { value: String(raw), kind };
|
|
4248
4256
|
}
|
|
4249
|
-
|
|
4250
|
-
|
|
4257
|
+
}
|
|
4258
|
+
function summarizeOldData(tableName, oldData) {
|
|
4259
|
+
if (!oldData) return [];
|
|
4260
|
+
const { value: row } = maskSensitiveData(oldData, tableName);
|
|
4261
|
+
const specific = ENTITY_FIELDS[tableName];
|
|
4262
|
+
const specs = specific ?? GENERIC_FIELDS;
|
|
4263
|
+
const fields = [];
|
|
4264
|
+
const seenLabels = /* @__PURE__ */ new Set();
|
|
4265
|
+
for (const spec of specs) {
|
|
4266
|
+
const raw = spec.derive ? spec.derive(row) : row[spec.key];
|
|
4267
|
+
const formatted = formatValue(raw, spec.kind ?? "text", row);
|
|
4268
|
+
if (!formatted || seenLabels.has(spec.label)) continue;
|
|
4269
|
+
seenLabels.add(spec.label);
|
|
4270
|
+
const value = spec.key === "currency_code" ? formatted.value.toUpperCase() : formatted.value;
|
|
4271
|
+
fields.push({ key: spec.key, label: spec.label, value, kind: formatted.kind });
|
|
4272
|
+
if (!specific && fields.length >= MAX_GENERIC_FIELDS) break;
|
|
4251
4273
|
}
|
|
4252
|
-
|
|
4253
|
-
|
|
4274
|
+
return fields;
|
|
4275
|
+
}
|
|
4276
|
+
function readLastListSearch() {
|
|
4277
|
+
try {
|
|
4278
|
+
return window.sessionStorage.getItem(LAST_LIST_URL_KEY) ?? "";
|
|
4279
|
+
} catch {
|
|
4280
|
+
return "";
|
|
4254
4281
|
}
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
const ReturnDetailPage = () => {
|
|
4282
|
+
}
|
|
4283
|
+
const DeletedRecordDetailPage = () => {
|
|
4258
4284
|
const navigate = reactRouterDom.useNavigate();
|
|
4259
|
-
const
|
|
4260
|
-
const
|
|
4261
|
-
const [
|
|
4262
|
-
const [
|
|
4263
|
-
const
|
|
4264
|
-
const
|
|
4265
|
-
|
|
4285
|
+
const location = reactRouterDom.useLocation();
|
|
4286
|
+
const { id = "" } = reactRouterDom.useParams();
|
|
4287
|
+
const [state, setState] = react.useState({ status: "loading" });
|
|
4288
|
+
const [reloadToken, setReloadToken] = react.useState(0);
|
|
4289
|
+
const cameFromList = location.state?.fromList === true;
|
|
4290
|
+
const goBack = () => {
|
|
4291
|
+
if (cameFromList) navigate(-1);
|
|
4292
|
+
else navigate(`/deleted-records-audit${readLastListSearch()}`);
|
|
4293
|
+
};
|
|
4266
4294
|
react.useEffect(() => {
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
const response = await fetch(`/admin/return/${id}`, {
|
|
4276
|
-
credentials: "include"
|
|
4277
|
-
});
|
|
4278
|
-
if (!response.ok) {
|
|
4279
|
-
const message = await response.text();
|
|
4280
|
-
throw new Error(message || "Unable to load return order");
|
|
4281
|
-
}
|
|
4282
|
-
const payload = await response.json();
|
|
4283
|
-
setReturnOrder(payload.return);
|
|
4284
|
-
} catch (loadError) {
|
|
4285
|
-
const message = loadError instanceof Error ? loadError.message : "Unable to load return order";
|
|
4286
|
-
setError(message);
|
|
4287
|
-
} finally {
|
|
4288
|
-
setIsLoading(false);
|
|
4289
|
-
}
|
|
4290
|
-
};
|
|
4291
|
-
void loadReturn();
|
|
4292
|
-
}, [id, navigate]);
|
|
4293
|
-
const handleReject = async () => {
|
|
4294
|
-
if (!id) {
|
|
4295
|
-
return;
|
|
4296
|
-
}
|
|
4297
|
-
try {
|
|
4298
|
-
setIsRejecting(true);
|
|
4299
|
-
setUpdateError(null);
|
|
4300
|
-
setUpdateSuccess(false);
|
|
4301
|
-
const response = await fetch(`/admin/return/${id}/reject`, {
|
|
4302
|
-
method: "POST",
|
|
4303
|
-
headers: {
|
|
4304
|
-
"Content-Type": "application/json"
|
|
4305
|
-
},
|
|
4306
|
-
credentials: "include",
|
|
4307
|
-
body: JSON.stringify({ reason: "Rejected by admin" })
|
|
4295
|
+
const controller = new AbortController();
|
|
4296
|
+
setState({ status: "loading" });
|
|
4297
|
+
fetchAuditDetail(id, controller.signal).then((audit) => setState({ status: "ready", audit })).catch((e) => {
|
|
4298
|
+
if (controller.signal.aborted) return;
|
|
4299
|
+
setState({
|
|
4300
|
+
status: "error",
|
|
4301
|
+
message: e instanceof Error ? e.message : "Unknown error",
|
|
4302
|
+
notFound: e instanceof AuditApiError && e.status === 404
|
|
4308
4303
|
});
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4304
|
+
});
|
|
4305
|
+
return () => controller.abort();
|
|
4306
|
+
}, [id, reloadToken]);
|
|
4307
|
+
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: [
|
|
4308
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: "transparent", size: "small", onClick: goBack, className: "-ml-2", children: [
|
|
4309
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, {}),
|
|
4310
|
+
"Back to Deleted Records"
|
|
4311
|
+
] }) }),
|
|
4312
|
+
state.status === "loading" ? /* @__PURE__ */ jsxRuntime.jsx(DetailSkeleton, {}) : state.status === "error" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4313
|
+
DetailError,
|
|
4314
|
+
{
|
|
4315
|
+
notFound: state.notFound,
|
|
4316
|
+
message: state.message,
|
|
4317
|
+
onRetry: () => setReloadToken((t) => t + 1),
|
|
4318
|
+
onBack: goBack
|
|
4312
4319
|
}
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4320
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(DetailContent, { audit: state.audit })
|
|
4321
|
+
] }) });
|
|
4322
|
+
};
|
|
4323
|
+
const DetailContent = ({ audit }) => {
|
|
4324
|
+
const navigate = reactRouterDom.useNavigate();
|
|
4325
|
+
const entity = getEntityInfo(audit.table_name);
|
|
4326
|
+
const source = describeSource(audit.source);
|
|
4327
|
+
const summary = react.useMemo(() => summarizeOldData(audit.table_name, audit.old_data), [audit]);
|
|
4328
|
+
const masked = react.useMemo(() => maskSensitiveData(audit.old_data, audit.table_name), [audit]);
|
|
4329
|
+
const guidance = getNextSteps(entity.category.id);
|
|
4330
|
+
const related = getRelatedLinks(audit.table_name, audit.old_data);
|
|
4331
|
+
const [showRaw, setShowRaw] = react.useState(false);
|
|
4332
|
+
const copyJson = async () => {
|
|
4333
|
+
try {
|
|
4334
|
+
await navigator.clipboard.writeText(JSON.stringify(masked.value, null, 2));
|
|
4335
|
+
ui.toast.success("Record data copied", {
|
|
4336
|
+
description: masked.maskedCount ? "Sensitive values were left hidden." : void 0
|
|
4319
4337
|
});
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
setReturnOrder(detailPayload.return);
|
|
4323
|
-
}
|
|
4324
|
-
} catch (updateErr) {
|
|
4325
|
-
const message = updateErr instanceof Error ? updateErr.message : "Unable to reject return";
|
|
4326
|
-
setUpdateError(message);
|
|
4327
|
-
} finally {
|
|
4328
|
-
setIsRejecting(false);
|
|
4338
|
+
} catch {
|
|
4339
|
+
ui.toast.error("Couldn’t copy to clipboard");
|
|
4329
4340
|
}
|
|
4330
4341
|
};
|
|
4331
|
-
|
|
4332
|
-
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..." }) }) }) });
|
|
4333
|
-
}
|
|
4334
|
-
if (error || !returnOrder) {
|
|
4335
|
-
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: [
|
|
4336
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error || "Return order not found" }),
|
|
4337
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => navigate("/returns"), children: "Back to list" }) })
|
|
4338
|
-
] }) }) });
|
|
4339
|
-
}
|
|
4340
|
-
const statusHistory = returnOrder.metadata?.status_history || [];
|
|
4341
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: [
|
|
4342
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4342
4343
|
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3", children: [
|
|
4343
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4344
|
-
ui.
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
className: "w-fit",
|
|
4350
|
-
children: [
|
|
4351
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, { className: "mr-2" }),
|
|
4352
|
-
"Back to list"
|
|
4353
|
-
]
|
|
4354
|
-
}
|
|
4355
|
-
),
|
|
4356
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 md:flex-row md:items-center md:justify-between", children: [
|
|
4357
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
4358
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Return Order Details" }),
|
|
4359
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: returnOrder.id })
|
|
4360
|
-
] }),
|
|
4361
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4362
|
-
ui.Badge,
|
|
4363
|
-
{
|
|
4364
|
-
size: "small",
|
|
4365
|
-
className: `uppercase ${getStatusBadgeClass$1(returnOrder.status)}`,
|
|
4366
|
-
children: returnOrder.status.replace(/_/g, " ")
|
|
4367
|
-
}
|
|
4368
|
-
)
|
|
4369
|
-
] })
|
|
4370
|
-
] }),
|
|
4371
|
-
returnOrder.status === "requested" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
4372
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4373
|
-
ui.Button,
|
|
4374
|
-
{
|
|
4375
|
-
variant: "danger",
|
|
4376
|
-
onClick: handleReject,
|
|
4377
|
-
disabled: isRejecting,
|
|
4378
|
-
isLoading: isRejecting,
|
|
4379
|
-
children: "Reject (Cancel) Return"
|
|
4380
|
-
}
|
|
4381
|
-
) }),
|
|
4382
|
-
/* @__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.' })
|
|
4383
|
-
] }),
|
|
4384
|
-
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,
|
|
4385
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4386
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Information" }),
|
|
4387
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
4388
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4389
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Return ID" }),
|
|
4390
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.id })
|
|
4391
|
-
] }),
|
|
4392
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4393
|
-
ui.Button,
|
|
4394
|
-
{
|
|
4395
|
-
variant: "secondary",
|
|
4396
|
-
onClick: () => {
|
|
4397
|
-
window.open(
|
|
4398
|
-
`/app/orders/${returnOrder.order_id}`,
|
|
4399
|
-
"_blank"
|
|
4400
|
-
);
|
|
4401
|
-
},
|
|
4402
|
-
children: "View order"
|
|
4403
|
-
}
|
|
4404
|
-
) })
|
|
4405
|
-
] })
|
|
4406
|
-
] }),
|
|
4407
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-6 md:grid-cols-2", children: [
|
|
4408
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
4409
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-4 text-lg", children: "Return Details" }),
|
|
4410
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
4411
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4412
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Return ID" }),
|
|
4413
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.id })
|
|
4414
|
-
] }),
|
|
4415
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4416
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Status" }),
|
|
4417
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.status })
|
|
4418
|
-
] }),
|
|
4419
|
-
returnOrder.reason && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4420
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Reason" }),
|
|
4421
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.reason })
|
|
4422
|
-
] }),
|
|
4423
|
-
returnOrder.note && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4424
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Note" }),
|
|
4425
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: returnOrder.note })
|
|
4426
|
-
] }),
|
|
4427
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4428
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Created" }),
|
|
4429
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(returnOrder.created_at).toLocaleString() })
|
|
4430
|
-
] }),
|
|
4431
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4432
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Last Updated" }),
|
|
4433
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: new Date(returnOrder.updated_at).toLocaleString() })
|
|
4434
|
-
] })
|
|
4435
|
-
] })
|
|
4344
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
4345
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Badge, { size: "small", color: "red", children: [
|
|
4346
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.Trash, {}),
|
|
4347
|
+
"Deleted"
|
|
4348
|
+
] }),
|
|
4349
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: entity.category.label })
|
|
4436
4350
|
] }),
|
|
4437
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
size: "2xsmall",
|
|
4448
|
-
className: `uppercase ${getStatusBadgeClass$1(entry.status)}`,
|
|
4449
|
-
children: entry.status.replace(/_/g, " ")
|
|
4450
|
-
}
|
|
4451
|
-
) }),
|
|
4452
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
4453
|
-
new Date(entry.timestamp).toLocaleString(),
|
|
4454
|
-
entry.admin_id && ` by ${entry.admin_id}`,
|
|
4455
|
-
entry.reason && ` - ${entry.reason}`
|
|
4456
|
-
] })
|
|
4457
|
-
] })
|
|
4458
|
-
},
|
|
4459
|
-
index
|
|
4460
|
-
)) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "No status history available" })
|
|
4351
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Heading, { level: "h1", children: [
|
|
4352
|
+
"Deleted ",
|
|
4353
|
+
entity.label
|
|
4354
|
+
] }),
|
|
4355
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
4356
|
+
/* @__PURE__ */ jsxRuntime.jsx(CopyableId, { value: audit.record_id, emptyLabel: "This record type has no ID column", className: "text-sm" }),
|
|
4357
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: [
|
|
4358
|
+
"Database table: ",
|
|
4359
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: audit.table_name })
|
|
4360
|
+
] })
|
|
4461
4361
|
] })
|
|
4462
4362
|
] }),
|
|
4463
|
-
|
|
4464
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4465
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
4466
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4363
|
+
/* @__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: [
|
|
4364
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.InformationCircle, { className: "mt-0.5 shrink-0 text-ui-tag-orange-icon" }),
|
|
4365
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-tag-orange-text", children: [
|
|
4366
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "This is a historical snapshot" }),
|
|
4367
|
+
" captured immediately before deletion. The record no longer exists in the database, so changes elsewhere in the admin are not reflected here."
|
|
4368
|
+
] })
|
|
4369
|
+
] }),
|
|
4370
|
+
/* @__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: [
|
|
4371
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Deleted", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
|
|
4372
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: formatExactDateTime(audit.occurred_at) }),
|
|
4373
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1 text-xs text-ui-fg-muted", children: [
|
|
4374
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ClockSolid, { className: "size-3" }),
|
|
4375
|
+
formatRelativeTime(audit.occurred_at)
|
|
4376
|
+
] })
|
|
4377
|
+
] }) }),
|
|
4378
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Deleted by", children: audit.deleted_by ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "break-all text-sm text-ui-fg-base", children: audit.deleted_by }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-muted", children: "Not recorded" }) }),
|
|
4379
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Source", children: source.kind === "unknown" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-muted", children: "Unknown" }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "small", color: sourceBadgeColor(source.kind), children: source.label }) }),
|
|
4380
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Action", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Permanently deleted" }) })
|
|
4381
|
+
] }) }),
|
|
4382
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4383
|
+
Section,
|
|
4384
|
+
{
|
|
4385
|
+
title: "Record summary",
|
|
4386
|
+
description: `Key details of this ${entity.label.toLowerCase()} at the moment it was deleted.`,
|
|
4387
|
+
children: summary.length ? /* @__PURE__ */ jsxRuntime.jsx("dl", { className: "grid grid-cols-1 gap-x-6 gap-y-4 sm:grid-cols-2", children: summary.map((field) => /* @__PURE__ */ jsxRuntime.jsx(Field, { label: field.label, children: field.kind === "id" ? /* @__PURE__ */ jsxRuntime.jsx(CopyableId, { value: field.value }) : field.kind === "status" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", color: "grey", className: "capitalize", children: field.value }) : field.kind === "masked" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-muted", children: "Hidden for security" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "break-words text-sm text-ui-fg-base", children: field.value }) }, field.label)) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "No key details could be extracted for this record type. See the original record data below." })
|
|
4388
|
+
}
|
|
4389
|
+
),
|
|
4390
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4391
|
+
Section,
|
|
4392
|
+
{
|
|
4393
|
+
title: "Original record data",
|
|
4394
|
+
description: "The complete data captured before deletion.",
|
|
4395
|
+
actions: showRaw && audit.old_data ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: "secondary", size: "small", onClick: copyJson, children: [
|
|
4396
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.SquareTwoStack, {}),
|
|
4397
|
+
"Copy JSON"
|
|
4398
|
+
] }) : null,
|
|
4399
|
+
children: audit.old_data ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
4400
|
+
masked.maskedCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
4401
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ShieldCheck, { className: "shrink-0 text-ui-fg-muted" }),
|
|
4402
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
4403
|
+
masked.maskedCount,
|
|
4404
|
+
" sensitive ",
|
|
4405
|
+
masked.maskedCount === 1 ? "value is" : "values are",
|
|
4406
|
+
" hidden for security (passwords, tokens, card or account numbers)."
|
|
4407
|
+
] })
|
|
4408
|
+
] }) : null,
|
|
4409
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: "secondary", size: "small", onClick: () => setShowRaw((s2) => !s2), "aria-expanded": showRaw, children: [
|
|
4410
|
+
showRaw ? /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDownMini, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRightMini, {}),
|
|
4411
|
+
showRaw ? "Hide full record" : "View full record"
|
|
4412
|
+
] }) }),
|
|
4413
|
+
showRaw ? /* @__PURE__ */ jsxRuntime.jsx(JsonViewer, { data: masked.value }) : null
|
|
4414
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "No data was captured for this deletion." })
|
|
4415
|
+
}
|
|
4416
|
+
),
|
|
4417
|
+
/* @__PURE__ */ jsxRuntime.jsx(Section, { title: "What you can do now", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
4418
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-base", children: [
|
|
4419
|
+
"This record was permanently deleted. ",
|
|
4420
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Automatic restoration is not available" }),
|
|
4421
|
+
" ",
|
|
4422
|
+
"from this screen."
|
|
4423
|
+
] }),
|
|
4424
|
+
/* @__PURE__ */ jsxRuntime.jsxs("ol", { className: "flex list-decimal flex-col gap-3 pl-5 text-sm text-ui-fg-subtle marker:text-ui-fg-muted", children: [
|
|
4425
|
+
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
4426
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: "Check whether this was expected." }),
|
|
4427
|
+
" ",
|
|
4428
|
+
audit.deleted_by || source.kind !== "unknown" ? "Confirm with the person or system shown above." : `Who deleted it wasn’t recorded—check with your team or integrations active around ${formatExactDateTime(audit.occurred_at)}.`,
|
|
4429
|
+
" ",
|
|
4430
|
+
guidance.headline
|
|
4477
4431
|
] }),
|
|
4478
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
4479
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4480
|
-
|
|
4432
|
+
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
4433
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: "If it needs to come back:" }),
|
|
4434
|
+
" ",
|
|
4435
|
+
guidance.recreate
|
|
4481
4436
|
] }),
|
|
4482
|
-
|
|
4483
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4484
|
-
|
|
4485
|
-
returnOrder.order.currency_code || "$",
|
|
4486
|
-
(Number(returnOrder.order.total) / 100).toFixed(2)
|
|
4487
|
-
] })
|
|
4437
|
+
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
4438
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: "Need the details?" }),
|
|
4439
|
+
" Use “View full record” above to see or copy everything that was stored. Sensitive values stay hidden."
|
|
4488
4440
|
] })
|
|
4489
|
-
] })
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4441
|
+
] }),
|
|
4442
|
+
guidance.adminSection || related.length ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
4443
|
+
guidance.adminSection ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", size: "small", onClick: () => navigate(guidance.adminSection.path), children: guidance.adminSection.label }) : null,
|
|
4444
|
+
related.map((link) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4445
|
+
ui.Button,
|
|
4446
|
+
{
|
|
4447
|
+
variant: "transparent",
|
|
4448
|
+
size: "small",
|
|
4449
|
+
onClick: () => navigate(link.path),
|
|
4450
|
+
title: `Opens ${link.label.toLowerCase()} ${link.id} if it still exists`,
|
|
4451
|
+
children: [
|
|
4452
|
+
"Open related ",
|
|
4453
|
+
link.label.toLowerCase(),
|
|
4454
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRightMini, {})
|
|
4455
|
+
]
|
|
4456
|
+
},
|
|
4457
|
+
link.path
|
|
4458
|
+
))
|
|
4459
|
+
] }) : null,
|
|
4460
|
+
related.length ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: "Related records open only if they haven’t been deleted too." }) : null
|
|
4461
|
+
] }) })
|
|
4462
|
+
] });
|
|
4509
4463
|
};
|
|
4510
|
-
const
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4464
|
+
const Section = ({
|
|
4465
|
+
title,
|
|
4466
|
+
description,
|
|
4467
|
+
actions,
|
|
4468
|
+
children
|
|
4469
|
+
}) => /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "flex flex-col gap-4 rounded-lg border border-ui-border-base p-5", children: [
|
|
4470
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-2", children: [
|
|
4471
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
4472
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: title }),
|
|
4473
|
+
description ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: description }) : null
|
|
4474
|
+
] }),
|
|
4475
|
+
actions
|
|
4476
|
+
] }),
|
|
4477
|
+
children
|
|
4478
|
+
] });
|
|
4479
|
+
const Field = ({ label, children }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
|
|
4480
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-xs font-medium uppercase tracking-wide text-ui-fg-muted", children: label }),
|
|
4481
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { className: "min-w-0", children })
|
|
4482
|
+
] });
|
|
4483
|
+
const DetailSkeleton = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", "aria-busy": "true", children: [
|
|
4484
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
4485
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-5 w-24 rounded-full" }),
|
|
4486
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-8 w-64" }),
|
|
4487
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-4 w-48" })
|
|
4488
|
+
] }),
|
|
4489
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-14 w-full" }),
|
|
4490
|
+
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: [
|
|
4491
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-5 w-40" }),
|
|
4492
|
+
/* @__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: [
|
|
4493
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-3 w-20" }),
|
|
4494
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-4 w-36" })
|
|
4495
|
+
] }, j)) })
|
|
4496
|
+
] }, i))
|
|
4497
|
+
] });
|
|
4498
|
+
const DetailError = ({
|
|
4499
|
+
notFound,
|
|
4500
|
+
message,
|
|
4501
|
+
onRetry,
|
|
4502
|
+
onBack
|
|
4503
|
+
}) => /* @__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: [
|
|
4504
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ExclamationCircle, { className: ui.clx(notFound ? "text-ui-fg-muted" : "text-ui-fg-error") }),
|
|
4505
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: notFound ? "Audit entry not found" : "Unable to load this deleted record" }),
|
|
4506
|
+
/* @__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." }),
|
|
4507
|
+
!notFound ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "max-w-md font-mono text-ui-fg-muted", children: message }) : null,
|
|
4508
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex gap-2", children: [
|
|
4509
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", size: "small", onClick: onBack, children: "Back to Deleted Records" }),
|
|
4510
|
+
!notFound ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", size: "small", onClick: onRetry, children: "Try again" }) : null
|
|
4511
|
+
] })
|
|
4512
|
+
] });
|
|
4513
|
+
const config$1 = adminSdk.defineRouteConfig({});
|
|
4514
4514
|
const getStatusBadgeClass = (status) => {
|
|
4515
4515
|
const statusLower = status.toLowerCase();
|
|
4516
4516
|
if (statusLower === "requested") {
|
|
@@ -4840,13 +4840,13 @@ const routeModule = {
|
|
|
4840
4840
|
handle: { label: config$3.label, translationNs: config$3.translationNs }
|
|
4841
4841
|
},
|
|
4842
4842
|
{
|
|
4843
|
-
Component:
|
|
4844
|
-
path: "/
|
|
4843
|
+
Component: ReturnDetailPage,
|
|
4844
|
+
path: "/returns/:id",
|
|
4845
4845
|
handle: { label: config$2.label, translationNs: config$2.translationNs }
|
|
4846
4846
|
},
|
|
4847
4847
|
{
|
|
4848
|
-
Component:
|
|
4849
|
-
path: "/
|
|
4848
|
+
Component: DeletedRecordDetailPage,
|
|
4849
|
+
path: "/deleted-records-audit/:id",
|
|
4850
4850
|
handle: { label: config$1.label, translationNs: config$1.translationNs }
|
|
4851
4851
|
},
|
|
4852
4852
|
{
|
|
@@ -4875,17 +4875,17 @@ const menuItemModule = {
|
|
|
4875
4875
|
translationNs: void 0
|
|
4876
4876
|
},
|
|
4877
4877
|
{
|
|
4878
|
-
label: config$
|
|
4879
|
-
icon: config$
|
|
4880
|
-
path: "/
|
|
4878
|
+
label: config$7.label,
|
|
4879
|
+
icon: config$7.icon,
|
|
4880
|
+
path: "/returns",
|
|
4881
4881
|
nested: void 0,
|
|
4882
4882
|
rank: void 0,
|
|
4883
4883
|
translationNs: void 0
|
|
4884
4884
|
},
|
|
4885
4885
|
{
|
|
4886
|
-
label: config$
|
|
4887
|
-
icon: config$
|
|
4888
|
-
path: "/
|
|
4886
|
+
label: config$8.label,
|
|
4887
|
+
icon: config$8.icon,
|
|
4888
|
+
path: "/refunds",
|
|
4889
4889
|
nested: void 0,
|
|
4890
4890
|
rank: void 0,
|
|
4891
4891
|
translationNs: void 0
|
|
@@ -4907,17 +4907,17 @@ const menuItemModule = {
|
|
|
4907
4907
|
translationNs: void 0
|
|
4908
4908
|
},
|
|
4909
4909
|
{
|
|
4910
|
-
label: config$
|
|
4911
|
-
icon: config$
|
|
4912
|
-
path: "/
|
|
4910
|
+
label: config$2.label,
|
|
4911
|
+
icon: config$2.icon,
|
|
4912
|
+
path: "/returns/:id",
|
|
4913
4913
|
nested: void 0,
|
|
4914
4914
|
rank: void 0,
|
|
4915
4915
|
translationNs: void 0
|
|
4916
4916
|
},
|
|
4917
4917
|
{
|
|
4918
|
-
label: config$
|
|
4919
|
-
icon: config$
|
|
4920
|
-
path: "/
|
|
4918
|
+
label: config$3.label,
|
|
4919
|
+
icon: config$3.icon,
|
|
4920
|
+
path: "/refunds/:id",
|
|
4921
4921
|
nested: void 0,
|
|
4922
4922
|
rank: void 0,
|
|
4923
4923
|
translationNs: void 0
|