@easypayment/medusa-paypal 0.2.7 → 0.2.8
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 +752 -997
- package/.medusa/server/src/admin/index.mjs +752 -997
- 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-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/modules/paypal/service.d.ts +67 -61
- package/.medusa/server/src/modules/paypal/service.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/service.js +34 -4
- 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 +9 -9
- package/.medusa/server/src/modules/paypal/webhook-processor.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/webhook-processor.js +20 -7
- package/.medusa/server/src/modules/paypal/webhook-processor.js.map +1 -1
- package/package.json +1 -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/disputes/page.tsx +186 -259
- 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-complete/route.ts +75 -45
- package/src/jobs/paypal-reconcile.ts +21 -6
- package/src/modules/paypal/service.ts +39 -4
- package/src/modules/paypal/utils/paypal-auth.ts +32 -0
- package/src/modules/paypal/webhook-processor.ts +22 -8
- package/tsconfig.json +1 -1
|
@@ -40,6 +40,39 @@ function PayPalTabs() {
|
|
|
40
40
|
);
|
|
41
41
|
}) }) });
|
|
42
42
|
}
|
|
43
|
+
async function adminFetch$5(path, opts = {}) {
|
|
44
|
+
var _a;
|
|
45
|
+
const { method = "GET", body, query } = opts;
|
|
46
|
+
let url = path;
|
|
47
|
+
if (query && Object.keys(query).length > 0) {
|
|
48
|
+
const params = new URLSearchParams(query);
|
|
49
|
+
url = `${path}?${params.toString()}`;
|
|
50
|
+
}
|
|
51
|
+
const headers = { Accept: "application/json" };
|
|
52
|
+
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
53
|
+
if (typeof window !== "undefined") {
|
|
54
|
+
const token = (_a = window.__medusa__) == null ? void 0 : _a.token;
|
|
55
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
56
|
+
}
|
|
57
|
+
const res = await fetch(url, {
|
|
58
|
+
method,
|
|
59
|
+
headers,
|
|
60
|
+
credentials: "include",
|
|
61
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
62
|
+
});
|
|
63
|
+
const text = await res.text().catch(() => "");
|
|
64
|
+
if (!res.ok) {
|
|
65
|
+
if (res.status === 401) throw new Error("Unauthorized (401) - session may have expired. Please reload and log in again.");
|
|
66
|
+
if (res.status === 403) throw new Error("Forbidden (403) - you do not have permission to perform this action.");
|
|
67
|
+
throw new Error(text || `Request failed with status ${res.status}`);
|
|
68
|
+
}
|
|
69
|
+
if (!text) return {};
|
|
70
|
+
try {
|
|
71
|
+
return JSON.parse(text);
|
|
72
|
+
} catch {
|
|
73
|
+
return {};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
43
76
|
const DEFAULT_FORM$1 = {
|
|
44
77
|
paymentAction: "capture",
|
|
45
78
|
brandName: "PayPal",
|
|
@@ -56,17 +89,9 @@ const DEFAULT_FORM$1 = {
|
|
|
56
89
|
function mergeWithDefaults$1(saved) {
|
|
57
90
|
if (!saved) return { ...DEFAULT_FORM$1 };
|
|
58
91
|
const entries = Object.entries(saved).filter(([, value]) => value !== void 0);
|
|
59
|
-
return {
|
|
60
|
-
...DEFAULT_FORM$1,
|
|
61
|
-
...Object.fromEntries(entries)
|
|
62
|
-
};
|
|
92
|
+
return { ...DEFAULT_FORM$1, ...Object.fromEntries(entries) };
|
|
63
93
|
}
|
|
64
|
-
function SectionCard$2({
|
|
65
|
-
title,
|
|
66
|
-
description,
|
|
67
|
-
right,
|
|
68
|
-
children
|
|
69
|
-
}) {
|
|
94
|
+
function SectionCard$2({ title, description, right, children }) {
|
|
70
95
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
71
96
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4 border-b border-ui-border-base p-4", children: [
|
|
72
97
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
@@ -78,11 +103,7 @@ function SectionCard$2({
|
|
|
78
103
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children })
|
|
79
104
|
] });
|
|
80
105
|
}
|
|
81
|
-
function FieldRow$2({
|
|
82
|
-
label,
|
|
83
|
-
hint,
|
|
84
|
-
children
|
|
85
|
-
}) {
|
|
106
|
+
function FieldRow$2({ label, hint, children }) {
|
|
86
107
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-12 items-start gap-4 py-3", children: [
|
|
87
108
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-12 md:col-span-4", children: [
|
|
88
109
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-ui-fg-base", children: label }),
|
|
@@ -95,6 +116,7 @@ function AdditionalSettingsTab() {
|
|
|
95
116
|
const [form, setForm] = react.useState(() => ({ ...DEFAULT_FORM$1 }));
|
|
96
117
|
const [loading, setLoading] = react.useState(false);
|
|
97
118
|
const [saving, setSaving] = react.useState(false);
|
|
119
|
+
const [toast, setToast] = react.useState(null);
|
|
98
120
|
const didInit = react.useRef(false);
|
|
99
121
|
react.useEffect(() => {
|
|
100
122
|
if (didInit.current) return;
|
|
@@ -102,52 +124,28 @@ function AdditionalSettingsTab() {
|
|
|
102
124
|
(async () => {
|
|
103
125
|
try {
|
|
104
126
|
setLoading(true);
|
|
105
|
-
const
|
|
106
|
-
credentials: "include",
|
|
107
|
-
headers: { "Accept": "application/json" }
|
|
108
|
-
});
|
|
109
|
-
if (!r.ok) return;
|
|
110
|
-
const json = await r.json();
|
|
127
|
+
const json = await adminFetch$5("/admin/paypal/settings");
|
|
111
128
|
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
112
129
|
const saved = payload == null ? void 0 : payload.additional_settings;
|
|
113
|
-
if (saved && typeof saved === "object")
|
|
114
|
-
|
|
115
|
-
}
|
|
130
|
+
if (saved && typeof saved === "object") setForm(mergeWithDefaults$1(saved));
|
|
131
|
+
} catch {
|
|
116
132
|
} finally {
|
|
117
133
|
setLoading(false);
|
|
118
134
|
}
|
|
119
135
|
})();
|
|
120
136
|
}, []);
|
|
121
|
-
const [toast, setToast] = react.useState(null);
|
|
122
137
|
async function onSave() {
|
|
123
138
|
try {
|
|
124
139
|
setSaving(true);
|
|
125
140
|
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(() => ({}));
|
|
141
|
+
const json = await adminFetch$5("/admin/paypal/settings", { method: "POST", body: { additional_settings: form } });
|
|
142
142
|
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
143
143
|
const saved = payload == null ? void 0 : payload.additional_settings;
|
|
144
|
-
if (saved && typeof saved === "object")
|
|
145
|
-
setForm(mergeWithDefaults$1(saved));
|
|
146
|
-
}
|
|
144
|
+
if (saved && typeof saved === "object") setForm(mergeWithDefaults$1(saved));
|
|
147
145
|
setToast({ type: "success", message: "Settings saved" });
|
|
148
146
|
window.setTimeout(() => setToast(null), 2500);
|
|
149
147
|
} catch (e) {
|
|
150
|
-
setToast({ type: "error", message:
|
|
148
|
+
setToast({ type: "error", message: e instanceof Error ? e.message : "Failed to save settings" });
|
|
151
149
|
window.setTimeout(() => setToast(null), 3500);
|
|
152
150
|
} finally {
|
|
153
151
|
setSaving(false);
|
|
@@ -156,200 +154,98 @@ function AdditionalSettingsTab() {
|
|
|
156
154
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
157
155
|
/* @__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
156
|
/* @__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,
|
|
157
|
+
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
158
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
169
159
|
SectionCard$2,
|
|
170
160
|
{
|
|
171
161
|
title: "Additional Settings",
|
|
172
162
|
description: "These settings control checkout behavior, PayPal experience, and logging.",
|
|
173
163
|
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
|
|
164
|
+
/* @__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" }),
|
|
165
|
+
loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading..." }) : null
|
|
185
166
|
] }),
|
|
186
167
|
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
|
-
) }),
|
|
168
|
+
/* @__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: [
|
|
169
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "capture", children: "Capture" }),
|
|
170
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "authorize", children: "Authorize" })
|
|
171
|
+
] }) }),
|
|
172
|
+
/* @__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" }) }),
|
|
173
|
+
/* @__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: [
|
|
174
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "no_preference", children: "No Preference" }),
|
|
175
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "login", children: "Login" }),
|
|
176
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "billing", children: "Billing" })
|
|
177
|
+
] }) }),
|
|
221
178
|
/* @__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
|
-
),
|
|
179
|
+
/* @__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
180
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Require Instant Payment" })
|
|
232
181
|
] }) }),
|
|
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
|
-
)
|
|
182
|
+
/* @__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: [
|
|
183
|
+
/* @__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" }),
|
|
184
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Use PayPal Shipping Address as Billing" })
|
|
185
|
+
] }) }),
|
|
186
|
+
/* @__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: [
|
|
187
|
+
/* @__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" }),
|
|
188
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Send line item details to PayPal" })
|
|
189
|
+
] }) }),
|
|
190
|
+
/* @__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: [
|
|
191
|
+
/* @__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" }),
|
|
192
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Skip Order Review Page" })
|
|
193
|
+
] }) }),
|
|
194
|
+
/* @__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-" }) }),
|
|
195
|
+
/* @__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" }) }),
|
|
196
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "Debug log", hint: /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
197
|
+
"Log PayPal events such as Webhook, Payment, Refund. ",
|
|
198
|
+
form.logPath ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
199
|
+
"Log location: ",
|
|
200
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: form.logPath })
|
|
201
|
+
] }) : null
|
|
202
|
+
] }), children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
203
|
+
/* @__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" }),
|
|
204
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable logging" })
|
|
205
|
+
] }) })
|
|
334
206
|
] })
|
|
335
207
|
}
|
|
336
208
|
)
|
|
337
209
|
] }) });
|
|
338
210
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
}
|
|
211
|
+
async function adminFetch$4(path, opts = {}) {
|
|
212
|
+
var _a;
|
|
213
|
+
const { method = "GET", body, query } = opts;
|
|
214
|
+
let url = path;
|
|
215
|
+
if (query && Object.keys(query).length > 0) {
|
|
216
|
+
const params = new URLSearchParams(query);
|
|
217
|
+
url = `${path}?${params.toString()}`;
|
|
218
|
+
}
|
|
219
|
+
const headers = { Accept: "application/json" };
|
|
220
|
+
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
221
|
+
if (typeof window !== "undefined") {
|
|
222
|
+
const token = (_a = window.__medusa__) == null ? void 0 : _a.token;
|
|
223
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
224
|
+
}
|
|
225
|
+
const res = await fetch(url, {
|
|
226
|
+
method,
|
|
227
|
+
headers,
|
|
228
|
+
credentials: "include",
|
|
229
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
230
|
+
});
|
|
231
|
+
const text = await res.text().catch(() => "");
|
|
232
|
+
if (!res.ok) {
|
|
233
|
+
if (res.status === 401) throw new Error("Unauthorized (401) - session may have expired. Please reload and log in again.");
|
|
234
|
+
if (res.status === 403) throw new Error("Forbidden (403) - you do not have permission to perform this action.");
|
|
235
|
+
throw new Error(text || `Request failed with status ${res.status}`);
|
|
236
|
+
}
|
|
237
|
+
if (!text) return {};
|
|
238
|
+
try {
|
|
239
|
+
return JSON.parse(text);
|
|
240
|
+
} catch {
|
|
241
|
+
return {};
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const DEFAULT_FORM = { enabled: true, title: "Credit or Debit Card", disabledCards: [], threeDS: "when_required", cardSaveEnabled: false };
|
|
346
245
|
function mergeWithDefaults(saved) {
|
|
347
246
|
if (!saved) return { ...DEFAULT_FORM };
|
|
348
247
|
const entries = Object.entries(saved).filter(([, value]) => value !== void 0);
|
|
349
|
-
return {
|
|
350
|
-
...DEFAULT_FORM,
|
|
351
|
-
...Object.fromEntries(entries)
|
|
352
|
-
};
|
|
248
|
+
return { ...DEFAULT_FORM, ...Object.fromEntries(entries) };
|
|
353
249
|
}
|
|
354
250
|
const CARD_BRANDS = [
|
|
355
251
|
{ value: "visa", label: "Visa" },
|
|
@@ -361,49 +257,17 @@ const CARD_BRANDS = [
|
|
|
361
257
|
{ value: "unionpay", label: "UnionPay" }
|
|
362
258
|
];
|
|
363
259
|
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
|
-
}
|
|
260
|
+
{ value: "when_required", label: "3D Secure when required", hint: "Triggers 3DS only when the card / issuer requires it." },
|
|
261
|
+
{ value: "sli", label: "3D Secure (SCA) / liability shift (recommended)", hint: "Attempts to optimize for liability shift while remaining compliant." },
|
|
262
|
+
{ value: "always", label: "Always request 3D Secure", hint: "Forces 3DS challenge whenever possible (may reduce conversion)." }
|
|
379
263
|
];
|
|
380
|
-
function
|
|
381
|
-
return parts.filter(Boolean).join(" ");
|
|
382
|
-
}
|
|
383
|
-
function Pill$1({
|
|
384
|
-
children,
|
|
385
|
-
onRemove
|
|
386
|
-
}) {
|
|
264
|
+
function Pill$1({ children, onRemove }) {
|
|
387
265
|
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
266
|
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
|
|
267
|
+
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
268
|
] });
|
|
400
269
|
}
|
|
401
|
-
function SectionCard$1({
|
|
402
|
-
title,
|
|
403
|
-
description,
|
|
404
|
-
right,
|
|
405
|
-
children
|
|
406
|
-
}) {
|
|
270
|
+
function SectionCard$1({ title, description, right, children }) {
|
|
407
271
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
408
272
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4 border-b border-ui-border-base p-4", children: [
|
|
409
273
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
@@ -415,11 +279,7 @@ function SectionCard$1({
|
|
|
415
279
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children })
|
|
416
280
|
] });
|
|
417
281
|
}
|
|
418
|
-
function FieldRow$1({
|
|
419
|
-
label,
|
|
420
|
-
hint,
|
|
421
|
-
children
|
|
422
|
-
}) {
|
|
282
|
+
function FieldRow$1({ label, hint, children }) {
|
|
423
283
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-12 items-start gap-4 py-3", children: [
|
|
424
284
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-12 md:col-span-4", children: [
|
|
425
285
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-ui-fg-base", children: label }),
|
|
@@ -441,17 +301,11 @@ function AdvancedCardPaymentsTab() {
|
|
|
441
301
|
(async () => {
|
|
442
302
|
try {
|
|
443
303
|
setLoading(true);
|
|
444
|
-
const
|
|
445
|
-
credentials: "include",
|
|
446
|
-
headers: { "Accept": "application/json" }
|
|
447
|
-
});
|
|
448
|
-
if (!r.ok) return;
|
|
449
|
-
const json = await r.json();
|
|
304
|
+
const json = await adminFetch$4("/admin/paypal/settings");
|
|
450
305
|
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
451
306
|
const saved = payload == null ? void 0 : payload.advanced_card_payments;
|
|
452
|
-
if (saved && typeof saved === "object")
|
|
453
|
-
|
|
454
|
-
}
|
|
307
|
+
if (saved && typeof saved === "object") setForm(mergeWithDefaults(saved));
|
|
308
|
+
} catch {
|
|
455
309
|
} finally {
|
|
456
310
|
setLoading(false);
|
|
457
311
|
}
|
|
@@ -460,29 +314,15 @@ function AdvancedCardPaymentsTab() {
|
|
|
460
314
|
async function onSave() {
|
|
461
315
|
try {
|
|
462
316
|
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);
|
|
317
|
+
const json = await adminFetch$4("/admin/paypal/settings", { method: "POST", body: { advanced_card_payments: form } });
|
|
479
318
|
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
480
319
|
const saved = payload == null ? void 0 : payload.advanced_card_payments;
|
|
481
|
-
if (saved && typeof saved === "object")
|
|
482
|
-
setForm(mergeWithDefaults(saved));
|
|
483
|
-
}
|
|
320
|
+
if (saved && typeof saved === "object") setForm(mergeWithDefaults(saved));
|
|
484
321
|
setToast({ type: "success", message: "Settings saved" });
|
|
485
322
|
window.setTimeout(() => setToast(null), 2500);
|
|
323
|
+
} catch (e) {
|
|
324
|
+
setToast({ type: "error", message: (e instanceof Error ? e.message : "") || "Failed to save settings." });
|
|
325
|
+
window.setTimeout(() => setToast(null), 3500);
|
|
486
326
|
} finally {
|
|
487
327
|
setSaving(false);
|
|
488
328
|
}
|
|
@@ -491,138 +331,47 @@ function AdvancedCardPaymentsTab() {
|
|
|
491
331
|
function toggleDisabledCard(value) {
|
|
492
332
|
setForm((prev) => {
|
|
493
333
|
const exists = prev.disabledCards.includes(value);
|
|
494
|
-
return {
|
|
495
|
-
...prev,
|
|
496
|
-
disabledCards: exists ? prev.disabledCards.filter((v) => v !== value) : [...prev.disabledCards, value]
|
|
497
|
-
};
|
|
334
|
+
return { ...prev, disabledCards: exists ? prev.disabledCards.filter((v) => v !== value) : [...prev.disabledCards, value] };
|
|
498
335
|
});
|
|
499
336
|
}
|
|
500
337
|
function removeDisabledCard(value) {
|
|
501
|
-
setForm((prev) => ({
|
|
502
|
-
...prev,
|
|
503
|
-
disabledCards: prev.disabledCards.filter((v) => v !== value)
|
|
504
|
-
}));
|
|
338
|
+
setForm((prev) => ({ ...prev, disabledCards: prev.disabledCards.filter((v) => v !== value) }));
|
|
505
339
|
}
|
|
506
340
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
507
341
|
/* @__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
342
|
/* @__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,
|
|
343
|
+
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
344
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
519
345
|
SectionCard$1,
|
|
520
346
|
{
|
|
521
347
|
title: "Advanced Card Payments",
|
|
522
348
|
description: "Control card checkout settings, 3D Secure behavior, and card saving.",
|
|
523
349
|
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
|
|
350
|
+
/* @__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" }),
|
|
351
|
+
loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading..." }) : null
|
|
535
352
|
] }),
|
|
536
353
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-ui-border-base", children: [
|
|
537
354
|
/* @__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
|
-
),
|
|
355
|
+
/* @__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
356
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable Advanced Credit/Debit Card" })
|
|
548
357
|
] }) }),
|
|
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
|
-
),
|
|
358
|
+
/* @__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" }) }),
|
|
359
|
+
/* @__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: [
|
|
360
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: form.disabledCards.length ? form.disabledCards.map((v) => {
|
|
361
|
+
var _a2;
|
|
362
|
+
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);
|
|
363
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "No card brands disabled." }) }),
|
|
364
|
+
/* @__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: [
|
|
365
|
+
/* @__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" }),
|
|
366
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: b.label })
|
|
367
|
+
] }, b.value)) }) })
|
|
368
|
+
] }) }),
|
|
369
|
+
/* @__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: [
|
|
370
|
+
/* @__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)) }),
|
|
371
|
+
((_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
|
|
372
|
+
] }) }),
|
|
616
373
|
/* @__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
|
-
),
|
|
374
|
+
/* @__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
375
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable card saving at checkout" })
|
|
627
376
|
] }) })
|
|
628
377
|
] })
|
|
@@ -630,305 +379,34 @@ function AdvancedCardPaymentsTab() {
|
|
|
630
379
|
)
|
|
631
380
|
] }) });
|
|
632
381
|
}
|
|
633
|
-
function
|
|
634
|
-
|
|
635
|
-
|
|
382
|
+
function PayPalApplePayPage() {
|
|
383
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
384
|
+
}
|
|
385
|
+
const config = adminSdk.defineRouteConfig({
|
|
386
|
+
label: "PayPal Connection",
|
|
387
|
+
hide: true
|
|
388
|
+
});
|
|
389
|
+
if (typeof window !== "undefined") {
|
|
390
|
+
const preloadHref = "https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js";
|
|
391
|
+
const existingPreload = document.head.querySelector(
|
|
392
|
+
`link[rel="preload"][href="${preloadHref}"]`
|
|
393
|
+
);
|
|
394
|
+
if (!existingPreload) {
|
|
395
|
+
const preloadLink = document.createElement("link");
|
|
396
|
+
preloadLink.rel = "preload";
|
|
397
|
+
preloadLink.href = preloadHref;
|
|
398
|
+
preloadLink.as = "script";
|
|
399
|
+
document.head.appendChild(preloadLink);
|
|
636
400
|
}
|
|
637
|
-
const
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
const [error, setError] = react.useState(null);
|
|
647
|
-
const fetchLogs = react.useCallback(async () => {
|
|
648
|
-
try {
|
|
649
|
-
setLoading(true);
|
|
650
|
-
setError(null);
|
|
651
|
-
const response = await fetch("/admin/paypal/audit-logs?limit=50", {
|
|
652
|
-
credentials: "include",
|
|
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) || []);
|
|
663
|
-
} catch (fetchError) {
|
|
664
|
-
setError((fetchError == null ? void 0 : fetchError.message) || "Failed to load audit logs.");
|
|
665
|
-
setLogs([]);
|
|
666
|
-
} finally {
|
|
667
|
-
setLoading(false);
|
|
668
|
-
}
|
|
669
|
-
}, []);
|
|
670
|
-
react.useEffect(() => {
|
|
671
|
-
fetchLogs();
|
|
672
|
-
}, [fetchLogs]);
|
|
673
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
674
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
675
|
-
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Audit Logs" }),
|
|
676
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-ui-fg-subtle", children: "Track administrative changes and credential events for PayPal configuration." })
|
|
677
|
-
] }),
|
|
678
|
-
/* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
|
|
679
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
680
|
-
/* @__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
|
-
/* @__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
|
-
)
|
|
692
|
-
] }) }),
|
|
693
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4", children: [
|
|
694
|
-
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,
|
|
695
|
-
!error && logs.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-ui-fg-subtle", children: loading ? "Loading audit logs..." : "No audit log entries found yet." }) : null,
|
|
696
|
-
logs.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full text-left text-sm", children: [
|
|
697
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "text-ui-fg-muted", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
698
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "pb-2 pr-4 font-medium", children: "Timestamp" }),
|
|
699
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "pb-2 pr-4 font-medium", children: "Event" }),
|
|
700
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "pb-2 font-medium", children: "Details" })
|
|
701
|
-
] }) }),
|
|
702
|
-
/* @__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$2(entry.created_at) || "—" }),
|
|
704
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-3 pr-4 text-ui-fg-base", children: entry.event_type || "—" }),
|
|
705
|
-
/* @__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
|
-
] }, entry.id)) })
|
|
707
|
-
] }) }) : null
|
|
708
|
-
] })
|
|
709
|
-
] })
|
|
710
|
-
] }) });
|
|
711
|
-
}
|
|
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
|
-
const config = adminSdk.defineRouteConfig({
|
|
908
|
-
label: "PayPal Connection",
|
|
909
|
-
hide: true
|
|
910
|
-
});
|
|
911
|
-
if (typeof window !== "undefined") {
|
|
912
|
-
const preloadHref = "https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js";
|
|
913
|
-
const existingPreload = document.head.querySelector(
|
|
914
|
-
`link[rel="preload"][href="${preloadHref}"]`
|
|
915
|
-
);
|
|
916
|
-
if (!existingPreload) {
|
|
917
|
-
const preloadLink = document.createElement("link");
|
|
918
|
-
preloadLink.rel = "preload";
|
|
919
|
-
preloadLink.href = preloadHref;
|
|
920
|
-
preloadLink.as = "script";
|
|
921
|
-
document.head.appendChild(preloadLink);
|
|
922
|
-
}
|
|
923
|
-
const existingScript = document.getElementById(
|
|
924
|
-
"paypal-partner-js"
|
|
925
|
-
);
|
|
926
|
-
if (!existingScript) {
|
|
927
|
-
const ppScript = document.createElement("script");
|
|
928
|
-
ppScript.id = "paypal-partner-js";
|
|
929
|
-
ppScript.src = preloadHref;
|
|
930
|
-
ppScript.async = true;
|
|
931
|
-
document.head.appendChild(ppScript);
|
|
401
|
+
const existingScript = document.getElementById(
|
|
402
|
+
"paypal-partner-js"
|
|
403
|
+
);
|
|
404
|
+
if (!existingScript) {
|
|
405
|
+
const ppScript = document.createElement("script");
|
|
406
|
+
ppScript.id = "paypal-partner-js";
|
|
407
|
+
ppScript.src = preloadHref;
|
|
408
|
+
ppScript.async = true;
|
|
409
|
+
document.head.appendChild(ppScript);
|
|
932
410
|
}
|
|
933
411
|
}
|
|
934
412
|
const SERVICE_URL = "/admin/paypal/onboarding-link";
|
|
@@ -1444,55 +922,449 @@ function PayPalConnectionPage() {
|
|
|
1444
922
|
}
|
|
1445
923
|
)
|
|
1446
924
|
] }),
|
|
1447
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md:col-span-2 flex items-center gap-2 mt-2", children: [
|
|
1448
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1449
|
-
"button",
|
|
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
|
-
)
|
|
925
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md:col-span-2 flex items-center gap-2 mt-2", children: [
|
|
926
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
927
|
+
"button",
|
|
928
|
+
{
|
|
929
|
+
type: "button",
|
|
930
|
+
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",
|
|
931
|
+
onClick: () => setShowManual(false),
|
|
932
|
+
disabled: onboardingInProgress,
|
|
933
|
+
children: "Cancel"
|
|
934
|
+
}
|
|
935
|
+
),
|
|
936
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
937
|
+
"button",
|
|
938
|
+
{
|
|
939
|
+
type: "button",
|
|
940
|
+
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",
|
|
941
|
+
disabled: !canSaveManual || onboardingInProgress,
|
|
942
|
+
onClick: handleSaveManual,
|
|
943
|
+
children: "Save credentials"
|
|
944
|
+
}
|
|
945
|
+
)
|
|
946
|
+
] })
|
|
947
|
+
] }) })
|
|
948
|
+
] }) })
|
|
949
|
+
] }),
|
|
950
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { children: `
|
|
951
|
+
.loader {
|
|
952
|
+
border: 3px solid #f3f3f3;
|
|
953
|
+
border-top: 3px solid #0070ba;
|
|
954
|
+
border-radius: 50%;
|
|
955
|
+
width: 18px;
|
|
956
|
+
height: 18px;
|
|
957
|
+
animation: spin 1s linear infinite;
|
|
958
|
+
display: inline-block;
|
|
959
|
+
vertical-align: middle;
|
|
960
|
+
margin-right: 8px;
|
|
961
|
+
}
|
|
962
|
+
@keyframes spin {
|
|
963
|
+
0% { transform: rotate(0deg); }
|
|
964
|
+
100% { transform: rotate(360deg); }
|
|
965
|
+
}
|
|
966
|
+
` })
|
|
967
|
+
] });
|
|
968
|
+
}
|
|
969
|
+
async function adminFetch$3(path, opts = {}) {
|
|
970
|
+
var _a;
|
|
971
|
+
const { method = "GET", body, query } = opts;
|
|
972
|
+
let url = path;
|
|
973
|
+
if (query && Object.keys(query).length > 0) {
|
|
974
|
+
const params = new URLSearchParams(query);
|
|
975
|
+
url = `${path}?${params.toString()}`;
|
|
976
|
+
}
|
|
977
|
+
const headers = { Accept: "application/json" };
|
|
978
|
+
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
979
|
+
if (typeof window !== "undefined") {
|
|
980
|
+
const token = (_a = window.__medusa__) == null ? void 0 : _a.token;
|
|
981
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
982
|
+
}
|
|
983
|
+
const res = await fetch(url, {
|
|
984
|
+
method,
|
|
985
|
+
headers,
|
|
986
|
+
credentials: "include",
|
|
987
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
988
|
+
});
|
|
989
|
+
const text = await res.text().catch(() => "");
|
|
990
|
+
if (!res.ok) {
|
|
991
|
+
if (res.status === 401) throw new Error("Unauthorized (401) - session may have expired. Please reload and log in again.");
|
|
992
|
+
if (res.status === 403) throw new Error("Forbidden (403) - you do not have permission to perform this action.");
|
|
993
|
+
throw new Error(text || `Request failed with status ${res.status}`);
|
|
994
|
+
}
|
|
995
|
+
if (!text) return {};
|
|
996
|
+
try {
|
|
997
|
+
return JSON.parse(text);
|
|
998
|
+
} catch {
|
|
999
|
+
return {};
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
const EMPTY_FILTERS = { dispute_id: "", status: "", order_id: "", cart_id: "" };
|
|
1003
|
+
function formatDate$2(value) {
|
|
1004
|
+
if (!value) return "";
|
|
1005
|
+
const parsed = new Date(value);
|
|
1006
|
+
if (Number.isNaN(parsed.getTime())) return value;
|
|
1007
|
+
return parsed.toLocaleString();
|
|
1008
|
+
}
|
|
1009
|
+
function PayPalDisputesPage() {
|
|
1010
|
+
const [filters, setFilters] = react.useState({ ...EMPTY_FILTERS });
|
|
1011
|
+
const [disputes, setDisputes] = react.useState([]);
|
|
1012
|
+
const [loading, setLoading] = react.useState(false);
|
|
1013
|
+
const [error, setError] = react.useState(null);
|
|
1014
|
+
const queryString = react.useMemo(() => {
|
|
1015
|
+
const params = new URLSearchParams();
|
|
1016
|
+
Object.entries(filters).forEach(([key, value]) => {
|
|
1017
|
+
if (value.trim()) params.set(key, value.trim());
|
|
1018
|
+
});
|
|
1019
|
+
const qs = params.toString();
|
|
1020
|
+
return qs ? `?${qs}` : "";
|
|
1021
|
+
}, [filters]);
|
|
1022
|
+
const fetchDisputes = react.useCallback(async (source) => {
|
|
1023
|
+
try {
|
|
1024
|
+
setLoading(true);
|
|
1025
|
+
setError(null);
|
|
1026
|
+
const query = {};
|
|
1027
|
+
Object.entries(source).forEach(([key, value]) => {
|
|
1028
|
+
if (value.trim()) query[key] = value.trim();
|
|
1029
|
+
});
|
|
1030
|
+
const json = await adminFetch$3("/admin/paypal/disputes", { query });
|
|
1031
|
+
setDisputes((json == null ? void 0 : json.disputes) ?? []);
|
|
1032
|
+
} catch (fetchError) {
|
|
1033
|
+
setError(fetchError instanceof Error ? fetchError.message : "Failed to load disputes");
|
|
1034
|
+
setDisputes([]);
|
|
1035
|
+
} finally {
|
|
1036
|
+
setLoading(false);
|
|
1037
|
+
}
|
|
1038
|
+
}, []);
|
|
1039
|
+
react.useEffect(() => {
|
|
1040
|
+
fetchDisputes(EMPTY_FILTERS);
|
|
1041
|
+
}, [fetchDisputes]);
|
|
1042
|
+
const onSubmit = (event) => {
|
|
1043
|
+
event.preventDefault();
|
|
1044
|
+
fetchDisputes(filters);
|
|
1045
|
+
};
|
|
1046
|
+
const onReset = () => {
|
|
1047
|
+
setFilters({ ...EMPTY_FILTERS });
|
|
1048
|
+
fetchDisputes(EMPTY_FILTERS);
|
|
1049
|
+
};
|
|
1050
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
1051
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1052
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Disputes" }),
|
|
1053
|
+
/* @__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." })
|
|
1054
|
+
] }),
|
|
1055
|
+
/* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
|
|
1056
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
1057
|
+
/* @__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" }) }),
|
|
1058
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit, className: "flex flex-col gap-4", children: [
|
|
1059
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-4", children: [
|
|
1060
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
|
|
1061
|
+
"Dispute ID",
|
|
1062
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base", value: filters.dispute_id, onChange: (e) => setFilters((p) => ({ ...p, dispute_id: e.target.value })), placeholder: "PP-D-123" })
|
|
1063
|
+
] }),
|
|
1064
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
|
|
1065
|
+
"Status",
|
|
1066
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base", value: filters.status, onChange: (e) => setFilters((p) => ({ ...p, status: e.target.value })), placeholder: "OPEN" })
|
|
1067
|
+
] }),
|
|
1068
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
|
|
1069
|
+
"Order ID",
|
|
1070
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base", value: filters.order_id, onChange: (e) => setFilters((p) => ({ ...p, order_id: e.target.value })), placeholder: "order_..." })
|
|
1071
|
+
] }),
|
|
1072
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
|
|
1073
|
+
"Cart ID",
|
|
1074
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base", value: filters.cart_id, onChange: (e) => setFilters((p) => ({ ...p, cart_id: e.target.value })), placeholder: "cart_..." })
|
|
1075
|
+
] })
|
|
1076
|
+
] }),
|
|
1077
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-3", children: [
|
|
1078
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", className: "rounded-md bg-ui-fg-base px-4 py-2 text-sm font-medium text-ui-bg-base", disabled: loading, children: loading ? "Loading..." : "Apply filters" }),
|
|
1079
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "rounded-md border border-ui-border-base px-4 py-2 text-sm text-ui-fg-base", onClick: onReset, disabled: loading, children: "Reset" }),
|
|
1080
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-ui-fg-subtle", children: [
|
|
1081
|
+
"Showing ",
|
|
1082
|
+
disputes.length,
|
|
1083
|
+
" dispute",
|
|
1084
|
+
disputes.length === 1 ? "" : "s",
|
|
1085
|
+
queryString ? " (filtered)" : ""
|
|
1086
|
+
] })
|
|
1087
|
+
] })
|
|
1088
|
+
] }) })
|
|
1089
|
+
] }),
|
|
1090
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
1091
|
+
/* @__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" }) }),
|
|
1092
|
+
/* @__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: [
|
|
1093
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "text-left text-ui-fg-subtle", children: [
|
|
1094
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Dispute" }),
|
|
1095
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Status" }),
|
|
1096
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Reason" }),
|
|
1097
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Stage" }),
|
|
1098
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Amount" }),
|
|
1099
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Order" }),
|
|
1100
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Cart" }),
|
|
1101
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Updated" })
|
|
1102
|
+
] }) }),
|
|
1103
|
+
/* @__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: [
|
|
1104
|
+
/* @__PURE__ */ jsxRuntime.jsxs("td", { className: "px-4 py-3", children: [
|
|
1105
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-ui-fg-base", children: dispute.dispute_id }),
|
|
1106
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-ui-fg-subtle", children: dispute.transaction_id || "No transaction" })
|
|
1107
|
+
] }),
|
|
1108
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.status || "Unknown" }),
|
|
1109
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.reason || "-" }),
|
|
1110
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.stage || "-" }),
|
|
1111
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.amount ? `${dispute.amount} ${dispute.currency_code || ""}` : "-" }),
|
|
1112
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.order_id || "-" }),
|
|
1113
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.cart_id || "-" }),
|
|
1114
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 text-ui-fg-subtle", children: formatDate$2(dispute.updated_at || dispute.created_at) })
|
|
1115
|
+
] }, dispute.id)) })
|
|
1116
|
+
] }) }),
|
|
1117
|
+
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
|
|
1118
|
+
] })
|
|
1119
|
+
] }) });
|
|
1120
|
+
}
|
|
1121
|
+
async function adminFetch$2(path, opts = {}) {
|
|
1122
|
+
var _a;
|
|
1123
|
+
const { method = "GET", body, query } = opts;
|
|
1124
|
+
let url = path;
|
|
1125
|
+
if (query && Object.keys(query).length > 0) {
|
|
1126
|
+
const params = new URLSearchParams(query);
|
|
1127
|
+
url = `${path}?${params.toString()}`;
|
|
1128
|
+
}
|
|
1129
|
+
const headers = { Accept: "application/json" };
|
|
1130
|
+
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
1131
|
+
if (typeof window !== "undefined") {
|
|
1132
|
+
const token = (_a = window.__medusa__) == null ? void 0 : _a.token;
|
|
1133
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
1134
|
+
}
|
|
1135
|
+
const res = await fetch(url, {
|
|
1136
|
+
method,
|
|
1137
|
+
headers,
|
|
1138
|
+
credentials: "include",
|
|
1139
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
1140
|
+
});
|
|
1141
|
+
const text = await res.text().catch(() => "");
|
|
1142
|
+
if (!res.ok) {
|
|
1143
|
+
if (res.status === 401) throw new Error("Unauthorized (401) - session may have expired. Please reload and log in again.");
|
|
1144
|
+
if (res.status === 403) throw new Error("Forbidden (403) - you do not have permission to perform this action.");
|
|
1145
|
+
throw new Error(text || `Request failed with status ${res.status}`);
|
|
1146
|
+
}
|
|
1147
|
+
if (!text) return {};
|
|
1148
|
+
try {
|
|
1149
|
+
return JSON.parse(text);
|
|
1150
|
+
} catch {
|
|
1151
|
+
return {};
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
function formatDate$1(value) {
|
|
1155
|
+
if (!value) return "";
|
|
1156
|
+
const parsed = new Date(value);
|
|
1157
|
+
if (Number.isNaN(parsed.getTime())) return value;
|
|
1158
|
+
return parsed.toLocaleString();
|
|
1159
|
+
}
|
|
1160
|
+
function PayPalAuditLogsPage() {
|
|
1161
|
+
const [logs, setLogs] = react.useState([]);
|
|
1162
|
+
const [loading, setLoading] = react.useState(false);
|
|
1163
|
+
const [error, setError] = react.useState(null);
|
|
1164
|
+
const fetchLogs = react.useCallback(async () => {
|
|
1165
|
+
try {
|
|
1166
|
+
setLoading(true);
|
|
1167
|
+
setError(null);
|
|
1168
|
+
const data = await adminFetch$2("/admin/paypal/audit-logs", { query: { limit: "50" } });
|
|
1169
|
+
setLogs((data == null ? void 0 : data.logs) ?? []);
|
|
1170
|
+
} catch (fetchError) {
|
|
1171
|
+
setError(fetchError instanceof Error ? fetchError.message : "Failed to load audit logs.");
|
|
1172
|
+
setLogs([]);
|
|
1173
|
+
} finally {
|
|
1174
|
+
setLoading(false);
|
|
1175
|
+
}
|
|
1176
|
+
}, []);
|
|
1177
|
+
react.useEffect(() => {
|
|
1178
|
+
fetchLogs();
|
|
1179
|
+
}, [fetchLogs]);
|
|
1180
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
1181
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1182
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Audit Logs" }),
|
|
1183
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-ui-fg-subtle", children: "Track administrative changes and credential events for PayPal configuration." })
|
|
1184
|
+
] }),
|
|
1185
|
+
/* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
|
|
1186
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
1187
|
+
/* @__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: [
|
|
1188
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Latest events" }),
|
|
1189
|
+
/* @__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" })
|
|
1190
|
+
] }) }),
|
|
1191
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4", children: [
|
|
1192
|
+
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,
|
|
1193
|
+
!error && logs.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-ui-fg-subtle", children: loading ? "Loading audit logs..." : "No audit log entries found yet." }) : null,
|
|
1194
|
+
logs.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full text-left text-sm", children: [
|
|
1195
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "text-ui-fg-muted", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
1196
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "pb-2 pr-4 font-medium", children: "Timestamp" }),
|
|
1197
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "pb-2 pr-4 font-medium", children: "Event" }),
|
|
1198
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "pb-2 font-medium", children: "Details" })
|
|
1199
|
+
] }) }),
|
|
1200
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: logs.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-t border-ui-border-base", children: [
|
|
1201
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-3 pr-4 text-ui-fg-base", children: formatDate$1(entry.created_at) || "—" }),
|
|
1202
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-3 pr-4 text-ui-fg-base", children: entry.event_type || "—" }),
|
|
1203
|
+
/* @__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) }) })
|
|
1204
|
+
] }, entry.id)) })
|
|
1205
|
+
] }) }) : null
|
|
1206
|
+
] })
|
|
1207
|
+
] })
|
|
1208
|
+
] }) });
|
|
1209
|
+
}
|
|
1210
|
+
function PayPalGooglePayPage() {
|
|
1211
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
1212
|
+
}
|
|
1213
|
+
function PayPalPayLaterMessagingPage() {
|
|
1214
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
1215
|
+
}
|
|
1216
|
+
async function adminFetch$1(path, opts = {}) {
|
|
1217
|
+
var _a;
|
|
1218
|
+
const { method = "GET", body, query } = opts;
|
|
1219
|
+
let url = path;
|
|
1220
|
+
if (query && Object.keys(query).length > 0) {
|
|
1221
|
+
const params = new URLSearchParams(query);
|
|
1222
|
+
url = `${path}?${params.toString()}`;
|
|
1223
|
+
}
|
|
1224
|
+
const headers = { Accept: "application/json" };
|
|
1225
|
+
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
1226
|
+
if (typeof window !== "undefined") {
|
|
1227
|
+
const token = (_a = window.__medusa__) == null ? void 0 : _a.token;
|
|
1228
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
1229
|
+
}
|
|
1230
|
+
const res = await fetch(url, {
|
|
1231
|
+
method,
|
|
1232
|
+
headers,
|
|
1233
|
+
credentials: "include",
|
|
1234
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
1235
|
+
});
|
|
1236
|
+
const text = await res.text().catch(() => "");
|
|
1237
|
+
if (!res.ok) {
|
|
1238
|
+
if (res.status === 401) throw new Error("Unauthorized (401) - session may have expired. Please reload and log in again.");
|
|
1239
|
+
if (res.status === 403) throw new Error("Forbidden (403) - you do not have permission to perform this action.");
|
|
1240
|
+
throw new Error(text || `Request failed with status ${res.status}`);
|
|
1241
|
+
}
|
|
1242
|
+
if (!text) return {};
|
|
1243
|
+
try {
|
|
1244
|
+
return JSON.parse(text);
|
|
1245
|
+
} catch {
|
|
1246
|
+
return {};
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
function formatDate(value) {
|
|
1250
|
+
if (!value) return "—";
|
|
1251
|
+
const parsed = new Date(value);
|
|
1252
|
+
if (Number.isNaN(parsed.getTime())) return value;
|
|
1253
|
+
return parsed.toLocaleString();
|
|
1254
|
+
}
|
|
1255
|
+
function PayPalReconciliationStatusPage() {
|
|
1256
|
+
const [status, setStatus] = react.useState({});
|
|
1257
|
+
const [loading, setLoading] = react.useState(false);
|
|
1258
|
+
const [error, setError] = react.useState(null);
|
|
1259
|
+
const fetchStatus = react.useCallback(async () => {
|
|
1260
|
+
try {
|
|
1261
|
+
setLoading(true);
|
|
1262
|
+
setError(null);
|
|
1263
|
+
const data = await adminFetch$1("/admin/paypal/reconciliation-status");
|
|
1264
|
+
setStatus((data == null ? void 0 : data.status) ?? {});
|
|
1265
|
+
} catch (fetchError) {
|
|
1266
|
+
setError(fetchError instanceof Error ? fetchError.message : "Failed to load reconciliation status.");
|
|
1267
|
+
setStatus({});
|
|
1268
|
+
} finally {
|
|
1269
|
+
setLoading(false);
|
|
1270
|
+
}
|
|
1271
|
+
}, []);
|
|
1272
|
+
react.useEffect(() => {
|
|
1273
|
+
fetchStatus();
|
|
1274
|
+
}, [fetchStatus]);
|
|
1275
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
1276
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1277
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Reconciliation Status" }),
|
|
1278
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-ui-fg-subtle", children: "Monitor reconciliation health and drift detection for PayPal payment sessions." })
|
|
1279
|
+
] }),
|
|
1280
|
+
/* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
|
|
1281
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
1282
|
+
/* @__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: [
|
|
1283
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Latest reconciliation run" }),
|
|
1284
|
+
/* @__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" })
|
|
1285
|
+
] }) }),
|
|
1286
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4", children: [
|
|
1287
|
+
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,
|
|
1288
|
+
!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,
|
|
1289
|
+
Object.keys(status).length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 text-sm text-ui-fg-base md:grid-cols-2", children: [
|
|
1290
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1291
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last run" }),
|
|
1292
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_run_at) })
|
|
1293
|
+
] }),
|
|
1294
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1295
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last run status" }),
|
|
1296
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium capitalize", children: status.last_run_status || "—" })
|
|
1297
|
+
] }),
|
|
1298
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1299
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last success" }),
|
|
1300
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_success_at) })
|
|
1301
|
+
] }),
|
|
1302
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1303
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last failure" }),
|
|
1304
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_failure_at) })
|
|
1305
|
+
] }),
|
|
1306
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1307
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Sessions checked" }),
|
|
1308
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.sessions_checked ?? 0 })
|
|
1309
|
+
] }),
|
|
1310
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1311
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Sessions updated" }),
|
|
1312
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.sessions_updated ?? 0 })
|
|
1313
|
+
] }),
|
|
1314
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1315
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Drift detections" }),
|
|
1316
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.drift_count ?? 0 })
|
|
1317
|
+
] }),
|
|
1318
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1319
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last drift order" }),
|
|
1320
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.last_drift_order_id || "—" }),
|
|
1321
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-xs text-ui-fg-subtle", children: formatDate(status.last_drift_at) })
|
|
1322
|
+
] }),
|
|
1323
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 md:col-span-2", children: [
|
|
1324
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last error" }),
|
|
1325
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.last_error || "No errors recorded." })
|
|
1326
|
+
] }),
|
|
1327
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 md:col-span-2", children: [
|
|
1328
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Total runs" }),
|
|
1329
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.runs ?? 0 })
|
|
1468
1330
|
] })
|
|
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 });
|
|
1331
|
+
] }) : null
|
|
1332
|
+
] })
|
|
1333
|
+
] })
|
|
1334
|
+
] }) });
|
|
1493
1335
|
}
|
|
1494
|
-
function
|
|
1495
|
-
|
|
1336
|
+
async function adminFetch(path, opts = {}) {
|
|
1337
|
+
var _a;
|
|
1338
|
+
const { method = "GET", body, query } = opts;
|
|
1339
|
+
let url = path;
|
|
1340
|
+
if (query && Object.keys(query).length > 0) {
|
|
1341
|
+
const params = new URLSearchParams(query);
|
|
1342
|
+
url = `${path}?${params.toString()}`;
|
|
1343
|
+
}
|
|
1344
|
+
const headers = { Accept: "application/json" };
|
|
1345
|
+
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
1346
|
+
if (typeof window !== "undefined") {
|
|
1347
|
+
const token = (_a = window.__medusa__) == null ? void 0 : _a.token;
|
|
1348
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
1349
|
+
}
|
|
1350
|
+
const res = await fetch(url, {
|
|
1351
|
+
method,
|
|
1352
|
+
headers,
|
|
1353
|
+
credentials: "include",
|
|
1354
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
1355
|
+
});
|
|
1356
|
+
const text = await res.text().catch(() => "");
|
|
1357
|
+
if (!res.ok) {
|
|
1358
|
+
if (res.status === 401) throw new Error("Unauthorized (401) - session may have expired. Please reload and log in again.");
|
|
1359
|
+
if (res.status === 403) throw new Error("Forbidden (403) - you do not have permission to perform this action.");
|
|
1360
|
+
throw new Error(text || `Request failed with status ${res.status}`);
|
|
1361
|
+
}
|
|
1362
|
+
if (!text) return {};
|
|
1363
|
+
try {
|
|
1364
|
+
return JSON.parse(text);
|
|
1365
|
+
} catch {
|
|
1366
|
+
return {};
|
|
1367
|
+
}
|
|
1496
1368
|
}
|
|
1497
1369
|
const DISPLAY_LOCATION_OPTIONS = [
|
|
1498
1370
|
{ value: "product", label: "Product Page" },
|
|
@@ -1605,7 +1477,7 @@ function PayPalSettingsTab() {
|
|
|
1605
1477
|
const [form, setForm] = react.useState({
|
|
1606
1478
|
enabled: true,
|
|
1607
1479
|
title: "PayPal",
|
|
1608
|
-
description: "Pay via PayPal; you can pay with your credit card if you don
|
|
1480
|
+
description: "Pay via PayPal; you can pay with your credit card if you don't have a PayPal account",
|
|
1609
1481
|
displayOn: ["product", "cart", "express", "mini_cart"],
|
|
1610
1482
|
disableButtons: [],
|
|
1611
1483
|
buttonColor: "gold",
|
|
@@ -1624,12 +1496,9 @@ function PayPalSettingsTab() {
|
|
|
1624
1496
|
(async () => {
|
|
1625
1497
|
try {
|
|
1626
1498
|
setLoading(true);
|
|
1627
|
-
const
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
});
|
|
1631
|
-
if (!r.ok) return;
|
|
1632
|
-
const json = await r.json();
|
|
1499
|
+
const json = await adminFetch(
|
|
1500
|
+
"/admin/paypal/settings"
|
|
1501
|
+
);
|
|
1633
1502
|
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
1634
1503
|
const saved = payload == null ? void 0 : payload.paypal_settings;
|
|
1635
1504
|
if (saved && typeof saved === "object") {
|
|
@@ -1639,6 +1508,7 @@ function PayPalSettingsTab() {
|
|
|
1639
1508
|
disableButtons: filterHiddenDisableButtons(saved.disableButtons)
|
|
1640
1509
|
}));
|
|
1641
1510
|
}
|
|
1511
|
+
} catch {
|
|
1642
1512
|
} finally {
|
|
1643
1513
|
setLoading(false);
|
|
1644
1514
|
}
|
|
@@ -1651,22 +1521,13 @@ function PayPalSettingsTab() {
|
|
|
1651
1521
|
...form,
|
|
1652
1522
|
disableButtons: filterHiddenDisableButtons(form.disableButtons)
|
|
1653
1523
|
};
|
|
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);
|
|
1524
|
+
const json = await adminFetch(
|
|
1525
|
+
"/admin/paypal/settings",
|
|
1526
|
+
{
|
|
1527
|
+
method: "POST",
|
|
1528
|
+
body: { paypal_settings: cleaned }
|
|
1529
|
+
}
|
|
1530
|
+
);
|
|
1670
1531
|
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
1671
1532
|
const saved = payload == null ? void 0 : payload.paypal_settings;
|
|
1672
1533
|
if (saved && typeof saved === "object") {
|
|
@@ -1678,6 +1539,12 @@ function PayPalSettingsTab() {
|
|
|
1678
1539
|
}
|
|
1679
1540
|
setToast({ type: "success", message: "Settings saved" });
|
|
1680
1541
|
window.setTimeout(() => setToast(null), 2500);
|
|
1542
|
+
} catch (e) {
|
|
1543
|
+
setToast({
|
|
1544
|
+
type: "error",
|
|
1545
|
+
message: (e instanceof Error ? e.message : "") || "Failed to save settings."
|
|
1546
|
+
});
|
|
1547
|
+
window.setTimeout(() => setToast(null), 3500);
|
|
1681
1548
|
} finally {
|
|
1682
1549
|
setSaving(false);
|
|
1683
1550
|
}
|
|
@@ -1817,226 +1684,114 @@ function PayPalSettingsTab() {
|
|
|
1817
1684
|
] })
|
|
1818
1685
|
}
|
|
1819
1686
|
),
|
|
1820
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1687
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1821
1688
|
SectionCard,
|
|
1822
1689
|
{
|
|
1823
1690
|
title: "Button Appearance",
|
|
1824
1691
|
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.");
|
|
1692
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-ui-border-base", children: [
|
|
1693
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1694
|
+
FieldRow,
|
|
1695
|
+
{
|
|
1696
|
+
label: "Disable Specific Payment Buttons",
|
|
1697
|
+
hint: "Hide individual funding sources (ex: Card, Venmo).",
|
|
1698
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
1699
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
1700
|
+
filterHiddenDisableButtons(form.disableButtons).map((v) => {
|
|
1701
|
+
const opt = VISIBLE_DISABLE_BUTTON_OPTIONS.find((o) => o.value === v);
|
|
1702
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Pill, { onRemove: () => removeMulti("disableButtons", v), children: (opt == null ? void 0 : opt.label) ?? v }, v);
|
|
1703
|
+
}),
|
|
1704
|
+
filterHiddenDisableButtons(form.disableButtons).length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "No buttons disabled." }) : null
|
|
1705
|
+
] }),
|
|
1706
|
+
/* @__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) => {
|
|
1707
|
+
const checked = form.disableButtons.includes(o.value);
|
|
1708
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 rounded-md p-2 hover:bg-ui-bg-subtle", children: [
|
|
1709
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1710
|
+
"input",
|
|
1711
|
+
{
|
|
1712
|
+
type: "checkbox",
|
|
1713
|
+
checked,
|
|
1714
|
+
onChange: () => toggleMulti("disableButtons", o.value),
|
|
1715
|
+
className: "h-4 w-4 rounded border-ui-border-base"
|
|
1716
|
+
}
|
|
1717
|
+
),
|
|
1718
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: o.label })
|
|
1719
|
+
] }, o.value);
|
|
1720
|
+
}) }) })
|
|
1721
|
+
] })
|
|
1722
|
+
}
|
|
1723
|
+
),
|
|
1724
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Button Color", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1725
|
+
"select",
|
|
1726
|
+
{
|
|
1727
|
+
value: form.buttonColor,
|
|
1728
|
+
onChange: (e) => setForm((p) => ({ ...p, buttonColor: e.target.value })),
|
|
1729
|
+
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",
|
|
1730
|
+
children: COLOR_OPTIONS.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.value, children: o.label }, o.value))
|
|
1731
|
+
}
|
|
1732
|
+
) }),
|
|
1733
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Button Shape", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1734
|
+
"select",
|
|
1735
|
+
{
|
|
1736
|
+
value: form.buttonShape,
|
|
1737
|
+
onChange: (e) => setForm((p) => ({ ...p, buttonShape: e.target.value })),
|
|
1738
|
+
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",
|
|
1739
|
+
children: SHAPE_OPTIONS.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.value, children: o.label }, o.value))
|
|
1740
|
+
}
|
|
1741
|
+
) }),
|
|
1742
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Button Width", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1743
|
+
"select",
|
|
1744
|
+
{
|
|
1745
|
+
value: form.buttonWidth,
|
|
1746
|
+
onChange: (e) => setForm((p) => ({ ...p, buttonWidth: e.target.value })),
|
|
1747
|
+
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",
|
|
1748
|
+
children: WIDTH_OPTIONS.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.value, children: o.label }, o.value))
|
|
1749
|
+
}
|
|
1750
|
+
) }),
|
|
1751
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Button Height", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1752
|
+
"select",
|
|
1753
|
+
{
|
|
1754
|
+
value: String(form.buttonHeight),
|
|
1755
|
+
onChange: (e) => setForm((p) => ({ ...p, buttonHeight: Number(e.target.value) })),
|
|
1756
|
+
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",
|
|
1757
|
+
children: HEIGHT_OPTIONS.map((h) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: h, children: [
|
|
1758
|
+
h,
|
|
1759
|
+
" px"
|
|
1760
|
+
] }, h))
|
|
1761
|
+
}
|
|
1762
|
+
) }),
|
|
1763
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Button Label", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1764
|
+
"select",
|
|
1765
|
+
{
|
|
1766
|
+
value: form.buttonLabel,
|
|
1767
|
+
onChange: (e) => setForm((p) => ({ ...p, buttonLabel: e.target.value })),
|
|
1768
|
+
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",
|
|
1769
|
+
children: LABEL_OPTIONS.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.value, children: o.label }, o.value))
|
|
1770
|
+
}
|
|
1771
|
+
) })
|
|
1772
|
+
] })
|
|
1961
1773
|
}
|
|
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
|
|
1774
|
+
),
|
|
1775
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-6 rounded-md border border-ui-border-base bg-ui-bg-subtle p-4", children: [
|
|
1776
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-ui-fg-base", children: "Preview (UI only)" }),
|
|
1777
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 text-sm text-ui-fg-subtle", children: [
|
|
1778
|
+
"Color: ",
|
|
1779
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-base", children: form.buttonColor }),
|
|
1780
|
+
" · Shape:",
|
|
1781
|
+
" ",
|
|
1782
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-base", children: form.buttonShape }),
|
|
1783
|
+
" · Width:",
|
|
1784
|
+
" ",
|
|
1785
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-base", children: form.buttonWidth }),
|
|
1786
|
+
" · Height:",
|
|
1787
|
+
" ",
|
|
1788
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-fg-base", children: [
|
|
1789
|
+
form.buttonHeight,
|
|
1790
|
+
"px"
|
|
1791
|
+
] }),
|
|
1792
|
+
" · Label:",
|
|
1793
|
+
" ",
|
|
1794
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-base", children: form.buttonLabel })
|
|
2040
1795
|
] })
|
|
2041
1796
|
] })
|
|
2042
1797
|
] }) });
|
|
@@ -2056,21 +1811,21 @@ const routeModule = {
|
|
|
2056
1811
|
Component: AdvancedCardPaymentsTab,
|
|
2057
1812
|
path: "/settings/paypal/advanced-card-payments"
|
|
2058
1813
|
},
|
|
2059
|
-
{
|
|
2060
|
-
Component: PayPalAuditLogsPage,
|
|
2061
|
-
path: "/settings/paypal/audit-logs"
|
|
2062
|
-
},
|
|
2063
1814
|
{
|
|
2064
1815
|
Component: PayPalApplePayPage,
|
|
2065
1816
|
path: "/settings/paypal/apple-pay"
|
|
2066
1817
|
},
|
|
1818
|
+
{
|
|
1819
|
+
Component: PayPalConnectionPage,
|
|
1820
|
+
path: "/settings/paypal/connection"
|
|
1821
|
+
},
|
|
2067
1822
|
{
|
|
2068
1823
|
Component: PayPalDisputesPage,
|
|
2069
1824
|
path: "/settings/paypal/disputes"
|
|
2070
1825
|
},
|
|
2071
1826
|
{
|
|
2072
|
-
Component:
|
|
2073
|
-
path: "/settings/paypal/
|
|
1827
|
+
Component: PayPalAuditLogsPage,
|
|
1828
|
+
path: "/settings/paypal/audit-logs"
|
|
2074
1829
|
},
|
|
2075
1830
|
{
|
|
2076
1831
|
Component: PayPalGooglePayPage,
|
|
@@ -2080,13 +1835,13 @@ const routeModule = {
|
|
|
2080
1835
|
Component: PayPalPayLaterMessagingPage,
|
|
2081
1836
|
path: "/settings/paypal/pay-later-messaging"
|
|
2082
1837
|
},
|
|
2083
|
-
{
|
|
2084
|
-
Component: PayPalSettingsTab,
|
|
2085
|
-
path: "/settings/paypal/paypal-settings"
|
|
2086
|
-
},
|
|
2087
1838
|
{
|
|
2088
1839
|
Component: PayPalReconciliationStatusPage,
|
|
2089
1840
|
path: "/settings/paypal/reconciliation-status"
|
|
1841
|
+
},
|
|
1842
|
+
{
|
|
1843
|
+
Component: PayPalSettingsTab,
|
|
1844
|
+
path: "/settings/paypal/paypal-settings"
|
|
2090
1845
|
}
|
|
2091
1846
|
]
|
|
2092
1847
|
};
|