@easypayment/medusa-paypal 0.2.5 → 0.2.6
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 +529 -529
- package/.medusa/server/src/admin/index.mjs +529 -529
- package/.medusa/server/src/api/middlewares.d.ts +3 -0
- package/.medusa/server/src/api/middlewares.d.ts.map +1 -0
- package/.medusa/server/src/api/middlewares.js +16 -0
- package/.medusa/server/src/api/middlewares.js.map +1 -0
- 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 +78 -65
- package/.medusa/server/src/api/store/paypal/capture-order/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal-complete/route.d.ts +10 -0
- package/.medusa/server/src/api/store/paypal-complete/route.d.ts.map +1 -0
- package/.medusa/server/src/api/store/paypal-complete/route.js +56 -0
- package/.medusa/server/src/api/store/paypal-complete/route.js.map +1 -0
- package/.medusa/server/src/modules/paypal/payment-provider/service.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/payment-provider/service.js +32 -1
- package/.medusa/server/src/modules/paypal/payment-provider/service.js.map +1 -1
- package/package.json +1 -1
- package/src/api/middlewares.ts +14 -0
- package/src/api/store/paypal/capture-order/route.ts +284 -270
- package/src/api/store/paypal-complete/route.ts +65 -0
- package/src/modules/paypal/payment-provider/service.ts +37 -4
|
@@ -41,11 +41,17 @@ function PayPalTabs() {
|
|
|
41
41
|
}) }) });
|
|
42
42
|
}
|
|
43
43
|
const DEFAULT_FORM$1 = {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
paymentAction: "capture",
|
|
45
|
+
brandName: "PayPal",
|
|
46
|
+
landingPage: "no_preference",
|
|
47
|
+
requireInstantPayment: false,
|
|
48
|
+
useShippingAsBilling: true,
|
|
49
|
+
sendItemDetails: true,
|
|
50
|
+
skipOrderReviewPage: true,
|
|
51
|
+
invoicePrefix: "WC-",
|
|
52
|
+
creditCardStatementName: "PayPal",
|
|
53
|
+
enableLogging: true,
|
|
54
|
+
logPath: "/uploads/wc-logs/"
|
|
49
55
|
};
|
|
50
56
|
function mergeWithDefaults$1(saved) {
|
|
51
57
|
if (!saved) return { ...DEFAULT_FORM$1 };
|
|
@@ -55,53 +61,6 @@ function mergeWithDefaults$1(saved) {
|
|
|
55
61
|
...Object.fromEntries(entries)
|
|
56
62
|
};
|
|
57
63
|
}
|
|
58
|
-
const CARD_BRANDS = [
|
|
59
|
-
{ value: "visa", label: "Visa" },
|
|
60
|
-
{ value: "mastercard", label: "Mastercard" },
|
|
61
|
-
{ value: "amex", label: "American Express" },
|
|
62
|
-
{ value: "discover", label: "Discover" },
|
|
63
|
-
{ value: "diners", label: "Diners Club" },
|
|
64
|
-
{ value: "jcb", label: "JCB" },
|
|
65
|
-
{ value: "unionpay", label: "UnionPay" }
|
|
66
|
-
];
|
|
67
|
-
const THREE_DS_OPTIONS = [
|
|
68
|
-
{
|
|
69
|
-
value: "when_required",
|
|
70
|
-
label: "3D Secure when required",
|
|
71
|
-
hint: "Triggers 3DS only when the card / issuer requires it."
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
value: "sli",
|
|
75
|
-
label: "3D Secure (SCA) / liability shift (recommended)",
|
|
76
|
-
hint: "Attempts to optimize for liability shift while remaining compliant."
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
value: "always",
|
|
80
|
-
label: "Always request 3D Secure",
|
|
81
|
-
hint: "Forces 3DS challenge whenever possible (may reduce conversion)."
|
|
82
|
-
}
|
|
83
|
-
];
|
|
84
|
-
function cx$1(...parts) {
|
|
85
|
-
return parts.filter(Boolean).join(" ");
|
|
86
|
-
}
|
|
87
|
-
function Pill$1({
|
|
88
|
-
children,
|
|
89
|
-
onRemove
|
|
90
|
-
}) {
|
|
91
|
-
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: [
|
|
92
|
-
children,
|
|
93
|
-
onRemove ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
94
|
-
"button",
|
|
95
|
-
{
|
|
96
|
-
type: "button",
|
|
97
|
-
onClick: onRemove,
|
|
98
|
-
className: "ml-1 rounded px-1 text-ui-fg-subtle hover:text-ui-fg-base",
|
|
99
|
-
"aria-label": "Remove",
|
|
100
|
-
children: "×"
|
|
101
|
-
}
|
|
102
|
-
) : null
|
|
103
|
-
] });
|
|
104
|
-
}
|
|
105
64
|
function SectionCard$2({
|
|
106
65
|
title,
|
|
107
66
|
description,
|
|
@@ -132,12 +91,10 @@ function FieldRow$2({
|
|
|
132
91
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-12 md:col-span-8", children })
|
|
133
92
|
] });
|
|
134
93
|
}
|
|
135
|
-
function
|
|
136
|
-
var _a, _b;
|
|
94
|
+
function AdditionalSettingsTab() {
|
|
137
95
|
const [form, setForm] = react.useState(() => ({ ...DEFAULT_FORM$1 }));
|
|
138
96
|
const [loading, setLoading] = react.useState(false);
|
|
139
97
|
const [saving, setSaving] = react.useState(false);
|
|
140
|
-
const [toast, setToast] = react.useState(null);
|
|
141
98
|
const didInit = react.useRef(false);
|
|
142
99
|
react.useEffect(() => {
|
|
143
100
|
if (didInit.current) return;
|
|
@@ -152,7 +109,7 @@ function AdvancedCardPaymentsTab() {
|
|
|
152
109
|
if (!r.ok) return;
|
|
153
110
|
const json = await r.json();
|
|
154
111
|
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
155
|
-
const saved = payload == null ? void 0 : payload.
|
|
112
|
+
const saved = payload == null ? void 0 : payload.additional_settings;
|
|
156
113
|
if (saved && typeof saved === "object") {
|
|
157
114
|
setForm(mergeWithDefaults$1(saved));
|
|
158
115
|
}
|
|
@@ -161,9 +118,11 @@ function AdvancedCardPaymentsTab() {
|
|
|
161
118
|
}
|
|
162
119
|
})();
|
|
163
120
|
}, []);
|
|
121
|
+
const [toast, setToast] = react.useState(null);
|
|
164
122
|
async function onSave() {
|
|
165
123
|
try {
|
|
166
124
|
setSaving(true);
|
|
125
|
+
setToast(null);
|
|
167
126
|
const r = await fetch("/admin/paypal/settings", {
|
|
168
127
|
method: "POST",
|
|
169
128
|
credentials: "include",
|
|
@@ -171,42 +130,29 @@ function AdvancedCardPaymentsTab() {
|
|
|
171
130
|
"Content-Type": "application/json",
|
|
172
131
|
"Accept": "application/json"
|
|
173
132
|
},
|
|
174
|
-
body: JSON.stringify({
|
|
133
|
+
body: JSON.stringify({
|
|
134
|
+
additional_settings: form
|
|
135
|
+
})
|
|
175
136
|
});
|
|
176
137
|
if (!r.ok) {
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
window.setTimeout(() => setToast(null), 3500);
|
|
180
|
-
return;
|
|
138
|
+
const errText = await r.text().catch(() => "");
|
|
139
|
+
throw new Error(errText || "Failed to save settings");
|
|
181
140
|
}
|
|
182
|
-
const json = await r.json().catch(() =>
|
|
141
|
+
const json = await r.json().catch(() => ({}));
|
|
183
142
|
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
184
|
-
const saved = payload == null ? void 0 : payload.
|
|
143
|
+
const saved = payload == null ? void 0 : payload.additional_settings;
|
|
185
144
|
if (saved && typeof saved === "object") {
|
|
186
145
|
setForm(mergeWithDefaults$1(saved));
|
|
187
146
|
}
|
|
188
147
|
setToast({ type: "success", message: "Settings saved" });
|
|
189
148
|
window.setTimeout(() => setToast(null), 2500);
|
|
149
|
+
} catch (e) {
|
|
150
|
+
setToast({ type: "error", message: (e == null ? void 0 : e.message) || "Failed to save settings" });
|
|
151
|
+
window.setTimeout(() => setToast(null), 3500);
|
|
190
152
|
} finally {
|
|
191
153
|
setSaving(false);
|
|
192
154
|
}
|
|
193
155
|
}
|
|
194
|
-
const disabledSet = react.useMemo(() => new Set(form.disabledCards), [form.disabledCards]);
|
|
195
|
-
function toggleDisabledCard(value) {
|
|
196
|
-
setForm((prev) => {
|
|
197
|
-
const exists = prev.disabledCards.includes(value);
|
|
198
|
-
return {
|
|
199
|
-
...prev,
|
|
200
|
-
disabledCards: exists ? prev.disabledCards.filter((v) => v !== value) : [...prev.disabledCards, value]
|
|
201
|
-
};
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
function removeDisabledCard(value) {
|
|
205
|
-
setForm((prev) => ({
|
|
206
|
-
...prev,
|
|
207
|
-
disabledCards: prev.disabledCards.filter((v) => v !== value)
|
|
208
|
-
}));
|
|
209
|
-
}
|
|
210
156
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
211
157
|
/* @__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" }) }) }),
|
|
212
158
|
/* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
|
|
@@ -222,8 +168,8 @@ function AdvancedCardPaymentsTab() {
|
|
|
222
168
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
223
169
|
SectionCard$2,
|
|
224
170
|
{
|
|
225
|
-
title: "
|
|
226
|
-
description: "
|
|
171
|
+
title: "Additional Settings",
|
|
172
|
+
description: "These settings control checkout behavior, PayPal experience, and logging.",
|
|
227
173
|
right: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
228
174
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
229
175
|
"button",
|
|
@@ -238,350 +184,110 @@ function AdvancedCardPaymentsTab() {
|
|
|
238
184
|
loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading…" }) : null
|
|
239
185
|
] }),
|
|
240
186
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-ui-border-base", children: [
|
|
241
|
-
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "
|
|
187
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "Payment action", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
188
|
+
"select",
|
|
189
|
+
{
|
|
190
|
+
value: form.paymentAction,
|
|
191
|
+
onChange: (e) => setForm((p) => ({ ...p, paymentAction: e.target.value })),
|
|
192
|
+
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",
|
|
193
|
+
children: [
|
|
194
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "capture", children: "Capture" }),
|
|
195
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "authorize", children: "Authorize" })
|
|
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
|
+
) }),
|
|
221
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "Instant Payments", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
242
222
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
243
223
|
"input",
|
|
244
224
|
{
|
|
245
225
|
type: "checkbox",
|
|
246
|
-
checked: form.
|
|
247
|
-
onChange: (e) => setForm((p) => ({ ...p,
|
|
226
|
+
checked: form.requireInstantPayment,
|
|
227
|
+
onChange: (e) => setForm((p) => ({ ...p, requireInstantPayment: e.target.checked })),
|
|
248
228
|
className: "h-4 w-4 rounded border-ui-border-base"
|
|
249
229
|
}
|
|
250
230
|
),
|
|
251
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "
|
|
231
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Require Instant Payment" })
|
|
252
232
|
] }) }),
|
|
253
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
254
|
-
|
|
233
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
234
|
+
FieldRow$2,
|
|
255
235
|
{
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
236
|
+
label: "Billing Address",
|
|
237
|
+
hint: "If the billing address is empty and PayPal provides a shipping address, the order will use the shipping address as the billing address.",
|
|
238
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
239
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
240
|
+
"input",
|
|
241
|
+
{
|
|
242
|
+
type: "checkbox",
|
|
243
|
+
checked: form.useShippingAsBilling,
|
|
244
|
+
onChange: (e) => setForm((p) => ({ ...p, useShippingAsBilling: e.target.checked })),
|
|
245
|
+
className: "h-4 w-4 rounded border-ui-border-base"
|
|
246
|
+
}
|
|
247
|
+
),
|
|
248
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Use PayPal Shipping Address as Billing" })
|
|
249
|
+
] })
|
|
260
250
|
}
|
|
261
|
-
)
|
|
251
|
+
),
|
|
262
252
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
263
253
|
FieldRow$2,
|
|
264
254
|
{
|
|
265
|
-
label: "
|
|
266
|
-
hint: "
|
|
267
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("
|
|
268
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
className: cx$1(
|
|
279
|
-
"flex items-center gap-2 rounded-md p-2",
|
|
280
|
-
"hover:bg-ui-bg-subtle"
|
|
281
|
-
),
|
|
282
|
-
children: [
|
|
283
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
284
|
-
"input",
|
|
285
|
-
{
|
|
286
|
-
type: "checkbox",
|
|
287
|
-
checked,
|
|
288
|
-
onChange: () => toggleDisabledCard(b.value),
|
|
289
|
-
className: "h-4 w-4 rounded border-ui-border-base"
|
|
290
|
-
}
|
|
291
|
-
),
|
|
292
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: b.label })
|
|
293
|
-
]
|
|
294
|
-
},
|
|
295
|
-
b.value
|
|
296
|
-
);
|
|
297
|
-
}) }) })
|
|
255
|
+
label: "Send Item Details",
|
|
256
|
+
hint: "Include all line item details in the payment request to PayPal so that they can be seen from the PayPal transaction details page.",
|
|
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" })
|
|
298
268
|
] })
|
|
299
269
|
}
|
|
300
270
|
),
|
|
301
271
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
302
272
|
FieldRow$2,
|
|
303
273
|
{
|
|
304
|
-
label: "
|
|
305
|
-
hint: "
|
|
306
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("
|
|
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: [
|
|
307
277
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
308
|
-
"
|
|
278
|
+
"input",
|
|
309
279
|
{
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
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"
|
|
314
284
|
}
|
|
315
285
|
),
|
|
316
|
-
|
|
286
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Skip Order Review Page" })
|
|
317
287
|
] })
|
|
318
288
|
}
|
|
319
289
|
),
|
|
320
|
-
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "
|
|
321
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
322
|
-
"input",
|
|
323
|
-
{
|
|
324
|
-
type: "checkbox",
|
|
325
|
-
checked: form.cardSaveEnabled,
|
|
326
|
-
onChange: (e) => setForm((p) => ({ ...p, cardSaveEnabled: 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 card saving at checkout" })
|
|
331
|
-
] }) })
|
|
332
|
-
] })
|
|
333
|
-
}
|
|
334
|
-
)
|
|
335
|
-
] }) });
|
|
336
|
-
}
|
|
337
|
-
const DEFAULT_FORM = {
|
|
338
|
-
paymentAction: "capture",
|
|
339
|
-
brandName: "PayPal",
|
|
340
|
-
landingPage: "no_preference",
|
|
341
|
-
requireInstantPayment: false,
|
|
342
|
-
useShippingAsBilling: true,
|
|
343
|
-
sendItemDetails: true,
|
|
344
|
-
skipOrderReviewPage: true,
|
|
345
|
-
invoicePrefix: "WC-",
|
|
346
|
-
creditCardStatementName: "PayPal",
|
|
347
|
-
enableLogging: true,
|
|
348
|
-
logPath: "/uploads/wc-logs/"
|
|
349
|
-
};
|
|
350
|
-
function mergeWithDefaults(saved) {
|
|
351
|
-
if (!saved) return { ...DEFAULT_FORM };
|
|
352
|
-
const entries = Object.entries(saved).filter(([, value]) => value !== void 0);
|
|
353
|
-
return {
|
|
354
|
-
...DEFAULT_FORM,
|
|
355
|
-
...Object.fromEntries(entries)
|
|
356
|
-
};
|
|
357
|
-
}
|
|
358
|
-
function SectionCard$1({
|
|
359
|
-
title,
|
|
360
|
-
description,
|
|
361
|
-
right,
|
|
362
|
-
children
|
|
363
|
-
}) {
|
|
364
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
365
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4 border-b border-ui-border-base p-4", children: [
|
|
366
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
367
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: title }),
|
|
368
|
-
description ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-sm text-ui-fg-subtle", children: description }) : null
|
|
369
|
-
] }),
|
|
370
|
-
right
|
|
371
|
-
] }),
|
|
372
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children })
|
|
373
|
-
] });
|
|
374
|
-
}
|
|
375
|
-
function FieldRow$1({
|
|
376
|
-
label,
|
|
377
|
-
hint,
|
|
378
|
-
children
|
|
379
|
-
}) {
|
|
380
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-12 items-start gap-4 py-3", children: [
|
|
381
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-12 md:col-span-4", children: [
|
|
382
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-ui-fg-base", children: label }),
|
|
383
|
-
hint ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-xs text-ui-fg-subtle", children: hint }) : null
|
|
384
|
-
] }),
|
|
385
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-12 md:col-span-8", children })
|
|
386
|
-
] });
|
|
387
|
-
}
|
|
388
|
-
function AdditionalSettingsTab() {
|
|
389
|
-
const [form, setForm] = react.useState(() => ({ ...DEFAULT_FORM }));
|
|
390
|
-
const [loading, setLoading] = react.useState(false);
|
|
391
|
-
const [saving, setSaving] = react.useState(false);
|
|
392
|
-
const didInit = react.useRef(false);
|
|
393
|
-
react.useEffect(() => {
|
|
394
|
-
if (didInit.current) return;
|
|
395
|
-
didInit.current = true;
|
|
396
|
-
(async () => {
|
|
397
|
-
try {
|
|
398
|
-
setLoading(true);
|
|
399
|
-
const r = await fetch("/admin/paypal/settings", {
|
|
400
|
-
credentials: "include",
|
|
401
|
-
headers: { "Accept": "application/json" }
|
|
402
|
-
});
|
|
403
|
-
if (!r.ok) return;
|
|
404
|
-
const json = await r.json();
|
|
405
|
-
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
406
|
-
const saved = payload == null ? void 0 : payload.additional_settings;
|
|
407
|
-
if (saved && typeof saved === "object") {
|
|
408
|
-
setForm(mergeWithDefaults(saved));
|
|
409
|
-
}
|
|
410
|
-
} finally {
|
|
411
|
-
setLoading(false);
|
|
412
|
-
}
|
|
413
|
-
})();
|
|
414
|
-
}, []);
|
|
415
|
-
const [toast, setToast] = react.useState(null);
|
|
416
|
-
async function onSave() {
|
|
417
|
-
try {
|
|
418
|
-
setSaving(true);
|
|
419
|
-
setToast(null);
|
|
420
|
-
const r = await fetch("/admin/paypal/settings", {
|
|
421
|
-
method: "POST",
|
|
422
|
-
credentials: "include",
|
|
423
|
-
headers: {
|
|
424
|
-
"Content-Type": "application/json",
|
|
425
|
-
"Accept": "application/json"
|
|
426
|
-
},
|
|
427
|
-
body: JSON.stringify({
|
|
428
|
-
additional_settings: form
|
|
429
|
-
})
|
|
430
|
-
});
|
|
431
|
-
if (!r.ok) {
|
|
432
|
-
const errText = await r.text().catch(() => "");
|
|
433
|
-
throw new Error(errText || "Failed to save settings");
|
|
434
|
-
}
|
|
435
|
-
const json = await r.json().catch(() => ({}));
|
|
436
|
-
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
437
|
-
const saved = payload == null ? void 0 : payload.additional_settings;
|
|
438
|
-
if (saved && typeof saved === "object") {
|
|
439
|
-
setForm(mergeWithDefaults(saved));
|
|
440
|
-
}
|
|
441
|
-
setToast({ type: "success", message: "Settings saved" });
|
|
442
|
-
window.setTimeout(() => setToast(null), 2500);
|
|
443
|
-
} catch (e) {
|
|
444
|
-
setToast({ type: "error", message: (e == null ? void 0 : e.message) || "Failed to save settings" });
|
|
445
|
-
window.setTimeout(() => setToast(null), 3500);
|
|
446
|
-
} finally {
|
|
447
|
-
setSaving(false);
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
451
|
-
/* @__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" }) }) }),
|
|
452
|
-
/* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
|
|
453
|
-
toast ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
454
|
-
"div",
|
|
455
|
-
{
|
|
456
|
-
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",
|
|
457
|
-
role: "status",
|
|
458
|
-
"aria-live": "polite",
|
|
459
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: toast.type === "success" ? "text-ui-fg-base" : "text-ui-fg-error", children: toast.message })
|
|
460
|
-
}
|
|
461
|
-
) : null,
|
|
462
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
463
|
-
SectionCard$1,
|
|
464
|
-
{
|
|
465
|
-
title: "Additional Settings",
|
|
466
|
-
description: "These settings control checkout behavior, PayPal experience, and logging.",
|
|
467
|
-
right: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
468
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
469
|
-
"button",
|
|
470
|
-
{
|
|
471
|
-
type: "button",
|
|
472
|
-
onClick: onSave,
|
|
473
|
-
disabled: saving || loading,
|
|
474
|
-
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",
|
|
475
|
-
children: saving ? "Saving..." : "Save settings"
|
|
476
|
-
}
|
|
477
|
-
),
|
|
478
|
-
loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading…" }) : null
|
|
479
|
-
] }),
|
|
480
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-ui-border-base", children: [
|
|
481
|
-
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Payment action", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
482
|
-
"select",
|
|
483
|
-
{
|
|
484
|
-
value: form.paymentAction,
|
|
485
|
-
onChange: (e) => setForm((p) => ({ ...p, paymentAction: e.target.value })),
|
|
486
|
-
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",
|
|
487
|
-
children: [
|
|
488
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "capture", children: "Capture" }),
|
|
489
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "authorize", children: "Authorize" })
|
|
490
|
-
]
|
|
491
|
-
}
|
|
492
|
-
) }),
|
|
493
|
-
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Brand Name", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
494
|
-
"input",
|
|
495
|
-
{
|
|
496
|
-
value: form.brandName,
|
|
497
|
-
onChange: (e) => setForm((p) => ({ ...p, brandName: e.target.value })),
|
|
498
|
-
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",
|
|
499
|
-
placeholder: "PayPal"
|
|
500
|
-
}
|
|
501
|
-
) }),
|
|
502
|
-
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Landing Page", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
503
|
-
"select",
|
|
504
|
-
{
|
|
505
|
-
value: form.landingPage,
|
|
506
|
-
onChange: (e) => setForm((p) => ({ ...p, landingPage: e.target.value })),
|
|
507
|
-
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",
|
|
508
|
-
children: [
|
|
509
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "no_preference", children: "No Preference" }),
|
|
510
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "login", children: "Login" }),
|
|
511
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "billing", children: "Billing" })
|
|
512
|
-
]
|
|
513
|
-
}
|
|
514
|
-
) }),
|
|
515
|
-
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Instant Payments", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
516
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
517
|
-
"input",
|
|
518
|
-
{
|
|
519
|
-
type: "checkbox",
|
|
520
|
-
checked: form.requireInstantPayment,
|
|
521
|
-
onChange: (e) => setForm((p) => ({ ...p, requireInstantPayment: e.target.checked })),
|
|
522
|
-
className: "h-4 w-4 rounded border-ui-border-base"
|
|
523
|
-
}
|
|
524
|
-
),
|
|
525
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Require Instant Payment" })
|
|
526
|
-
] }) }),
|
|
527
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
528
|
-
FieldRow$1,
|
|
529
|
-
{
|
|
530
|
-
label: "Billing Address",
|
|
531
|
-
hint: "If the billing address is empty and PayPal provides a shipping address, the order will use the shipping address as the billing address.",
|
|
532
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
533
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
534
|
-
"input",
|
|
535
|
-
{
|
|
536
|
-
type: "checkbox",
|
|
537
|
-
checked: form.useShippingAsBilling,
|
|
538
|
-
onChange: (e) => setForm((p) => ({ ...p, useShippingAsBilling: e.target.checked })),
|
|
539
|
-
className: "h-4 w-4 rounded border-ui-border-base"
|
|
540
|
-
}
|
|
541
|
-
),
|
|
542
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Use PayPal Shipping Address as Billing" })
|
|
543
|
-
] })
|
|
544
|
-
}
|
|
545
|
-
),
|
|
546
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
547
|
-
FieldRow$1,
|
|
548
|
-
{
|
|
549
|
-
label: "Send Item Details",
|
|
550
|
-
hint: "Include all line item details in the payment request to PayPal so that they can be seen from the PayPal transaction details page.",
|
|
551
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
552
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
553
|
-
"input",
|
|
554
|
-
{
|
|
555
|
-
type: "checkbox",
|
|
556
|
-
checked: form.sendItemDetails,
|
|
557
|
-
onChange: (e) => setForm((p) => ({ ...p, sendItemDetails: e.target.checked })),
|
|
558
|
-
className: "h-4 w-4 rounded border-ui-border-base"
|
|
559
|
-
}
|
|
560
|
-
),
|
|
561
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Send line item details to PayPal" })
|
|
562
|
-
] })
|
|
563
|
-
}
|
|
564
|
-
),
|
|
565
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
566
|
-
FieldRow$1,
|
|
567
|
-
{
|
|
568
|
-
label: "Order Review Page",
|
|
569
|
-
hint: "Payments from the Product or Cart page skip the review step and go straight to the Thank You page.",
|
|
570
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
571
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
572
|
-
"input",
|
|
573
|
-
{
|
|
574
|
-
type: "checkbox",
|
|
575
|
-
checked: form.skipOrderReviewPage,
|
|
576
|
-
onChange: (e) => setForm((p) => ({ ...p, skipOrderReviewPage: e.target.checked })),
|
|
577
|
-
className: "h-4 w-4 rounded border-ui-border-base"
|
|
578
|
-
}
|
|
579
|
-
),
|
|
580
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Skip Order Review Page" })
|
|
581
|
-
] })
|
|
582
|
-
}
|
|
583
|
-
),
|
|
584
|
-
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Invoice prefix", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
290
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "Invoice prefix", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
585
291
|
"input",
|
|
586
292
|
{
|
|
587
293
|
value: form.invoicePrefix,
|
|
@@ -590,7 +296,7 @@ function AdditionalSettingsTab() {
|
|
|
590
296
|
placeholder: "WC-"
|
|
591
297
|
}
|
|
592
298
|
) }),
|
|
593
|
-
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$
|
|
299
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$2, { label: "Credit Card Statement Name", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
594
300
|
"input",
|
|
595
301
|
{
|
|
596
302
|
value: form.creditCardStatementName,
|
|
@@ -600,7 +306,7 @@ function AdditionalSettingsTab() {
|
|
|
600
306
|
}
|
|
601
307
|
) }),
|
|
602
308
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
603
|
-
FieldRow$
|
|
309
|
+
FieldRow$2,
|
|
604
310
|
{
|
|
605
311
|
label: "Debug log",
|
|
606
312
|
hint: /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
@@ -630,6 +336,9 @@ function AdditionalSettingsTab() {
|
|
|
630
336
|
)
|
|
631
337
|
] }) });
|
|
632
338
|
}
|
|
339
|
+
function PayPalApplePayPage() {
|
|
340
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
341
|
+
}
|
|
633
342
|
const config = adminSdk.defineRouteConfig({
|
|
634
343
|
label: "PayPal Connection",
|
|
635
344
|
hide: true
|
|
@@ -1214,6 +923,300 @@ function PayPalConnectionPage() {
|
|
|
1214
923
|
` })
|
|
1215
924
|
] });
|
|
1216
925
|
}
|
|
926
|
+
const DEFAULT_FORM = {
|
|
927
|
+
enabled: true,
|
|
928
|
+
title: "Credit or Debit Card",
|
|
929
|
+
disabledCards: [],
|
|
930
|
+
threeDS: "when_required",
|
|
931
|
+
cardSaveEnabled: false
|
|
932
|
+
};
|
|
933
|
+
function mergeWithDefaults(saved) {
|
|
934
|
+
if (!saved) return { ...DEFAULT_FORM };
|
|
935
|
+
const entries = Object.entries(saved).filter(([, value]) => value !== void 0);
|
|
936
|
+
return {
|
|
937
|
+
...DEFAULT_FORM,
|
|
938
|
+
...Object.fromEntries(entries)
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
const CARD_BRANDS = [
|
|
942
|
+
{ value: "visa", label: "Visa" },
|
|
943
|
+
{ value: "mastercard", label: "Mastercard" },
|
|
944
|
+
{ value: "amex", label: "American Express" },
|
|
945
|
+
{ value: "discover", label: "Discover" },
|
|
946
|
+
{ value: "diners", label: "Diners Club" },
|
|
947
|
+
{ value: "jcb", label: "JCB" },
|
|
948
|
+
{ value: "unionpay", label: "UnionPay" }
|
|
949
|
+
];
|
|
950
|
+
const THREE_DS_OPTIONS = [
|
|
951
|
+
{
|
|
952
|
+
value: "when_required",
|
|
953
|
+
label: "3D Secure when required",
|
|
954
|
+
hint: "Triggers 3DS only when the card / issuer requires it."
|
|
955
|
+
},
|
|
956
|
+
{
|
|
957
|
+
value: "sli",
|
|
958
|
+
label: "3D Secure (SCA) / liability shift (recommended)",
|
|
959
|
+
hint: "Attempts to optimize for liability shift while remaining compliant."
|
|
960
|
+
},
|
|
961
|
+
{
|
|
962
|
+
value: "always",
|
|
963
|
+
label: "Always request 3D Secure",
|
|
964
|
+
hint: "Forces 3DS challenge whenever possible (may reduce conversion)."
|
|
965
|
+
}
|
|
966
|
+
];
|
|
967
|
+
function cx$1(...parts) {
|
|
968
|
+
return parts.filter(Boolean).join(" ");
|
|
969
|
+
}
|
|
970
|
+
function Pill$1({
|
|
971
|
+
children,
|
|
972
|
+
onRemove
|
|
973
|
+
}) {
|
|
974
|
+
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: [
|
|
975
|
+
children,
|
|
976
|
+
onRemove ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
977
|
+
"button",
|
|
978
|
+
{
|
|
979
|
+
type: "button",
|
|
980
|
+
onClick: onRemove,
|
|
981
|
+
className: "ml-1 rounded px-1 text-ui-fg-subtle hover:text-ui-fg-base",
|
|
982
|
+
"aria-label": "Remove",
|
|
983
|
+
children: "×"
|
|
984
|
+
}
|
|
985
|
+
) : null
|
|
986
|
+
] });
|
|
987
|
+
}
|
|
988
|
+
function SectionCard$1({
|
|
989
|
+
title,
|
|
990
|
+
description,
|
|
991
|
+
right,
|
|
992
|
+
children
|
|
993
|
+
}) {
|
|
994
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
995
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4 border-b border-ui-border-base p-4", children: [
|
|
996
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
997
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: title }),
|
|
998
|
+
description ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-sm text-ui-fg-subtle", children: description }) : null
|
|
999
|
+
] }),
|
|
1000
|
+
right
|
|
1001
|
+
] }),
|
|
1002
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children })
|
|
1003
|
+
] });
|
|
1004
|
+
}
|
|
1005
|
+
function FieldRow$1({
|
|
1006
|
+
label,
|
|
1007
|
+
hint,
|
|
1008
|
+
children
|
|
1009
|
+
}) {
|
|
1010
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-12 items-start gap-4 py-3", children: [
|
|
1011
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-12 md:col-span-4", children: [
|
|
1012
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-ui-fg-base", children: label }),
|
|
1013
|
+
hint ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-xs text-ui-fg-subtle", children: hint }) : null
|
|
1014
|
+
] }),
|
|
1015
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-12 md:col-span-8", children })
|
|
1016
|
+
] });
|
|
1017
|
+
}
|
|
1018
|
+
function AdvancedCardPaymentsTab() {
|
|
1019
|
+
var _a, _b;
|
|
1020
|
+
const [form, setForm] = react.useState(() => ({ ...DEFAULT_FORM }));
|
|
1021
|
+
const [loading, setLoading] = react.useState(false);
|
|
1022
|
+
const [saving, setSaving] = react.useState(false);
|
|
1023
|
+
const [toast, setToast] = react.useState(null);
|
|
1024
|
+
const didInit = react.useRef(false);
|
|
1025
|
+
react.useEffect(() => {
|
|
1026
|
+
if (didInit.current) return;
|
|
1027
|
+
didInit.current = true;
|
|
1028
|
+
(async () => {
|
|
1029
|
+
try {
|
|
1030
|
+
setLoading(true);
|
|
1031
|
+
const r = await fetch("/admin/paypal/settings", {
|
|
1032
|
+
credentials: "include",
|
|
1033
|
+
headers: { "Accept": "application/json" }
|
|
1034
|
+
});
|
|
1035
|
+
if (!r.ok) return;
|
|
1036
|
+
const json = await r.json();
|
|
1037
|
+
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
1038
|
+
const saved = payload == null ? void 0 : payload.advanced_card_payments;
|
|
1039
|
+
if (saved && typeof saved === "object") {
|
|
1040
|
+
setForm(mergeWithDefaults(saved));
|
|
1041
|
+
}
|
|
1042
|
+
} finally {
|
|
1043
|
+
setLoading(false);
|
|
1044
|
+
}
|
|
1045
|
+
})();
|
|
1046
|
+
}, []);
|
|
1047
|
+
async function onSave() {
|
|
1048
|
+
try {
|
|
1049
|
+
setSaving(true);
|
|
1050
|
+
const r = await fetch("/admin/paypal/settings", {
|
|
1051
|
+
method: "POST",
|
|
1052
|
+
credentials: "include",
|
|
1053
|
+
headers: {
|
|
1054
|
+
"Content-Type": "application/json",
|
|
1055
|
+
"Accept": "application/json"
|
|
1056
|
+
},
|
|
1057
|
+
body: JSON.stringify({ advanced_card_payments: form })
|
|
1058
|
+
});
|
|
1059
|
+
if (!r.ok) {
|
|
1060
|
+
const t = await r.text();
|
|
1061
|
+
setToast({ type: "error", message: "Failed to save settings. " + t });
|
|
1062
|
+
window.setTimeout(() => setToast(null), 3500);
|
|
1063
|
+
return;
|
|
1064
|
+
}
|
|
1065
|
+
const json = await r.json().catch(() => null);
|
|
1066
|
+
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
1067
|
+
const saved = payload == null ? void 0 : payload.advanced_card_payments;
|
|
1068
|
+
if (saved && typeof saved === "object") {
|
|
1069
|
+
setForm(mergeWithDefaults(saved));
|
|
1070
|
+
}
|
|
1071
|
+
setToast({ type: "success", message: "Settings saved" });
|
|
1072
|
+
window.setTimeout(() => setToast(null), 2500);
|
|
1073
|
+
} finally {
|
|
1074
|
+
setSaving(false);
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
const disabledSet = react.useMemo(() => new Set(form.disabledCards), [form.disabledCards]);
|
|
1078
|
+
function toggleDisabledCard(value) {
|
|
1079
|
+
setForm((prev) => {
|
|
1080
|
+
const exists = prev.disabledCards.includes(value);
|
|
1081
|
+
return {
|
|
1082
|
+
...prev,
|
|
1083
|
+
disabledCards: exists ? prev.disabledCards.filter((v) => v !== value) : [...prev.disabledCards, value]
|
|
1084
|
+
};
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
function removeDisabledCard(value) {
|
|
1088
|
+
setForm((prev) => ({
|
|
1089
|
+
...prev,
|
|
1090
|
+
disabledCards: prev.disabledCards.filter((v) => v !== value)
|
|
1091
|
+
}));
|
|
1092
|
+
}
|
|
1093
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
1094
|
+
/* @__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" }) }) }),
|
|
1095
|
+
/* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
|
|
1096
|
+
toast ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1097
|
+
"div",
|
|
1098
|
+
{
|
|
1099
|
+
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",
|
|
1100
|
+
role: "status",
|
|
1101
|
+
"aria-live": "polite",
|
|
1102
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: toast.type === "success" ? "text-ui-fg-base" : "text-ui-fg-error", children: toast.message })
|
|
1103
|
+
}
|
|
1104
|
+
) : null,
|
|
1105
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1106
|
+
SectionCard$1,
|
|
1107
|
+
{
|
|
1108
|
+
title: "Advanced Card Payments",
|
|
1109
|
+
description: "Control card checkout settings, 3D Secure behavior, and card saving.",
|
|
1110
|
+
right: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
1111
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1112
|
+
"button",
|
|
1113
|
+
{
|
|
1114
|
+
type: "button",
|
|
1115
|
+
onClick: onSave,
|
|
1116
|
+
disabled: saving || loading,
|
|
1117
|
+
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",
|
|
1118
|
+
children: saving ? "Saving..." : "Save settings"
|
|
1119
|
+
}
|
|
1120
|
+
),
|
|
1121
|
+
loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading…" }) : null
|
|
1122
|
+
] }),
|
|
1123
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-ui-border-base", children: [
|
|
1124
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Enable/Disable", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
1125
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1126
|
+
"input",
|
|
1127
|
+
{
|
|
1128
|
+
type: "checkbox",
|
|
1129
|
+
checked: form.enabled,
|
|
1130
|
+
onChange: (e) => setForm((p) => ({ ...p, enabled: e.target.checked })),
|
|
1131
|
+
className: "h-4 w-4 rounded border-ui-border-base"
|
|
1132
|
+
}
|
|
1133
|
+
),
|
|
1134
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable Advanced Credit/Debit Card" })
|
|
1135
|
+
] }) }),
|
|
1136
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Title", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1137
|
+
"input",
|
|
1138
|
+
{
|
|
1139
|
+
value: form.title,
|
|
1140
|
+
onChange: (e) => setForm((p) => ({ ...p, title: e.target.value })),
|
|
1141
|
+
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",
|
|
1142
|
+
placeholder: "Credit or Debit Card"
|
|
1143
|
+
}
|
|
1144
|
+
) }),
|
|
1145
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1146
|
+
FieldRow$1,
|
|
1147
|
+
{
|
|
1148
|
+
label: "Disable specific credit cards",
|
|
1149
|
+
hint: "Select card brands to hide from the card form.",
|
|
1150
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
1151
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: form.disabledCards.length ? form.disabledCards.map((v) => {
|
|
1152
|
+
var _a2;
|
|
1153
|
+
const label = ((_a2 = CARD_BRANDS.find((b) => b.value === v)) == null ? void 0 : _a2.label) ?? v;
|
|
1154
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Pill$1, { onRemove: () => removeDisabledCard(v), children: label }, v);
|
|
1155
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "No card brands disabled." }) }),
|
|
1156
|
+
/* @__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) => {
|
|
1157
|
+
const checked = disabledSet.has(b.value);
|
|
1158
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1159
|
+
"label",
|
|
1160
|
+
{
|
|
1161
|
+
className: cx$1(
|
|
1162
|
+
"flex items-center gap-2 rounded-md p-2",
|
|
1163
|
+
"hover:bg-ui-bg-subtle"
|
|
1164
|
+
),
|
|
1165
|
+
children: [
|
|
1166
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1167
|
+
"input",
|
|
1168
|
+
{
|
|
1169
|
+
type: "checkbox",
|
|
1170
|
+
checked,
|
|
1171
|
+
onChange: () => toggleDisabledCard(b.value),
|
|
1172
|
+
className: "h-4 w-4 rounded border-ui-border-base"
|
|
1173
|
+
}
|
|
1174
|
+
),
|
|
1175
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: b.label })
|
|
1176
|
+
]
|
|
1177
|
+
},
|
|
1178
|
+
b.value
|
|
1179
|
+
);
|
|
1180
|
+
}) }) })
|
|
1181
|
+
] })
|
|
1182
|
+
}
|
|
1183
|
+
),
|
|
1184
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1185
|
+
FieldRow$1,
|
|
1186
|
+
{
|
|
1187
|
+
label: "Contingency for 3D Secure",
|
|
1188
|
+
hint: "Choose when 3D Secure should be triggered during card payments.",
|
|
1189
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
1190
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1191
|
+
"select",
|
|
1192
|
+
{
|
|
1193
|
+
value: form.threeDS,
|
|
1194
|
+
onChange: (e) => setForm((p) => ({ ...p, threeDS: e.target.value })),
|
|
1195
|
+
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",
|
|
1196
|
+
children: THREE_DS_OPTIONS.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.value, children: o.label }, o.value))
|
|
1197
|
+
}
|
|
1198
|
+
),
|
|
1199
|
+
((_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
|
|
1200
|
+
] })
|
|
1201
|
+
}
|
|
1202
|
+
),
|
|
1203
|
+
/* @__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: [
|
|
1204
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1205
|
+
"input",
|
|
1206
|
+
{
|
|
1207
|
+
type: "checkbox",
|
|
1208
|
+
checked: form.cardSaveEnabled,
|
|
1209
|
+
onChange: (e) => setForm((p) => ({ ...p, cardSaveEnabled: e.target.checked })),
|
|
1210
|
+
className: "h-4 w-4 rounded border-ui-border-base"
|
|
1211
|
+
}
|
|
1212
|
+
),
|
|
1213
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable card saving at checkout" })
|
|
1214
|
+
] }) })
|
|
1215
|
+
] })
|
|
1216
|
+
}
|
|
1217
|
+
)
|
|
1218
|
+
] }) });
|
|
1219
|
+
}
|
|
1217
1220
|
function formatDate$2(value) {
|
|
1218
1221
|
if (!value) {
|
|
1219
1222
|
return "";
|
|
@@ -1293,7 +1296,7 @@ function PayPalAuditLogsPage() {
|
|
|
1293
1296
|
] })
|
|
1294
1297
|
] }) });
|
|
1295
1298
|
}
|
|
1296
|
-
function
|
|
1299
|
+
function PayPalGooglePayPage() {
|
|
1297
1300
|
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
1298
1301
|
}
|
|
1299
1302
|
const EMPTY_FILTERS = {
|
|
@@ -1488,122 +1491,9 @@ function PayPalDisputesPage() {
|
|
|
1488
1491
|
] })
|
|
1489
1492
|
] }) });
|
|
1490
1493
|
}
|
|
1491
|
-
function PayPalGooglePayPage() {
|
|
1492
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
1493
|
-
}
|
|
1494
1494
|
function PayPalPayLaterMessagingPage() {
|
|
1495
1495
|
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
1496
1496
|
}
|
|
1497
|
-
function formatDate(value) {
|
|
1498
|
-
if (!value) {
|
|
1499
|
-
return "—";
|
|
1500
|
-
}
|
|
1501
|
-
const parsed = new Date(value);
|
|
1502
|
-
if (Number.isNaN(parsed.getTime())) {
|
|
1503
|
-
return value;
|
|
1504
|
-
}
|
|
1505
|
-
return parsed.toLocaleString();
|
|
1506
|
-
}
|
|
1507
|
-
function PayPalReconciliationStatusPage() {
|
|
1508
|
-
const [status, setStatus] = react.useState({});
|
|
1509
|
-
const [loading, setLoading] = react.useState(false);
|
|
1510
|
-
const [error, setError] = react.useState(null);
|
|
1511
|
-
const fetchStatus = react.useCallback(async () => {
|
|
1512
|
-
try {
|
|
1513
|
-
setLoading(true);
|
|
1514
|
-
setError(null);
|
|
1515
|
-
const response = await fetch("/admin/paypal/reconciliation-status", {
|
|
1516
|
-
credentials: "include",
|
|
1517
|
-
headers: {
|
|
1518
|
-
Accept: "application/json"
|
|
1519
|
-
}
|
|
1520
|
-
});
|
|
1521
|
-
if (!response.ok) {
|
|
1522
|
-
const message = await response.text().catch(() => "");
|
|
1523
|
-
throw new Error(message || "Failed to load reconciliation status.");
|
|
1524
|
-
}
|
|
1525
|
-
const data = await response.json().catch(() => ({}));
|
|
1526
|
-
setStatus((data == null ? void 0 : data.status) || {});
|
|
1527
|
-
} catch (fetchError) {
|
|
1528
|
-
setError((fetchError == null ? void 0 : fetchError.message) || "Failed to load reconciliation status.");
|
|
1529
|
-
setStatus({});
|
|
1530
|
-
} finally {
|
|
1531
|
-
setLoading(false);
|
|
1532
|
-
}
|
|
1533
|
-
}, []);
|
|
1534
|
-
react.useEffect(() => {
|
|
1535
|
-
fetchStatus();
|
|
1536
|
-
}, [fetchStatus]);
|
|
1537
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
1538
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1539
|
-
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Reconciliation Status" }),
|
|
1540
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-ui-fg-subtle", children: "Monitor reconciliation health and drift detection for PayPal payment sessions." })
|
|
1541
|
-
] }),
|
|
1542
|
-
/* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
|
|
1543
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
1544
|
-
/* @__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: [
|
|
1545
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Latest reconciliation run" }),
|
|
1546
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1547
|
-
"button",
|
|
1548
|
-
{
|
|
1549
|
-
type: "button",
|
|
1550
|
-
onClick: fetchStatus,
|
|
1551
|
-
className: "rounded-md border border-ui-border-base px-3 py-2 text-sm text-ui-fg-base",
|
|
1552
|
-
disabled: loading,
|
|
1553
|
-
children: loading ? "Refreshing..." : "Refresh"
|
|
1554
|
-
}
|
|
1555
|
-
)
|
|
1556
|
-
] }) }),
|
|
1557
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4", children: [
|
|
1558
|
-
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,
|
|
1559
|
-
!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,
|
|
1560
|
-
Object.keys(status).length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 text-sm text-ui-fg-base md:grid-cols-2", children: [
|
|
1561
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1562
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last run" }),
|
|
1563
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_run_at) })
|
|
1564
|
-
] }),
|
|
1565
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1566
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last run status" }),
|
|
1567
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium capitalize", children: status.last_run_status || "—" })
|
|
1568
|
-
] }),
|
|
1569
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1570
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last success" }),
|
|
1571
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_success_at) })
|
|
1572
|
-
] }),
|
|
1573
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1574
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last failure" }),
|
|
1575
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_failure_at) })
|
|
1576
|
-
] }),
|
|
1577
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1578
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Sessions checked" }),
|
|
1579
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.sessions_checked ?? 0 })
|
|
1580
|
-
] }),
|
|
1581
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1582
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Sessions updated" }),
|
|
1583
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.sessions_updated ?? 0 })
|
|
1584
|
-
] }),
|
|
1585
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1586
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Drift detections" }),
|
|
1587
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.drift_count ?? 0 })
|
|
1588
|
-
] }),
|
|
1589
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1590
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last drift order" }),
|
|
1591
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.last_drift_order_id || "—" }),
|
|
1592
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-xs text-ui-fg-subtle", children: formatDate(status.last_drift_at) })
|
|
1593
|
-
] }),
|
|
1594
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 md:col-span-2", children: [
|
|
1595
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last error" }),
|
|
1596
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.last_error || "No errors recorded." })
|
|
1597
|
-
] }),
|
|
1598
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 md:col-span-2", children: [
|
|
1599
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Total runs" }),
|
|
1600
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.runs ?? 0 })
|
|
1601
|
-
] })
|
|
1602
|
-
] }) : null
|
|
1603
|
-
] })
|
|
1604
|
-
] })
|
|
1605
|
-
] }) });
|
|
1606
|
-
}
|
|
1607
1497
|
const DISPLAY_LOCATION_OPTIONS = [
|
|
1608
1498
|
{ value: "product", label: "Product Page" },
|
|
1609
1499
|
{ value: "cart", label: "Cart Page" },
|
|
@@ -2041,6 +1931,116 @@ function PayPalSettingsTab() {
|
|
|
2041
1931
|
)
|
|
2042
1932
|
] }) });
|
|
2043
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.");
|
|
1961
|
+
}
|
|
1962
|
+
const data = await response.json().catch(() => ({}));
|
|
1963
|
+
setStatus((data == null ? void 0 : data.status) || {});
|
|
1964
|
+
} catch (fetchError) {
|
|
1965
|
+
setError((fetchError == null ? void 0 : fetchError.message) || "Failed to load reconciliation status.");
|
|
1966
|
+
setStatus({});
|
|
1967
|
+
} finally {
|
|
1968
|
+
setLoading(false);
|
|
1969
|
+
}
|
|
1970
|
+
}, []);
|
|
1971
|
+
react.useEffect(() => {
|
|
1972
|
+
fetchStatus();
|
|
1973
|
+
}, [fetchStatus]);
|
|
1974
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
1975
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1976
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Reconciliation Status" }),
|
|
1977
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-ui-fg-subtle", children: "Monitor reconciliation health and drift detection for PayPal payment sessions." })
|
|
1978
|
+
] }),
|
|
1979
|
+
/* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
|
|
1980
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
1981
|
+
/* @__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: [
|
|
1982
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Latest reconciliation run" }),
|
|
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
|
|
2040
|
+
] })
|
|
2041
|
+
] })
|
|
2042
|
+
] }) });
|
|
2043
|
+
}
|
|
2044
2044
|
const widgetModule = { widgets: [] };
|
|
2045
2045
|
const routeModule = {
|
|
2046
2046
|
routes: [
|
|
@@ -2048,45 +2048,45 @@ const routeModule = {
|
|
|
2048
2048
|
Component: PayPalSettingsIndexRoute,
|
|
2049
2049
|
path: "/settings/paypal"
|
|
2050
2050
|
},
|
|
2051
|
-
{
|
|
2052
|
-
Component: AdvancedCardPaymentsTab,
|
|
2053
|
-
path: "/settings/paypal/advanced-card-payments"
|
|
2054
|
-
},
|
|
2055
2051
|
{
|
|
2056
2052
|
Component: AdditionalSettingsTab,
|
|
2057
2053
|
path: "/settings/paypal/additional-settings"
|
|
2058
2054
|
},
|
|
2055
|
+
{
|
|
2056
|
+
Component: PayPalApplePayPage,
|
|
2057
|
+
path: "/settings/paypal/apple-pay"
|
|
2058
|
+
},
|
|
2059
2059
|
{
|
|
2060
2060
|
Component: PayPalConnectionPage,
|
|
2061
2061
|
path: "/settings/paypal/connection"
|
|
2062
2062
|
},
|
|
2063
|
+
{
|
|
2064
|
+
Component: AdvancedCardPaymentsTab,
|
|
2065
|
+
path: "/settings/paypal/advanced-card-payments"
|
|
2066
|
+
},
|
|
2063
2067
|
{
|
|
2064
2068
|
Component: PayPalAuditLogsPage,
|
|
2065
2069
|
path: "/settings/paypal/audit-logs"
|
|
2066
2070
|
},
|
|
2067
2071
|
{
|
|
2068
|
-
Component:
|
|
2069
|
-
path: "/settings/paypal/
|
|
2072
|
+
Component: PayPalGooglePayPage,
|
|
2073
|
+
path: "/settings/paypal/google-pay"
|
|
2070
2074
|
},
|
|
2071
2075
|
{
|
|
2072
2076
|
Component: PayPalDisputesPage,
|
|
2073
2077
|
path: "/settings/paypal/disputes"
|
|
2074
2078
|
},
|
|
2075
|
-
{
|
|
2076
|
-
Component: PayPalGooglePayPage,
|
|
2077
|
-
path: "/settings/paypal/google-pay"
|
|
2078
|
-
},
|
|
2079
2079
|
{
|
|
2080
2080
|
Component: PayPalPayLaterMessagingPage,
|
|
2081
2081
|
path: "/settings/paypal/pay-later-messaging"
|
|
2082
2082
|
},
|
|
2083
|
-
{
|
|
2084
|
-
Component: PayPalReconciliationStatusPage,
|
|
2085
|
-
path: "/settings/paypal/reconciliation-status"
|
|
2086
|
-
},
|
|
2087
2083
|
{
|
|
2088
2084
|
Component: PayPalSettingsTab,
|
|
2089
2085
|
path: "/settings/paypal/paypal-settings"
|
|
2086
|
+
},
|
|
2087
|
+
{
|
|
2088
|
+
Component: PayPalReconciliationStatusPage,
|
|
2089
|
+
path: "/settings/paypal/reconciliation-status"
|
|
2090
2090
|
}
|
|
2091
2091
|
]
|
|
2092
2092
|
};
|