@easypayment/medusa-paypal 0.2.7 → 0.2.9
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 +536 -938
- package/.medusa/server/src/admin/index.mjs +536 -938
- package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.js +1 -0
- package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal/capture-order/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/paypal/capture-order/route.js +61 -74
- package/.medusa/server/src/api/store/paypal/capture-order/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal/create-order/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/paypal/create-order/route.js +3 -24
- package/.medusa/server/src/api/store/paypal/create-order/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal/settings/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/paypal/settings/route.js +7 -1
- package/.medusa/server/src/api/store/paypal/settings/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal/webhook/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/paypal/webhook/route.js +1 -1
- package/.medusa/server/src/api/store/paypal/webhook/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal-complete/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/paypal-complete/route.js +46 -24
- package/.medusa/server/src/api/store/paypal-complete/route.js.map +1 -1
- package/.medusa/server/src/jobs/paypal-reconcile.d.ts.map +1 -1
- package/.medusa/server/src/jobs/paypal-reconcile.js +19 -5
- package/.medusa/server/src/jobs/paypal-reconcile.js.map +1 -1
- package/.medusa/server/src/jobs/paypal-webhook-retry.d.ts.map +1 -1
- package/.medusa/server/src/jobs/paypal-webhook-retry.js +1 -1
- package/.medusa/server/src/jobs/paypal-webhook-retry.js.map +1 -1
- package/.medusa/server/src/modules/paypal/index.d.ts +0 -14
- package/.medusa/server/src/modules/paypal/index.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/service.d.ts +56 -93
- package/.medusa/server/src/modules/paypal/service.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/service.js +34 -47
- package/.medusa/server/src/modules/paypal/service.js.map +1 -1
- package/.medusa/server/src/modules/paypal/utils/paypal-auth.d.ts +14 -0
- package/.medusa/server/src/modules/paypal/utils/paypal-auth.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/utils/paypal-auth.js +32 -0
- package/.medusa/server/src/modules/paypal/utils/paypal-auth.js.map +1 -0
- package/.medusa/server/src/modules/paypal/webhook-processor.d.ts +2 -15
- package/.medusa/server/src/modules/paypal/webhook-processor.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/webhook-processor.js +17 -100
- package/.medusa/server/src/modules/paypal/webhook-processor.js.map +1 -1
- package/package.json +1 -1
- package/src/admin/routes/settings/paypal/_components/Tabs.tsx +0 -1
- package/src/admin/routes/settings/paypal/additional-settings/page.tsx +226 -346
- package/src/admin/routes/settings/paypal/advanced-card-payments/page.tsx +227 -381
- package/src/admin/routes/settings/paypal/audit-logs/page.tsx +127 -131
- package/src/admin/routes/settings/paypal/paypal-settings/page.tsx +599 -557
- package/src/admin/routes/settings/paypal/reconciliation-status/page.tsx +120 -165
- package/src/api/store/payment-collections/[id]/payment-sessions/route.ts +12 -1
- package/src/api/store/paypal/capture-order/route.ts +276 -284
- package/src/api/store/paypal/create-order/route.ts +2 -32
- package/src/api/store/paypal/settings/route.ts +8 -1
- package/src/api/store/paypal/webhook/route.ts +1 -2
- package/src/api/store/paypal-complete/route.ts +75 -45
- package/src/jobs/paypal-reconcile.ts +21 -6
- package/src/jobs/paypal-webhook-retry.ts +1 -2
- package/src/modules/paypal/service.ts +39 -62
- package/src/modules/paypal/utils/paypal-auth.ts +32 -0
- package/src/modules/paypal/webhook-processor.ts +18 -116
- package/tsconfig.json +1 -1
- package/.medusa/server/src/api/admin/paypal/disputes/[id]/route.d.ts +0 -3
- package/.medusa/server/src/api/admin/paypal/disputes/[id]/route.d.ts.map +0 -1
- package/.medusa/server/src/api/admin/paypal/disputes/[id]/route.js +0 -17
- package/.medusa/server/src/api/admin/paypal/disputes/[id]/route.js.map +0 -1
- package/.medusa/server/src/api/admin/paypal/disputes/route.d.ts +0 -3
- package/.medusa/server/src/api/admin/paypal/disputes/route.d.ts.map +0 -1
- package/.medusa/server/src/api/admin/paypal/disputes/route.js +0 -27
- package/.medusa/server/src/api/admin/paypal/disputes/route.js.map +0 -1
- package/.medusa/server/src/api/admin/paypal/disputes/summary/route.d.ts +0 -3
- package/.medusa/server/src/api/admin/paypal/disputes/summary/route.d.ts.map +0 -1
- package/.medusa/server/src/api/admin/paypal/disputes/summary/route.js +0 -17
- package/.medusa/server/src/api/admin/paypal/disputes/summary/route.js.map +0 -1
- package/.medusa/server/src/api/store/paypal/disputes/route.d.ts +0 -3
- package/.medusa/server/src/api/store/paypal/disputes/route.d.ts.map +0 -1
- package/.medusa/server/src/api/store/paypal/disputes/route.js +0 -46
- package/.medusa/server/src/api/store/paypal/disputes/route.js.map +0 -1
- package/.medusa/server/src/modules/paypal/migrations/20260501090000_create_paypal_dispute.d.ts +0 -6
- package/.medusa/server/src/modules/paypal/migrations/20260501090000_create_paypal_dispute.d.ts.map +0 -1
- package/.medusa/server/src/modules/paypal/migrations/20260501090000_create_paypal_dispute.js +0 -43
- package/.medusa/server/src/modules/paypal/migrations/20260501090000_create_paypal_dispute.js.map +0 -1
- package/.medusa/server/src/modules/paypal/models/paypal_dispute.d.ts +0 -16
- package/.medusa/server/src/modules/paypal/models/paypal_dispute.d.ts.map +0 -1
- package/.medusa/server/src/modules/paypal/models/paypal_dispute.js +0 -19
- package/.medusa/server/src/modules/paypal/models/paypal_dispute.js.map +0 -1
- package/src/admin/routes/settings/paypal/disputes/page.tsx +0 -259
- package/src/api/admin/paypal/disputes/[id]/route.ts +0 -19
- package/src/api/admin/paypal/disputes/route.ts +0 -30
- package/src/api/admin/paypal/disputes/summary/route.ts +0 -18
- package/src/api/store/paypal/disputes/route.ts +0 -67
- package/src/modules/paypal/migrations/20260501090000_create_paypal_dispute.ts +0 -40
- package/src/modules/paypal/models/paypal_dispute.ts +0 -18
|
@@ -14,7 +14,6 @@ const TABS = [
|
|
|
14
14
|
{ label: "PayPal Connection", to: `${BASE}/connection` },
|
|
15
15
|
{ label: "PayPal Settings", to: `${BASE}/paypal-settings` },
|
|
16
16
|
{ label: "Advanced Card Payments", to: `${BASE}/advanced-card-payments` },
|
|
17
|
-
{ label: "Disputes", to: `${BASE}/disputes` },
|
|
18
17
|
{ label: "Reconciliation Status", to: `${BASE}/reconciliation-status` },
|
|
19
18
|
/* { label: "Google Pay", to: `${BASE}/google-pay` },
|
|
20
19
|
{ label: "Apple Pay", to: `${BASE}/apple-pay` },
|
|
@@ -40,6 +39,39 @@ function PayPalTabs() {
|
|
|
40
39
|
);
|
|
41
40
|
}) }) });
|
|
42
41
|
}
|
|
42
|
+
async function adminFetch$4(path, opts = {}) {
|
|
43
|
+
var _a;
|
|
44
|
+
const { method = "GET", body, query } = opts;
|
|
45
|
+
let url = path;
|
|
46
|
+
if (query && Object.keys(query).length > 0) {
|
|
47
|
+
const params = new URLSearchParams(query);
|
|
48
|
+
url = `${path}?${params.toString()}`;
|
|
49
|
+
}
|
|
50
|
+
const headers = { Accept: "application/json" };
|
|
51
|
+
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
52
|
+
if (typeof window !== "undefined") {
|
|
53
|
+
const token = (_a = window.__medusa__) == null ? void 0 : _a.token;
|
|
54
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
55
|
+
}
|
|
56
|
+
const res = await fetch(url, {
|
|
57
|
+
method,
|
|
58
|
+
headers,
|
|
59
|
+
credentials: "include",
|
|
60
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
61
|
+
});
|
|
62
|
+
const text = await res.text().catch(() => "");
|
|
63
|
+
if (!res.ok) {
|
|
64
|
+
if (res.status === 401) throw new Error("Unauthorized (401) - session may have expired. Please reload and log in again.");
|
|
65
|
+
if (res.status === 403) throw new Error("Forbidden (403) - you do not have permission to perform this action.");
|
|
66
|
+
throw new Error(text || `Request failed with status ${res.status}`);
|
|
67
|
+
}
|
|
68
|
+
if (!text) return {};
|
|
69
|
+
try {
|
|
70
|
+
return JSON.parse(text);
|
|
71
|
+
} catch {
|
|
72
|
+
return {};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
43
75
|
const DEFAULT_FORM$1 = {
|
|
44
76
|
paymentAction: "capture",
|
|
45
77
|
brandName: "PayPal",
|
|
@@ -56,17 +88,9 @@ const DEFAULT_FORM$1 = {
|
|
|
56
88
|
function mergeWithDefaults$1(saved) {
|
|
57
89
|
if (!saved) return { ...DEFAULT_FORM$1 };
|
|
58
90
|
const entries = Object.entries(saved).filter(([, value]) => value !== void 0);
|
|
59
|
-
return {
|
|
60
|
-
...DEFAULT_FORM$1,
|
|
61
|
-
...Object.fromEntries(entries)
|
|
62
|
-
};
|
|
91
|
+
return { ...DEFAULT_FORM$1, ...Object.fromEntries(entries) };
|
|
63
92
|
}
|
|
64
|
-
function SectionCard$2({
|
|
65
|
-
title,
|
|
66
|
-
description,
|
|
67
|
-
right,
|
|
68
|
-
children
|
|
69
|
-
}) {
|
|
93
|
+
function SectionCard$2({ title, description, right, children }) {
|
|
70
94
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
71
95
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4 border-b border-ui-border-base p-4", children: [
|
|
72
96
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
@@ -78,11 +102,7 @@ function SectionCard$2({
|
|
|
78
102
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children })
|
|
79
103
|
] });
|
|
80
104
|
}
|
|
81
|
-
function FieldRow$2({
|
|
82
|
-
label,
|
|
83
|
-
hint,
|
|
84
|
-
children
|
|
85
|
-
}) {
|
|
105
|
+
function FieldRow$2({ label, hint, children }) {
|
|
86
106
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-12 items-start gap-4 py-3", children: [
|
|
87
107
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-12 md:col-span-4", children: [
|
|
88
108
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-ui-fg-base", children: label }),
|
|
@@ -95,6 +115,7 @@ function AdditionalSettingsTab() {
|
|
|
95
115
|
const [form, setForm] = react.useState(() => ({ ...DEFAULT_FORM$1 }));
|
|
96
116
|
const [loading, setLoading] = react.useState(false);
|
|
97
117
|
const [saving, setSaving] = react.useState(false);
|
|
118
|
+
const [toast, setToast] = react.useState(null);
|
|
98
119
|
const didInit = react.useRef(false);
|
|
99
120
|
react.useEffect(() => {
|
|
100
121
|
if (didInit.current) return;
|
|
@@ -102,52 +123,28 @@ function AdditionalSettingsTab() {
|
|
|
102
123
|
(async () => {
|
|
103
124
|
try {
|
|
104
125
|
setLoading(true);
|
|
105
|
-
const
|
|
106
|
-
credentials: "include",
|
|
107
|
-
headers: { "Accept": "application/json" }
|
|
108
|
-
});
|
|
109
|
-
if (!r.ok) return;
|
|
110
|
-
const json = await r.json();
|
|
126
|
+
const json = await adminFetch$4("/admin/paypal/settings");
|
|
111
127
|
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
112
128
|
const saved = payload == null ? void 0 : payload.additional_settings;
|
|
113
|
-
if (saved && typeof saved === "object")
|
|
114
|
-
|
|
115
|
-
}
|
|
129
|
+
if (saved && typeof saved === "object") setForm(mergeWithDefaults$1(saved));
|
|
130
|
+
} catch {
|
|
116
131
|
} finally {
|
|
117
132
|
setLoading(false);
|
|
118
133
|
}
|
|
119
134
|
})();
|
|
120
135
|
}, []);
|
|
121
|
-
const [toast, setToast] = react.useState(null);
|
|
122
136
|
async function onSave() {
|
|
123
137
|
try {
|
|
124
138
|
setSaving(true);
|
|
125
139
|
setToast(null);
|
|
126
|
-
const
|
|
127
|
-
method: "POST",
|
|
128
|
-
credentials: "include",
|
|
129
|
-
headers: {
|
|
130
|
-
"Content-Type": "application/json",
|
|
131
|
-
"Accept": "application/json"
|
|
132
|
-
},
|
|
133
|
-
body: JSON.stringify({
|
|
134
|
-
additional_settings: form
|
|
135
|
-
})
|
|
136
|
-
});
|
|
137
|
-
if (!r.ok) {
|
|
138
|
-
const errText = await r.text().catch(() => "");
|
|
139
|
-
throw new Error(errText || "Failed to save settings");
|
|
140
|
-
}
|
|
141
|
-
const json = await r.json().catch(() => ({}));
|
|
140
|
+
const json = await adminFetch$4("/admin/paypal/settings", { method: "POST", body: { additional_settings: form } });
|
|
142
141
|
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
143
142
|
const saved = payload == null ? void 0 : payload.additional_settings;
|
|
144
|
-
if (saved && typeof saved === "object")
|
|
145
|
-
setForm(mergeWithDefaults$1(saved));
|
|
146
|
-
}
|
|
143
|
+
if (saved && typeof saved === "object") setForm(mergeWithDefaults$1(saved));
|
|
147
144
|
setToast({ type: "success", message: "Settings saved" });
|
|
148
145
|
window.setTimeout(() => setToast(null), 2500);
|
|
149
146
|
} catch (e) {
|
|
150
|
-
setToast({ type: "error", message:
|
|
147
|
+
setToast({ type: "error", message: e instanceof Error ? e.message : "Failed to save settings" });
|
|
151
148
|
window.setTimeout(() => setToast(null), 3500);
|
|
152
149
|
} finally {
|
|
153
150
|
setSaving(false);
|
|
@@ -156,200 +153,98 @@ function AdditionalSettingsTab() {
|
|
|
156
153
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
157
154
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-start justify-between gap-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Gateway By Easy Payment" }) }) }),
|
|
158
155
|
/* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
|
|
159
|
-
toast ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
160
|
-
"div",
|
|
161
|
-
{
|
|
162
|
-
className: "fixed right-6 top-6 z-50 rounded-md border border-ui-border-base bg-ui-bg-base px-4 py-3 text-sm shadow-lg",
|
|
163
|
-
role: "status",
|
|
164
|
-
"aria-live": "polite",
|
|
165
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: toast.type === "success" ? "text-ui-fg-base" : "text-ui-fg-error", children: toast.message })
|
|
166
|
-
}
|
|
167
|
-
) : null,
|
|
156
|
+
toast ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed right-6 top-6 z-50 rounded-md border border-ui-border-base bg-ui-bg-base px-4 py-3 text-sm shadow-lg", role: "status", "aria-live": "polite", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: toast.type === "success" ? "text-ui-fg-base" : "text-ui-fg-error", children: toast.message }) }) : null,
|
|
168
157
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
169
158
|
SectionCard$2,
|
|
170
159
|
{
|
|
171
160
|
title: "Additional Settings",
|
|
172
161
|
description: "These settings control checkout behavior, PayPal experience, and logging.",
|
|
173
162
|
right: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
174
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
175
|
-
|
|
176
|
-
{
|
|
177
|
-
type: "button",
|
|
178
|
-
onClick: onSave,
|
|
179
|
-
disabled: saving || loading,
|
|
180
|
-
className: "rounded-md bg-ui-button-neutral px-4 py-2 text-sm font-medium text-ui-fg-on-color shadow-sm hover:opacity-90 disabled:opacity-60",
|
|
181
|
-
children: saving ? "Saving..." : "Save settings"
|
|
182
|
-
}
|
|
183
|
-
),
|
|
184
|
-
loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading…" }) : null
|
|
163
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onSave, disabled: saving || loading, className: "rounded-md bg-ui-button-neutral px-4 py-2 text-sm font-medium text-ui-fg-on-color shadow-sm hover:opacity-90 disabled:opacity-60", children: saving ? "Saving..." : "Save settings" }),
|
|
164
|
+
loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading..." }) : null
|
|
185
165
|
] }),
|
|
186
166
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-ui-border-base", children: [
|
|
187
|
-
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "Payment action", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
188
|
-
"
|
|
189
|
-
{
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
198
|
-
) }),
|
|
199
|
-
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "Brand Name", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
200
|
-
"input",
|
|
201
|
-
{
|
|
202
|
-
value: form.brandName,
|
|
203
|
-
onChange: (e) => setForm((p) => ({ ...p, brandName: e.target.value })),
|
|
204
|
-
className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive",
|
|
205
|
-
placeholder: "PayPal"
|
|
206
|
-
}
|
|
207
|
-
) }),
|
|
208
|
-
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "Landing Page", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
209
|
-
"select",
|
|
210
|
-
{
|
|
211
|
-
value: form.landingPage,
|
|
212
|
-
onChange: (e) => setForm((p) => ({ ...p, landingPage: e.target.value })),
|
|
213
|
-
className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive",
|
|
214
|
-
children: [
|
|
215
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "no_preference", children: "No Preference" }),
|
|
216
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "login", children: "Login" }),
|
|
217
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "billing", children: "Billing" })
|
|
218
|
-
]
|
|
219
|
-
}
|
|
220
|
-
) }),
|
|
167
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "Payment action", children: /* @__PURE__ */ jsxRuntime.jsxs("select", { value: form.paymentAction, onChange: (e) => setForm((p) => ({ ...p, paymentAction: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", children: [
|
|
168
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "capture", children: "Capture" }),
|
|
169
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "authorize", children: "Authorize" })
|
|
170
|
+
] }) }),
|
|
171
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "Brand Name", children: /* @__PURE__ */ jsxRuntime.jsx("input", { value: form.brandName, onChange: (e) => setForm((p) => ({ ...p, brandName: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "PayPal" }) }),
|
|
172
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "Landing Page", children: /* @__PURE__ */ jsxRuntime.jsxs("select", { value: form.landingPage, onChange: (e) => setForm((p) => ({ ...p, landingPage: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", children: [
|
|
173
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "no_preference", children: "No Preference" }),
|
|
174
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "login", children: "Login" }),
|
|
175
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "billing", children: "Billing" })
|
|
176
|
+
] }) }),
|
|
221
177
|
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "Instant Payments", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
222
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
223
|
-
"input",
|
|
224
|
-
{
|
|
225
|
-
type: "checkbox",
|
|
226
|
-
checked: form.requireInstantPayment,
|
|
227
|
-
onChange: (e) => setForm((p) => ({ ...p, requireInstantPayment: e.target.checked })),
|
|
228
|
-
className: "h-4 w-4 rounded border-ui-border-base"
|
|
229
|
-
}
|
|
230
|
-
),
|
|
178
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: form.requireInstantPayment, onChange: (e) => setForm((p) => ({ ...p, requireInstantPayment: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
|
|
231
179
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Require Instant Payment" })
|
|
232
180
|
] }) }),
|
|
233
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
234
|
-
|
|
235
|
-
{
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
{
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
258
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
259
|
-
"input",
|
|
260
|
-
{
|
|
261
|
-
type: "checkbox",
|
|
262
|
-
checked: form.sendItemDetails,
|
|
263
|
-
onChange: (e) => setForm((p) => ({ ...p, sendItemDetails: e.target.checked })),
|
|
264
|
-
className: "h-4 w-4 rounded border-ui-border-base"
|
|
265
|
-
}
|
|
266
|
-
),
|
|
267
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Send line item details to PayPal" })
|
|
268
|
-
] })
|
|
269
|
-
}
|
|
270
|
-
),
|
|
271
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
272
|
-
FieldRow$2,
|
|
273
|
-
{
|
|
274
|
-
label: "Order Review Page",
|
|
275
|
-
hint: "Payments from the Product or Cart page skip the review step and go straight to the Thank You page.",
|
|
276
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
277
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
278
|
-
"input",
|
|
279
|
-
{
|
|
280
|
-
type: "checkbox",
|
|
281
|
-
checked: form.skipOrderReviewPage,
|
|
282
|
-
onChange: (e) => setForm((p) => ({ ...p, skipOrderReviewPage: e.target.checked })),
|
|
283
|
-
className: "h-4 w-4 rounded border-ui-border-base"
|
|
284
|
-
}
|
|
285
|
-
),
|
|
286
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Skip Order Review Page" })
|
|
287
|
-
] })
|
|
288
|
-
}
|
|
289
|
-
),
|
|
290
|
-
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "Invoice prefix", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
291
|
-
"input",
|
|
292
|
-
{
|
|
293
|
-
value: form.invoicePrefix,
|
|
294
|
-
onChange: (e) => setForm((p) => ({ ...p, invoicePrefix: e.target.value })),
|
|
295
|
-
className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive",
|
|
296
|
-
placeholder: "WC-"
|
|
297
|
-
}
|
|
298
|
-
) }),
|
|
299
|
-
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "Credit Card Statement Name", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
300
|
-
"input",
|
|
301
|
-
{
|
|
302
|
-
value: form.creditCardStatementName,
|
|
303
|
-
onChange: (e) => setForm((p) => ({ ...p, creditCardStatementName: e.target.value })),
|
|
304
|
-
className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive",
|
|
305
|
-
placeholder: "PayPal"
|
|
306
|
-
}
|
|
307
|
-
) }),
|
|
308
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
309
|
-
FieldRow$2,
|
|
310
|
-
{
|
|
311
|
-
label: "Debug log",
|
|
312
|
-
hint: /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
313
|
-
"Log PayPal events such as Webhook, Payment, Refund.",
|
|
314
|
-
" ",
|
|
315
|
-
form.logPath ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
316
|
-
"Log location: ",
|
|
317
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: form.logPath })
|
|
318
|
-
] }) : null
|
|
319
|
-
] }),
|
|
320
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
321
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
322
|
-
"input",
|
|
323
|
-
{
|
|
324
|
-
type: "checkbox",
|
|
325
|
-
checked: form.enableLogging,
|
|
326
|
-
onChange: (e) => setForm((p) => ({ ...p, enableLogging: e.target.checked })),
|
|
327
|
-
className: "h-4 w-4 rounded border-ui-border-base"
|
|
328
|
-
}
|
|
329
|
-
),
|
|
330
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable logging" })
|
|
331
|
-
] })
|
|
332
|
-
}
|
|
333
|
-
)
|
|
181
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "Billing Address", hint: "If the billing address is empty and PayPal provides a shipping address, the order will use the shipping address as the billing address.", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
182
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: form.useShippingAsBilling, onChange: (e) => setForm((p) => ({ ...p, useShippingAsBilling: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
|
|
183
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Use PayPal Shipping Address as Billing" })
|
|
184
|
+
] }) }),
|
|
185
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "Send Item Details", hint: "Include all line item details in the payment request to PayPal so that they can be seen from the PayPal transaction details page.", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
186
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: form.sendItemDetails, onChange: (e) => setForm((p) => ({ ...p, sendItemDetails: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
|
|
187
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Send line item details to PayPal" })
|
|
188
|
+
] }) }),
|
|
189
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "Order Review Page", hint: "Payments from the Product or Cart page skip the review step and go straight to the Thank You page.", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
190
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: form.skipOrderReviewPage, onChange: (e) => setForm((p) => ({ ...p, skipOrderReviewPage: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
|
|
191
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Skip Order Review Page" })
|
|
192
|
+
] }) }),
|
|
193
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "Invoice prefix", children: /* @__PURE__ */ jsxRuntime.jsx("input", { value: form.invoicePrefix, onChange: (e) => setForm((p) => ({ ...p, invoicePrefix: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "WC-" }) }),
|
|
194
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "Credit Card Statement Name", children: /* @__PURE__ */ jsxRuntime.jsx("input", { value: form.creditCardStatementName, onChange: (e) => setForm((p) => ({ ...p, creditCardStatementName: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "PayPal" }) }),
|
|
195
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "Debug log", hint: /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
196
|
+
"Log PayPal events such as Webhook, Payment, Refund. ",
|
|
197
|
+
form.logPath ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
198
|
+
"Log location: ",
|
|
199
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: form.logPath })
|
|
200
|
+
] }) : null
|
|
201
|
+
] }), children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
202
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: form.enableLogging, onChange: (e) => setForm((p) => ({ ...p, enableLogging: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
|
|
203
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable logging" })
|
|
204
|
+
] }) })
|
|
334
205
|
] })
|
|
335
206
|
}
|
|
336
207
|
)
|
|
337
208
|
] }) });
|
|
338
209
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
}
|
|
210
|
+
async function adminFetch$3(path, opts = {}) {
|
|
211
|
+
var _a;
|
|
212
|
+
const { method = "GET", body, query } = opts;
|
|
213
|
+
let url = path;
|
|
214
|
+
if (query && Object.keys(query).length > 0) {
|
|
215
|
+
const params = new URLSearchParams(query);
|
|
216
|
+
url = `${path}?${params.toString()}`;
|
|
217
|
+
}
|
|
218
|
+
const headers = { Accept: "application/json" };
|
|
219
|
+
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
220
|
+
if (typeof window !== "undefined") {
|
|
221
|
+
const token = (_a = window.__medusa__) == null ? void 0 : _a.token;
|
|
222
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
223
|
+
}
|
|
224
|
+
const res = await fetch(url, {
|
|
225
|
+
method,
|
|
226
|
+
headers,
|
|
227
|
+
credentials: "include",
|
|
228
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
229
|
+
});
|
|
230
|
+
const text = await res.text().catch(() => "");
|
|
231
|
+
if (!res.ok) {
|
|
232
|
+
if (res.status === 401) throw new Error("Unauthorized (401) - session may have expired. Please reload and log in again.");
|
|
233
|
+
if (res.status === 403) throw new Error("Forbidden (403) - you do not have permission to perform this action.");
|
|
234
|
+
throw new Error(text || `Request failed with status ${res.status}`);
|
|
235
|
+
}
|
|
236
|
+
if (!text) return {};
|
|
237
|
+
try {
|
|
238
|
+
return JSON.parse(text);
|
|
239
|
+
} catch {
|
|
240
|
+
return {};
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
const DEFAULT_FORM = { enabled: true, title: "Credit or Debit Card", disabledCards: [], threeDS: "when_required", cardSaveEnabled: false };
|
|
346
244
|
function mergeWithDefaults(saved) {
|
|
347
245
|
if (!saved) return { ...DEFAULT_FORM };
|
|
348
246
|
const entries = Object.entries(saved).filter(([, value]) => value !== void 0);
|
|
349
|
-
return {
|
|
350
|
-
...DEFAULT_FORM,
|
|
351
|
-
...Object.fromEntries(entries)
|
|
352
|
-
};
|
|
247
|
+
return { ...DEFAULT_FORM, ...Object.fromEntries(entries) };
|
|
353
248
|
}
|
|
354
249
|
const CARD_BRANDS = [
|
|
355
250
|
{ value: "visa", label: "Visa" },
|
|
@@ -361,49 +256,17 @@ const CARD_BRANDS = [
|
|
|
361
256
|
{ value: "unionpay", label: "UnionPay" }
|
|
362
257
|
];
|
|
363
258
|
const THREE_DS_OPTIONS = [
|
|
364
|
-
{
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
hint: "Triggers 3DS only when the card / issuer requires it."
|
|
368
|
-
},
|
|
369
|
-
{
|
|
370
|
-
value: "sli",
|
|
371
|
-
label: "3D Secure (SCA) / liability shift (recommended)",
|
|
372
|
-
hint: "Attempts to optimize for liability shift while remaining compliant."
|
|
373
|
-
},
|
|
374
|
-
{
|
|
375
|
-
value: "always",
|
|
376
|
-
label: "Always request 3D Secure",
|
|
377
|
-
hint: "Forces 3DS challenge whenever possible (may reduce conversion)."
|
|
378
|
-
}
|
|
259
|
+
{ value: "when_required", label: "3D Secure when required", hint: "Triggers 3DS only when the card / issuer requires it." },
|
|
260
|
+
{ value: "sli", label: "3D Secure (SCA) / liability shift (recommended)", hint: "Attempts to optimize for liability shift while remaining compliant." },
|
|
261
|
+
{ value: "always", label: "Always request 3D Secure", hint: "Forces 3DS challenge whenever possible (may reduce conversion)." }
|
|
379
262
|
];
|
|
380
|
-
function
|
|
381
|
-
return parts.filter(Boolean).join(" ");
|
|
382
|
-
}
|
|
383
|
-
function Pill$1({
|
|
384
|
-
children,
|
|
385
|
-
onRemove
|
|
386
|
-
}) {
|
|
263
|
+
function Pill$1({ children, onRemove }) {
|
|
387
264
|
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1 rounded-md border border-ui-border-base bg-ui-bg-base px-2 py-1 text-sm text-ui-fg-base", children: [
|
|
388
265
|
children,
|
|
389
|
-
onRemove ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
390
|
-
"button",
|
|
391
|
-
{
|
|
392
|
-
type: "button",
|
|
393
|
-
onClick: onRemove,
|
|
394
|
-
className: "ml-1 rounded px-1 text-ui-fg-subtle hover:text-ui-fg-base",
|
|
395
|
-
"aria-label": "Remove",
|
|
396
|
-
children: "×"
|
|
397
|
-
}
|
|
398
|
-
) : null
|
|
266
|
+
onRemove ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onRemove, className: "ml-1 rounded px-1 text-ui-fg-subtle hover:text-ui-fg-base", "aria-label": "Remove", children: "x" }) : null
|
|
399
267
|
] });
|
|
400
268
|
}
|
|
401
|
-
function SectionCard$1({
|
|
402
|
-
title,
|
|
403
|
-
description,
|
|
404
|
-
right,
|
|
405
|
-
children
|
|
406
|
-
}) {
|
|
269
|
+
function SectionCard$1({ title, description, right, children }) {
|
|
407
270
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
408
271
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4 border-b border-ui-border-base p-4", children: [
|
|
409
272
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
@@ -415,11 +278,7 @@ function SectionCard$1({
|
|
|
415
278
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children })
|
|
416
279
|
] });
|
|
417
280
|
}
|
|
418
|
-
function FieldRow$1({
|
|
419
|
-
label,
|
|
420
|
-
hint,
|
|
421
|
-
children
|
|
422
|
-
}) {
|
|
281
|
+
function FieldRow$1({ label, hint, children }) {
|
|
423
282
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-12 items-start gap-4 py-3", children: [
|
|
424
283
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-12 md:col-span-4", children: [
|
|
425
284
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-ui-fg-base", children: label }),
|
|
@@ -441,17 +300,11 @@ function AdvancedCardPaymentsTab() {
|
|
|
441
300
|
(async () => {
|
|
442
301
|
try {
|
|
443
302
|
setLoading(true);
|
|
444
|
-
const
|
|
445
|
-
credentials: "include",
|
|
446
|
-
headers: { "Accept": "application/json" }
|
|
447
|
-
});
|
|
448
|
-
if (!r.ok) return;
|
|
449
|
-
const json = await r.json();
|
|
303
|
+
const json = await adminFetch$3("/admin/paypal/settings");
|
|
450
304
|
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
451
305
|
const saved = payload == null ? void 0 : payload.advanced_card_payments;
|
|
452
|
-
if (saved && typeof saved === "object")
|
|
453
|
-
|
|
454
|
-
}
|
|
306
|
+
if (saved && typeof saved === "object") setForm(mergeWithDefaults(saved));
|
|
307
|
+
} catch {
|
|
455
308
|
} finally {
|
|
456
309
|
setLoading(false);
|
|
457
310
|
}
|
|
@@ -460,29 +313,15 @@ function AdvancedCardPaymentsTab() {
|
|
|
460
313
|
async function onSave() {
|
|
461
314
|
try {
|
|
462
315
|
setSaving(true);
|
|
463
|
-
const
|
|
464
|
-
method: "POST",
|
|
465
|
-
credentials: "include",
|
|
466
|
-
headers: {
|
|
467
|
-
"Content-Type": "application/json",
|
|
468
|
-
"Accept": "application/json"
|
|
469
|
-
},
|
|
470
|
-
body: JSON.stringify({ advanced_card_payments: form })
|
|
471
|
-
});
|
|
472
|
-
if (!r.ok) {
|
|
473
|
-
const t = await r.text();
|
|
474
|
-
setToast({ type: "error", message: "Failed to save settings. " + t });
|
|
475
|
-
window.setTimeout(() => setToast(null), 3500);
|
|
476
|
-
return;
|
|
477
|
-
}
|
|
478
|
-
const json = await r.json().catch(() => null);
|
|
316
|
+
const json = await adminFetch$3("/admin/paypal/settings", { method: "POST", body: { advanced_card_payments: form } });
|
|
479
317
|
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
480
318
|
const saved = payload == null ? void 0 : payload.advanced_card_payments;
|
|
481
|
-
if (saved && typeof saved === "object")
|
|
482
|
-
setForm(mergeWithDefaults(saved));
|
|
483
|
-
}
|
|
319
|
+
if (saved && typeof saved === "object") setForm(mergeWithDefaults(saved));
|
|
484
320
|
setToast({ type: "success", message: "Settings saved" });
|
|
485
321
|
window.setTimeout(() => setToast(null), 2500);
|
|
322
|
+
} catch (e) {
|
|
323
|
+
setToast({ type: "error", message: (e instanceof Error ? e.message : "") || "Failed to save settings." });
|
|
324
|
+
window.setTimeout(() => setToast(null), 3500);
|
|
486
325
|
} finally {
|
|
487
326
|
setSaving(false);
|
|
488
327
|
}
|
|
@@ -491,138 +330,47 @@ function AdvancedCardPaymentsTab() {
|
|
|
491
330
|
function toggleDisabledCard(value) {
|
|
492
331
|
setForm((prev) => {
|
|
493
332
|
const exists = prev.disabledCards.includes(value);
|
|
494
|
-
return {
|
|
495
|
-
...prev,
|
|
496
|
-
disabledCards: exists ? prev.disabledCards.filter((v) => v !== value) : [...prev.disabledCards, value]
|
|
497
|
-
};
|
|
333
|
+
return { ...prev, disabledCards: exists ? prev.disabledCards.filter((v) => v !== value) : [...prev.disabledCards, value] };
|
|
498
334
|
});
|
|
499
335
|
}
|
|
500
336
|
function removeDisabledCard(value) {
|
|
501
|
-
setForm((prev) => ({
|
|
502
|
-
...prev,
|
|
503
|
-
disabledCards: prev.disabledCards.filter((v) => v !== value)
|
|
504
|
-
}));
|
|
337
|
+
setForm((prev) => ({ ...prev, disabledCards: prev.disabledCards.filter((v) => v !== value) }));
|
|
505
338
|
}
|
|
506
339
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
507
340
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-start justify-between gap-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Gateway By Easy Payment" }) }) }),
|
|
508
341
|
/* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
|
|
509
|
-
toast ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
510
|
-
"div",
|
|
511
|
-
{
|
|
512
|
-
className: "fixed right-6 top-6 z-50 rounded-md border border-ui-border-base bg-ui-bg-base px-4 py-3 text-sm shadow-lg",
|
|
513
|
-
role: "status",
|
|
514
|
-
"aria-live": "polite",
|
|
515
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: toast.type === "success" ? "text-ui-fg-base" : "text-ui-fg-error", children: toast.message })
|
|
516
|
-
}
|
|
517
|
-
) : null,
|
|
342
|
+
toast ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed right-6 top-6 z-50 rounded-md border border-ui-border-base bg-ui-bg-base px-4 py-3 text-sm shadow-lg", role: "status", "aria-live": "polite", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: toast.type === "success" ? "text-ui-fg-base" : "text-ui-fg-error", children: toast.message }) }) : null,
|
|
518
343
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
519
344
|
SectionCard$1,
|
|
520
345
|
{
|
|
521
346
|
title: "Advanced Card Payments",
|
|
522
347
|
description: "Control card checkout settings, 3D Secure behavior, and card saving.",
|
|
523
348
|
right: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
524
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
525
|
-
|
|
526
|
-
{
|
|
527
|
-
type: "button",
|
|
528
|
-
onClick: onSave,
|
|
529
|
-
disabled: saving || loading,
|
|
530
|
-
className: "rounded-md bg-ui-button-neutral px-4 py-2 text-sm font-medium text-ui-fg-on-color shadow-sm hover:opacity-90 disabled:opacity-60",
|
|
531
|
-
children: saving ? "Saving..." : "Save settings"
|
|
532
|
-
}
|
|
533
|
-
),
|
|
534
|
-
loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading…" }) : null
|
|
349
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onSave, disabled: saving || loading, className: "rounded-md bg-ui-button-neutral px-4 py-2 text-sm font-medium text-ui-fg-on-color shadow-sm hover:opacity-90 disabled:opacity-60", children: saving ? "Saving..." : "Save settings" }),
|
|
350
|
+
loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading..." }) : null
|
|
535
351
|
] }),
|
|
536
352
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-ui-border-base", children: [
|
|
537
353
|
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Enable/Disable", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
538
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
539
|
-
"input",
|
|
540
|
-
{
|
|
541
|
-
type: "checkbox",
|
|
542
|
-
checked: form.enabled,
|
|
543
|
-
onChange: (e) => setForm((p) => ({ ...p, enabled: e.target.checked })),
|
|
544
|
-
className: "h-4 w-4 rounded border-ui-border-base"
|
|
545
|
-
}
|
|
546
|
-
),
|
|
354
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: form.enabled, onChange: (e) => setForm((p) => ({ ...p, enabled: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
|
|
547
355
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable Advanced Credit/Debit Card" })
|
|
548
356
|
] }) }),
|
|
549
|
-
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Title", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
550
|
-
|
|
551
|
-
{
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: form.disabledCards.length ? form.disabledCards.map((v) => {
|
|
565
|
-
var _a2;
|
|
566
|
-
const label = ((_a2 = CARD_BRANDS.find((b) => b.value === v)) == null ? void 0 : _a2.label) ?? v;
|
|
567
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Pill$1, { onRemove: () => removeDisabledCard(v), children: label }, v);
|
|
568
|
-
}) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "No card brands disabled." }) }),
|
|
569
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-ui-border-base p-3", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-2 md:grid-cols-2", children: CARD_BRANDS.map((b) => {
|
|
570
|
-
const checked = disabledSet.has(b.value);
|
|
571
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
572
|
-
"label",
|
|
573
|
-
{
|
|
574
|
-
className: cx$1(
|
|
575
|
-
"flex items-center gap-2 rounded-md p-2",
|
|
576
|
-
"hover:bg-ui-bg-subtle"
|
|
577
|
-
),
|
|
578
|
-
children: [
|
|
579
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
580
|
-
"input",
|
|
581
|
-
{
|
|
582
|
-
type: "checkbox",
|
|
583
|
-
checked,
|
|
584
|
-
onChange: () => toggleDisabledCard(b.value),
|
|
585
|
-
className: "h-4 w-4 rounded border-ui-border-base"
|
|
586
|
-
}
|
|
587
|
-
),
|
|
588
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: b.label })
|
|
589
|
-
]
|
|
590
|
-
},
|
|
591
|
-
b.value
|
|
592
|
-
);
|
|
593
|
-
}) }) })
|
|
594
|
-
] })
|
|
595
|
-
}
|
|
596
|
-
),
|
|
597
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
598
|
-
FieldRow$1,
|
|
599
|
-
{
|
|
600
|
-
label: "Contingency for 3D Secure",
|
|
601
|
-
hint: "Choose when 3D Secure should be triggered during card payments.",
|
|
602
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
603
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
604
|
-
"select",
|
|
605
|
-
{
|
|
606
|
-
value: form.threeDS,
|
|
607
|
-
onChange: (e) => setForm((p) => ({ ...p, threeDS: e.target.value })),
|
|
608
|
-
className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive",
|
|
609
|
-
children: THREE_DS_OPTIONS.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.value, children: o.label }, o.value))
|
|
610
|
-
}
|
|
611
|
-
),
|
|
612
|
-
((_a = THREE_DS_OPTIONS.find((o) => o.value === form.threeDS)) == null ? void 0 : _a.hint) ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-ui-fg-subtle", children: (_b = THREE_DS_OPTIONS.find((o) => o.value === form.threeDS)) == null ? void 0 : _b.hint }) : null
|
|
613
|
-
] })
|
|
614
|
-
}
|
|
615
|
-
),
|
|
357
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Title", children: /* @__PURE__ */ jsxRuntime.jsx("input", { value: form.title, onChange: (e) => setForm((p) => ({ ...p, title: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "Credit or Debit Card" }) }),
|
|
358
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Disable specific credit cards", hint: "Select card brands to hide from the card form.", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
359
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: form.disabledCards.length ? form.disabledCards.map((v) => {
|
|
360
|
+
var _a2;
|
|
361
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Pill$1, { onRemove: () => removeDisabledCard(v), children: ((_a2 = CARD_BRANDS.find((b) => b.value === v)) == null ? void 0 : _a2.label) ?? v }, v);
|
|
362
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "No card brands disabled." }) }),
|
|
363
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-ui-border-base p-3", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-2 md:grid-cols-2", children: CARD_BRANDS.map((b) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 rounded-md p-2 hover:bg-ui-bg-subtle", children: [
|
|
364
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: disabledSet.has(b.value), onChange: () => toggleDisabledCard(b.value), className: "h-4 w-4 rounded border-ui-border-base" }),
|
|
365
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: b.label })
|
|
366
|
+
] }, b.value)) }) })
|
|
367
|
+
] }) }),
|
|
368
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Contingency for 3D Secure", hint: "Choose when 3D Secure should be triggered during card payments.", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
369
|
+
/* @__PURE__ */ jsxRuntime.jsx("select", { value: form.threeDS, onChange: (e) => setForm((p) => ({ ...p, threeDS: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", children: THREE_DS_OPTIONS.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.value, children: o.label }, o.value)) }),
|
|
370
|
+
((_a = THREE_DS_OPTIONS.find((o) => o.value === form.threeDS)) == null ? void 0 : _a.hint) ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-ui-fg-subtle", children: (_b = THREE_DS_OPTIONS.find((o) => o.value === form.threeDS)) == null ? void 0 : _b.hint }) : null
|
|
371
|
+
] }) }),
|
|
616
372
|
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Card Save Enabled", hint: "Allow customers to save a card at checkout for future use.", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
617
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
618
|
-
"input",
|
|
619
|
-
{
|
|
620
|
-
type: "checkbox",
|
|
621
|
-
checked: form.cardSaveEnabled,
|
|
622
|
-
onChange: (e) => setForm((p) => ({ ...p, cardSaveEnabled: e.target.checked })),
|
|
623
|
-
className: "h-4 w-4 rounded border-ui-border-base"
|
|
624
|
-
}
|
|
625
|
-
),
|
|
373
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: form.cardSaveEnabled, onChange: (e) => setForm((p) => ({ ...p, cardSaveEnabled: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
|
|
626
374
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable card saving at checkout" })
|
|
627
375
|
] }) })
|
|
628
376
|
] })
|
|
@@ -630,14 +378,46 @@ function AdvancedCardPaymentsTab() {
|
|
|
630
378
|
)
|
|
631
379
|
] }) });
|
|
632
380
|
}
|
|
633
|
-
function
|
|
634
|
-
|
|
635
|
-
|
|
381
|
+
function PayPalApplePayPage() {
|
|
382
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
383
|
+
}
|
|
384
|
+
async function adminFetch$2(path, opts = {}) {
|
|
385
|
+
var _a;
|
|
386
|
+
const { method = "GET", body, query } = opts;
|
|
387
|
+
let url = path;
|
|
388
|
+
if (query && Object.keys(query).length > 0) {
|
|
389
|
+
const params = new URLSearchParams(query);
|
|
390
|
+
url = `${path}?${params.toString()}`;
|
|
636
391
|
}
|
|
637
|
-
const
|
|
638
|
-
if (
|
|
639
|
-
|
|
392
|
+
const headers = { Accept: "application/json" };
|
|
393
|
+
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
394
|
+
if (typeof window !== "undefined") {
|
|
395
|
+
const token = (_a = window.__medusa__) == null ? void 0 : _a.token;
|
|
396
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
397
|
+
}
|
|
398
|
+
const res = await fetch(url, {
|
|
399
|
+
method,
|
|
400
|
+
headers,
|
|
401
|
+
credentials: "include",
|
|
402
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
403
|
+
});
|
|
404
|
+
const text = await res.text().catch(() => "");
|
|
405
|
+
if (!res.ok) {
|
|
406
|
+
if (res.status === 401) throw new Error("Unauthorized (401) - session may have expired. Please reload and log in again.");
|
|
407
|
+
if (res.status === 403) throw new Error("Forbidden (403) - you do not have permission to perform this action.");
|
|
408
|
+
throw new Error(text || `Request failed with status ${res.status}`);
|
|
409
|
+
}
|
|
410
|
+
if (!text) return {};
|
|
411
|
+
try {
|
|
412
|
+
return JSON.parse(text);
|
|
413
|
+
} catch {
|
|
414
|
+
return {};
|
|
640
415
|
}
|
|
416
|
+
}
|
|
417
|
+
function formatDate$1(value) {
|
|
418
|
+
if (!value) return "";
|
|
419
|
+
const parsed = new Date(value);
|
|
420
|
+
if (Number.isNaN(parsed.getTime())) return value;
|
|
641
421
|
return parsed.toLocaleString();
|
|
642
422
|
}
|
|
643
423
|
function PayPalAuditLogsPage() {
|
|
@@ -648,20 +428,10 @@ function PayPalAuditLogsPage() {
|
|
|
648
428
|
try {
|
|
649
429
|
setLoading(true);
|
|
650
430
|
setError(null);
|
|
651
|
-
const
|
|
652
|
-
|
|
653
|
-
headers: {
|
|
654
|
-
Accept: "application/json"
|
|
655
|
-
}
|
|
656
|
-
});
|
|
657
|
-
if (!response.ok) {
|
|
658
|
-
const message = await response.text().catch(() => "");
|
|
659
|
-
throw new Error(message || "Failed to load audit logs.");
|
|
660
|
-
}
|
|
661
|
-
const data = await response.json().catch(() => ({}));
|
|
662
|
-
setLogs((data == null ? void 0 : data.logs) || []);
|
|
431
|
+
const data = await adminFetch$2("/admin/paypal/audit-logs", { query: { limit: "50" } });
|
|
432
|
+
setLogs((data == null ? void 0 : data.logs) ?? []);
|
|
663
433
|
} catch (fetchError) {
|
|
664
|
-
setError(
|
|
434
|
+
setError(fetchError instanceof Error ? fetchError.message : "Failed to load audit logs.");
|
|
665
435
|
setLogs([]);
|
|
666
436
|
} finally {
|
|
667
437
|
setLoading(false);
|
|
@@ -679,16 +449,7 @@ function PayPalAuditLogsPage() {
|
|
|
679
449
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
680
450
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-ui-border-base p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-4", children: [
|
|
681
451
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Latest events" }),
|
|
682
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
683
|
-
"button",
|
|
684
|
-
{
|
|
685
|
-
type: "button",
|
|
686
|
-
onClick: fetchLogs,
|
|
687
|
-
className: "rounded-md border border-ui-border-base px-3 py-2 text-sm text-ui-fg-base",
|
|
688
|
-
disabled: loading,
|
|
689
|
-
children: loading ? "Refreshing..." : "Refresh"
|
|
690
|
-
}
|
|
691
|
-
)
|
|
452
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: fetchLogs, className: "rounded-md border border-ui-border-base px-3 py-2 text-sm text-ui-fg-base", disabled: loading, children: loading ? "Refreshing..." : "Refresh" })
|
|
692
453
|
] }) }),
|
|
693
454
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4", children: [
|
|
694
455
|
error ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-600", children: error }) : null,
|
|
@@ -700,7 +461,7 @@ function PayPalAuditLogsPage() {
|
|
|
700
461
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "pb-2 font-medium", children: "Details" })
|
|
701
462
|
] }) }),
|
|
702
463
|
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: logs.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-t border-ui-border-base", children: [
|
|
703
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-3 pr-4 text-ui-fg-base", children: formatDate$
|
|
464
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-3 pr-4 text-ui-fg-base", children: formatDate$1(entry.created_at) || "—" }),
|
|
704
465
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-3 pr-4 text-ui-fg-base", children: entry.event_type || "—" }),
|
|
705
466
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-3 text-ui-fg-subtle", children: /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "whitespace-pre-wrap rounded-md bg-ui-bg-subtle p-2 text-xs text-ui-fg-subtle", children: JSON.stringify(entry.metadata || {}, null, 2) }) })
|
|
706
467
|
] }, entry.id)) })
|
|
@@ -709,201 +470,6 @@ function PayPalAuditLogsPage() {
|
|
|
709
470
|
] })
|
|
710
471
|
] }) });
|
|
711
472
|
}
|
|
712
|
-
function PayPalApplePayPage() {
|
|
713
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
714
|
-
}
|
|
715
|
-
const EMPTY_FILTERS = {
|
|
716
|
-
dispute_id: "",
|
|
717
|
-
status: "",
|
|
718
|
-
order_id: "",
|
|
719
|
-
cart_id: ""
|
|
720
|
-
};
|
|
721
|
-
function formatDate$1(value) {
|
|
722
|
-
if (!value) {
|
|
723
|
-
return "";
|
|
724
|
-
}
|
|
725
|
-
const parsed = new Date(value);
|
|
726
|
-
if (Number.isNaN(parsed.getTime())) {
|
|
727
|
-
return value;
|
|
728
|
-
}
|
|
729
|
-
return parsed.toLocaleString();
|
|
730
|
-
}
|
|
731
|
-
function PayPalDisputesPage() {
|
|
732
|
-
const [filters, setFilters] = react.useState({ ...EMPTY_FILTERS });
|
|
733
|
-
const [disputes, setDisputes] = react.useState([]);
|
|
734
|
-
const [loading, setLoading] = react.useState(false);
|
|
735
|
-
const [error, setError] = react.useState(null);
|
|
736
|
-
const queryString = react.useMemo(() => {
|
|
737
|
-
const params = new URLSearchParams();
|
|
738
|
-
Object.entries(filters).forEach(([key, value]) => {
|
|
739
|
-
if (value.trim()) {
|
|
740
|
-
params.set(key, value.trim());
|
|
741
|
-
}
|
|
742
|
-
});
|
|
743
|
-
const qs = params.toString();
|
|
744
|
-
return qs ? `?${qs}` : "";
|
|
745
|
-
}, [filters]);
|
|
746
|
-
const fetchDisputes = react.useCallback(async (source) => {
|
|
747
|
-
try {
|
|
748
|
-
setLoading(true);
|
|
749
|
-
setError(null);
|
|
750
|
-
const params = new URLSearchParams();
|
|
751
|
-
Object.entries(source).forEach(([key, value]) => {
|
|
752
|
-
if (value.trim()) {
|
|
753
|
-
params.set(key, value.trim());
|
|
754
|
-
}
|
|
755
|
-
});
|
|
756
|
-
const qs = params.toString();
|
|
757
|
-
const resp = await fetch(`/admin/paypal/disputes${qs ? `?${qs}` : ""}`, {
|
|
758
|
-
credentials: "include",
|
|
759
|
-
headers: {
|
|
760
|
-
Accept: "application/json"
|
|
761
|
-
}
|
|
762
|
-
});
|
|
763
|
-
if (!resp.ok) {
|
|
764
|
-
const message = await resp.text().catch(() => "");
|
|
765
|
-
throw new Error(message || "Failed to load disputes");
|
|
766
|
-
}
|
|
767
|
-
const json = await resp.json().catch(() => ({}));
|
|
768
|
-
setDisputes((json == null ? void 0 : json.disputes) || []);
|
|
769
|
-
} catch (fetchError) {
|
|
770
|
-
setError((fetchError == null ? void 0 : fetchError.message) || "Failed to load disputes");
|
|
771
|
-
setDisputes([]);
|
|
772
|
-
} finally {
|
|
773
|
-
setLoading(false);
|
|
774
|
-
}
|
|
775
|
-
}, []);
|
|
776
|
-
react.useEffect(() => {
|
|
777
|
-
fetchDisputes(EMPTY_FILTERS);
|
|
778
|
-
}, [fetchDisputes]);
|
|
779
|
-
const onSubmit = (event) => {
|
|
780
|
-
event.preventDefault();
|
|
781
|
-
fetchDisputes(filters);
|
|
782
|
-
};
|
|
783
|
-
const onReset = () => {
|
|
784
|
-
setFilters({ ...EMPTY_FILTERS });
|
|
785
|
-
fetchDisputes(EMPTY_FILTERS);
|
|
786
|
-
};
|
|
787
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
788
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
789
|
-
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Disputes" }),
|
|
790
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-ui-fg-subtle", children: "Review PayPal dispute activity tied to your Medusa orders. This view is read-only." })
|
|
791
|
-
] }),
|
|
792
|
-
/* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
|
|
793
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
794
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-ui-border-base p-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Filters" }) }),
|
|
795
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit, className: "flex flex-col gap-4", children: [
|
|
796
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-4", children: [
|
|
797
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
|
|
798
|
-
"Dispute ID",
|
|
799
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
800
|
-
"input",
|
|
801
|
-
{
|
|
802
|
-
className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base",
|
|
803
|
-
value: filters.dispute_id,
|
|
804
|
-
onChange: (event) => setFilters((prev) => ({ ...prev, dispute_id: event.target.value })),
|
|
805
|
-
placeholder: "PP-D-123"
|
|
806
|
-
}
|
|
807
|
-
)
|
|
808
|
-
] }),
|
|
809
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
|
|
810
|
-
"Status",
|
|
811
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
812
|
-
"input",
|
|
813
|
-
{
|
|
814
|
-
className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base",
|
|
815
|
-
value: filters.status,
|
|
816
|
-
onChange: (event) => setFilters((prev) => ({ ...prev, status: event.target.value })),
|
|
817
|
-
placeholder: "OPEN"
|
|
818
|
-
}
|
|
819
|
-
)
|
|
820
|
-
] }),
|
|
821
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
|
|
822
|
-
"Order ID",
|
|
823
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
824
|
-
"input",
|
|
825
|
-
{
|
|
826
|
-
className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base",
|
|
827
|
-
value: filters.order_id,
|
|
828
|
-
onChange: (event) => setFilters((prev) => ({ ...prev, order_id: event.target.value })),
|
|
829
|
-
placeholder: "order_..."
|
|
830
|
-
}
|
|
831
|
-
)
|
|
832
|
-
] }),
|
|
833
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
|
|
834
|
-
"Cart ID",
|
|
835
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
836
|
-
"input",
|
|
837
|
-
{
|
|
838
|
-
className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base",
|
|
839
|
-
value: filters.cart_id,
|
|
840
|
-
onChange: (event) => setFilters((prev) => ({ ...prev, cart_id: event.target.value })),
|
|
841
|
-
placeholder: "cart_..."
|
|
842
|
-
}
|
|
843
|
-
)
|
|
844
|
-
] })
|
|
845
|
-
] }),
|
|
846
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-3", children: [
|
|
847
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
848
|
-
"button",
|
|
849
|
-
{
|
|
850
|
-
type: "submit",
|
|
851
|
-
className: "rounded-md bg-ui-fg-base px-4 py-2 text-sm font-medium text-ui-bg-base",
|
|
852
|
-
disabled: loading,
|
|
853
|
-
children: loading ? "Loading..." : "Apply filters"
|
|
854
|
-
}
|
|
855
|
-
),
|
|
856
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
857
|
-
"button",
|
|
858
|
-
{
|
|
859
|
-
type: "button",
|
|
860
|
-
className: "rounded-md border border-ui-border-base px-4 py-2 text-sm text-ui-fg-base",
|
|
861
|
-
onClick: onReset,
|
|
862
|
-
disabled: loading,
|
|
863
|
-
children: "Reset"
|
|
864
|
-
}
|
|
865
|
-
),
|
|
866
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-ui-fg-subtle", children: [
|
|
867
|
-
"Showing ",
|
|
868
|
-
disputes.length,
|
|
869
|
-
" dispute",
|
|
870
|
-
disputes.length === 1 ? "" : "s",
|
|
871
|
-
queryString ? " (filtered)" : ""
|
|
872
|
-
] })
|
|
873
|
-
] })
|
|
874
|
-
] }) })
|
|
875
|
-
] }),
|
|
876
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
877
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-ui-border-base p-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Dispute Records" }) }),
|
|
878
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-ui-border-base text-sm", children: [
|
|
879
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "text-left text-ui-fg-subtle", children: [
|
|
880
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Dispute" }),
|
|
881
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Status" }),
|
|
882
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Reason" }),
|
|
883
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Stage" }),
|
|
884
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Amount" }),
|
|
885
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Order" }),
|
|
886
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Cart" }),
|
|
887
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Updated" })
|
|
888
|
-
] }) }),
|
|
889
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-base text-ui-fg-base", children: disputes.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-6 text-center text-ui-fg-subtle", colSpan: 8, children: loading ? "Loading disputes..." : "No disputes found." }) }) : disputes.map((dispute) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
890
|
-
/* @__PURE__ */ jsxRuntime.jsxs("td", { className: "px-4 py-3", children: [
|
|
891
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-ui-fg-base", children: dispute.dispute_id }),
|
|
892
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-ui-fg-subtle", children: dispute.transaction_id || "No transaction" })
|
|
893
|
-
] }),
|
|
894
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.status || "Unknown" }),
|
|
895
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.reason || "-" }),
|
|
896
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.stage || "-" }),
|
|
897
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.amount ? `${dispute.amount} ${dispute.currency_code || ""}` : "-" }),
|
|
898
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.order_id || "-" }),
|
|
899
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.cart_id || "-" }),
|
|
900
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 text-ui-fg-subtle", children: formatDate$1(dispute.updated_at || dispute.created_at) })
|
|
901
|
-
] }, dispute.id)) })
|
|
902
|
-
] }) }),
|
|
903
|
-
error ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-ui-border-base px-4 py-3 text-sm text-ui-fg-error", children: error }) : null
|
|
904
|
-
] })
|
|
905
|
-
] }) });
|
|
906
|
-
}
|
|
907
473
|
const config = adminSdk.defineRouteConfig({
|
|
908
474
|
label: "PayPal Connection",
|
|
909
475
|
hide: true
|
|
@@ -1430,69 +996,222 @@ function PayPalConnectionPage() {
|
|
|
1430
996
|
}
|
|
1431
997
|
)
|
|
1432
998
|
] }),
|
|
1433
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 md:col-span-2", children: [
|
|
1434
|
-
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium", children: "Merchant ID (optional)" }),
|
|
1435
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1436
|
-
"input",
|
|
1437
|
-
{
|
|
1438
|
-
type: "text",
|
|
1439
|
-
value: merchantId,
|
|
1440
|
-
onChange: (e) => setMerchantId(e.target.value),
|
|
1441
|
-
disabled: onboardingInProgress,
|
|
1442
|
-
className: "rounded-md border border-ui-border-base bg-transparent px-3 py-2 text-sm disabled:opacity-50",
|
|
1443
|
-
placeholder: "Merchant ID"
|
|
1444
|
-
}
|
|
1445
|
-
)
|
|
999
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 md:col-span-2", children: [
|
|
1000
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium", children: "Merchant ID (optional)" }),
|
|
1001
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1002
|
+
"input",
|
|
1003
|
+
{
|
|
1004
|
+
type: "text",
|
|
1005
|
+
value: merchantId,
|
|
1006
|
+
onChange: (e) => setMerchantId(e.target.value),
|
|
1007
|
+
disabled: onboardingInProgress,
|
|
1008
|
+
className: "rounded-md border border-ui-border-base bg-transparent px-3 py-2 text-sm disabled:opacity-50",
|
|
1009
|
+
placeholder: "Merchant ID"
|
|
1010
|
+
}
|
|
1011
|
+
)
|
|
1012
|
+
] }),
|
|
1013
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md:col-span-2 flex items-center gap-2 mt-2", children: [
|
|
1014
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1015
|
+
"button",
|
|
1016
|
+
{
|
|
1017
|
+
type: "button",
|
|
1018
|
+
className: "rounded-md border border-ui-border-base px-3 py-2 text-sm font-medium hover:bg-ui-bg-subtle disabled:opacity-50 disabled:cursor-not-allowed",
|
|
1019
|
+
onClick: () => setShowManual(false),
|
|
1020
|
+
disabled: onboardingInProgress,
|
|
1021
|
+
children: "Cancel"
|
|
1022
|
+
}
|
|
1023
|
+
),
|
|
1024
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1025
|
+
"button",
|
|
1026
|
+
{
|
|
1027
|
+
type: "button",
|
|
1028
|
+
className: "rounded-md border border-ui-border-base px-3 py-2 text-sm font-medium bg-ui-bg-base hover:bg-ui-bg-subtle disabled:opacity-50 disabled:cursor-not-allowed",
|
|
1029
|
+
disabled: !canSaveManual || onboardingInProgress,
|
|
1030
|
+
onClick: handleSaveManual,
|
|
1031
|
+
children: "Save credentials"
|
|
1032
|
+
}
|
|
1033
|
+
)
|
|
1034
|
+
] })
|
|
1035
|
+
] }) })
|
|
1036
|
+
] }) })
|
|
1037
|
+
] }),
|
|
1038
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { children: `
|
|
1039
|
+
.loader {
|
|
1040
|
+
border: 3px solid #f3f3f3;
|
|
1041
|
+
border-top: 3px solid #0070ba;
|
|
1042
|
+
border-radius: 50%;
|
|
1043
|
+
width: 18px;
|
|
1044
|
+
height: 18px;
|
|
1045
|
+
animation: spin 1s linear infinite;
|
|
1046
|
+
display: inline-block;
|
|
1047
|
+
vertical-align: middle;
|
|
1048
|
+
margin-right: 8px;
|
|
1049
|
+
}
|
|
1050
|
+
@keyframes spin {
|
|
1051
|
+
0% { transform: rotate(0deg); }
|
|
1052
|
+
100% { transform: rotate(360deg); }
|
|
1053
|
+
}
|
|
1054
|
+
` })
|
|
1055
|
+
] });
|
|
1056
|
+
}
|
|
1057
|
+
function PayPalGooglePayPage() {
|
|
1058
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
1059
|
+
}
|
|
1060
|
+
function PayPalPayLaterMessagingPage() {
|
|
1061
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
1062
|
+
}
|
|
1063
|
+
async function adminFetch$1(path, opts = {}) {
|
|
1064
|
+
var _a;
|
|
1065
|
+
const { method = "GET", body, query } = opts;
|
|
1066
|
+
let url = path;
|
|
1067
|
+
if (query && Object.keys(query).length > 0) {
|
|
1068
|
+
const params = new URLSearchParams(query);
|
|
1069
|
+
url = `${path}?${params.toString()}`;
|
|
1070
|
+
}
|
|
1071
|
+
const headers = { Accept: "application/json" };
|
|
1072
|
+
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
1073
|
+
if (typeof window !== "undefined") {
|
|
1074
|
+
const token = (_a = window.__medusa__) == null ? void 0 : _a.token;
|
|
1075
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
1076
|
+
}
|
|
1077
|
+
const res = await fetch(url, {
|
|
1078
|
+
method,
|
|
1079
|
+
headers,
|
|
1080
|
+
credentials: "include",
|
|
1081
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
1082
|
+
});
|
|
1083
|
+
const text = await res.text().catch(() => "");
|
|
1084
|
+
if (!res.ok) {
|
|
1085
|
+
if (res.status === 401) throw new Error("Unauthorized (401) - session may have expired. Please reload and log in again.");
|
|
1086
|
+
if (res.status === 403) throw new Error("Forbidden (403) - you do not have permission to perform this action.");
|
|
1087
|
+
throw new Error(text || `Request failed with status ${res.status}`);
|
|
1088
|
+
}
|
|
1089
|
+
if (!text) return {};
|
|
1090
|
+
try {
|
|
1091
|
+
return JSON.parse(text);
|
|
1092
|
+
} catch {
|
|
1093
|
+
return {};
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
function formatDate(value) {
|
|
1097
|
+
if (!value) return "—";
|
|
1098
|
+
const parsed = new Date(value);
|
|
1099
|
+
if (Number.isNaN(parsed.getTime())) return value;
|
|
1100
|
+
return parsed.toLocaleString();
|
|
1101
|
+
}
|
|
1102
|
+
function PayPalReconciliationStatusPage() {
|
|
1103
|
+
const [status, setStatus] = react.useState({});
|
|
1104
|
+
const [loading, setLoading] = react.useState(false);
|
|
1105
|
+
const [error, setError] = react.useState(null);
|
|
1106
|
+
const fetchStatus = react.useCallback(async () => {
|
|
1107
|
+
try {
|
|
1108
|
+
setLoading(true);
|
|
1109
|
+
setError(null);
|
|
1110
|
+
const data = await adminFetch$1("/admin/paypal/reconciliation-status");
|
|
1111
|
+
setStatus((data == null ? void 0 : data.status) ?? {});
|
|
1112
|
+
} catch (fetchError) {
|
|
1113
|
+
setError(fetchError instanceof Error ? fetchError.message : "Failed to load reconciliation status.");
|
|
1114
|
+
setStatus({});
|
|
1115
|
+
} finally {
|
|
1116
|
+
setLoading(false);
|
|
1117
|
+
}
|
|
1118
|
+
}, []);
|
|
1119
|
+
react.useEffect(() => {
|
|
1120
|
+
fetchStatus();
|
|
1121
|
+
}, [fetchStatus]);
|
|
1122
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
1123
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1124
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Reconciliation Status" }),
|
|
1125
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-ui-fg-subtle", children: "Monitor reconciliation health and drift detection for PayPal payment sessions." })
|
|
1126
|
+
] }),
|
|
1127
|
+
/* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
|
|
1128
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
1129
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-ui-border-base p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-4", children: [
|
|
1130
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Latest reconciliation run" }),
|
|
1131
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: fetchStatus, className: "rounded-md border border-ui-border-base px-3 py-2 text-sm text-ui-fg-base", disabled: loading, children: loading ? "Refreshing..." : "Refresh" })
|
|
1132
|
+
] }) }),
|
|
1133
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4", children: [
|
|
1134
|
+
error ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-600", children: error }) : null,
|
|
1135
|
+
!error && Object.keys(status).length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-ui-fg-subtle", children: loading ? "Loading reconciliation status..." : "No reconciliation data yet." }) : null,
|
|
1136
|
+
Object.keys(status).length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 text-sm text-ui-fg-base md:grid-cols-2", children: [
|
|
1137
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1138
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last run" }),
|
|
1139
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_run_at) })
|
|
1140
|
+
] }),
|
|
1141
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1142
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last run status" }),
|
|
1143
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium capitalize", children: status.last_run_status || "—" })
|
|
1144
|
+
] }),
|
|
1145
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1146
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last success" }),
|
|
1147
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_success_at) })
|
|
1148
|
+
] }),
|
|
1149
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1150
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last failure" }),
|
|
1151
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_failure_at) })
|
|
1152
|
+
] }),
|
|
1153
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1154
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Sessions checked" }),
|
|
1155
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.sessions_checked ?? 0 })
|
|
1156
|
+
] }),
|
|
1157
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1158
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Sessions updated" }),
|
|
1159
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.sessions_updated ?? 0 })
|
|
1160
|
+
] }),
|
|
1161
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1162
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Drift detections" }),
|
|
1163
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.drift_count ?? 0 })
|
|
1164
|
+
] }),
|
|
1165
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1166
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last drift order" }),
|
|
1167
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.last_drift_order_id || "—" }),
|
|
1168
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-xs text-ui-fg-subtle", children: formatDate(status.last_drift_at) })
|
|
1169
|
+
] }),
|
|
1170
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 md:col-span-2", children: [
|
|
1171
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last error" }),
|
|
1172
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.last_error || "No errors recorded." })
|
|
1446
1173
|
] }),
|
|
1447
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
1448
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1449
|
-
|
|
1450
|
-
{
|
|
1451
|
-
type: "button",
|
|
1452
|
-
className: "rounded-md border border-ui-border-base px-3 py-2 text-sm font-medium hover:bg-ui-bg-subtle disabled:opacity-50 disabled:cursor-not-allowed",
|
|
1453
|
-
onClick: () => setShowManual(false),
|
|
1454
|
-
disabled: onboardingInProgress,
|
|
1455
|
-
children: "Cancel"
|
|
1456
|
-
}
|
|
1457
|
-
),
|
|
1458
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1459
|
-
"button",
|
|
1460
|
-
{
|
|
1461
|
-
type: "button",
|
|
1462
|
-
className: "rounded-md border border-ui-border-base px-3 py-2 text-sm font-medium bg-ui-bg-base hover:bg-ui-bg-subtle disabled:opacity-50 disabled:cursor-not-allowed",
|
|
1463
|
-
disabled: !canSaveManual || onboardingInProgress,
|
|
1464
|
-
onClick: handleSaveManual,
|
|
1465
|
-
children: "Save credentials"
|
|
1466
|
-
}
|
|
1467
|
-
)
|
|
1174
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 md:col-span-2", children: [
|
|
1175
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Total runs" }),
|
|
1176
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.runs ?? 0 })
|
|
1468
1177
|
] })
|
|
1469
|
-
] })
|
|
1470
|
-
] })
|
|
1471
|
-
] })
|
|
1472
|
-
|
|
1473
|
-
.loader {
|
|
1474
|
-
border: 3px solid #f3f3f3;
|
|
1475
|
-
border-top: 3px solid #0070ba;
|
|
1476
|
-
border-radius: 50%;
|
|
1477
|
-
width: 18px;
|
|
1478
|
-
height: 18px;
|
|
1479
|
-
animation: spin 1s linear infinite;
|
|
1480
|
-
display: inline-block;
|
|
1481
|
-
vertical-align: middle;
|
|
1482
|
-
margin-right: 8px;
|
|
1483
|
-
}
|
|
1484
|
-
@keyframes spin {
|
|
1485
|
-
0% { transform: rotate(0deg); }
|
|
1486
|
-
100% { transform: rotate(360deg); }
|
|
1487
|
-
}
|
|
1488
|
-
` })
|
|
1489
|
-
] });
|
|
1490
|
-
}
|
|
1491
|
-
function PayPalGooglePayPage() {
|
|
1492
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
1178
|
+
] }) : null
|
|
1179
|
+
] })
|
|
1180
|
+
] })
|
|
1181
|
+
] }) });
|
|
1493
1182
|
}
|
|
1494
|
-
function
|
|
1495
|
-
|
|
1183
|
+
async function adminFetch(path, opts = {}) {
|
|
1184
|
+
var _a;
|
|
1185
|
+
const { method = "GET", body, query } = opts;
|
|
1186
|
+
let url = path;
|
|
1187
|
+
if (query && Object.keys(query).length > 0) {
|
|
1188
|
+
const params = new URLSearchParams(query);
|
|
1189
|
+
url = `${path}?${params.toString()}`;
|
|
1190
|
+
}
|
|
1191
|
+
const headers = { Accept: "application/json" };
|
|
1192
|
+
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
1193
|
+
if (typeof window !== "undefined") {
|
|
1194
|
+
const token = (_a = window.__medusa__) == null ? void 0 : _a.token;
|
|
1195
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
1196
|
+
}
|
|
1197
|
+
const res = await fetch(url, {
|
|
1198
|
+
method,
|
|
1199
|
+
headers,
|
|
1200
|
+
credentials: "include",
|
|
1201
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
1202
|
+
});
|
|
1203
|
+
const text = await res.text().catch(() => "");
|
|
1204
|
+
if (!res.ok) {
|
|
1205
|
+
if (res.status === 401) throw new Error("Unauthorized (401) - session may have expired. Please reload and log in again.");
|
|
1206
|
+
if (res.status === 403) throw new Error("Forbidden (403) - you do not have permission to perform this action.");
|
|
1207
|
+
throw new Error(text || `Request failed with status ${res.status}`);
|
|
1208
|
+
}
|
|
1209
|
+
if (!text) return {};
|
|
1210
|
+
try {
|
|
1211
|
+
return JSON.parse(text);
|
|
1212
|
+
} catch {
|
|
1213
|
+
return {};
|
|
1214
|
+
}
|
|
1496
1215
|
}
|
|
1497
1216
|
const DISPLAY_LOCATION_OPTIONS = [
|
|
1498
1217
|
{ value: "product", label: "Product Page" },
|
|
@@ -1605,7 +1324,7 @@ function PayPalSettingsTab() {
|
|
|
1605
1324
|
const [form, setForm] = react.useState({
|
|
1606
1325
|
enabled: true,
|
|
1607
1326
|
title: "PayPal",
|
|
1608
|
-
description: "Pay via PayPal; you can pay with your credit card if you don
|
|
1327
|
+
description: "Pay via PayPal; you can pay with your credit card if you don't have a PayPal account",
|
|
1609
1328
|
displayOn: ["product", "cart", "express", "mini_cart"],
|
|
1610
1329
|
disableButtons: [],
|
|
1611
1330
|
buttonColor: "gold",
|
|
@@ -1624,12 +1343,9 @@ function PayPalSettingsTab() {
|
|
|
1624
1343
|
(async () => {
|
|
1625
1344
|
try {
|
|
1626
1345
|
setLoading(true);
|
|
1627
|
-
const
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
});
|
|
1631
|
-
if (!r.ok) return;
|
|
1632
|
-
const json = await r.json();
|
|
1346
|
+
const json = await adminFetch(
|
|
1347
|
+
"/admin/paypal/settings"
|
|
1348
|
+
);
|
|
1633
1349
|
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
1634
1350
|
const saved = payload == null ? void 0 : payload.paypal_settings;
|
|
1635
1351
|
if (saved && typeof saved === "object") {
|
|
@@ -1639,6 +1355,7 @@ function PayPalSettingsTab() {
|
|
|
1639
1355
|
disableButtons: filterHiddenDisableButtons(saved.disableButtons)
|
|
1640
1356
|
}));
|
|
1641
1357
|
}
|
|
1358
|
+
} catch {
|
|
1642
1359
|
} finally {
|
|
1643
1360
|
setLoading(false);
|
|
1644
1361
|
}
|
|
@@ -1651,22 +1368,13 @@ function PayPalSettingsTab() {
|
|
|
1651
1368
|
...form,
|
|
1652
1369
|
disableButtons: filterHiddenDisableButtons(form.disableButtons)
|
|
1653
1370
|
};
|
|
1654
|
-
const
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
body: JSON.stringify({ paypal_settings: cleaned })
|
|
1662
|
-
});
|
|
1663
|
-
if (!r.ok) {
|
|
1664
|
-
const t = await r.text();
|
|
1665
|
-
setToast({ type: "error", message: "Failed to save settings. " + t });
|
|
1666
|
-
window.setTimeout(() => setToast(null), 3500);
|
|
1667
|
-
return;
|
|
1668
|
-
}
|
|
1669
|
-
const json = await r.json().catch(() => null);
|
|
1371
|
+
const json = await adminFetch(
|
|
1372
|
+
"/admin/paypal/settings",
|
|
1373
|
+
{
|
|
1374
|
+
method: "POST",
|
|
1375
|
+
body: { paypal_settings: cleaned }
|
|
1376
|
+
}
|
|
1377
|
+
);
|
|
1670
1378
|
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
1671
1379
|
const saved = payload == null ? void 0 : payload.paypal_settings;
|
|
1672
1380
|
if (saved && typeof saved === "object") {
|
|
@@ -1678,6 +1386,12 @@ function PayPalSettingsTab() {
|
|
|
1678
1386
|
}
|
|
1679
1387
|
setToast({ type: "success", message: "Settings saved" });
|
|
1680
1388
|
window.setTimeout(() => setToast(null), 2500);
|
|
1389
|
+
} catch (e) {
|
|
1390
|
+
setToast({
|
|
1391
|
+
type: "error",
|
|
1392
|
+
message: (e instanceof Error ? e.message : "") || "Failed to save settings."
|
|
1393
|
+
});
|
|
1394
|
+
window.setTimeout(() => setToast(null), 3500);
|
|
1681
1395
|
} finally {
|
|
1682
1396
|
setSaving(false);
|
|
1683
1397
|
}
|
|
@@ -1817,226 +1531,114 @@ function PayPalSettingsTab() {
|
|
|
1817
1531
|
] })
|
|
1818
1532
|
}
|
|
1819
1533
|
),
|
|
1820
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1534
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1821
1535
|
SectionCard,
|
|
1822
1536
|
{
|
|
1823
1537
|
title: "Button Appearance",
|
|
1824
1538
|
description: "Control PayPal Smart Button styling (color/shape/size/label) and optionally disable specific buttons.",
|
|
1825
|
-
children: [
|
|
1826
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
] }),
|
|
1907
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-6 rounded-md border border-ui-border-base bg-ui-bg-subtle p-4", children: [
|
|
1908
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-ui-fg-base", children: "Preview (UI only)" }),
|
|
1909
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 text-sm text-ui-fg-subtle", children: [
|
|
1910
|
-
"Color: ",
|
|
1911
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-base", children: form.buttonColor }),
|
|
1912
|
-
" · Shape:",
|
|
1913
|
-
" ",
|
|
1914
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-base", children: form.buttonShape }),
|
|
1915
|
-
" · Width:",
|
|
1916
|
-
" ",
|
|
1917
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-base", children: form.buttonWidth }),
|
|
1918
|
-
" · Height:",
|
|
1919
|
-
" ",
|
|
1920
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-fg-base", children: [
|
|
1921
|
-
form.buttonHeight,
|
|
1922
|
-
"px"
|
|
1923
|
-
] }),
|
|
1924
|
-
" · Label:",
|
|
1925
|
-
" ",
|
|
1926
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-base", children: form.buttonLabel })
|
|
1927
|
-
] })
|
|
1928
|
-
] })
|
|
1929
|
-
]
|
|
1930
|
-
}
|
|
1931
|
-
)
|
|
1932
|
-
] }) });
|
|
1933
|
-
}
|
|
1934
|
-
function formatDate(value) {
|
|
1935
|
-
if (!value) {
|
|
1936
|
-
return "—";
|
|
1937
|
-
}
|
|
1938
|
-
const parsed = new Date(value);
|
|
1939
|
-
if (Number.isNaN(parsed.getTime())) {
|
|
1940
|
-
return value;
|
|
1941
|
-
}
|
|
1942
|
-
return parsed.toLocaleString();
|
|
1943
|
-
}
|
|
1944
|
-
function PayPalReconciliationStatusPage() {
|
|
1945
|
-
const [status, setStatus] = react.useState({});
|
|
1946
|
-
const [loading, setLoading] = react.useState(false);
|
|
1947
|
-
const [error, setError] = react.useState(null);
|
|
1948
|
-
const fetchStatus = react.useCallback(async () => {
|
|
1949
|
-
try {
|
|
1950
|
-
setLoading(true);
|
|
1951
|
-
setError(null);
|
|
1952
|
-
const response = await fetch("/admin/paypal/reconciliation-status", {
|
|
1953
|
-
credentials: "include",
|
|
1954
|
-
headers: {
|
|
1955
|
-
Accept: "application/json"
|
|
1956
|
-
}
|
|
1957
|
-
});
|
|
1958
|
-
if (!response.ok) {
|
|
1959
|
-
const message = await response.text().catch(() => "");
|
|
1960
|
-
throw new Error(message || "Failed to load reconciliation status.");
|
|
1539
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-ui-border-base", children: [
|
|
1540
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1541
|
+
FieldRow,
|
|
1542
|
+
{
|
|
1543
|
+
label: "Disable Specific Payment Buttons",
|
|
1544
|
+
hint: "Hide individual funding sources (ex: Card, Venmo).",
|
|
1545
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
1546
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
1547
|
+
filterHiddenDisableButtons(form.disableButtons).map((v) => {
|
|
1548
|
+
const opt = VISIBLE_DISABLE_BUTTON_OPTIONS.find((o) => o.value === v);
|
|
1549
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Pill, { onRemove: () => removeMulti("disableButtons", v), children: (opt == null ? void 0 : opt.label) ?? v }, v);
|
|
1550
|
+
}),
|
|
1551
|
+
filterHiddenDisableButtons(form.disableButtons).length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "No buttons disabled." }) : null
|
|
1552
|
+
] }),
|
|
1553
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-ui-border-base p-3", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-2 md:grid-cols-2", children: VISIBLE_DISABLE_BUTTON_OPTIONS.map((o) => {
|
|
1554
|
+
const checked = form.disableButtons.includes(o.value);
|
|
1555
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 rounded-md p-2 hover:bg-ui-bg-subtle", children: [
|
|
1556
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1557
|
+
"input",
|
|
1558
|
+
{
|
|
1559
|
+
type: "checkbox",
|
|
1560
|
+
checked,
|
|
1561
|
+
onChange: () => toggleMulti("disableButtons", o.value),
|
|
1562
|
+
className: "h-4 w-4 rounded border-ui-border-base"
|
|
1563
|
+
}
|
|
1564
|
+
),
|
|
1565
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: o.label })
|
|
1566
|
+
] }, o.value);
|
|
1567
|
+
}) }) })
|
|
1568
|
+
] })
|
|
1569
|
+
}
|
|
1570
|
+
),
|
|
1571
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Button Color", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1572
|
+
"select",
|
|
1573
|
+
{
|
|
1574
|
+
value: form.buttonColor,
|
|
1575
|
+
onChange: (e) => setForm((p) => ({ ...p, buttonColor: e.target.value })),
|
|
1576
|
+
className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive",
|
|
1577
|
+
children: COLOR_OPTIONS.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.value, children: o.label }, o.value))
|
|
1578
|
+
}
|
|
1579
|
+
) }),
|
|
1580
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Button Shape", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1581
|
+
"select",
|
|
1582
|
+
{
|
|
1583
|
+
value: form.buttonShape,
|
|
1584
|
+
onChange: (e) => setForm((p) => ({ ...p, buttonShape: e.target.value })),
|
|
1585
|
+
className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive",
|
|
1586
|
+
children: SHAPE_OPTIONS.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.value, children: o.label }, o.value))
|
|
1587
|
+
}
|
|
1588
|
+
) }),
|
|
1589
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Button Width", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1590
|
+
"select",
|
|
1591
|
+
{
|
|
1592
|
+
value: form.buttonWidth,
|
|
1593
|
+
onChange: (e) => setForm((p) => ({ ...p, buttonWidth: e.target.value })),
|
|
1594
|
+
className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive",
|
|
1595
|
+
children: WIDTH_OPTIONS.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.value, children: o.label }, o.value))
|
|
1596
|
+
}
|
|
1597
|
+
) }),
|
|
1598
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Button Height", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1599
|
+
"select",
|
|
1600
|
+
{
|
|
1601
|
+
value: String(form.buttonHeight),
|
|
1602
|
+
onChange: (e) => setForm((p) => ({ ...p, buttonHeight: Number(e.target.value) })),
|
|
1603
|
+
className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive",
|
|
1604
|
+
children: HEIGHT_OPTIONS.map((h) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: h, children: [
|
|
1605
|
+
h,
|
|
1606
|
+
" px"
|
|
1607
|
+
] }, h))
|
|
1608
|
+
}
|
|
1609
|
+
) }),
|
|
1610
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Button Label", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1611
|
+
"select",
|
|
1612
|
+
{
|
|
1613
|
+
value: form.buttonLabel,
|
|
1614
|
+
onChange: (e) => setForm((p) => ({ ...p, buttonLabel: e.target.value })),
|
|
1615
|
+
className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive",
|
|
1616
|
+
children: LABEL_OPTIONS.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.value, children: o.label }, o.value))
|
|
1617
|
+
}
|
|
1618
|
+
) })
|
|
1619
|
+
] })
|
|
1961
1620
|
}
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
1983
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1984
|
-
"button",
|
|
1985
|
-
{
|
|
1986
|
-
type: "button",
|
|
1987
|
-
onClick: fetchStatus,
|
|
1988
|
-
className: "rounded-md border border-ui-border-base px-3 py-2 text-sm text-ui-fg-base",
|
|
1989
|
-
disabled: loading,
|
|
1990
|
-
children: loading ? "Refreshing..." : "Refresh"
|
|
1991
|
-
}
|
|
1992
|
-
)
|
|
1993
|
-
] }) }),
|
|
1994
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4", children: [
|
|
1995
|
-
error ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-600", children: error }) : null,
|
|
1996
|
-
!error && Object.keys(status).length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-ui-fg-subtle", children: loading ? "Loading reconciliation status..." : "No reconciliation data yet." }) : null,
|
|
1997
|
-
Object.keys(status).length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 text-sm text-ui-fg-base md:grid-cols-2", children: [
|
|
1998
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1999
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last run" }),
|
|
2000
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_run_at) })
|
|
2001
|
-
] }),
|
|
2002
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
2003
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last run status" }),
|
|
2004
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium capitalize", children: status.last_run_status || "—" })
|
|
2005
|
-
] }),
|
|
2006
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
2007
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last success" }),
|
|
2008
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_success_at) })
|
|
2009
|
-
] }),
|
|
2010
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
2011
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last failure" }),
|
|
2012
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_failure_at) })
|
|
2013
|
-
] }),
|
|
2014
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
2015
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Sessions checked" }),
|
|
2016
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.sessions_checked ?? 0 })
|
|
2017
|
-
] }),
|
|
2018
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
2019
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Sessions updated" }),
|
|
2020
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.sessions_updated ?? 0 })
|
|
2021
|
-
] }),
|
|
2022
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
2023
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Drift detections" }),
|
|
2024
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.drift_count ?? 0 })
|
|
2025
|
-
] }),
|
|
2026
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
2027
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last drift order" }),
|
|
2028
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.last_drift_order_id || "—" }),
|
|
2029
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-xs text-ui-fg-subtle", children: formatDate(status.last_drift_at) })
|
|
2030
|
-
] }),
|
|
2031
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 md:col-span-2", children: [
|
|
2032
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last error" }),
|
|
2033
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.last_error || "No errors recorded." })
|
|
2034
|
-
] }),
|
|
2035
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 md:col-span-2", children: [
|
|
2036
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Total runs" }),
|
|
2037
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.runs ?? 0 })
|
|
2038
|
-
] })
|
|
2039
|
-
] }) : null
|
|
1621
|
+
),
|
|
1622
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-6 rounded-md border border-ui-border-base bg-ui-bg-subtle p-4", children: [
|
|
1623
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-ui-fg-base", children: "Preview (UI only)" }),
|
|
1624
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 text-sm text-ui-fg-subtle", children: [
|
|
1625
|
+
"Color: ",
|
|
1626
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-base", children: form.buttonColor }),
|
|
1627
|
+
" · Shape:",
|
|
1628
|
+
" ",
|
|
1629
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-base", children: form.buttonShape }),
|
|
1630
|
+
" · Width:",
|
|
1631
|
+
" ",
|
|
1632
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-base", children: form.buttonWidth }),
|
|
1633
|
+
" · Height:",
|
|
1634
|
+
" ",
|
|
1635
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-fg-base", children: [
|
|
1636
|
+
form.buttonHeight,
|
|
1637
|
+
"px"
|
|
1638
|
+
] }),
|
|
1639
|
+
" · Label:",
|
|
1640
|
+
" ",
|
|
1641
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-base", children: form.buttonLabel })
|
|
2040
1642
|
] })
|
|
2041
1643
|
] })
|
|
2042
1644
|
] }) });
|
|
@@ -2056,17 +1658,13 @@ const routeModule = {
|
|
|
2056
1658
|
Component: AdvancedCardPaymentsTab,
|
|
2057
1659
|
path: "/settings/paypal/advanced-card-payments"
|
|
2058
1660
|
},
|
|
2059
|
-
{
|
|
2060
|
-
Component: PayPalAuditLogsPage,
|
|
2061
|
-
path: "/settings/paypal/audit-logs"
|
|
2062
|
-
},
|
|
2063
1661
|
{
|
|
2064
1662
|
Component: PayPalApplePayPage,
|
|
2065
1663
|
path: "/settings/paypal/apple-pay"
|
|
2066
1664
|
},
|
|
2067
1665
|
{
|
|
2068
|
-
Component:
|
|
2069
|
-
path: "/settings/paypal/
|
|
1666
|
+
Component: PayPalAuditLogsPage,
|
|
1667
|
+
path: "/settings/paypal/audit-logs"
|
|
2070
1668
|
},
|
|
2071
1669
|
{
|
|
2072
1670
|
Component: PayPalConnectionPage,
|
|
@@ -2080,13 +1678,13 @@ const routeModule = {
|
|
|
2080
1678
|
Component: PayPalPayLaterMessagingPage,
|
|
2081
1679
|
path: "/settings/paypal/pay-later-messaging"
|
|
2082
1680
|
},
|
|
2083
|
-
{
|
|
2084
|
-
Component: PayPalSettingsTab,
|
|
2085
|
-
path: "/settings/paypal/paypal-settings"
|
|
2086
|
-
},
|
|
2087
1681
|
{
|
|
2088
1682
|
Component: PayPalReconciliationStatusPage,
|
|
2089
1683
|
path: "/settings/paypal/reconciliation-status"
|
|
1684
|
+
},
|
|
1685
|
+
{
|
|
1686
|
+
Component: PayPalSettingsTab,
|
|
1687
|
+
path: "/settings/paypal/paypal-settings"
|
|
2090
1688
|
}
|
|
2091
1689
|
]
|
|
2092
1690
|
};
|