@easypayment/medusa-paypal 0.2.5 → 0.2.7
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 +1194 -1194
- package/.medusa/server/src/admin/index.mjs +1194 -1194
- 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 +79 -65
- package/.medusa/server/src/api/store/paypal/capture-order/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal/config/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/paypal/config/route.js +9 -2
- package/.medusa/server/src/api/store/paypal/config/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal-complete/route.d.ts +3 -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 +42 -0
- package/.medusa/server/src/api/store/paypal-complete/route.js.map +1 -0
- package/.medusa/server/src/modules/paypal/payment-provider/card-service.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/payment-provider/card-service.js +54 -4
- package/.medusa/server/src/modules/paypal/payment-provider/card-service.js.map +1 -1
- package/.medusa/server/src/modules/paypal/payment-provider/service.d.ts +4 -1
- package/.medusa/server/src/modules/paypal/payment-provider/service.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/payment-provider/service.js +63 -5
- 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/config/route.ts +12 -8
- package/src/api/store/paypal-complete/route.ts +46 -0
- package/src/modules/paypal/payment-provider/card-service.ts +54 -4
- package/src/modules/paypal/payment-provider/service.ts +77 -17
|
@@ -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,114 +184,164 @@ 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
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
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
|
+
)
|
|
334
|
+
] })
|
|
335
|
+
}
|
|
336
|
+
)
|
|
337
|
+
] }) });
|
|
338
|
+
}
|
|
339
|
+
const DEFAULT_FORM = {
|
|
340
|
+
enabled: true,
|
|
341
|
+
title: "Credit or Debit Card",
|
|
342
|
+
disabledCards: [],
|
|
343
|
+
threeDS: "when_required",
|
|
344
|
+
cardSaveEnabled: false
|
|
349
345
|
};
|
|
350
346
|
function mergeWithDefaults(saved) {
|
|
351
347
|
if (!saved) return { ...DEFAULT_FORM };
|
|
@@ -355,6 +351,53 @@ function mergeWithDefaults(saved) {
|
|
|
355
351
|
...Object.fromEntries(entries)
|
|
356
352
|
};
|
|
357
353
|
}
|
|
354
|
+
const CARD_BRANDS = [
|
|
355
|
+
{ value: "visa", label: "Visa" },
|
|
356
|
+
{ value: "mastercard", label: "Mastercard" },
|
|
357
|
+
{ value: "amex", label: "American Express" },
|
|
358
|
+
{ value: "discover", label: "Discover" },
|
|
359
|
+
{ value: "diners", label: "Diners Club" },
|
|
360
|
+
{ value: "jcb", label: "JCB" },
|
|
361
|
+
{ value: "unionpay", label: "UnionPay" }
|
|
362
|
+
];
|
|
363
|
+
const THREE_DS_OPTIONS = [
|
|
364
|
+
{
|
|
365
|
+
value: "when_required",
|
|
366
|
+
label: "3D Secure when required",
|
|
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
|
+
}
|
|
379
|
+
];
|
|
380
|
+
function cx$1(...parts) {
|
|
381
|
+
return parts.filter(Boolean).join(" ");
|
|
382
|
+
}
|
|
383
|
+
function Pill$1({
|
|
384
|
+
children,
|
|
385
|
+
onRemove
|
|
386
|
+
}) {
|
|
387
|
+
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
|
+
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
|
|
399
|
+
] });
|
|
400
|
+
}
|
|
358
401
|
function SectionCard$1({
|
|
359
402
|
title,
|
|
360
403
|
description,
|
|
@@ -385,10 +428,12 @@ function FieldRow$1({
|
|
|
385
428
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-12 md:col-span-8", children })
|
|
386
429
|
] });
|
|
387
430
|
}
|
|
388
|
-
function
|
|
431
|
+
function AdvancedCardPaymentsTab() {
|
|
432
|
+
var _a, _b;
|
|
389
433
|
const [form, setForm] = react.useState(() => ({ ...DEFAULT_FORM }));
|
|
390
434
|
const [loading, setLoading] = react.useState(false);
|
|
391
435
|
const [saving, setSaving] = react.useState(false);
|
|
436
|
+
const [toast, setToast] = react.useState(null);
|
|
392
437
|
const didInit = react.useRef(false);
|
|
393
438
|
react.useEffect(() => {
|
|
394
439
|
if (didInit.current) return;
|
|
@@ -403,7 +448,7 @@ function AdditionalSettingsTab() {
|
|
|
403
448
|
if (!r.ok) return;
|
|
404
449
|
const json = await r.json();
|
|
405
450
|
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
406
|
-
const saved = payload == null ? void 0 : payload.
|
|
451
|
+
const saved = payload == null ? void 0 : payload.advanced_card_payments;
|
|
407
452
|
if (saved && typeof saved === "object") {
|
|
408
453
|
setForm(mergeWithDefaults(saved));
|
|
409
454
|
}
|
|
@@ -412,11 +457,9 @@ function AdditionalSettingsTab() {
|
|
|
412
457
|
}
|
|
413
458
|
})();
|
|
414
459
|
}, []);
|
|
415
|
-
const [toast, setToast] = react.useState(null);
|
|
416
460
|
async function onSave() {
|
|
417
461
|
try {
|
|
418
462
|
setSaving(true);
|
|
419
|
-
setToast(null);
|
|
420
463
|
const r = await fetch("/admin/paypal/settings", {
|
|
421
464
|
method: "POST",
|
|
422
465
|
credentials: "include",
|
|
@@ -424,29 +467,42 @@ function AdditionalSettingsTab() {
|
|
|
424
467
|
"Content-Type": "application/json",
|
|
425
468
|
"Accept": "application/json"
|
|
426
469
|
},
|
|
427
|
-
body: JSON.stringify({
|
|
428
|
-
additional_settings: form
|
|
429
|
-
})
|
|
470
|
+
body: JSON.stringify({ advanced_card_payments: form })
|
|
430
471
|
});
|
|
431
472
|
if (!r.ok) {
|
|
432
|
-
const
|
|
433
|
-
|
|
473
|
+
const t = await r.text();
|
|
474
|
+
setToast({ type: "error", message: "Failed to save settings. " + t });
|
|
475
|
+
window.setTimeout(() => setToast(null), 3500);
|
|
476
|
+
return;
|
|
434
477
|
}
|
|
435
|
-
const json = await r.json().catch(() =>
|
|
478
|
+
const json = await r.json().catch(() => null);
|
|
436
479
|
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
437
|
-
const saved = payload == null ? void 0 : payload.
|
|
480
|
+
const saved = payload == null ? void 0 : payload.advanced_card_payments;
|
|
438
481
|
if (saved && typeof saved === "object") {
|
|
439
482
|
setForm(mergeWithDefaults(saved));
|
|
440
483
|
}
|
|
441
484
|
setToast({ type: "success", message: "Settings saved" });
|
|
442
485
|
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
486
|
} finally {
|
|
447
487
|
setSaving(false);
|
|
448
488
|
}
|
|
449
489
|
}
|
|
490
|
+
const disabledSet = react.useMemo(() => new Set(form.disabledCards), [form.disabledCards]);
|
|
491
|
+
function toggleDisabledCard(value) {
|
|
492
|
+
setForm((prev) => {
|
|
493
|
+
const exists = prev.disabledCards.includes(value);
|
|
494
|
+
return {
|
|
495
|
+
...prev,
|
|
496
|
+
disabledCards: exists ? prev.disabledCards.filter((v) => v !== value) : [...prev.disabledCards, value]
|
|
497
|
+
};
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
function removeDisabledCard(value) {
|
|
501
|
+
setForm((prev) => ({
|
|
502
|
+
...prev,
|
|
503
|
+
disabledCards: prev.disabledCards.filter((v) => v !== value)
|
|
504
|
+
}));
|
|
505
|
+
}
|
|
450
506
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
451
507
|
/* @__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
508
|
/* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
|
|
@@ -462,8 +518,8 @@ function AdditionalSettingsTab() {
|
|
|
462
518
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
463
519
|
SectionCard$1,
|
|
464
520
|
{
|
|
465
|
-
title: "
|
|
466
|
-
description: "
|
|
521
|
+
title: "Advanced Card Payments",
|
|
522
|
+
description: "Control card checkout settings, 3D Secure behavior, and card saving.",
|
|
467
523
|
right: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
468
524
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
469
525
|
"button",
|
|
@@ -478,1015 +534,959 @@ function AdditionalSettingsTab() {
|
|
|
478
534
|
loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading…" }) : null
|
|
479
535
|
] }),
|
|
480
536
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-ui-border-base", children: [
|
|
481
|
-
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "
|
|
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: [
|
|
537
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Enable/Disable", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
516
538
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
517
539
|
"input",
|
|
518
540
|
{
|
|
519
541
|
type: "checkbox",
|
|
520
|
-
checked: form.
|
|
521
|
-
onChange: (e) => setForm((p) => ({ ...p,
|
|
542
|
+
checked: form.enabled,
|
|
543
|
+
onChange: (e) => setForm((p) => ({ ...p, enabled: e.target.checked })),
|
|
522
544
|
className: "h-4 w-4 rounded border-ui-border-base"
|
|
523
545
|
}
|
|
524
546
|
),
|
|
525
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "
|
|
547
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable Advanced Credit/Debit Card" })
|
|
526
548
|
] }) }),
|
|
549
|
+
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Title", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
550
|
+
"input",
|
|
551
|
+
{
|
|
552
|
+
value: form.title,
|
|
553
|
+
onChange: (e) => setForm((p) => ({ ...p, title: e.target.value })),
|
|
554
|
+
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",
|
|
555
|
+
placeholder: "Credit or Debit Card"
|
|
556
|
+
}
|
|
557
|
+
) }),
|
|
527
558
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
528
559
|
FieldRow$1,
|
|
529
560
|
{
|
|
530
|
-
label: "
|
|
531
|
-
hint: "
|
|
532
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("
|
|
533
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
561
|
+
label: "Disable specific credit cards",
|
|
562
|
+
hint: "Select card brands to hide from the card form.",
|
|
563
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
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
|
+
}) }) })
|
|
543
594
|
] })
|
|
544
595
|
}
|
|
545
596
|
),
|
|
546
597
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
547
598
|
FieldRow$1,
|
|
548
599
|
{
|
|
549
|
-
label: "
|
|
550
|
-
hint: "
|
|
551
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("
|
|
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: [
|
|
552
603
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
553
|
-
"
|
|
604
|
+
"select",
|
|
554
605
|
{
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
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))
|
|
559
610
|
}
|
|
560
611
|
),
|
|
561
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
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" })
|
|
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
|
|
581
613
|
] })
|
|
582
614
|
}
|
|
583
615
|
),
|
|
584
|
-
/* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
"
|
|
595
|
-
|
|
596
|
-
value: form.creditCardStatementName,
|
|
597
|
-
onChange: (e) => setForm((p) => ({ ...p, creditCardStatementName: e.target.value })),
|
|
598
|
-
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",
|
|
599
|
-
placeholder: "PayPal"
|
|
600
|
-
}
|
|
601
|
-
) }),
|
|
602
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
603
|
-
FieldRow$1,
|
|
604
|
-
{
|
|
605
|
-
label: "Debug log",
|
|
606
|
-
hint: /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
607
|
-
"Log PayPal events such as Webhook, Payment, Refund.",
|
|
608
|
-
" ",
|
|
609
|
-
form.logPath ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
610
|
-
"Log location: ",
|
|
611
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: form.logPath })
|
|
612
|
-
] }) : null
|
|
613
|
-
] }),
|
|
614
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
615
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
616
|
-
"input",
|
|
617
|
-
{
|
|
618
|
-
type: "checkbox",
|
|
619
|
-
checked: form.enableLogging,
|
|
620
|
-
onChange: (e) => setForm((p) => ({ ...p, enableLogging: e.target.checked })),
|
|
621
|
-
className: "h-4 w-4 rounded border-ui-border-base"
|
|
622
|
-
}
|
|
623
|
-
),
|
|
624
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable logging" })
|
|
625
|
-
] })
|
|
626
|
-
}
|
|
627
|
-
)
|
|
616
|
+
/* @__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
|
+
),
|
|
626
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable card saving at checkout" })
|
|
627
|
+
] }) })
|
|
628
628
|
] })
|
|
629
629
|
}
|
|
630
630
|
)
|
|
631
631
|
] }) });
|
|
632
632
|
}
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
});
|
|
637
|
-
if (typeof window !== "undefined") {
|
|
638
|
-
const preloadHref = "https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js";
|
|
639
|
-
const existingPreload = document.head.querySelector(
|
|
640
|
-
`link[rel="preload"][href="${preloadHref}"]`
|
|
641
|
-
);
|
|
642
|
-
if (!existingPreload) {
|
|
643
|
-
const preloadLink = document.createElement("link");
|
|
644
|
-
preloadLink.rel = "preload";
|
|
645
|
-
preloadLink.href = preloadHref;
|
|
646
|
-
preloadLink.as = "script";
|
|
647
|
-
document.head.appendChild(preloadLink);
|
|
648
|
-
}
|
|
649
|
-
const existingScript = document.getElementById(
|
|
650
|
-
"paypal-partner-js"
|
|
651
|
-
);
|
|
652
|
-
if (!existingScript) {
|
|
653
|
-
const ppScript = document.createElement("script");
|
|
654
|
-
ppScript.id = "paypal-partner-js";
|
|
655
|
-
ppScript.src = preloadHref;
|
|
656
|
-
ppScript.async = true;
|
|
657
|
-
document.head.appendChild(ppScript);
|
|
633
|
+
function formatDate$2(value) {
|
|
634
|
+
if (!value) {
|
|
635
|
+
return "";
|
|
658
636
|
}
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
const RELOAD_KEY = "pp_onboard_reloaded_once";
|
|
663
|
-
const CACHE_EXPIRY = 10 * 60 * 1e3;
|
|
664
|
-
const ONBOARDING_COMPLETE_ENDPOINT = "/admin/paypal/onboard-complete";
|
|
665
|
-
const STATUS_ENDPOINT = "/admin/paypal/status";
|
|
666
|
-
const SAVE_CREDENTIALS_ENDPOINT = "/admin/paypal/save-credentials";
|
|
667
|
-
const DISCONNECT_ENDPOINT = "/admin/paypal/disconnect";
|
|
668
|
-
let cachedUrl = null;
|
|
669
|
-
if (typeof window !== "undefined") {
|
|
670
|
-
try {
|
|
671
|
-
const cached = localStorage.getItem(CACHE_KEY);
|
|
672
|
-
if (cached) {
|
|
673
|
-
const data = JSON.parse(cached);
|
|
674
|
-
if ((/* @__PURE__ */ new Date()).getTime() - data.ts < CACHE_EXPIRY) {
|
|
675
|
-
cachedUrl = data.url;
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
} catch (e) {
|
|
679
|
-
console.error("Cache read error:", e);
|
|
637
|
+
const parsed = new Date(value);
|
|
638
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
639
|
+
return value;
|
|
680
640
|
}
|
|
641
|
+
return parsed.toLocaleString();
|
|
681
642
|
}
|
|
682
|
-
function
|
|
683
|
-
const [
|
|
684
|
-
react.
|
|
685
|
-
fetch("/admin/paypal/environment", { method: "GET" }).then((r) => r.json()).then((d) => {
|
|
686
|
-
const v = (d == null ? void 0 : d.environment) === "live" ? "live" : "sandbox";
|
|
687
|
-
setEnv(v);
|
|
688
|
-
}).catch(() => {
|
|
689
|
-
});
|
|
690
|
-
}, []);
|
|
691
|
-
const [connState, setConnState] = react.useState("loading");
|
|
643
|
+
function PayPalAuditLogsPage() {
|
|
644
|
+
const [logs, setLogs] = react.useState([]);
|
|
645
|
+
const [loading, setLoading] = react.useState(false);
|
|
692
646
|
const [error, setError] = react.useState(null);
|
|
693
|
-
const
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
const paypalButtonRef = react.useRef(null);
|
|
702
|
-
const errorLogRef = react.useRef(null);
|
|
703
|
-
const runIdRef = react.useRef(0);
|
|
704
|
-
const currentRunId = react.useRef(0);
|
|
705
|
-
const ppBtnMeasureRef = react.useRef(null);
|
|
706
|
-
const [ppBtnWidth, setPpBtnWidth] = react.useState(null);
|
|
707
|
-
const canSaveManual = react.useMemo(() => {
|
|
708
|
-
return clientId.trim().length > 0 && secret.trim().length > 0;
|
|
709
|
-
}, [clientId, secret]);
|
|
710
|
-
const maskValue = react.useCallback((value, visibleChars = 4) => {
|
|
711
|
-
if (!value) return "";
|
|
712
|
-
if (value.length <= visibleChars) {
|
|
713
|
-
return "•".repeat(value.length);
|
|
714
|
-
}
|
|
715
|
-
return `${"•".repeat(Math.max(0, value.length - visibleChars))}${value.slice(
|
|
716
|
-
-visibleChars
|
|
717
|
-
)}`;
|
|
718
|
-
}, []);
|
|
719
|
-
const fetchFreshLink = react.useCallback(
|
|
720
|
-
(runId) => {
|
|
721
|
-
if (initLoaderRef.current) {
|
|
722
|
-
const loaderText = initLoaderRef.current.querySelector("#loader-text");
|
|
723
|
-
if (loaderText)
|
|
724
|
-
loaderText.textContent = "Generating onboarding session...";
|
|
725
|
-
}
|
|
726
|
-
fetch(SERVICE_URL, {
|
|
727
|
-
method: "POST",
|
|
728
|
-
headers: { "content-type": "application/json" },
|
|
729
|
-
body: JSON.stringify({
|
|
730
|
-
products: ["PPCP"]
|
|
731
|
-
})
|
|
732
|
-
}).then((r) => r.json()).then((data) => {
|
|
733
|
-
if (runId !== currentRunId.current) return;
|
|
734
|
-
const href = data == null ? void 0 : data.onboarding_url;
|
|
735
|
-
if (!href) {
|
|
736
|
-
showError("Onboarding URL not returned.");
|
|
737
|
-
return;
|
|
738
|
-
}
|
|
739
|
-
const finalUrl2 = href + (href.includes("?") ? "&" : "?") + "displayMode=minibrowser";
|
|
740
|
-
localStorage.setItem(
|
|
741
|
-
CACHE_KEY,
|
|
742
|
-
JSON.stringify({
|
|
743
|
-
url: finalUrl2,
|
|
744
|
-
ts: Date.now()
|
|
745
|
-
})
|
|
746
|
-
);
|
|
747
|
-
if (!localStorage.getItem(RELOAD_KEY)) {
|
|
748
|
-
localStorage.setItem(RELOAD_KEY, "1");
|
|
749
|
-
window.location.reload();
|
|
750
|
-
return;
|
|
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"
|
|
751
655
|
}
|
|
752
|
-
activatePayPal(finalUrl2, runId);
|
|
753
|
-
}).catch(() => {
|
|
754
|
-
if (runId !== currentRunId.current) return;
|
|
755
|
-
showError("Unable to connect to service.");
|
|
756
656
|
});
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
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);
|
|
765
668
|
}
|
|
766
|
-
setConnState("ready");
|
|
767
|
-
}, []);
|
|
768
|
-
const showError = react.useCallback((msg) => {
|
|
769
|
-
setConnState("error");
|
|
770
|
-
setError(msg);
|
|
771
669
|
}, []);
|
|
772
|
-
const activatePayPal = react.useCallback(
|
|
773
|
-
(url, runId) => {
|
|
774
|
-
if (paypalButtonRef.current) {
|
|
775
|
-
paypalButtonRef.current.href = url;
|
|
776
|
-
}
|
|
777
|
-
setFinalUrl(url);
|
|
778
|
-
const tryInit = () => {
|
|
779
|
-
var _a, _b;
|
|
780
|
-
if (runId !== currentRunId.current) return;
|
|
781
|
-
if ((_b = (_a = window.PAYPAL) == null ? void 0 : _a.apps) == null ? void 0 : _b.Signup) {
|
|
782
|
-
showUI();
|
|
783
|
-
return;
|
|
784
|
-
}
|
|
785
|
-
setTimeout(tryInit, 50);
|
|
786
|
-
};
|
|
787
|
-
tryInit();
|
|
788
|
-
},
|
|
789
|
-
[showUI]
|
|
790
|
-
);
|
|
791
670
|
react.useEffect(() => {
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
})
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
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());
|
|
835
741
|
}
|
|
836
|
-
|
|
837
|
-
|
|
742
|
+
});
|
|
743
|
+
const qs = params.toString();
|
|
744
|
+
return qs ? `?${qs}` : "";
|
|
745
|
+
}, [filters]);
|
|
746
|
+
const fetchDisputes = react.useCallback(async (source) => {
|
|
747
|
+
try {
|
|
748
|
+
setLoading(true);
|
|
838
749
|
setError(null);
|
|
839
|
-
const
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
};
|
|
844
|
-
try {
|
|
845
|
-
const res = await fetch(ONBOARDING_COMPLETE_ENDPOINT, {
|
|
846
|
-
method: "POST",
|
|
847
|
-
headers: { "content-type": "application/json" },
|
|
848
|
-
body: JSON.stringify(payload)
|
|
849
|
-
});
|
|
850
|
-
if (!res.ok) {
|
|
851
|
-
const txt = await res.text().catch(() => "");
|
|
852
|
-
throw new Error(txt || `Onboarding exchange failed (${res.status})`);
|
|
853
|
-
}
|
|
854
|
-
try {
|
|
855
|
-
const close1 = (_d = (_c = (_b = (_a = window.PAYPAL) == null ? void 0 : _a.apps) == null ? void 0 : _b.Signup) == null ? void 0 : _c.MiniBrowser) == null ? void 0 : _d.closeFlow;
|
|
856
|
-
if (typeof close1 === "function") close1();
|
|
857
|
-
} catch {
|
|
858
|
-
}
|
|
859
|
-
try {
|
|
860
|
-
const close2 = ((_g = (_f = (_e = window.PAYPAL) == null ? void 0 : _e.apps) == null ? void 0 : _f.Signup) == null ? void 0 : _g.miniBrowser) && window.PAYPAL.apps.Signup.miniBrowser.closeFlow;
|
|
861
|
-
if (typeof close2 === "function") close2();
|
|
862
|
-
} catch {
|
|
863
|
-
}
|
|
864
|
-
try {
|
|
865
|
-
localStorage.removeItem(CACHE_KEY);
|
|
866
|
-
localStorage.removeItem(RELOAD_KEY);
|
|
867
|
-
} catch {
|
|
750
|
+
const params = new URLSearchParams();
|
|
751
|
+
Object.entries(source).forEach(([key, value]) => {
|
|
752
|
+
if (value.trim()) {
|
|
753
|
+
params.set(key, value.trim());
|
|
868
754
|
}
|
|
869
|
-
window.location.href = window.location.href;
|
|
870
|
-
} catch (e) {
|
|
871
|
-
console.error(e);
|
|
872
|
-
setConnState("error");
|
|
873
|
-
setError((e == null ? void 0 : e.message) || "Exchange failed while saving credentials.");
|
|
874
|
-
setOnboardingInProgress(false);
|
|
875
|
-
}
|
|
876
|
-
};
|
|
877
|
-
return () => {
|
|
878
|
-
window.onboardingCallback = void 0;
|
|
879
|
-
};
|
|
880
|
-
}, [env]);
|
|
881
|
-
react.useLayoutEffect(() => {
|
|
882
|
-
const el = ppBtnMeasureRef.current;
|
|
883
|
-
if (!el) return;
|
|
884
|
-
const update = () => {
|
|
885
|
-
const w = Math.round(el.getBoundingClientRect().width || 0);
|
|
886
|
-
if (w > 0) setPpBtnWidth(w);
|
|
887
|
-
};
|
|
888
|
-
update();
|
|
889
|
-
let ro = null;
|
|
890
|
-
if (typeof ResizeObserver !== "undefined") {
|
|
891
|
-
ro = new ResizeObserver(() => update());
|
|
892
|
-
ro.observe(el);
|
|
893
|
-
} else {
|
|
894
|
-
window.addEventListener("resize", update);
|
|
895
|
-
}
|
|
896
|
-
return () => {
|
|
897
|
-
if (ro) ro.disconnect();
|
|
898
|
-
else window.removeEventListener("resize", update);
|
|
899
|
-
};
|
|
900
|
-
}, [connState, env, finalUrl]);
|
|
901
|
-
const handleConnectClick = (e) => {
|
|
902
|
-
if (connState !== "ready" || !finalUrl || onboardingInProgress) {
|
|
903
|
-
e.preventDefault();
|
|
904
|
-
}
|
|
905
|
-
};
|
|
906
|
-
const handleSaveManual = async () => {
|
|
907
|
-
if (!canSaveManual || onboardingInProgress) return;
|
|
908
|
-
setOnboardingInProgress(true);
|
|
909
|
-
setConnState("loading");
|
|
910
|
-
setError(null);
|
|
911
|
-
try {
|
|
912
|
-
const res = await fetch(SAVE_CREDENTIALS_ENDPOINT, {
|
|
913
|
-
method: "POST",
|
|
914
|
-
headers: { "content-type": "application/json" },
|
|
915
|
-
body: JSON.stringify({
|
|
916
|
-
clientId: clientId.trim(),
|
|
917
|
-
clientSecret: secret.trim()
|
|
918
|
-
})
|
|
919
755
|
});
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
seller_client_id_masked: maskValue(clientId.trim()),
|
|
927
|
-
seller_client_secret_masked: "••••••••"
|
|
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
|
+
}
|
|
928
762
|
});
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
localStorage.removeItem(RELOAD_KEY);
|
|
933
|
-
} catch {
|
|
763
|
+
if (!resp.ok) {
|
|
764
|
+
const message = await resp.text().catch(() => "");
|
|
765
|
+
throw new Error(message || "Failed to load disputes");
|
|
934
766
|
}
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
setError((
|
|
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([]);
|
|
939
772
|
} finally {
|
|
940
|
-
|
|
773
|
+
setLoading(false);
|
|
941
774
|
}
|
|
775
|
+
}, []);
|
|
776
|
+
react.useEffect(() => {
|
|
777
|
+
fetchDisputes(EMPTY_FILTERS);
|
|
778
|
+
}, [fetchDisputes]);
|
|
779
|
+
const onSubmit = (event) => {
|
|
780
|
+
event.preventDefault();
|
|
781
|
+
fetchDisputes(filters);
|
|
942
782
|
};
|
|
943
|
-
const
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
setOnboardingInProgress(true);
|
|
947
|
-
setConnState("loading");
|
|
948
|
-
setError(null);
|
|
949
|
-
setFinalUrl("");
|
|
950
|
-
setShowManual(false);
|
|
951
|
-
try {
|
|
952
|
-
const res = await fetch(DISCONNECT_ENDPOINT, {
|
|
953
|
-
method: "POST",
|
|
954
|
-
headers: { "content-type": "application/json" },
|
|
955
|
-
body: JSON.stringify({ environment: env })
|
|
956
|
-
});
|
|
957
|
-
if (!res.ok) {
|
|
958
|
-
const t = await res.text().catch(() => "");
|
|
959
|
-
throw new Error(t || `Disconnect failed (${res.status})`);
|
|
960
|
-
}
|
|
961
|
-
try {
|
|
962
|
-
localStorage.removeItem(CACHE_KEY);
|
|
963
|
-
localStorage.removeItem(RELOAD_KEY);
|
|
964
|
-
} catch {
|
|
965
|
-
}
|
|
966
|
-
currentRunId.current = ++runIdRef.current;
|
|
967
|
-
const runId = currentRunId.current;
|
|
968
|
-
fetchFreshLink(runId);
|
|
969
|
-
} catch (e) {
|
|
970
|
-
console.error(e);
|
|
971
|
-
setConnState("error");
|
|
972
|
-
setError((e == null ? void 0 : e.message) || "Failed to disconnect.");
|
|
973
|
-
} finally {
|
|
974
|
-
setOnboardingInProgress(false);
|
|
975
|
-
}
|
|
976
|
-
};
|
|
977
|
-
const handleEnvChange = async (e) => {
|
|
978
|
-
const next = e.target.value;
|
|
979
|
-
setEnv(next);
|
|
980
|
-
cachedUrl = null;
|
|
981
|
-
try {
|
|
982
|
-
await fetch("/admin/paypal/environment", {
|
|
983
|
-
method: "POST",
|
|
984
|
-
headers: { "content-type": "application/json" },
|
|
985
|
-
body: JSON.stringify({ environment: next })
|
|
986
|
-
});
|
|
987
|
-
} catch {
|
|
988
|
-
}
|
|
989
|
-
try {
|
|
990
|
-
localStorage.removeItem(CACHE_KEY);
|
|
991
|
-
localStorage.removeItem(RELOAD_KEY);
|
|
992
|
-
} catch {
|
|
993
|
-
}
|
|
783
|
+
const onReset = () => {
|
|
784
|
+
setFilters({ ...EMPTY_FILTERS });
|
|
785
|
+
fetchDisputes(EMPTY_FILTERS);
|
|
994
786
|
};
|
|
995
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
996
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
997
|
-
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold", children: "PayPal
|
|
998
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
className: "w-full rounded-md border border-ui-border-base bg-transparent px-3 py-2 text-sm",
|
|
1008
|
-
children: [
|
|
1009
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "sandbox", children: "Sandbox (Test Mode)" }),
|
|
1010
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "live", children: "Live (Production)" })
|
|
1011
|
-
]
|
|
1012
|
-
}
|
|
1013
|
-
) }),
|
|
1014
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium pt-2", children: env === "sandbox" ? "Connect to PayPal Sandbox" : "Connect to PayPal Live" }),
|
|
1015
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-xl", children: connState === "connected" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1016
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm text-green-600 bg-green-50 p-3 rounded border border-green-200", children: [
|
|
1017
|
-
"✅ Successfully connected to PayPal!",
|
|
1018
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1019
|
-
"a",
|
|
1020
|
-
{
|
|
1021
|
-
"data-paypal-button": "true",
|
|
1022
|
-
"data-paypal-onboard-complete": "onboardingCallback",
|
|
1023
|
-
href: "#",
|
|
1024
|
-
style: { display: "none" },
|
|
1025
|
-
children: "PayPal"
|
|
1026
|
-
}
|
|
1027
|
-
)
|
|
1028
|
-
] }),
|
|
1029
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 rounded-md border border-ui-border-base bg-ui-bg-subtle p-3 text-xs text-ui-fg-subtle", children: [
|
|
1030
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-ui-fg-base", children: "Connected PayPal account" }),
|
|
1031
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1", children: [
|
|
1032
|
-
"Email:",
|
|
1033
|
-
" ",
|
|
1034
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-ui-fg-base", children: (statusInfo == null ? void 0 : statusInfo.seller_email) || "Unavailable" })
|
|
1035
|
-
] })
|
|
1036
|
-
] }),
|
|
1037
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1038
|
-
"button",
|
|
1039
|
-
{
|
|
1040
|
-
type: "button",
|
|
1041
|
-
onClick: handleDisconnect,
|
|
1042
|
-
disabled: onboardingInProgress,
|
|
1043
|
-
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",
|
|
1044
|
-
children: "Disconnect"
|
|
1045
|
-
}
|
|
1046
|
-
) })
|
|
1047
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1048
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1049
|
-
"div",
|
|
1050
|
-
{
|
|
1051
|
-
ref: initLoaderRef,
|
|
1052
|
-
id: "init-loader",
|
|
1053
|
-
className: `status-msg mb-4 ${connState !== "loading" ? "hidden" : "block"}`,
|
|
1054
|
-
children: [
|
|
1055
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "loader inline-block align-middle mr-2" }),
|
|
1056
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { id: "loader-text", className: "text-sm", children: onboardingInProgress ? "Configuring connection to PayPal…" : "Checking connection..." })
|
|
1057
|
-
]
|
|
1058
|
-
}
|
|
1059
|
-
),
|
|
1060
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${connState === "ready" ? "block" : "hidden"}`, children: [
|
|
1061
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1062
|
-
"a",
|
|
1063
|
-
{
|
|
1064
|
-
ref: (node) => {
|
|
1065
|
-
paypalButtonRef.current = node;
|
|
1066
|
-
ppBtnMeasureRef.current = node;
|
|
1067
|
-
},
|
|
1068
|
-
id: "paypal-button",
|
|
1069
|
-
"data-paypal-button": "true",
|
|
1070
|
-
href: finalUrl || "#",
|
|
1071
|
-
"data-paypal-onboard-complete": "onboardingCallback",
|
|
1072
|
-
onClick: handleConnectClick,
|
|
1073
|
-
className: "btn-paypal",
|
|
1074
|
-
style: {
|
|
1075
|
-
borderRadius: "50px",
|
|
1076
|
-
textDecoration: "none",
|
|
1077
|
-
display: "inline-block",
|
|
1078
|
-
fontWeight: "bold",
|
|
1079
|
-
border: "none",
|
|
1080
|
-
cursor: onboardingInProgress ? "not-allowed" : "pointer",
|
|
1081
|
-
opacity: onboardingInProgress ? 0.6 : 1,
|
|
1082
|
-
pointerEvents: onboardingInProgress ? "none" : "auto"
|
|
1083
|
-
},
|
|
1084
|
-
children: "Connect to PayPal"
|
|
1085
|
-
}
|
|
1086
|
-
),
|
|
1087
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1088
|
-
"div",
|
|
1089
|
-
{
|
|
1090
|
-
className: "mt-2",
|
|
1091
|
-
style: {
|
|
1092
|
-
width: ppBtnWidth ? `${ppBtnWidth}px` : "auto",
|
|
1093
|
-
marginTop: "20px",
|
|
1094
|
-
marginBottom: "10px"
|
|
1095
|
-
},
|
|
1096
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] text-ui-fg-muted leading-none", children: "OR" }) })
|
|
1097
|
-
}
|
|
1098
|
-
),
|
|
1099
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1100
|
-
"button",
|
|
1101
|
-
{
|
|
1102
|
-
type: "button",
|
|
1103
|
-
onClick: () => setShowManual(!showManual),
|
|
1104
|
-
disabled: onboardingInProgress,
|
|
1105
|
-
className: "text-sm text-ui-fg-interactive underline whitespace-nowrap disabled:opacity-50 disabled:cursor-not-allowed",
|
|
1106
|
-
children: "Click here to insert credentials manually"
|
|
1107
|
-
}
|
|
1108
|
-
) })
|
|
1109
|
-
] }),
|
|
1110
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `${connState === "ready" ? "hidden" : "block"} mt-3`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1111
|
-
"button",
|
|
1112
|
-
{
|
|
1113
|
-
type: "button",
|
|
1114
|
-
onClick: () => setShowManual(!showManual),
|
|
1115
|
-
disabled: onboardingInProgress,
|
|
1116
|
-
className: "text-sm text-ui-fg-interactive underline whitespace-nowrap disabled:opacity-50 disabled:cursor-not-allowed",
|
|
1117
|
-
children: "Click here to insert credentials manually"
|
|
1118
|
-
}
|
|
1119
|
-
) }),
|
|
1120
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1121
|
-
"div",
|
|
1122
|
-
{
|
|
1123
|
-
ref: errorLogRef,
|
|
1124
|
-
id: "error-log",
|
|
1125
|
-
className: `mt-4 text-left text-xs bg-red-50 text-red-600 p-3 border border-red-200 rounded ${connState === "error" && error ? "block" : "hidden"}`,
|
|
1126
|
-
children: error
|
|
1127
|
-
}
|
|
1128
|
-
)
|
|
1129
|
-
] }) }),
|
|
1130
|
-
showManual && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "md:col-span-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ml-[260px] max-w-xl mt-4 grid grid-cols-1 gap-3 md:grid-cols-2", children: [
|
|
1131
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1132
|
-
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium", children: "Client ID" }),
|
|
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",
|
|
1133
799
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1134
800
|
"input",
|
|
1135
801
|
{
|
|
1136
|
-
|
|
1137
|
-
value:
|
|
1138
|
-
onChange: (
|
|
1139
|
-
|
|
1140
|
-
className: "rounded-md border border-ui-border-base bg-transparent px-3 py-2 text-sm disabled:opacity-50",
|
|
1141
|
-
placeholder: env === "sandbox" ? "Sandbox Client ID" : "Live Client ID"
|
|
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"
|
|
1142
806
|
}
|
|
1143
807
|
)
|
|
1144
808
|
] }),
|
|
1145
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
1146
|
-
|
|
809
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
|
|
810
|
+
"Status",
|
|
1147
811
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1148
812
|
"input",
|
|
1149
813
|
{
|
|
1150
|
-
|
|
1151
|
-
value:
|
|
1152
|
-
onChange: (
|
|
1153
|
-
|
|
1154
|
-
className: "rounded-md border border-ui-border-base bg-transparent px-3 py-2 text-sm disabled:opacity-50",
|
|
1155
|
-
placeholder: env === "sandbox" ? "Sandbox Secret" : "Live Secret"
|
|
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"
|
|
1156
818
|
}
|
|
1157
819
|
)
|
|
1158
820
|
] }),
|
|
1159
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
1160
|
-
|
|
821
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
|
|
822
|
+
"Order ID",
|
|
1161
823
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1162
824
|
"input",
|
|
1163
825
|
{
|
|
1164
|
-
|
|
1165
|
-
value:
|
|
1166
|
-
onChange: (
|
|
1167
|
-
|
|
1168
|
-
className: "rounded-md border border-ui-border-base bg-transparent px-3 py-2 text-sm disabled:opacity-50",
|
|
1169
|
-
placeholder: "Merchant ID"
|
|
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_..."
|
|
1170
830
|
}
|
|
1171
831
|
)
|
|
1172
832
|
] }),
|
|
1173
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
1174
|
-
|
|
1175
|
-
"button",
|
|
1176
|
-
{
|
|
1177
|
-
type: "button",
|
|
1178
|
-
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",
|
|
1179
|
-
onClick: () => setShowManual(false),
|
|
1180
|
-
disabled: onboardingInProgress,
|
|
1181
|
-
children: "Cancel"
|
|
1182
|
-
}
|
|
1183
|
-
),
|
|
833
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
|
|
834
|
+
"Cart ID",
|
|
1184
835
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1185
|
-
"
|
|
836
|
+
"input",
|
|
1186
837
|
{
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
children: "Save credentials"
|
|
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_..."
|
|
1192
842
|
}
|
|
1193
843
|
)
|
|
1194
844
|
] })
|
|
1195
|
-
] })
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
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
|
+
] }) });
|
|
1216
906
|
}
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
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);
|
|
1220
922
|
}
|
|
1221
|
-
const
|
|
1222
|
-
|
|
1223
|
-
|
|
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);
|
|
1224
932
|
}
|
|
1225
|
-
return parsed.toLocaleString();
|
|
1226
933
|
}
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
934
|
+
const SERVICE_URL = "/admin/paypal/onboarding-link";
|
|
935
|
+
const CACHE_KEY = "pp_onboard_cache";
|
|
936
|
+
const RELOAD_KEY = "pp_onboard_reloaded_once";
|
|
937
|
+
const CACHE_EXPIRY = 10 * 60 * 1e3;
|
|
938
|
+
const ONBOARDING_COMPLETE_ENDPOINT = "/admin/paypal/onboard-complete";
|
|
939
|
+
const STATUS_ENDPOINT = "/admin/paypal/status";
|
|
940
|
+
const SAVE_CREDENTIALS_ENDPOINT = "/admin/paypal/save-credentials";
|
|
941
|
+
const DISCONNECT_ENDPOINT = "/admin/paypal/disconnect";
|
|
942
|
+
let cachedUrl = null;
|
|
943
|
+
if (typeof window !== "undefined") {
|
|
944
|
+
try {
|
|
945
|
+
const cached = localStorage.getItem(CACHE_KEY);
|
|
946
|
+
if (cached) {
|
|
947
|
+
const data = JSON.parse(cached);
|
|
948
|
+
if ((/* @__PURE__ */ new Date()).getTime() - data.ts < CACHE_EXPIRY) {
|
|
949
|
+
cachedUrl = data.url;
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
} catch (e) {
|
|
953
|
+
console.error("Cache read error:", e);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
function PayPalConnectionPage() {
|
|
957
|
+
const [env, setEnv] = react.useState("sandbox");
|
|
958
|
+
react.useEffect(() => {
|
|
959
|
+
fetch("/admin/paypal/environment", { method: "GET" }).then((r) => r.json()).then((d) => {
|
|
960
|
+
const v = (d == null ? void 0 : d.environment) === "live" ? "live" : "sandbox";
|
|
961
|
+
setEnv(v);
|
|
962
|
+
}).catch(() => {
|
|
963
|
+
});
|
|
964
|
+
}, []);
|
|
965
|
+
const [connState, setConnState] = react.useState("loading");
|
|
1230
966
|
const [error, setError] = react.useState(null);
|
|
1231
|
-
const
|
|
1232
|
-
|
|
1233
|
-
|
|
967
|
+
const [finalUrl, setFinalUrl] = react.useState("");
|
|
968
|
+
const [showManual, setShowManual] = react.useState(false);
|
|
969
|
+
const [clientId, setClientId] = react.useState("");
|
|
970
|
+
const [secret, setSecret] = react.useState("");
|
|
971
|
+
const [merchantId, setMerchantId] = react.useState("");
|
|
972
|
+
const [statusInfo, setStatusInfo] = react.useState(null);
|
|
973
|
+
const [onboardingInProgress, setOnboardingInProgress] = react.useState(false);
|
|
974
|
+
const initLoaderRef = react.useRef(null);
|
|
975
|
+
const paypalButtonRef = react.useRef(null);
|
|
976
|
+
const errorLogRef = react.useRef(null);
|
|
977
|
+
const runIdRef = react.useRef(0);
|
|
978
|
+
const currentRunId = react.useRef(0);
|
|
979
|
+
const ppBtnMeasureRef = react.useRef(null);
|
|
980
|
+
const [ppBtnWidth, setPpBtnWidth] = react.useState(null);
|
|
981
|
+
const canSaveManual = react.useMemo(() => {
|
|
982
|
+
return clientId.trim().length > 0 && secret.trim().length > 0;
|
|
983
|
+
}, [clientId, secret]);
|
|
984
|
+
const maskValue = react.useCallback((value, visibleChars = 4) => {
|
|
985
|
+
if (!value) return "";
|
|
986
|
+
if (value.length <= visibleChars) {
|
|
987
|
+
return "•".repeat(value.length);
|
|
988
|
+
}
|
|
989
|
+
return `${"•".repeat(Math.max(0, value.length - visibleChars))}${value.slice(
|
|
990
|
+
-visibleChars
|
|
991
|
+
)}`;
|
|
992
|
+
}, []);
|
|
993
|
+
const fetchFreshLink = react.useCallback(
|
|
994
|
+
(runId) => {
|
|
995
|
+
if (initLoaderRef.current) {
|
|
996
|
+
const loaderText = initLoaderRef.current.querySelector("#loader-text");
|
|
997
|
+
if (loaderText)
|
|
998
|
+
loaderText.textContent = "Generating onboarding session...";
|
|
999
|
+
}
|
|
1000
|
+
fetch(SERVICE_URL, {
|
|
1001
|
+
method: "POST",
|
|
1002
|
+
headers: { "content-type": "application/json" },
|
|
1003
|
+
body: JSON.stringify({
|
|
1004
|
+
products: ["PPCP"]
|
|
1005
|
+
})
|
|
1006
|
+
}).then((r) => r.json()).then((data) => {
|
|
1007
|
+
if (runId !== currentRunId.current) return;
|
|
1008
|
+
const href = data == null ? void 0 : data.onboarding_url;
|
|
1009
|
+
if (!href) {
|
|
1010
|
+
showError("Onboarding URL not returned.");
|
|
1011
|
+
return;
|
|
1012
|
+
}
|
|
1013
|
+
const finalUrl2 = href + (href.includes("?") ? "&" : "?") + "displayMode=minibrowser";
|
|
1014
|
+
localStorage.setItem(
|
|
1015
|
+
CACHE_KEY,
|
|
1016
|
+
JSON.stringify({
|
|
1017
|
+
url: finalUrl2,
|
|
1018
|
+
ts: Date.now()
|
|
1019
|
+
})
|
|
1020
|
+
);
|
|
1021
|
+
if (!localStorage.getItem(RELOAD_KEY)) {
|
|
1022
|
+
localStorage.setItem(RELOAD_KEY, "1");
|
|
1023
|
+
window.location.reload();
|
|
1024
|
+
return;
|
|
1025
|
+
}
|
|
1026
|
+
activatePayPal(finalUrl2, runId);
|
|
1027
|
+
}).catch(() => {
|
|
1028
|
+
if (runId !== currentRunId.current) return;
|
|
1029
|
+
showError("Unable to connect to service.");
|
|
1030
|
+
});
|
|
1031
|
+
},
|
|
1032
|
+
[env]
|
|
1033
|
+
);
|
|
1034
|
+
const showUI = react.useCallback(() => {
|
|
1035
|
+
var _a, _b, _c, _d;
|
|
1036
|
+
const btn = document.querySelector('[data-paypal-button="true"]');
|
|
1037
|
+
if (btn && ((_d = (_c = (_b = (_a = window.PAYPAL) == null ? void 0 : _a.apps) == null ? void 0 : _b.Signup) == null ? void 0 : _c.miniBrowser) == null ? void 0 : _d.init)) {
|
|
1038
|
+
window.PAYPAL.apps.Signup.miniBrowser.init();
|
|
1039
|
+
}
|
|
1040
|
+
setConnState("ready");
|
|
1041
|
+
}, []);
|
|
1042
|
+
const showError = react.useCallback((msg) => {
|
|
1043
|
+
setConnState("error");
|
|
1044
|
+
setError(msg);
|
|
1045
|
+
}, []);
|
|
1046
|
+
const activatePayPal = react.useCallback(
|
|
1047
|
+
(url, runId) => {
|
|
1048
|
+
if (paypalButtonRef.current) {
|
|
1049
|
+
paypalButtonRef.current.href = url;
|
|
1050
|
+
}
|
|
1051
|
+
setFinalUrl(url);
|
|
1052
|
+
const tryInit = () => {
|
|
1053
|
+
var _a, _b;
|
|
1054
|
+
if (runId !== currentRunId.current) return;
|
|
1055
|
+
if ((_b = (_a = window.PAYPAL) == null ? void 0 : _a.apps) == null ? void 0 : _b.Signup) {
|
|
1056
|
+
showUI();
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
setTimeout(tryInit, 50);
|
|
1060
|
+
};
|
|
1061
|
+
tryInit();
|
|
1062
|
+
},
|
|
1063
|
+
[showUI]
|
|
1064
|
+
);
|
|
1065
|
+
react.useEffect(() => {
|
|
1066
|
+
currentRunId.current = ++runIdRef.current;
|
|
1067
|
+
const runId = currentRunId.current;
|
|
1068
|
+
let cancelled = false;
|
|
1069
|
+
const run = async () => {
|
|
1070
|
+
setConnState("loading");
|
|
1234
1071
|
setError(null);
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1072
|
+
setFinalUrl("");
|
|
1073
|
+
try {
|
|
1074
|
+
const r = await fetch(`${STATUS_ENDPOINT}?environment=${env}`, {
|
|
1075
|
+
method: "GET"
|
|
1076
|
+
});
|
|
1077
|
+
const st = await r.json().catch(() => ({}));
|
|
1078
|
+
if (cancelled || runId !== currentRunId.current) return;
|
|
1079
|
+
setStatusInfo(st);
|
|
1080
|
+
const isConnected = (st == null ? void 0 : st.status) === "connected" && (st == null ? void 0 : st.seller_client_id_present) === true;
|
|
1081
|
+
if (isConnected) {
|
|
1082
|
+
setConnState("connected");
|
|
1083
|
+
setShowManual(false);
|
|
1084
|
+
return;
|
|
1085
|
+
}
|
|
1086
|
+
} catch (e) {
|
|
1087
|
+
console.error(e);
|
|
1088
|
+
}
|
|
1089
|
+
if (cachedUrl) {
|
|
1090
|
+
console.log("Using prioritized cache...");
|
|
1091
|
+
activatePayPal(cachedUrl, runId);
|
|
1092
|
+
} else {
|
|
1093
|
+
fetchFreshLink(runId);
|
|
1094
|
+
}
|
|
1095
|
+
};
|
|
1096
|
+
run();
|
|
1097
|
+
return () => {
|
|
1098
|
+
cancelled = true;
|
|
1099
|
+
currentRunId.current = 0;
|
|
1100
|
+
};
|
|
1101
|
+
}, [env, fetchFreshLink, activatePayPal]);
|
|
1102
|
+
react.useLayoutEffect(() => {
|
|
1103
|
+
window.onboardingCallback = async function(authCode, sharedId) {
|
|
1104
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1105
|
+
try {
|
|
1106
|
+
;
|
|
1107
|
+
window.onbeforeunload = "";
|
|
1108
|
+
} catch {
|
|
1109
|
+
}
|
|
1110
|
+
setOnboardingInProgress(true);
|
|
1111
|
+
setConnState("loading");
|
|
1112
|
+
setError(null);
|
|
1113
|
+
const payload = {
|
|
1114
|
+
authCode,
|
|
1115
|
+
sharedId,
|
|
1116
|
+
env: env === "sandbox" ? "sandbox" : "live"
|
|
1117
|
+
};
|
|
1118
|
+
try {
|
|
1119
|
+
const res = await fetch(ONBOARDING_COMPLETE_ENDPOINT, {
|
|
1120
|
+
method: "POST",
|
|
1121
|
+
headers: { "content-type": "application/json" },
|
|
1122
|
+
body: JSON.stringify(payload)
|
|
1123
|
+
});
|
|
1124
|
+
if (!res.ok) {
|
|
1125
|
+
const txt = await res.text().catch(() => "");
|
|
1126
|
+
throw new Error(txt || `Onboarding exchange failed (${res.status})`);
|
|
1127
|
+
}
|
|
1128
|
+
try {
|
|
1129
|
+
const close1 = (_d = (_c = (_b = (_a = window.PAYPAL) == null ? void 0 : _a.apps) == null ? void 0 : _b.Signup) == null ? void 0 : _c.MiniBrowser) == null ? void 0 : _d.closeFlow;
|
|
1130
|
+
if (typeof close1 === "function") close1();
|
|
1131
|
+
} catch {
|
|
1132
|
+
}
|
|
1133
|
+
try {
|
|
1134
|
+
const close2 = ((_g = (_f = (_e = window.PAYPAL) == null ? void 0 : _e.apps) == null ? void 0 : _f.Signup) == null ? void 0 : _g.miniBrowser) && window.PAYPAL.apps.Signup.miniBrowser.closeFlow;
|
|
1135
|
+
if (typeof close2 === "function") close2();
|
|
1136
|
+
} catch {
|
|
1137
|
+
}
|
|
1138
|
+
try {
|
|
1139
|
+
localStorage.removeItem(CACHE_KEY);
|
|
1140
|
+
localStorage.removeItem(RELOAD_KEY);
|
|
1141
|
+
} catch {
|
|
1239
1142
|
}
|
|
1143
|
+
window.location.href = window.location.href;
|
|
1144
|
+
} catch (e) {
|
|
1145
|
+
console.error(e);
|
|
1146
|
+
setConnState("error");
|
|
1147
|
+
setError((e == null ? void 0 : e.message) || "Exchange failed while saving credentials.");
|
|
1148
|
+
setOnboardingInProgress(false);
|
|
1149
|
+
}
|
|
1150
|
+
};
|
|
1151
|
+
return () => {
|
|
1152
|
+
window.onboardingCallback = void 0;
|
|
1153
|
+
};
|
|
1154
|
+
}, [env]);
|
|
1155
|
+
react.useLayoutEffect(() => {
|
|
1156
|
+
const el = ppBtnMeasureRef.current;
|
|
1157
|
+
if (!el) return;
|
|
1158
|
+
const update = () => {
|
|
1159
|
+
const w = Math.round(el.getBoundingClientRect().width || 0);
|
|
1160
|
+
if (w > 0) setPpBtnWidth(w);
|
|
1161
|
+
};
|
|
1162
|
+
update();
|
|
1163
|
+
let ro = null;
|
|
1164
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
1165
|
+
ro = new ResizeObserver(() => update());
|
|
1166
|
+
ro.observe(el);
|
|
1167
|
+
} else {
|
|
1168
|
+
window.addEventListener("resize", update);
|
|
1169
|
+
}
|
|
1170
|
+
return () => {
|
|
1171
|
+
if (ro) ro.disconnect();
|
|
1172
|
+
else window.removeEventListener("resize", update);
|
|
1173
|
+
};
|
|
1174
|
+
}, [connState, env, finalUrl]);
|
|
1175
|
+
const handleConnectClick = (e) => {
|
|
1176
|
+
if (connState !== "ready" || !finalUrl || onboardingInProgress) {
|
|
1177
|
+
e.preventDefault();
|
|
1178
|
+
}
|
|
1179
|
+
};
|
|
1180
|
+
const handleSaveManual = async () => {
|
|
1181
|
+
if (!canSaveManual || onboardingInProgress) return;
|
|
1182
|
+
setOnboardingInProgress(true);
|
|
1183
|
+
setConnState("loading");
|
|
1184
|
+
setError(null);
|
|
1185
|
+
try {
|
|
1186
|
+
const res = await fetch(SAVE_CREDENTIALS_ENDPOINT, {
|
|
1187
|
+
method: "POST",
|
|
1188
|
+
headers: { "content-type": "application/json" },
|
|
1189
|
+
body: JSON.stringify({
|
|
1190
|
+
clientId: clientId.trim(),
|
|
1191
|
+
clientSecret: secret.trim()
|
|
1192
|
+
})
|
|
1240
1193
|
});
|
|
1241
|
-
if (!
|
|
1242
|
-
const
|
|
1243
|
-
throw new Error(
|
|
1194
|
+
if (!res.ok) {
|
|
1195
|
+
const txt = await res.text().catch(() => "");
|
|
1196
|
+
throw new Error(txt || `Save credentials failed (${res.status})`);
|
|
1244
1197
|
}
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1198
|
+
setConnState("connected");
|
|
1199
|
+
setStatusInfo({
|
|
1200
|
+
seller_client_id_masked: maskValue(clientId.trim()),
|
|
1201
|
+
seller_client_secret_masked: "••••••••"
|
|
1202
|
+
});
|
|
1203
|
+
setShowManual(false);
|
|
1204
|
+
try {
|
|
1205
|
+
localStorage.removeItem(CACHE_KEY);
|
|
1206
|
+
localStorage.removeItem(RELOAD_KEY);
|
|
1207
|
+
} catch {
|
|
1208
|
+
}
|
|
1209
|
+
} catch (e) {
|
|
1210
|
+
console.error(e);
|
|
1211
|
+
setConnState("error");
|
|
1212
|
+
setError((e == null ? void 0 : e.message) || "Failed to save credentials.");
|
|
1250
1213
|
} finally {
|
|
1251
|
-
|
|
1214
|
+
setOnboardingInProgress(false);
|
|
1252
1215
|
}
|
|
1253
|
-
}
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
/* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
|
|
1263
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
1264
|
-
/* @__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: [
|
|
1265
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Latest events" }),
|
|
1266
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1267
|
-
"button",
|
|
1268
|
-
{
|
|
1269
|
-
type: "button",
|
|
1270
|
-
onClick: fetchLogs,
|
|
1271
|
-
className: "rounded-md border border-ui-border-base px-3 py-2 text-sm text-ui-fg-base",
|
|
1272
|
-
disabled: loading,
|
|
1273
|
-
children: loading ? "Refreshing..." : "Refresh"
|
|
1274
|
-
}
|
|
1275
|
-
)
|
|
1276
|
-
] }) }),
|
|
1277
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4", children: [
|
|
1278
|
-
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,
|
|
1279
|
-
!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,
|
|
1280
|
-
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: [
|
|
1281
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "text-ui-fg-muted", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
1282
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "pb-2 pr-4 font-medium", children: "Timestamp" }),
|
|
1283
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "pb-2 pr-4 font-medium", children: "Event" }),
|
|
1284
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "pb-2 font-medium", children: "Details" })
|
|
1285
|
-
] }) }),
|
|
1286
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: logs.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-t border-ui-border-base", children: [
|
|
1287
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-3 pr-4 text-ui-fg-base", children: formatDate$2(entry.created_at) || "—" }),
|
|
1288
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-3 pr-4 text-ui-fg-base", children: entry.event_type || "—" }),
|
|
1289
|
-
/* @__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) }) })
|
|
1290
|
-
] }, entry.id)) })
|
|
1291
|
-
] }) }) : null
|
|
1292
|
-
] })
|
|
1293
|
-
] })
|
|
1294
|
-
] }) });
|
|
1295
|
-
}
|
|
1296
|
-
function PayPalApplePayPage() {
|
|
1297
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
1298
|
-
}
|
|
1299
|
-
const EMPTY_FILTERS = {
|
|
1300
|
-
dispute_id: "",
|
|
1301
|
-
status: "",
|
|
1302
|
-
order_id: "",
|
|
1303
|
-
cart_id: ""
|
|
1304
|
-
};
|
|
1305
|
-
function formatDate$1(value) {
|
|
1306
|
-
if (!value) {
|
|
1307
|
-
return "";
|
|
1308
|
-
}
|
|
1309
|
-
const parsed = new Date(value);
|
|
1310
|
-
if (Number.isNaN(parsed.getTime())) {
|
|
1311
|
-
return value;
|
|
1312
|
-
}
|
|
1313
|
-
return parsed.toLocaleString();
|
|
1314
|
-
}
|
|
1315
|
-
function PayPalDisputesPage() {
|
|
1316
|
-
const [filters, setFilters] = react.useState({ ...EMPTY_FILTERS });
|
|
1317
|
-
const [disputes, setDisputes] = react.useState([]);
|
|
1318
|
-
const [loading, setLoading] = react.useState(false);
|
|
1319
|
-
const [error, setError] = react.useState(null);
|
|
1320
|
-
const queryString = react.useMemo(() => {
|
|
1321
|
-
const params = new URLSearchParams();
|
|
1322
|
-
Object.entries(filters).forEach(([key, value]) => {
|
|
1323
|
-
if (value.trim()) {
|
|
1324
|
-
params.set(key, value.trim());
|
|
1325
|
-
}
|
|
1326
|
-
});
|
|
1327
|
-
const qs = params.toString();
|
|
1328
|
-
return qs ? `?${qs}` : "";
|
|
1329
|
-
}, [filters]);
|
|
1330
|
-
const fetchDisputes = react.useCallback(async (source) => {
|
|
1216
|
+
};
|
|
1217
|
+
const handleDisconnect = async () => {
|
|
1218
|
+
if (onboardingInProgress) return;
|
|
1219
|
+
if (!window.confirm("Disconnect PayPal for this environment?")) return;
|
|
1220
|
+
setOnboardingInProgress(true);
|
|
1221
|
+
setConnState("loading");
|
|
1222
|
+
setError(null);
|
|
1223
|
+
setFinalUrl("");
|
|
1224
|
+
setShowManual(false);
|
|
1331
1225
|
try {
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
if (value.trim()) {
|
|
1337
|
-
params.set(key, value.trim());
|
|
1338
|
-
}
|
|
1339
|
-
});
|
|
1340
|
-
const qs = params.toString();
|
|
1341
|
-
const resp = await fetch(`/admin/paypal/disputes${qs ? `?${qs}` : ""}`, {
|
|
1342
|
-
credentials: "include",
|
|
1343
|
-
headers: {
|
|
1344
|
-
Accept: "application/json"
|
|
1345
|
-
}
|
|
1226
|
+
const res = await fetch(DISCONNECT_ENDPOINT, {
|
|
1227
|
+
method: "POST",
|
|
1228
|
+
headers: { "content-type": "application/json" },
|
|
1229
|
+
body: JSON.stringify({ environment: env })
|
|
1346
1230
|
});
|
|
1347
|
-
if (!
|
|
1348
|
-
const
|
|
1349
|
-
throw new Error(
|
|
1231
|
+
if (!res.ok) {
|
|
1232
|
+
const t = await res.text().catch(() => "");
|
|
1233
|
+
throw new Error(t || `Disconnect failed (${res.status})`);
|
|
1350
1234
|
}
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1235
|
+
try {
|
|
1236
|
+
localStorage.removeItem(CACHE_KEY);
|
|
1237
|
+
localStorage.removeItem(RELOAD_KEY);
|
|
1238
|
+
} catch {
|
|
1239
|
+
}
|
|
1240
|
+
currentRunId.current = ++runIdRef.current;
|
|
1241
|
+
const runId = currentRunId.current;
|
|
1242
|
+
fetchFreshLink(runId);
|
|
1243
|
+
} catch (e) {
|
|
1244
|
+
console.error(e);
|
|
1245
|
+
setConnState("error");
|
|
1246
|
+
setError((e == null ? void 0 : e.message) || "Failed to disconnect.");
|
|
1356
1247
|
} finally {
|
|
1357
|
-
|
|
1248
|
+
setOnboardingInProgress(false);
|
|
1358
1249
|
}
|
|
1359
|
-
}, []);
|
|
1360
|
-
react.useEffect(() => {
|
|
1361
|
-
fetchDisputes(EMPTY_FILTERS);
|
|
1362
|
-
}, [fetchDisputes]);
|
|
1363
|
-
const onSubmit = (event) => {
|
|
1364
|
-
event.preventDefault();
|
|
1365
|
-
fetchDisputes(filters);
|
|
1366
1250
|
};
|
|
1367
|
-
const
|
|
1368
|
-
|
|
1369
|
-
|
|
1251
|
+
const handleEnvChange = async (e) => {
|
|
1252
|
+
const next = e.target.value;
|
|
1253
|
+
setEnv(next);
|
|
1254
|
+
cachedUrl = null;
|
|
1255
|
+
try {
|
|
1256
|
+
await fetch("/admin/paypal/environment", {
|
|
1257
|
+
method: "POST",
|
|
1258
|
+
headers: { "content-type": "application/json" },
|
|
1259
|
+
body: JSON.stringify({ environment: next })
|
|
1260
|
+
});
|
|
1261
|
+
} catch {
|
|
1262
|
+
}
|
|
1263
|
+
try {
|
|
1264
|
+
localStorage.removeItem(CACHE_KEY);
|
|
1265
|
+
localStorage.removeItem(RELOAD_KEY);
|
|
1266
|
+
} catch {
|
|
1267
|
+
}
|
|
1370
1268
|
};
|
|
1371
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
1372
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1373
|
-
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold
|
|
1374
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1269
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6", children: [
|
|
1270
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
1271
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold", children: "PayPal Gateway By Easy Payment" }),
|
|
1272
|
+
/* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
|
|
1273
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-ui-border-base p-4 shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-y-6 md:grid-cols-[260px_1fr] md:items-start", children: [
|
|
1274
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium pt-2", children: "Environment" }),
|
|
1275
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-xl", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1276
|
+
"select",
|
|
1277
|
+
{
|
|
1278
|
+
value: env,
|
|
1279
|
+
onChange: handleEnvChange,
|
|
1280
|
+
disabled: onboardingInProgress,
|
|
1281
|
+
className: "w-full rounded-md border border-ui-border-base bg-transparent px-3 py-2 text-sm",
|
|
1282
|
+
children: [
|
|
1283
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "sandbox", children: "Sandbox (Test Mode)" }),
|
|
1284
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "live", children: "Live (Production)" })
|
|
1285
|
+
]
|
|
1286
|
+
}
|
|
1287
|
+
) }),
|
|
1288
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium pt-2", children: env === "sandbox" ? "Connect to PayPal Sandbox" : "Connect to PayPal Live" }),
|
|
1289
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-xl", children: connState === "connected" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1290
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm text-green-600 bg-green-50 p-3 rounded border border-green-200", children: [
|
|
1291
|
+
"✅ Successfully connected to PayPal!",
|
|
1383
1292
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1384
|
-
"
|
|
1293
|
+
"a",
|
|
1385
1294
|
{
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1295
|
+
"data-paypal-button": "true",
|
|
1296
|
+
"data-paypal-onboard-complete": "onboardingCallback",
|
|
1297
|
+
href: "#",
|
|
1298
|
+
style: { display: "none" },
|
|
1299
|
+
children: "PayPal"
|
|
1390
1300
|
}
|
|
1391
1301
|
)
|
|
1392
1302
|
] }),
|
|
1393
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
1394
|
-
"
|
|
1303
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 rounded-md border border-ui-border-base bg-ui-bg-subtle p-3 text-xs text-ui-fg-subtle", children: [
|
|
1304
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-ui-fg-base", children: "Connected PayPal account" }),
|
|
1305
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1", children: [
|
|
1306
|
+
"Email:",
|
|
1307
|
+
" ",
|
|
1308
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-ui-fg-base", children: (statusInfo == null ? void 0 : statusInfo.seller_email) || "Unavailable" })
|
|
1309
|
+
] })
|
|
1310
|
+
] }),
|
|
1311
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1312
|
+
"button",
|
|
1313
|
+
{
|
|
1314
|
+
type: "button",
|
|
1315
|
+
onClick: handleDisconnect,
|
|
1316
|
+
disabled: onboardingInProgress,
|
|
1317
|
+
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",
|
|
1318
|
+
children: "Disconnect"
|
|
1319
|
+
}
|
|
1320
|
+
) })
|
|
1321
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1322
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1323
|
+
"div",
|
|
1324
|
+
{
|
|
1325
|
+
ref: initLoaderRef,
|
|
1326
|
+
id: "init-loader",
|
|
1327
|
+
className: `status-msg mb-4 ${connState !== "loading" ? "hidden" : "block"}`,
|
|
1328
|
+
children: [
|
|
1329
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "loader inline-block align-middle mr-2" }),
|
|
1330
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { id: "loader-text", className: "text-sm", children: onboardingInProgress ? "Configuring connection to PayPal…" : "Checking connection..." })
|
|
1331
|
+
]
|
|
1332
|
+
}
|
|
1333
|
+
),
|
|
1334
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${connState === "ready" ? "block" : "hidden"}`, children: [
|
|
1335
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1336
|
+
"a",
|
|
1337
|
+
{
|
|
1338
|
+
ref: (node) => {
|
|
1339
|
+
paypalButtonRef.current = node;
|
|
1340
|
+
ppBtnMeasureRef.current = node;
|
|
1341
|
+
},
|
|
1342
|
+
id: "paypal-button",
|
|
1343
|
+
"data-paypal-button": "true",
|
|
1344
|
+
href: finalUrl || "#",
|
|
1345
|
+
"data-paypal-onboard-complete": "onboardingCallback",
|
|
1346
|
+
onClick: handleConnectClick,
|
|
1347
|
+
className: "btn-paypal",
|
|
1348
|
+
style: {
|
|
1349
|
+
borderRadius: "50px",
|
|
1350
|
+
textDecoration: "none",
|
|
1351
|
+
display: "inline-block",
|
|
1352
|
+
fontWeight: "bold",
|
|
1353
|
+
border: "none",
|
|
1354
|
+
cursor: onboardingInProgress ? "not-allowed" : "pointer",
|
|
1355
|
+
opacity: onboardingInProgress ? 0.6 : 1,
|
|
1356
|
+
pointerEvents: onboardingInProgress ? "none" : "auto"
|
|
1357
|
+
},
|
|
1358
|
+
children: "Connect to PayPal"
|
|
1359
|
+
}
|
|
1360
|
+
),
|
|
1361
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1362
|
+
"div",
|
|
1363
|
+
{
|
|
1364
|
+
className: "mt-2",
|
|
1365
|
+
style: {
|
|
1366
|
+
width: ppBtnWidth ? `${ppBtnWidth}px` : "auto",
|
|
1367
|
+
marginTop: "20px",
|
|
1368
|
+
marginBottom: "10px"
|
|
1369
|
+
},
|
|
1370
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] text-ui-fg-muted leading-none", children: "OR" }) })
|
|
1371
|
+
}
|
|
1372
|
+
),
|
|
1373
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1374
|
+
"button",
|
|
1375
|
+
{
|
|
1376
|
+
type: "button",
|
|
1377
|
+
onClick: () => setShowManual(!showManual),
|
|
1378
|
+
disabled: onboardingInProgress,
|
|
1379
|
+
className: "text-sm text-ui-fg-interactive underline whitespace-nowrap disabled:opacity-50 disabled:cursor-not-allowed",
|
|
1380
|
+
children: "Click here to insert credentials manually"
|
|
1381
|
+
}
|
|
1382
|
+
) })
|
|
1383
|
+
] }),
|
|
1384
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `${connState === "ready" ? "hidden" : "block"} mt-3`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1385
|
+
"button",
|
|
1386
|
+
{
|
|
1387
|
+
type: "button",
|
|
1388
|
+
onClick: () => setShowManual(!showManual),
|
|
1389
|
+
disabled: onboardingInProgress,
|
|
1390
|
+
className: "text-sm text-ui-fg-interactive underline whitespace-nowrap disabled:opacity-50 disabled:cursor-not-allowed",
|
|
1391
|
+
children: "Click here to insert credentials manually"
|
|
1392
|
+
}
|
|
1393
|
+
) }),
|
|
1394
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1395
|
+
"div",
|
|
1396
|
+
{
|
|
1397
|
+
ref: errorLogRef,
|
|
1398
|
+
id: "error-log",
|
|
1399
|
+
className: `mt-4 text-left text-xs bg-red-50 text-red-600 p-3 border border-red-200 rounded ${connState === "error" && error ? "block" : "hidden"}`,
|
|
1400
|
+
children: error
|
|
1401
|
+
}
|
|
1402
|
+
)
|
|
1403
|
+
] }) }),
|
|
1404
|
+
showManual && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "md:col-span-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ml-[260px] max-w-xl mt-4 grid grid-cols-1 gap-3 md:grid-cols-2", children: [
|
|
1405
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1406
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium", children: "Client ID" }),
|
|
1395
1407
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1396
1408
|
"input",
|
|
1397
1409
|
{
|
|
1398
|
-
|
|
1399
|
-
value:
|
|
1400
|
-
onChange: (
|
|
1401
|
-
|
|
1410
|
+
type: "text",
|
|
1411
|
+
value: clientId,
|
|
1412
|
+
onChange: (e) => setClientId(e.target.value),
|
|
1413
|
+
disabled: onboardingInProgress,
|
|
1414
|
+
className: "rounded-md border border-ui-border-base bg-transparent px-3 py-2 text-sm disabled:opacity-50",
|
|
1415
|
+
placeholder: env === "sandbox" ? "Sandbox Client ID" : "Live Client ID"
|
|
1402
1416
|
}
|
|
1403
1417
|
)
|
|
1404
1418
|
] }),
|
|
1405
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
1406
|
-
"
|
|
1419
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1420
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium", children: "Client Secret" }),
|
|
1407
1421
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1408
1422
|
"input",
|
|
1409
1423
|
{
|
|
1410
|
-
|
|
1411
|
-
value:
|
|
1412
|
-
onChange: (
|
|
1413
|
-
|
|
1424
|
+
type: "password",
|
|
1425
|
+
value: secret,
|
|
1426
|
+
onChange: (e) => setSecret(e.target.value),
|
|
1427
|
+
disabled: onboardingInProgress,
|
|
1428
|
+
className: "rounded-md border border-ui-border-base bg-transparent px-3 py-2 text-sm disabled:opacity-50",
|
|
1429
|
+
placeholder: env === "sandbox" ? "Sandbox Secret" : "Live Secret"
|
|
1414
1430
|
}
|
|
1415
1431
|
)
|
|
1416
1432
|
] }),
|
|
1417
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
1418
|
-
"
|
|
1433
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 md:col-span-2", children: [
|
|
1434
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium", children: "Merchant ID (optional)" }),
|
|
1419
1435
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1420
1436
|
"input",
|
|
1421
1437
|
{
|
|
1422
|
-
|
|
1423
|
-
value:
|
|
1424
|
-
onChange: (
|
|
1425
|
-
|
|
1438
|
+
type: "text",
|
|
1439
|
+
value: merchantId,
|
|
1440
|
+
onChange: (e) => setMerchantId(e.target.value),
|
|
1441
|
+
disabled: onboardingInProgress,
|
|
1442
|
+
className: "rounded-md border border-ui-border-base bg-transparent px-3 py-2 text-sm disabled:opacity-50",
|
|
1443
|
+
placeholder: "Merchant ID"
|
|
1444
|
+
}
|
|
1445
|
+
)
|
|
1446
|
+
] }),
|
|
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"
|
|
1426
1466
|
}
|
|
1427
1467
|
)
|
|
1428
1468
|
] })
|
|
1429
|
-
] })
|
|
1430
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-3", children: [
|
|
1431
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1432
|
-
"button",
|
|
1433
|
-
{
|
|
1434
|
-
type: "submit",
|
|
1435
|
-
className: "rounded-md bg-ui-fg-base px-4 py-2 text-sm font-medium text-ui-bg-base",
|
|
1436
|
-
disabled: loading,
|
|
1437
|
-
children: loading ? "Loading..." : "Apply filters"
|
|
1438
|
-
}
|
|
1439
|
-
),
|
|
1440
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1441
|
-
"button",
|
|
1442
|
-
{
|
|
1443
|
-
type: "button",
|
|
1444
|
-
className: "rounded-md border border-ui-border-base px-4 py-2 text-sm text-ui-fg-base",
|
|
1445
|
-
onClick: onReset,
|
|
1446
|
-
disabled: loading,
|
|
1447
|
-
children: "Reset"
|
|
1448
|
-
}
|
|
1449
|
-
),
|
|
1450
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-ui-fg-subtle", children: [
|
|
1451
|
-
"Showing ",
|
|
1452
|
-
disputes.length,
|
|
1453
|
-
" dispute",
|
|
1454
|
-
disputes.length === 1 ? "" : "s",
|
|
1455
|
-
queryString ? " (filtered)" : ""
|
|
1456
|
-
] })
|
|
1457
|
-
] })
|
|
1469
|
+
] }) })
|
|
1458
1470
|
] }) })
|
|
1459
1471
|
] }),
|
|
1460
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.status || "Unknown" }),
|
|
1479
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.reason || "-" }),
|
|
1480
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.stage || "-" }),
|
|
1481
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.amount ? `${dispute.amount} ${dispute.currency_code || ""}` : "-" }),
|
|
1482
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.order_id || "-" }),
|
|
1483
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.cart_id || "-" }),
|
|
1484
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 text-ui-fg-subtle", children: formatDate$1(dispute.updated_at || dispute.created_at) })
|
|
1485
|
-
] }, dispute.id)) })
|
|
1486
|
-
] }) }),
|
|
1487
|
-
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
|
|
1488
|
-
] })
|
|
1489
|
-
] }) });
|
|
1472
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { children: `
|
|
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
1490
|
}
|
|
1491
1491
|
function PayPalGooglePayPage() {
|
|
1492
1492
|
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
@@ -1494,116 +1494,6 @@ function PayPalGooglePayPage() {
|
|
|
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,17 +2048,13 @@ 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
|
},
|
|
2059
2055
|
{
|
|
2060
|
-
Component:
|
|
2061
|
-
path: "/settings/paypal/
|
|
2056
|
+
Component: AdvancedCardPaymentsTab,
|
|
2057
|
+
path: "/settings/paypal/advanced-card-payments"
|
|
2062
2058
|
},
|
|
2063
2059
|
{
|
|
2064
2060
|
Component: PayPalAuditLogsPage,
|
|
@@ -2072,6 +2068,10 @@ const routeModule = {
|
|
|
2072
2068
|
Component: PayPalDisputesPage,
|
|
2073
2069
|
path: "/settings/paypal/disputes"
|
|
2074
2070
|
},
|
|
2071
|
+
{
|
|
2072
|
+
Component: PayPalConnectionPage,
|
|
2073
|
+
path: "/settings/paypal/connection"
|
|
2074
|
+
},
|
|
2075
2075
|
{
|
|
2076
2076
|
Component: PayPalGooglePayPage,
|
|
2077
2077
|
path: "/settings/paypal/google-pay"
|
|
@@ -2080,13 +2080,13 @@ const routeModule = {
|
|
|
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
|
};
|