@easypayment/medusa-paypal 0.2.6 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.medusa/server/src/admin/index.js +689 -934
- package/.medusa/server/src/admin/index.mjs +689 -934
- package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.js +1 -0
- package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal/capture-order/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/paypal/capture-order/route.js +62 -74
- 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/create-order/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/paypal/create-order/route.js +3 -24
- package/.medusa/server/src/api/store/paypal/create-order/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal/settings/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/paypal/settings/route.js +7 -1
- package/.medusa/server/src/api/store/paypal/settings/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal-complete/route.d.ts +1 -8
- package/.medusa/server/src/api/store/paypal-complete/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/paypal-complete/route.js +47 -39
- package/.medusa/server/src/api/store/paypal-complete/route.js.map +1 -1
- package/.medusa/server/src/jobs/paypal-reconcile.d.ts.map +1 -1
- package/.medusa/server/src/jobs/paypal-reconcile.js +19 -5
- package/.medusa/server/src/jobs/paypal-reconcile.js.map +1 -1
- package/.medusa/server/src/modules/paypal/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 +35 -8
- package/.medusa/server/src/modules/paypal/payment-provider/service.js.map +1 -1
- package/.medusa/server/src/modules/paypal/service.d.ts +67 -61
- package/.medusa/server/src/modules/paypal/service.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/service.js +34 -4
- package/.medusa/server/src/modules/paypal/service.js.map +1 -1
- package/.medusa/server/src/modules/paypal/utils/paypal-auth.d.ts +14 -0
- package/.medusa/server/src/modules/paypal/utils/paypal-auth.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/utils/paypal-auth.js +32 -0
- package/.medusa/server/src/modules/paypal/utils/paypal-auth.js.map +1 -0
- package/.medusa/server/src/modules/paypal/webhook-processor.d.ts +9 -9
- package/.medusa/server/src/modules/paypal/webhook-processor.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/webhook-processor.js +20 -7
- package/.medusa/server/src/modules/paypal/webhook-processor.js.map +1 -1
- package/package.json +1 -1
- package/src/admin/routes/settings/paypal/additional-settings/page.tsx +226 -346
- package/src/admin/routes/settings/paypal/advanced-card-payments/page.tsx +227 -381
- package/src/admin/routes/settings/paypal/audit-logs/page.tsx +127 -131
- package/src/admin/routes/settings/paypal/disputes/page.tsx +186 -259
- package/src/admin/routes/settings/paypal/paypal-settings/page.tsx +599 -557
- package/src/admin/routes/settings/paypal/reconciliation-status/page.tsx +120 -165
- package/src/api/store/payment-collections/[id]/payment-sessions/route.ts +12 -1
- package/src/api/store/paypal/capture-order/route.ts +276 -284
- package/src/api/store/paypal/config/route.ts +12 -8
- package/src/api/store/paypal/create-order/route.ts +2 -32
- package/src/api/store/paypal/settings/route.ts +8 -1
- package/src/api/store/paypal-complete/route.ts +76 -65
- package/src/jobs/paypal-reconcile.ts +21 -6
- package/src/modules/paypal/payment-provider/card-service.ts +54 -4
- package/src/modules/paypal/payment-provider/service.ts +47 -20
- package/src/modules/paypal/service.ts +39 -4
- package/src/modules/paypal/utils/paypal-auth.ts +32 -0
- package/src/modules/paypal/webhook-processor.ts +22 -8
- package/tsconfig.json +1 -1
|
@@ -39,6 +39,39 @@ function PayPalTabs() {
|
|
|
39
39
|
);
|
|
40
40
|
}) }) });
|
|
41
41
|
}
|
|
42
|
+
async function adminFetch$5(path, opts = {}) {
|
|
43
|
+
var _a;
|
|
44
|
+
const { method = "GET", body, query } = opts;
|
|
45
|
+
let url = path;
|
|
46
|
+
if (query && Object.keys(query).length > 0) {
|
|
47
|
+
const params = new URLSearchParams(query);
|
|
48
|
+
url = `${path}?${params.toString()}`;
|
|
49
|
+
}
|
|
50
|
+
const headers = { Accept: "application/json" };
|
|
51
|
+
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
52
|
+
if (typeof window !== "undefined") {
|
|
53
|
+
const token = (_a = window.__medusa__) == null ? void 0 : _a.token;
|
|
54
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
55
|
+
}
|
|
56
|
+
const res = await fetch(url, {
|
|
57
|
+
method,
|
|
58
|
+
headers,
|
|
59
|
+
credentials: "include",
|
|
60
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
61
|
+
});
|
|
62
|
+
const text = await res.text().catch(() => "");
|
|
63
|
+
if (!res.ok) {
|
|
64
|
+
if (res.status === 401) throw new Error("Unauthorized (401) - session may have expired. Please reload and log in again.");
|
|
65
|
+
if (res.status === 403) throw new Error("Forbidden (403) - you do not have permission to perform this action.");
|
|
66
|
+
throw new Error(text || `Request failed with status ${res.status}`);
|
|
67
|
+
}
|
|
68
|
+
if (!text) return {};
|
|
69
|
+
try {
|
|
70
|
+
return JSON.parse(text);
|
|
71
|
+
} catch {
|
|
72
|
+
return {};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
42
75
|
const DEFAULT_FORM$1 = {
|
|
43
76
|
paymentAction: "capture",
|
|
44
77
|
brandName: "PayPal",
|
|
@@ -55,17 +88,9 @@ const DEFAULT_FORM$1 = {
|
|
|
55
88
|
function mergeWithDefaults$1(saved) {
|
|
56
89
|
if (!saved) return { ...DEFAULT_FORM$1 };
|
|
57
90
|
const entries = Object.entries(saved).filter(([, value]) => value !== void 0);
|
|
58
|
-
return {
|
|
59
|
-
...DEFAULT_FORM$1,
|
|
60
|
-
...Object.fromEntries(entries)
|
|
61
|
-
};
|
|
91
|
+
return { ...DEFAULT_FORM$1, ...Object.fromEntries(entries) };
|
|
62
92
|
}
|
|
63
|
-
function SectionCard$2({
|
|
64
|
-
title,
|
|
65
|
-
description,
|
|
66
|
-
right,
|
|
67
|
-
children
|
|
68
|
-
}) {
|
|
93
|
+
function SectionCard$2({ title, description, right, children }) {
|
|
69
94
|
return /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
70
95
|
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4 border-b border-ui-border-base p-4", children: [
|
|
71
96
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
@@ -77,11 +102,7 @@ function SectionCard$2({
|
|
|
77
102
|
/* @__PURE__ */ jsx("div", { className: "p-4", children })
|
|
78
103
|
] });
|
|
79
104
|
}
|
|
80
|
-
function FieldRow$2({
|
|
81
|
-
label,
|
|
82
|
-
hint,
|
|
83
|
-
children
|
|
84
|
-
}) {
|
|
105
|
+
function FieldRow$2({ label, hint, children }) {
|
|
85
106
|
return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-12 items-start gap-4 py-3", children: [
|
|
86
107
|
/* @__PURE__ */ jsxs("div", { className: "col-span-12 md:col-span-4", children: [
|
|
87
108
|
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium text-ui-fg-base", children: label }),
|
|
@@ -94,6 +115,7 @@ function AdditionalSettingsTab() {
|
|
|
94
115
|
const [form, setForm] = useState(() => ({ ...DEFAULT_FORM$1 }));
|
|
95
116
|
const [loading, setLoading] = useState(false);
|
|
96
117
|
const [saving, setSaving] = useState(false);
|
|
118
|
+
const [toast, setToast] = useState(null);
|
|
97
119
|
const didInit = useRef(false);
|
|
98
120
|
useEffect(() => {
|
|
99
121
|
if (didInit.current) return;
|
|
@@ -101,52 +123,28 @@ function AdditionalSettingsTab() {
|
|
|
101
123
|
(async () => {
|
|
102
124
|
try {
|
|
103
125
|
setLoading(true);
|
|
104
|
-
const
|
|
105
|
-
credentials: "include",
|
|
106
|
-
headers: { "Accept": "application/json" }
|
|
107
|
-
});
|
|
108
|
-
if (!r.ok) return;
|
|
109
|
-
const json = await r.json();
|
|
126
|
+
const json = await adminFetch$5("/admin/paypal/settings");
|
|
110
127
|
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
111
128
|
const saved = payload == null ? void 0 : payload.additional_settings;
|
|
112
|
-
if (saved && typeof saved === "object")
|
|
113
|
-
|
|
114
|
-
}
|
|
129
|
+
if (saved && typeof saved === "object") setForm(mergeWithDefaults$1(saved));
|
|
130
|
+
} catch {
|
|
115
131
|
} finally {
|
|
116
132
|
setLoading(false);
|
|
117
133
|
}
|
|
118
134
|
})();
|
|
119
135
|
}, []);
|
|
120
|
-
const [toast, setToast] = useState(null);
|
|
121
136
|
async function onSave() {
|
|
122
137
|
try {
|
|
123
138
|
setSaving(true);
|
|
124
139
|
setToast(null);
|
|
125
|
-
const
|
|
126
|
-
method: "POST",
|
|
127
|
-
credentials: "include",
|
|
128
|
-
headers: {
|
|
129
|
-
"Content-Type": "application/json",
|
|
130
|
-
"Accept": "application/json"
|
|
131
|
-
},
|
|
132
|
-
body: JSON.stringify({
|
|
133
|
-
additional_settings: form
|
|
134
|
-
})
|
|
135
|
-
});
|
|
136
|
-
if (!r.ok) {
|
|
137
|
-
const errText = await r.text().catch(() => "");
|
|
138
|
-
throw new Error(errText || "Failed to save settings");
|
|
139
|
-
}
|
|
140
|
-
const json = await r.json().catch(() => ({}));
|
|
140
|
+
const json = await adminFetch$5("/admin/paypal/settings", { method: "POST", body: { additional_settings: form } });
|
|
141
141
|
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
142
142
|
const saved = payload == null ? void 0 : payload.additional_settings;
|
|
143
|
-
if (saved && typeof saved === "object")
|
|
144
|
-
setForm(mergeWithDefaults$1(saved));
|
|
145
|
-
}
|
|
143
|
+
if (saved && typeof saved === "object") setForm(mergeWithDefaults$1(saved));
|
|
146
144
|
setToast({ type: "success", message: "Settings saved" });
|
|
147
145
|
window.setTimeout(() => setToast(null), 2500);
|
|
148
146
|
} catch (e) {
|
|
149
|
-
setToast({ type: "error", message:
|
|
147
|
+
setToast({ type: "error", message: e instanceof Error ? e.message : "Failed to save settings" });
|
|
150
148
|
window.setTimeout(() => setToast(null), 3500);
|
|
151
149
|
} finally {
|
|
152
150
|
setSaving(false);
|
|
@@ -155,181 +153,226 @@ function AdditionalSettingsTab() {
|
|
|
155
153
|
return /* @__PURE__ */ jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
156
154
|
/* @__PURE__ */ jsx("div", { className: "flex items-start justify-between gap-4", children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Gateway By Easy Payment" }) }) }),
|
|
157
155
|
/* @__PURE__ */ jsx(PayPalTabs, {}),
|
|
158
|
-
toast ? /* @__PURE__ */ jsx(
|
|
159
|
-
"div",
|
|
160
|
-
{
|
|
161
|
-
className: "fixed right-6 top-6 z-50 rounded-md border border-ui-border-base bg-ui-bg-base px-4 py-3 text-sm shadow-lg",
|
|
162
|
-
role: "status",
|
|
163
|
-
"aria-live": "polite",
|
|
164
|
-
children: /* @__PURE__ */ jsx("span", { className: toast.type === "success" ? "text-ui-fg-base" : "text-ui-fg-error", children: toast.message })
|
|
165
|
-
}
|
|
166
|
-
) : null,
|
|
156
|
+
toast ? /* @__PURE__ */ jsx("div", { className: "fixed right-6 top-6 z-50 rounded-md border border-ui-border-base bg-ui-bg-base px-4 py-3 text-sm shadow-lg", role: "status", "aria-live": "polite", children: /* @__PURE__ */ jsx("span", { className: toast.type === "success" ? "text-ui-fg-base" : "text-ui-fg-error", children: toast.message }) }) : null,
|
|
167
157
|
/* @__PURE__ */ jsx(
|
|
168
158
|
SectionCard$2,
|
|
169
159
|
{
|
|
170
160
|
title: "Additional Settings",
|
|
171
161
|
description: "These settings control checkout behavior, PayPal experience, and logging.",
|
|
172
162
|
right: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
173
|
-
/* @__PURE__ */ jsx(
|
|
174
|
-
|
|
175
|
-
{
|
|
176
|
-
type: "button",
|
|
177
|
-
onClick: onSave,
|
|
178
|
-
disabled: saving || loading,
|
|
179
|
-
className: "rounded-md bg-ui-button-neutral px-4 py-2 text-sm font-medium text-ui-fg-on-color shadow-sm hover:opacity-90 disabled:opacity-60",
|
|
180
|
-
children: saving ? "Saving..." : "Save settings"
|
|
181
|
-
}
|
|
182
|
-
),
|
|
183
|
-
loading ? /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading…" }) : null
|
|
163
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: onSave, disabled: saving || loading, className: "rounded-md bg-ui-button-neutral px-4 py-2 text-sm font-medium text-ui-fg-on-color shadow-sm hover:opacity-90 disabled:opacity-60", children: saving ? "Saving..." : "Save settings" }),
|
|
164
|
+
loading ? /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading..." }) : null
|
|
184
165
|
] }),
|
|
185
166
|
children: /* @__PURE__ */ jsxs("div", { className: "divide-y divide-ui-border-base", children: [
|
|
186
|
-
/* @__PURE__ */ jsx(FieldRow$2, { label: "Payment action", children: /* @__PURE__ */ jsxs(
|
|
187
|
-
"
|
|
188
|
-
{
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
197
|
-
) }),
|
|
198
|
-
/* @__PURE__ */ jsx(FieldRow$2, { label: "Brand Name", children: /* @__PURE__ */ jsx(
|
|
199
|
-
"input",
|
|
200
|
-
{
|
|
201
|
-
value: form.brandName,
|
|
202
|
-
onChange: (e) => setForm((p) => ({ ...p, brandName: e.target.value })),
|
|
203
|
-
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",
|
|
204
|
-
placeholder: "PayPal"
|
|
205
|
-
}
|
|
206
|
-
) }),
|
|
207
|
-
/* @__PURE__ */ jsx(FieldRow$2, { label: "Landing Page", children: /* @__PURE__ */ jsxs(
|
|
208
|
-
"select",
|
|
209
|
-
{
|
|
210
|
-
value: form.landingPage,
|
|
211
|
-
onChange: (e) => setForm((p) => ({ ...p, landingPage: e.target.value })),
|
|
212
|
-
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",
|
|
213
|
-
children: [
|
|
214
|
-
/* @__PURE__ */ jsx("option", { value: "no_preference", children: "No Preference" }),
|
|
215
|
-
/* @__PURE__ */ jsx("option", { value: "login", children: "Login" }),
|
|
216
|
-
/* @__PURE__ */ jsx("option", { value: "billing", children: "Billing" })
|
|
217
|
-
]
|
|
218
|
-
}
|
|
219
|
-
) }),
|
|
167
|
+
/* @__PURE__ */ jsx(FieldRow$2, { label: "Payment action", children: /* @__PURE__ */ jsxs("select", { value: form.paymentAction, onChange: (e) => setForm((p) => ({ ...p, paymentAction: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", children: [
|
|
168
|
+
/* @__PURE__ */ jsx("option", { value: "capture", children: "Capture" }),
|
|
169
|
+
/* @__PURE__ */ jsx("option", { value: "authorize", children: "Authorize" })
|
|
170
|
+
] }) }),
|
|
171
|
+
/* @__PURE__ */ jsx(FieldRow$2, { label: "Brand Name", children: /* @__PURE__ */ jsx("input", { value: form.brandName, onChange: (e) => setForm((p) => ({ ...p, brandName: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "PayPal" }) }),
|
|
172
|
+
/* @__PURE__ */ jsx(FieldRow$2, { label: "Landing Page", children: /* @__PURE__ */ jsxs("select", { value: form.landingPage, onChange: (e) => setForm((p) => ({ ...p, landingPage: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", children: [
|
|
173
|
+
/* @__PURE__ */ jsx("option", { value: "no_preference", children: "No Preference" }),
|
|
174
|
+
/* @__PURE__ */ jsx("option", { value: "login", children: "Login" }),
|
|
175
|
+
/* @__PURE__ */ jsx("option", { value: "billing", children: "Billing" })
|
|
176
|
+
] }) }),
|
|
220
177
|
/* @__PURE__ */ jsx(FieldRow$2, { label: "Instant Payments", children: /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
221
|
-
/* @__PURE__ */ jsx(
|
|
222
|
-
"input",
|
|
223
|
-
{
|
|
224
|
-
type: "checkbox",
|
|
225
|
-
checked: form.requireInstantPayment,
|
|
226
|
-
onChange: (e) => setForm((p) => ({ ...p, requireInstantPayment: e.target.checked })),
|
|
227
|
-
className: "h-4 w-4 rounded border-ui-border-base"
|
|
228
|
-
}
|
|
229
|
-
),
|
|
178
|
+
/* @__PURE__ */ jsx("input", { type: "checkbox", checked: form.requireInstantPayment, onChange: (e) => setForm((p) => ({ ...p, requireInstantPayment: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
|
|
230
179
|
/* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Require Instant Payment" })
|
|
231
180
|
] }) }),
|
|
232
|
-
/* @__PURE__ */ jsx(
|
|
233
|
-
|
|
234
|
-
{
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
{
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
181
|
+
/* @__PURE__ */ jsx(FieldRow$2, { label: "Billing Address", hint: "If the billing address is empty and PayPal provides a shipping address, the order will use the shipping address as the billing address.", children: /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
182
|
+
/* @__PURE__ */ jsx("input", { type: "checkbox", checked: form.useShippingAsBilling, onChange: (e) => setForm((p) => ({ ...p, useShippingAsBilling: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
|
|
183
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Use PayPal Shipping Address as Billing" })
|
|
184
|
+
] }) }),
|
|
185
|
+
/* @__PURE__ */ jsx(FieldRow$2, { label: "Send Item Details", hint: "Include all line item details in the payment request to PayPal so that they can be seen from the PayPal transaction details page.", children: /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
186
|
+
/* @__PURE__ */ jsx("input", { type: "checkbox", checked: form.sendItemDetails, onChange: (e) => setForm((p) => ({ ...p, sendItemDetails: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
|
|
187
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Send line item details to PayPal" })
|
|
188
|
+
] }) }),
|
|
189
|
+
/* @__PURE__ */ jsx(FieldRow$2, { label: "Order Review Page", hint: "Payments from the Product or Cart page skip the review step and go straight to the Thank You page.", children: /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
190
|
+
/* @__PURE__ */ jsx("input", { type: "checkbox", checked: form.skipOrderReviewPage, onChange: (e) => setForm((p) => ({ ...p, skipOrderReviewPage: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
|
|
191
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Skip Order Review Page" })
|
|
192
|
+
] }) }),
|
|
193
|
+
/* @__PURE__ */ jsx(FieldRow$2, { label: "Invoice prefix", children: /* @__PURE__ */ jsx("input", { value: form.invoicePrefix, onChange: (e) => setForm((p) => ({ ...p, invoicePrefix: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "WC-" }) }),
|
|
194
|
+
/* @__PURE__ */ jsx(FieldRow$2, { label: "Credit Card Statement Name", children: /* @__PURE__ */ jsx("input", { value: form.creditCardStatementName, onChange: (e) => setForm((p) => ({ ...p, creditCardStatementName: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "PayPal" }) }),
|
|
195
|
+
/* @__PURE__ */ jsx(FieldRow$2, { label: "Debug log", hint: /* @__PURE__ */ jsxs("span", { children: [
|
|
196
|
+
"Log PayPal events such as Webhook, Payment, Refund. ",
|
|
197
|
+
form.logPath ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
198
|
+
"Log location: ",
|
|
199
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono", children: form.logPath })
|
|
200
|
+
] }) : null
|
|
201
|
+
] }), children: /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
202
|
+
/* @__PURE__ */ jsx("input", { type: "checkbox", checked: form.enableLogging, onChange: (e) => setForm((p) => ({ ...p, enableLogging: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
|
|
203
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable logging" })
|
|
204
|
+
] }) })
|
|
205
|
+
] })
|
|
206
|
+
}
|
|
207
|
+
)
|
|
208
|
+
] }) });
|
|
209
|
+
}
|
|
210
|
+
async function adminFetch$4(path, opts = {}) {
|
|
211
|
+
var _a;
|
|
212
|
+
const { method = "GET", body, query } = opts;
|
|
213
|
+
let url = path;
|
|
214
|
+
if (query && Object.keys(query).length > 0) {
|
|
215
|
+
const params = new URLSearchParams(query);
|
|
216
|
+
url = `${path}?${params.toString()}`;
|
|
217
|
+
}
|
|
218
|
+
const headers = { Accept: "application/json" };
|
|
219
|
+
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
220
|
+
if (typeof window !== "undefined") {
|
|
221
|
+
const token = (_a = window.__medusa__) == null ? void 0 : _a.token;
|
|
222
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
223
|
+
}
|
|
224
|
+
const res = await fetch(url, {
|
|
225
|
+
method,
|
|
226
|
+
headers,
|
|
227
|
+
credentials: "include",
|
|
228
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
229
|
+
});
|
|
230
|
+
const text = await res.text().catch(() => "");
|
|
231
|
+
if (!res.ok) {
|
|
232
|
+
if (res.status === 401) throw new Error("Unauthorized (401) - session may have expired. Please reload and log in again.");
|
|
233
|
+
if (res.status === 403) throw new Error("Forbidden (403) - you do not have permission to perform this action.");
|
|
234
|
+
throw new Error(text || `Request failed with status ${res.status}`);
|
|
235
|
+
}
|
|
236
|
+
if (!text) return {};
|
|
237
|
+
try {
|
|
238
|
+
return JSON.parse(text);
|
|
239
|
+
} catch {
|
|
240
|
+
return {};
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
const DEFAULT_FORM = { enabled: true, title: "Credit or Debit Card", disabledCards: [], threeDS: "when_required", cardSaveEnabled: false };
|
|
244
|
+
function mergeWithDefaults(saved) {
|
|
245
|
+
if (!saved) return { ...DEFAULT_FORM };
|
|
246
|
+
const entries = Object.entries(saved).filter(([, value]) => value !== void 0);
|
|
247
|
+
return { ...DEFAULT_FORM, ...Object.fromEntries(entries) };
|
|
248
|
+
}
|
|
249
|
+
const CARD_BRANDS = [
|
|
250
|
+
{ value: "visa", label: "Visa" },
|
|
251
|
+
{ value: "mastercard", label: "Mastercard" },
|
|
252
|
+
{ value: "amex", label: "American Express" },
|
|
253
|
+
{ value: "discover", label: "Discover" },
|
|
254
|
+
{ value: "diners", label: "Diners Club" },
|
|
255
|
+
{ value: "jcb", label: "JCB" },
|
|
256
|
+
{ value: "unionpay", label: "UnionPay" }
|
|
257
|
+
];
|
|
258
|
+
const THREE_DS_OPTIONS = [
|
|
259
|
+
{ value: "when_required", label: "3D Secure when required", hint: "Triggers 3DS only when the card / issuer requires it." },
|
|
260
|
+
{ value: "sli", label: "3D Secure (SCA) / liability shift (recommended)", hint: "Attempts to optimize for liability shift while remaining compliant." },
|
|
261
|
+
{ value: "always", label: "Always request 3D Secure", hint: "Forces 3DS challenge whenever possible (may reduce conversion)." }
|
|
262
|
+
];
|
|
263
|
+
function Pill$1({ children, onRemove }) {
|
|
264
|
+
return /* @__PURE__ */ 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: [
|
|
265
|
+
children,
|
|
266
|
+
onRemove ? /* @__PURE__ */ jsx("button", { type: "button", onClick: onRemove, className: "ml-1 rounded px-1 text-ui-fg-subtle hover:text-ui-fg-base", "aria-label": "Remove", children: "x" }) : null
|
|
267
|
+
] });
|
|
268
|
+
}
|
|
269
|
+
function SectionCard$1({ title, description, right, children }) {
|
|
270
|
+
return /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
271
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4 border-b border-ui-border-base p-4", children: [
|
|
272
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
273
|
+
/* @__PURE__ */ jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: title }),
|
|
274
|
+
description ? /* @__PURE__ */ jsx("div", { className: "mt-1 text-sm text-ui-fg-subtle", children: description }) : null
|
|
275
|
+
] }),
|
|
276
|
+
right
|
|
277
|
+
] }),
|
|
278
|
+
/* @__PURE__ */ jsx("div", { className: "p-4", children })
|
|
279
|
+
] });
|
|
280
|
+
}
|
|
281
|
+
function FieldRow$1({ label, hint, children }) {
|
|
282
|
+
return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-12 items-start gap-4 py-3", children: [
|
|
283
|
+
/* @__PURE__ */ jsxs("div", { className: "col-span-12 md:col-span-4", children: [
|
|
284
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium text-ui-fg-base", children: label }),
|
|
285
|
+
hint ? /* @__PURE__ */ jsx("div", { className: "mt-1 text-xs text-ui-fg-subtle", children: hint }) : null
|
|
286
|
+
] }),
|
|
287
|
+
/* @__PURE__ */ jsx("div", { className: "col-span-12 md:col-span-8", children })
|
|
288
|
+
] });
|
|
289
|
+
}
|
|
290
|
+
function AdvancedCardPaymentsTab() {
|
|
291
|
+
var _a, _b;
|
|
292
|
+
const [form, setForm] = useState(() => ({ ...DEFAULT_FORM }));
|
|
293
|
+
const [loading, setLoading] = useState(false);
|
|
294
|
+
const [saving, setSaving] = useState(false);
|
|
295
|
+
const [toast, setToast] = useState(null);
|
|
296
|
+
const didInit = useRef(false);
|
|
297
|
+
useEffect(() => {
|
|
298
|
+
if (didInit.current) return;
|
|
299
|
+
didInit.current = true;
|
|
300
|
+
(async () => {
|
|
301
|
+
try {
|
|
302
|
+
setLoading(true);
|
|
303
|
+
const json = await adminFetch$4("/admin/paypal/settings");
|
|
304
|
+
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
305
|
+
const saved = payload == null ? void 0 : payload.advanced_card_payments;
|
|
306
|
+
if (saved && typeof saved === "object") setForm(mergeWithDefaults(saved));
|
|
307
|
+
} catch {
|
|
308
|
+
} finally {
|
|
309
|
+
setLoading(false);
|
|
310
|
+
}
|
|
311
|
+
})();
|
|
312
|
+
}, []);
|
|
313
|
+
async function onSave() {
|
|
314
|
+
try {
|
|
315
|
+
setSaving(true);
|
|
316
|
+
const json = await adminFetch$4("/admin/paypal/settings", { method: "POST", body: { advanced_card_payments: form } });
|
|
317
|
+
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
318
|
+
const saved = payload == null ? void 0 : payload.advanced_card_payments;
|
|
319
|
+
if (saved && typeof saved === "object") setForm(mergeWithDefaults(saved));
|
|
320
|
+
setToast({ type: "success", message: "Settings saved" });
|
|
321
|
+
window.setTimeout(() => setToast(null), 2500);
|
|
322
|
+
} catch (e) {
|
|
323
|
+
setToast({ type: "error", message: (e instanceof Error ? e.message : "") || "Failed to save settings." });
|
|
324
|
+
window.setTimeout(() => setToast(null), 3500);
|
|
325
|
+
} finally {
|
|
326
|
+
setSaving(false);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
const disabledSet = useMemo(() => new Set(form.disabledCards), [form.disabledCards]);
|
|
330
|
+
function toggleDisabledCard(value) {
|
|
331
|
+
setForm((prev) => {
|
|
332
|
+
const exists = prev.disabledCards.includes(value);
|
|
333
|
+
return { ...prev, disabledCards: exists ? prev.disabledCards.filter((v) => v !== value) : [...prev.disabledCards, value] };
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
function removeDisabledCard(value) {
|
|
337
|
+
setForm((prev) => ({ ...prev, disabledCards: prev.disabledCards.filter((v) => v !== value) }));
|
|
338
|
+
}
|
|
339
|
+
return /* @__PURE__ */ jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
340
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-start justify-between gap-4", children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Gateway By Easy Payment" }) }) }),
|
|
341
|
+
/* @__PURE__ */ jsx(PayPalTabs, {}),
|
|
342
|
+
toast ? /* @__PURE__ */ jsx("div", { className: "fixed right-6 top-6 z-50 rounded-md border border-ui-border-base bg-ui-bg-base px-4 py-3 text-sm shadow-lg", role: "status", "aria-live": "polite", children: /* @__PURE__ */ jsx("span", { className: toast.type === "success" ? "text-ui-fg-base" : "text-ui-fg-error", children: toast.message }) }) : null,
|
|
343
|
+
/* @__PURE__ */ jsx(
|
|
344
|
+
SectionCard$1,
|
|
345
|
+
{
|
|
346
|
+
title: "Advanced Card Payments",
|
|
347
|
+
description: "Control card checkout settings, 3D Secure behavior, and card saving.",
|
|
348
|
+
right: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
349
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: onSave, disabled: saving || loading, className: "rounded-md bg-ui-button-neutral px-4 py-2 text-sm font-medium text-ui-fg-on-color shadow-sm hover:opacity-90 disabled:opacity-60", children: saving ? "Saving..." : "Save settings" }),
|
|
350
|
+
loading ? /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading..." }) : null
|
|
351
|
+
] }),
|
|
352
|
+
children: /* @__PURE__ */ jsxs("div", { className: "divide-y divide-ui-border-base", children: [
|
|
353
|
+
/* @__PURE__ */ jsx(FieldRow$1, { label: "Enable/Disable", children: /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
354
|
+
/* @__PURE__ */ jsx("input", { type: "checkbox", checked: form.enabled, onChange: (e) => setForm((p) => ({ ...p, enabled: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
|
|
355
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable Advanced Credit/Debit Card" })
|
|
356
|
+
] }) }),
|
|
357
|
+
/* @__PURE__ */ jsx(FieldRow$1, { label: "Title", children: /* @__PURE__ */ jsx("input", { value: form.title, onChange: (e) => setForm((p) => ({ ...p, title: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "Credit or Debit Card" }) }),
|
|
358
|
+
/* @__PURE__ */ jsx(FieldRow$1, { label: "Disable specific credit cards", hint: "Select card brands to hide from the card form.", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
359
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: form.disabledCards.length ? form.disabledCards.map((v) => {
|
|
360
|
+
var _a2;
|
|
361
|
+
return /* @__PURE__ */ jsx(Pill$1, { onRemove: () => removeDisabledCard(v), children: ((_a2 = CARD_BRANDS.find((b) => b.value === v)) == null ? void 0 : _a2.label) ?? v }, v);
|
|
362
|
+
}) : /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-subtle", children: "No card brands disabled." }) }),
|
|
363
|
+
/* @__PURE__ */ jsx("div", { className: "rounded-md border border-ui-border-base p-3", children: /* @__PURE__ */ jsx("div", { className: "grid gap-2 md:grid-cols-2", children: CARD_BRANDS.map((b) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 rounded-md p-2 hover:bg-ui-bg-subtle", children: [
|
|
364
|
+
/* @__PURE__ */ jsx("input", { type: "checkbox", checked: disabledSet.has(b.value), onChange: () => toggleDisabledCard(b.value), className: "h-4 w-4 rounded border-ui-border-base" }),
|
|
365
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: b.label })
|
|
366
|
+
] }, b.value)) }) })
|
|
367
|
+
] }) }),
|
|
368
|
+
/* @__PURE__ */ jsx(FieldRow$1, { label: "Contingency for 3D Secure", hint: "Choose when 3D Secure should be triggered during card payments.", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
369
|
+
/* @__PURE__ */ jsx("select", { value: form.threeDS, onChange: (e) => setForm((p) => ({ ...p, threeDS: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", children: THREE_DS_OPTIONS.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: o.label }, o.value)) }),
|
|
370
|
+
((_a = THREE_DS_OPTIONS.find((o) => o.value === form.threeDS)) == null ? void 0 : _a.hint) ? /* @__PURE__ */ jsx("div", { className: "text-xs text-ui-fg-subtle", children: (_b = THREE_DS_OPTIONS.find((o) => o.value === form.threeDS)) == null ? void 0 : _b.hint }) : null
|
|
371
|
+
] }) }),
|
|
372
|
+
/* @__PURE__ */ jsx(FieldRow$1, { label: "Card Save Enabled", hint: "Allow customers to save a card at checkout for future use.", children: /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
373
|
+
/* @__PURE__ */ jsx("input", { type: "checkbox", checked: form.cardSaveEnabled, onChange: (e) => setForm((p) => ({ ...p, cardSaveEnabled: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
|
|
374
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable card saving at checkout" })
|
|
375
|
+
] }) })
|
|
333
376
|
] })
|
|
334
377
|
}
|
|
335
378
|
)
|
|
@@ -922,308 +965,195 @@ function PayPalConnectionPage() {
|
|
|
922
965
|
` })
|
|
923
966
|
] });
|
|
924
967
|
}
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
value: "sli",
|
|
957
|
-
label: "3D Secure (SCA) / liability shift (recommended)",
|
|
958
|
-
hint: "Attempts to optimize for liability shift while remaining compliant."
|
|
959
|
-
},
|
|
960
|
-
{
|
|
961
|
-
value: "always",
|
|
962
|
-
label: "Always request 3D Secure",
|
|
963
|
-
hint: "Forces 3DS challenge whenever possible (may reduce conversion)."
|
|
968
|
+
async function adminFetch$3(path, opts = {}) {
|
|
969
|
+
var _a;
|
|
970
|
+
const { method = "GET", body, query } = opts;
|
|
971
|
+
let url = path;
|
|
972
|
+
if (query && Object.keys(query).length > 0) {
|
|
973
|
+
const params = new URLSearchParams(query);
|
|
974
|
+
url = `${path}?${params.toString()}`;
|
|
975
|
+
}
|
|
976
|
+
const headers = { Accept: "application/json" };
|
|
977
|
+
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
978
|
+
if (typeof window !== "undefined") {
|
|
979
|
+
const token = (_a = window.__medusa__) == null ? void 0 : _a.token;
|
|
980
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
981
|
+
}
|
|
982
|
+
const res = await fetch(url, {
|
|
983
|
+
method,
|
|
984
|
+
headers,
|
|
985
|
+
credentials: "include",
|
|
986
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
987
|
+
});
|
|
988
|
+
const text = await res.text().catch(() => "");
|
|
989
|
+
if (!res.ok) {
|
|
990
|
+
if (res.status === 401) throw new Error("Unauthorized (401) - session may have expired. Please reload and log in again.");
|
|
991
|
+
if (res.status === 403) throw new Error("Forbidden (403) - you do not have permission to perform this action.");
|
|
992
|
+
throw new Error(text || `Request failed with status ${res.status}`);
|
|
993
|
+
}
|
|
994
|
+
if (!text) return {};
|
|
995
|
+
try {
|
|
996
|
+
return JSON.parse(text);
|
|
997
|
+
} catch {
|
|
998
|
+
return {};
|
|
964
999
|
}
|
|
965
|
-
];
|
|
966
|
-
function cx$1(...parts) {
|
|
967
|
-
return parts.filter(Boolean).join(" ");
|
|
968
|
-
}
|
|
969
|
-
function Pill$1({
|
|
970
|
-
children,
|
|
971
|
-
onRemove
|
|
972
|
-
}) {
|
|
973
|
-
return /* @__PURE__ */ 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: [
|
|
974
|
-
children,
|
|
975
|
-
onRemove ? /* @__PURE__ */ jsx(
|
|
976
|
-
"button",
|
|
977
|
-
{
|
|
978
|
-
type: "button",
|
|
979
|
-
onClick: onRemove,
|
|
980
|
-
className: "ml-1 rounded px-1 text-ui-fg-subtle hover:text-ui-fg-base",
|
|
981
|
-
"aria-label": "Remove",
|
|
982
|
-
children: "×"
|
|
983
|
-
}
|
|
984
|
-
) : null
|
|
985
|
-
] });
|
|
986
1000
|
}
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
return /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
994
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4 border-b border-ui-border-base p-4", children: [
|
|
995
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
996
|
-
/* @__PURE__ */ jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: title }),
|
|
997
|
-
description ? /* @__PURE__ */ jsx("div", { className: "mt-1 text-sm text-ui-fg-subtle", children: description }) : null
|
|
998
|
-
] }),
|
|
999
|
-
right
|
|
1000
|
-
] }),
|
|
1001
|
-
/* @__PURE__ */ jsx("div", { className: "p-4", children })
|
|
1002
|
-
] });
|
|
1003
|
-
}
|
|
1004
|
-
function FieldRow$1({
|
|
1005
|
-
label,
|
|
1006
|
-
hint,
|
|
1007
|
-
children
|
|
1008
|
-
}) {
|
|
1009
|
-
return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-12 items-start gap-4 py-3", children: [
|
|
1010
|
-
/* @__PURE__ */ jsxs("div", { className: "col-span-12 md:col-span-4", children: [
|
|
1011
|
-
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium text-ui-fg-base", children: label }),
|
|
1012
|
-
hint ? /* @__PURE__ */ jsx("div", { className: "mt-1 text-xs text-ui-fg-subtle", children: hint }) : null
|
|
1013
|
-
] }),
|
|
1014
|
-
/* @__PURE__ */ jsx("div", { className: "col-span-12 md:col-span-8", children })
|
|
1015
|
-
] });
|
|
1001
|
+
const EMPTY_FILTERS = { dispute_id: "", status: "", order_id: "", cart_id: "" };
|
|
1002
|
+
function formatDate$2(value) {
|
|
1003
|
+
if (!value) return "";
|
|
1004
|
+
const parsed = new Date(value);
|
|
1005
|
+
if (Number.isNaN(parsed.getTime())) return value;
|
|
1006
|
+
return parsed.toLocaleString();
|
|
1016
1007
|
}
|
|
1017
|
-
function
|
|
1018
|
-
|
|
1019
|
-
const [
|
|
1008
|
+
function PayPalDisputesPage() {
|
|
1009
|
+
const [filters, setFilters] = useState({ ...EMPTY_FILTERS });
|
|
1010
|
+
const [disputes, setDisputes] = useState([]);
|
|
1020
1011
|
const [loading, setLoading] = useState(false);
|
|
1021
|
-
const [
|
|
1022
|
-
const
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
credentials: "include",
|
|
1032
|
-
headers: { "Accept": "application/json" }
|
|
1033
|
-
});
|
|
1034
|
-
if (!r.ok) return;
|
|
1035
|
-
const json = await r.json();
|
|
1036
|
-
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
1037
|
-
const saved = payload == null ? void 0 : payload.advanced_card_payments;
|
|
1038
|
-
if (saved && typeof saved === "object") {
|
|
1039
|
-
setForm(mergeWithDefaults(saved));
|
|
1040
|
-
}
|
|
1041
|
-
} finally {
|
|
1042
|
-
setLoading(false);
|
|
1043
|
-
}
|
|
1044
|
-
})();
|
|
1045
|
-
}, []);
|
|
1046
|
-
async function onSave() {
|
|
1012
|
+
const [error, setError] = useState(null);
|
|
1013
|
+
const queryString = useMemo(() => {
|
|
1014
|
+
const params = new URLSearchParams();
|
|
1015
|
+
Object.entries(filters).forEach(([key, value]) => {
|
|
1016
|
+
if (value.trim()) params.set(key, value.trim());
|
|
1017
|
+
});
|
|
1018
|
+
const qs = params.toString();
|
|
1019
|
+
return qs ? `?${qs}` : "";
|
|
1020
|
+
}, [filters]);
|
|
1021
|
+
const fetchDisputes = useCallback(async (source) => {
|
|
1047
1022
|
try {
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
"Content-Type": "application/json",
|
|
1054
|
-
"Accept": "application/json"
|
|
1055
|
-
},
|
|
1056
|
-
body: JSON.stringify({ advanced_card_payments: form })
|
|
1023
|
+
setLoading(true);
|
|
1024
|
+
setError(null);
|
|
1025
|
+
const query = {};
|
|
1026
|
+
Object.entries(source).forEach(([key, value]) => {
|
|
1027
|
+
if (value.trim()) query[key] = value.trim();
|
|
1057
1028
|
});
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
}
|
|
1064
|
-
const json = await r.json().catch(() => null);
|
|
1065
|
-
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
1066
|
-
const saved = payload == null ? void 0 : payload.advanced_card_payments;
|
|
1067
|
-
if (saved && typeof saved === "object") {
|
|
1068
|
-
setForm(mergeWithDefaults(saved));
|
|
1069
|
-
}
|
|
1070
|
-
setToast({ type: "success", message: "Settings saved" });
|
|
1071
|
-
window.setTimeout(() => setToast(null), 2500);
|
|
1029
|
+
const json = await adminFetch$3("/admin/paypal/disputes", { query });
|
|
1030
|
+
setDisputes((json == null ? void 0 : json.disputes) ?? []);
|
|
1031
|
+
} catch (fetchError) {
|
|
1032
|
+
setError(fetchError instanceof Error ? fetchError.message : "Failed to load disputes");
|
|
1033
|
+
setDisputes([]);
|
|
1072
1034
|
} finally {
|
|
1073
|
-
|
|
1035
|
+
setLoading(false);
|
|
1074
1036
|
}
|
|
1075
|
-
}
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
});
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
setForm((prev) => ({
|
|
1088
|
-
...prev,
|
|
1089
|
-
disabledCards: prev.disabledCards.filter((v) => v !== value)
|
|
1090
|
-
}));
|
|
1091
|
-
}
|
|
1037
|
+
}, []);
|
|
1038
|
+
useEffect(() => {
|
|
1039
|
+
fetchDisputes(EMPTY_FILTERS);
|
|
1040
|
+
}, [fetchDisputes]);
|
|
1041
|
+
const onSubmit = (event) => {
|
|
1042
|
+
event.preventDefault();
|
|
1043
|
+
fetchDisputes(filters);
|
|
1044
|
+
};
|
|
1045
|
+
const onReset = () => {
|
|
1046
|
+
setFilters({ ...EMPTY_FILTERS });
|
|
1047
|
+
fetchDisputes(EMPTY_FILTERS);
|
|
1048
|
+
};
|
|
1092
1049
|
return /* @__PURE__ */ jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
1093
|
-
/* @__PURE__ */
|
|
1050
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1051
|
+
/* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Disputes" }),
|
|
1052
|
+
/* @__PURE__ */ 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." })
|
|
1053
|
+
] }),
|
|
1094
1054
|
/* @__PURE__ */ jsx(PayPalTabs, {}),
|
|
1095
|
-
|
|
1096
|
-
"div",
|
|
1097
|
-
{
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
disabled: saving || loading,
|
|
1116
|
-
className: "rounded-md bg-ui-button-neutral px-4 py-2 text-sm font-medium text-ui-fg-on-color shadow-sm hover:opacity-90 disabled:opacity-60",
|
|
1117
|
-
children: saving ? "Saving..." : "Save settings"
|
|
1118
|
-
}
|
|
1119
|
-
),
|
|
1120
|
-
loading ? /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading…" }) : null
|
|
1055
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
1056
|
+
/* @__PURE__ */ jsx("div", { className: "border-b border-ui-border-base p-4", children: /* @__PURE__ */ jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Filters" }) }),
|
|
1057
|
+
/* @__PURE__ */ jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxs("form", { onSubmit, className: "flex flex-col gap-4", children: [
|
|
1058
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-4", children: [
|
|
1059
|
+
/* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
|
|
1060
|
+
"Dispute ID",
|
|
1061
|
+
/* @__PURE__ */ jsx("input", { className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base", value: filters.dispute_id, onChange: (e) => setFilters((p) => ({ ...p, dispute_id: e.target.value })), placeholder: "PP-D-123" })
|
|
1062
|
+
] }),
|
|
1063
|
+
/* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
|
|
1064
|
+
"Status",
|
|
1065
|
+
/* @__PURE__ */ jsx("input", { className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base", value: filters.status, onChange: (e) => setFilters((p) => ({ ...p, status: e.target.value })), placeholder: "OPEN" })
|
|
1066
|
+
] }),
|
|
1067
|
+
/* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
|
|
1068
|
+
"Order ID",
|
|
1069
|
+
/* @__PURE__ */ jsx("input", { className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base", value: filters.order_id, onChange: (e) => setFilters((p) => ({ ...p, order_id: e.target.value })), placeholder: "order_..." })
|
|
1070
|
+
] }),
|
|
1071
|
+
/* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
|
|
1072
|
+
"Cart ID",
|
|
1073
|
+
/* @__PURE__ */ jsx("input", { className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base", value: filters.cart_id, onChange: (e) => setFilters((p) => ({ ...p, cart_id: e.target.value })), placeholder: "cart_..." })
|
|
1074
|
+
] })
|
|
1121
1075
|
] }),
|
|
1122
|
-
|
|
1123
|
-
/* @__PURE__ */ jsx(
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
),
|
|
1133
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable Advanced Credit/Debit Card" })
|
|
1134
|
-
] }) }),
|
|
1135
|
-
/* @__PURE__ */ jsx(FieldRow$1, { label: "Title", children: /* @__PURE__ */ jsx(
|
|
1136
|
-
"input",
|
|
1137
|
-
{
|
|
1138
|
-
value: form.title,
|
|
1139
|
-
onChange: (e) => setForm((p) => ({ ...p, title: e.target.value })),
|
|
1140
|
-
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",
|
|
1141
|
-
placeholder: "Credit or Debit Card"
|
|
1142
|
-
}
|
|
1143
|
-
) }),
|
|
1144
|
-
/* @__PURE__ */ jsx(
|
|
1145
|
-
FieldRow$1,
|
|
1146
|
-
{
|
|
1147
|
-
label: "Disable specific credit cards",
|
|
1148
|
-
hint: "Select card brands to hide from the card form.",
|
|
1149
|
-
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
1150
|
-
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: form.disabledCards.length ? form.disabledCards.map((v) => {
|
|
1151
|
-
var _a2;
|
|
1152
|
-
const label = ((_a2 = CARD_BRANDS.find((b) => b.value === v)) == null ? void 0 : _a2.label) ?? v;
|
|
1153
|
-
return /* @__PURE__ */ jsx(Pill$1, { onRemove: () => removeDisabledCard(v), children: label }, v);
|
|
1154
|
-
}) : /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-subtle", children: "No card brands disabled." }) }),
|
|
1155
|
-
/* @__PURE__ */ jsx("div", { className: "rounded-md border border-ui-border-base p-3", children: /* @__PURE__ */ jsx("div", { className: "grid gap-2 md:grid-cols-2", children: CARD_BRANDS.map((b) => {
|
|
1156
|
-
const checked = disabledSet.has(b.value);
|
|
1157
|
-
return /* @__PURE__ */ jsxs(
|
|
1158
|
-
"label",
|
|
1159
|
-
{
|
|
1160
|
-
className: cx$1(
|
|
1161
|
-
"flex items-center gap-2 rounded-md p-2",
|
|
1162
|
-
"hover:bg-ui-bg-subtle"
|
|
1163
|
-
),
|
|
1164
|
-
children: [
|
|
1165
|
-
/* @__PURE__ */ jsx(
|
|
1166
|
-
"input",
|
|
1167
|
-
{
|
|
1168
|
-
type: "checkbox",
|
|
1169
|
-
checked,
|
|
1170
|
-
onChange: () => toggleDisabledCard(b.value),
|
|
1171
|
-
className: "h-4 w-4 rounded border-ui-border-base"
|
|
1172
|
-
}
|
|
1173
|
-
),
|
|
1174
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: b.label })
|
|
1175
|
-
]
|
|
1176
|
-
},
|
|
1177
|
-
b.value
|
|
1178
|
-
);
|
|
1179
|
-
}) }) })
|
|
1180
|
-
] })
|
|
1181
|
-
}
|
|
1182
|
-
),
|
|
1183
|
-
/* @__PURE__ */ jsx(
|
|
1184
|
-
FieldRow$1,
|
|
1185
|
-
{
|
|
1186
|
-
label: "Contingency for 3D Secure",
|
|
1187
|
-
hint: "Choose when 3D Secure should be triggered during card payments.",
|
|
1188
|
-
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
1189
|
-
/* @__PURE__ */ jsx(
|
|
1190
|
-
"select",
|
|
1191
|
-
{
|
|
1192
|
-
value: form.threeDS,
|
|
1193
|
-
onChange: (e) => setForm((p) => ({ ...p, threeDS: e.target.value })),
|
|
1194
|
-
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",
|
|
1195
|
-
children: THREE_DS_OPTIONS.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: o.label }, o.value))
|
|
1196
|
-
}
|
|
1197
|
-
),
|
|
1198
|
-
((_a = THREE_DS_OPTIONS.find((o) => o.value === form.threeDS)) == null ? void 0 : _a.hint) ? /* @__PURE__ */ 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
|
|
1199
|
-
] })
|
|
1200
|
-
}
|
|
1201
|
-
),
|
|
1202
|
-
/* @__PURE__ */ jsx(FieldRow$1, { label: "Card Save Enabled", hint: "Allow customers to save a card at checkout for future use.", children: /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2", children: [
|
|
1203
|
-
/* @__PURE__ */ jsx(
|
|
1204
|
-
"input",
|
|
1205
|
-
{
|
|
1206
|
-
type: "checkbox",
|
|
1207
|
-
checked: form.cardSaveEnabled,
|
|
1208
|
-
onChange: (e) => setForm((p) => ({ ...p, cardSaveEnabled: e.target.checked })),
|
|
1209
|
-
className: "h-4 w-4 rounded border-ui-border-base"
|
|
1210
|
-
}
|
|
1211
|
-
),
|
|
1212
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable card saving at checkout" })
|
|
1213
|
-
] }) })
|
|
1076
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-3", children: [
|
|
1077
|
+
/* @__PURE__ */ jsx("button", { type: "submit", className: "rounded-md bg-ui-fg-base px-4 py-2 text-sm font-medium text-ui-bg-base", disabled: loading, children: loading ? "Loading..." : "Apply filters" }),
|
|
1078
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "rounded-md border border-ui-border-base px-4 py-2 text-sm text-ui-fg-base", onClick: onReset, disabled: loading, children: "Reset" }),
|
|
1079
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm text-ui-fg-subtle", children: [
|
|
1080
|
+
"Showing ",
|
|
1081
|
+
disputes.length,
|
|
1082
|
+
" dispute",
|
|
1083
|
+
disputes.length === 1 ? "" : "s",
|
|
1084
|
+
queryString ? " (filtered)" : ""
|
|
1085
|
+
] })
|
|
1214
1086
|
] })
|
|
1215
|
-
}
|
|
1216
|
-
)
|
|
1087
|
+
] }) })
|
|
1088
|
+
] }),
|
|
1089
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
1090
|
+
/* @__PURE__ */ jsx("div", { className: "border-b border-ui-border-base p-4", children: /* @__PURE__ */ jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Dispute Records" }) }),
|
|
1091
|
+
/* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base text-sm", children: [
|
|
1092
|
+
/* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { className: "text-left text-ui-fg-subtle", children: [
|
|
1093
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 font-medium", children: "Dispute" }),
|
|
1094
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 font-medium", children: "Status" }),
|
|
1095
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 font-medium", children: "Reason" }),
|
|
1096
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 font-medium", children: "Stage" }),
|
|
1097
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 font-medium", children: "Amount" }),
|
|
1098
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 font-medium", children: "Order" }),
|
|
1099
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 font-medium", children: "Cart" }),
|
|
1100
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 font-medium", children: "Updated" })
|
|
1101
|
+
] }) }),
|
|
1102
|
+
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-base text-ui-fg-base", children: disputes.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ 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__ */ jsxs("tr", { children: [
|
|
1103
|
+
/* @__PURE__ */ jsxs("td", { className: "px-4 py-3", children: [
|
|
1104
|
+
/* @__PURE__ */ jsx("div", { className: "font-medium text-ui-fg-base", children: dispute.dispute_id }),
|
|
1105
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs text-ui-fg-subtle", children: dispute.transaction_id || "No transaction" })
|
|
1106
|
+
] }),
|
|
1107
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: dispute.status || "Unknown" }),
|
|
1108
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: dispute.reason || "-" }),
|
|
1109
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: dispute.stage || "-" }),
|
|
1110
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: dispute.amount ? `${dispute.amount} ${dispute.currency_code || ""}` : "-" }),
|
|
1111
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: dispute.order_id || "-" }),
|
|
1112
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: dispute.cart_id || "-" }),
|
|
1113
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-3 text-ui-fg-subtle", children: formatDate$2(dispute.updated_at || dispute.created_at) })
|
|
1114
|
+
] }, dispute.id)) })
|
|
1115
|
+
] }) }),
|
|
1116
|
+
error ? /* @__PURE__ */ jsx("div", { className: "border-t border-ui-border-base px-4 py-3 text-sm text-ui-fg-error", children: error }) : null
|
|
1117
|
+
] })
|
|
1217
1118
|
] }) });
|
|
1218
1119
|
}
|
|
1219
|
-
function
|
|
1220
|
-
|
|
1221
|
-
|
|
1120
|
+
async function adminFetch$2(path, opts = {}) {
|
|
1121
|
+
var _a;
|
|
1122
|
+
const { method = "GET", body, query } = opts;
|
|
1123
|
+
let url = path;
|
|
1124
|
+
if (query && Object.keys(query).length > 0) {
|
|
1125
|
+
const params = new URLSearchParams(query);
|
|
1126
|
+
url = `${path}?${params.toString()}`;
|
|
1222
1127
|
}
|
|
1223
|
-
const
|
|
1224
|
-
if (
|
|
1225
|
-
|
|
1128
|
+
const headers = { Accept: "application/json" };
|
|
1129
|
+
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
1130
|
+
if (typeof window !== "undefined") {
|
|
1131
|
+
const token = (_a = window.__medusa__) == null ? void 0 : _a.token;
|
|
1132
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
1133
|
+
}
|
|
1134
|
+
const res = await fetch(url, {
|
|
1135
|
+
method,
|
|
1136
|
+
headers,
|
|
1137
|
+
credentials: "include",
|
|
1138
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
1139
|
+
});
|
|
1140
|
+
const text = await res.text().catch(() => "");
|
|
1141
|
+
if (!res.ok) {
|
|
1142
|
+
if (res.status === 401) throw new Error("Unauthorized (401) - session may have expired. Please reload and log in again.");
|
|
1143
|
+
if (res.status === 403) throw new Error("Forbidden (403) - you do not have permission to perform this action.");
|
|
1144
|
+
throw new Error(text || `Request failed with status ${res.status}`);
|
|
1226
1145
|
}
|
|
1146
|
+
if (!text) return {};
|
|
1147
|
+
try {
|
|
1148
|
+
return JSON.parse(text);
|
|
1149
|
+
} catch {
|
|
1150
|
+
return {};
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
function formatDate$1(value) {
|
|
1154
|
+
if (!value) return "";
|
|
1155
|
+
const parsed = new Date(value);
|
|
1156
|
+
if (Number.isNaN(parsed.getTime())) return value;
|
|
1227
1157
|
return parsed.toLocaleString();
|
|
1228
1158
|
}
|
|
1229
1159
|
function PayPalAuditLogsPage() {
|
|
@@ -1234,20 +1164,10 @@ function PayPalAuditLogsPage() {
|
|
|
1234
1164
|
try {
|
|
1235
1165
|
setLoading(true);
|
|
1236
1166
|
setError(null);
|
|
1237
|
-
const
|
|
1238
|
-
|
|
1239
|
-
headers: {
|
|
1240
|
-
Accept: "application/json"
|
|
1241
|
-
}
|
|
1242
|
-
});
|
|
1243
|
-
if (!response.ok) {
|
|
1244
|
-
const message = await response.text().catch(() => "");
|
|
1245
|
-
throw new Error(message || "Failed to load audit logs.");
|
|
1246
|
-
}
|
|
1247
|
-
const data = await response.json().catch(() => ({}));
|
|
1248
|
-
setLogs((data == null ? void 0 : data.logs) || []);
|
|
1167
|
+
const data = await adminFetch$2("/admin/paypal/audit-logs", { query: { limit: "50" } });
|
|
1168
|
+
setLogs((data == null ? void 0 : data.logs) ?? []);
|
|
1249
1169
|
} catch (fetchError) {
|
|
1250
|
-
setError(
|
|
1170
|
+
setError(fetchError instanceof Error ? fetchError.message : "Failed to load audit logs.");
|
|
1251
1171
|
setLogs([]);
|
|
1252
1172
|
} finally {
|
|
1253
1173
|
setLoading(false);
|
|
@@ -1265,16 +1185,7 @@ function PayPalAuditLogsPage() {
|
|
|
1265
1185
|
/* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
1266
1186
|
/* @__PURE__ */ jsx("div", { className: "border-b border-ui-border-base p-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4", children: [
|
|
1267
1187
|
/* @__PURE__ */ jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Latest events" }),
|
|
1268
|
-
/* @__PURE__ */ jsx(
|
|
1269
|
-
"button",
|
|
1270
|
-
{
|
|
1271
|
-
type: "button",
|
|
1272
|
-
onClick: fetchLogs,
|
|
1273
|
-
className: "rounded-md border border-ui-border-base px-3 py-2 text-sm text-ui-fg-base",
|
|
1274
|
-
disabled: loading,
|
|
1275
|
-
children: loading ? "Refreshing..." : "Refresh"
|
|
1276
|
-
}
|
|
1277
|
-
)
|
|
1188
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: fetchLogs, className: "rounded-md border border-ui-border-base px-3 py-2 text-sm text-ui-fg-base", disabled: loading, children: loading ? "Refreshing..." : "Refresh" })
|
|
1278
1189
|
] }) }),
|
|
1279
1190
|
/* @__PURE__ */ jsxs("div", { className: "p-4", children: [
|
|
1280
1191
|
error ? /* @__PURE__ */ jsx("div", { className: "rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-600", children: error }) : null,
|
|
@@ -1286,7 +1197,7 @@ function PayPalAuditLogsPage() {
|
|
|
1286
1197
|
/* @__PURE__ */ jsx("th", { className: "pb-2 font-medium", children: "Details" })
|
|
1287
1198
|
] }) }),
|
|
1288
1199
|
/* @__PURE__ */ jsx("tbody", { children: logs.map((entry) => /* @__PURE__ */ jsxs("tr", { className: "border-t border-ui-border-base", children: [
|
|
1289
|
-
/* @__PURE__ */ jsx("td", { className: "py-3 pr-4 text-ui-fg-base", children: formatDate$
|
|
1200
|
+
/* @__PURE__ */ jsx("td", { className: "py-3 pr-4 text-ui-fg-base", children: formatDate$1(entry.created_at) || "—" }),
|
|
1290
1201
|
/* @__PURE__ */ jsx("td", { className: "py-3 pr-4 text-ui-fg-base", children: entry.event_type || "—" }),
|
|
1291
1202
|
/* @__PURE__ */ jsx("td", { className: "py-3 text-ui-fg-subtle", children: /* @__PURE__ */ 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) }) })
|
|
1292
1203
|
] }, entry.id)) })
|
|
@@ -1298,200 +1209,161 @@ function PayPalAuditLogsPage() {
|
|
|
1298
1209
|
function PayPalGooglePayPage() {
|
|
1299
1210
|
return /* @__PURE__ */ jsx(Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
1300
1211
|
}
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
};
|
|
1307
|
-
|
|
1308
|
-
if (
|
|
1309
|
-
|
|
1212
|
+
function PayPalPayLaterMessagingPage() {
|
|
1213
|
+
return /* @__PURE__ */ jsx(Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
1214
|
+
}
|
|
1215
|
+
async function adminFetch$1(path, opts = {}) {
|
|
1216
|
+
var _a;
|
|
1217
|
+
const { method = "GET", body, query } = opts;
|
|
1218
|
+
let url = path;
|
|
1219
|
+
if (query && Object.keys(query).length > 0) {
|
|
1220
|
+
const params = new URLSearchParams(query);
|
|
1221
|
+
url = `${path}?${params.toString()}`;
|
|
1310
1222
|
}
|
|
1311
|
-
const
|
|
1312
|
-
if (
|
|
1313
|
-
|
|
1223
|
+
const headers = { Accept: "application/json" };
|
|
1224
|
+
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
1225
|
+
if (typeof window !== "undefined") {
|
|
1226
|
+
const token = (_a = window.__medusa__) == null ? void 0 : _a.token;
|
|
1227
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
1314
1228
|
}
|
|
1229
|
+
const res = await fetch(url, {
|
|
1230
|
+
method,
|
|
1231
|
+
headers,
|
|
1232
|
+
credentials: "include",
|
|
1233
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
1234
|
+
});
|
|
1235
|
+
const text = await res.text().catch(() => "");
|
|
1236
|
+
if (!res.ok) {
|
|
1237
|
+
if (res.status === 401) throw new Error("Unauthorized (401) - session may have expired. Please reload and log in again.");
|
|
1238
|
+
if (res.status === 403) throw new Error("Forbidden (403) - you do not have permission to perform this action.");
|
|
1239
|
+
throw new Error(text || `Request failed with status ${res.status}`);
|
|
1240
|
+
}
|
|
1241
|
+
if (!text) return {};
|
|
1242
|
+
try {
|
|
1243
|
+
return JSON.parse(text);
|
|
1244
|
+
} catch {
|
|
1245
|
+
return {};
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
function formatDate(value) {
|
|
1249
|
+
if (!value) return "—";
|
|
1250
|
+
const parsed = new Date(value);
|
|
1251
|
+
if (Number.isNaN(parsed.getTime())) return value;
|
|
1315
1252
|
return parsed.toLocaleString();
|
|
1316
1253
|
}
|
|
1317
|
-
function
|
|
1318
|
-
const [
|
|
1319
|
-
const [disputes, setDisputes] = useState([]);
|
|
1254
|
+
function PayPalReconciliationStatusPage() {
|
|
1255
|
+
const [status, setStatus] = useState({});
|
|
1320
1256
|
const [loading, setLoading] = useState(false);
|
|
1321
1257
|
const [error, setError] = useState(null);
|
|
1322
|
-
const
|
|
1323
|
-
const params = new URLSearchParams();
|
|
1324
|
-
Object.entries(filters).forEach(([key, value]) => {
|
|
1325
|
-
if (value.trim()) {
|
|
1326
|
-
params.set(key, value.trim());
|
|
1327
|
-
}
|
|
1328
|
-
});
|
|
1329
|
-
const qs = params.toString();
|
|
1330
|
-
return qs ? `?${qs}` : "";
|
|
1331
|
-
}, [filters]);
|
|
1332
|
-
const fetchDisputes = useCallback(async (source) => {
|
|
1258
|
+
const fetchStatus = useCallback(async () => {
|
|
1333
1259
|
try {
|
|
1334
1260
|
setLoading(true);
|
|
1335
1261
|
setError(null);
|
|
1336
|
-
const
|
|
1337
|
-
|
|
1338
|
-
if (value.trim()) {
|
|
1339
|
-
params.set(key, value.trim());
|
|
1340
|
-
}
|
|
1341
|
-
});
|
|
1342
|
-
const qs = params.toString();
|
|
1343
|
-
const resp = await fetch(`/admin/paypal/disputes${qs ? `?${qs}` : ""}`, {
|
|
1344
|
-
credentials: "include",
|
|
1345
|
-
headers: {
|
|
1346
|
-
Accept: "application/json"
|
|
1347
|
-
}
|
|
1348
|
-
});
|
|
1349
|
-
if (!resp.ok) {
|
|
1350
|
-
const message = await resp.text().catch(() => "");
|
|
1351
|
-
throw new Error(message || "Failed to load disputes");
|
|
1352
|
-
}
|
|
1353
|
-
const json = await resp.json().catch(() => ({}));
|
|
1354
|
-
setDisputes((json == null ? void 0 : json.disputes) || []);
|
|
1262
|
+
const data = await adminFetch$1("/admin/paypal/reconciliation-status");
|
|
1263
|
+
setStatus((data == null ? void 0 : data.status) ?? {});
|
|
1355
1264
|
} catch (fetchError) {
|
|
1356
|
-
setError(
|
|
1357
|
-
|
|
1265
|
+
setError(fetchError instanceof Error ? fetchError.message : "Failed to load reconciliation status.");
|
|
1266
|
+
setStatus({});
|
|
1358
1267
|
} finally {
|
|
1359
1268
|
setLoading(false);
|
|
1360
1269
|
}
|
|
1361
1270
|
}, []);
|
|
1362
1271
|
useEffect(() => {
|
|
1363
|
-
|
|
1364
|
-
}, [
|
|
1365
|
-
const onSubmit = (event) => {
|
|
1366
|
-
event.preventDefault();
|
|
1367
|
-
fetchDisputes(filters);
|
|
1368
|
-
};
|
|
1369
|
-
const onReset = () => {
|
|
1370
|
-
setFilters({ ...EMPTY_FILTERS });
|
|
1371
|
-
fetchDisputes(EMPTY_FILTERS);
|
|
1372
|
-
};
|
|
1272
|
+
fetchStatus();
|
|
1273
|
+
}, [fetchStatus]);
|
|
1373
1274
|
return /* @__PURE__ */ jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
1374
1275
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
1375
|
-
/* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal
|
|
1376
|
-
/* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-ui-fg-subtle", children: "
|
|
1276
|
+
/* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Reconciliation Status" }),
|
|
1277
|
+
/* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-ui-fg-subtle", children: "Monitor reconciliation health and drift detection for PayPal payment sessions." })
|
|
1377
1278
|
] }),
|
|
1378
1279
|
/* @__PURE__ */ jsx(PayPalTabs, {}),
|
|
1379
1280
|
/* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
1380
|
-
/* @__PURE__ */ jsx("div", { className: "border-b border-ui-border-base p-4", children: /* @__PURE__ */
|
|
1381
|
-
|
|
1382
|
-
/* @__PURE__ */
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
placeholder: "PP-D-123"
|
|
1392
|
-
}
|
|
1393
|
-
)
|
|
1281
|
+
/* @__PURE__ */ jsx("div", { className: "border-b border-ui-border-base p-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4", children: [
|
|
1282
|
+
/* @__PURE__ */ jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Latest reconciliation run" }),
|
|
1283
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: fetchStatus, className: "rounded-md border border-ui-border-base px-3 py-2 text-sm text-ui-fg-base", disabled: loading, children: loading ? "Refreshing..." : "Refresh" })
|
|
1284
|
+
] }) }),
|
|
1285
|
+
/* @__PURE__ */ jsxs("div", { className: "p-4", children: [
|
|
1286
|
+
error ? /* @__PURE__ */ jsx("div", { className: "rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-600", children: error }) : null,
|
|
1287
|
+
!error && Object.keys(status).length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-sm text-ui-fg-subtle", children: loading ? "Loading reconciliation status..." : "No reconciliation data yet." }) : null,
|
|
1288
|
+
Object.keys(status).length > 0 ? /* @__PURE__ */ jsxs("div", { className: "grid gap-4 text-sm text-ui-fg-base md:grid-cols-2", children: [
|
|
1289
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1290
|
+
/* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Last run" }),
|
|
1291
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_run_at) })
|
|
1394
1292
|
] }),
|
|
1395
|
-
/* @__PURE__ */ jsxs("
|
|
1396
|
-
"
|
|
1397
|
-
/* @__PURE__ */ jsx(
|
|
1398
|
-
"input",
|
|
1399
|
-
{
|
|
1400
|
-
className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base",
|
|
1401
|
-
value: filters.status,
|
|
1402
|
-
onChange: (event) => setFilters((prev) => ({ ...prev, status: event.target.value })),
|
|
1403
|
-
placeholder: "OPEN"
|
|
1404
|
-
}
|
|
1405
|
-
)
|
|
1293
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1294
|
+
/* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Last run status" }),
|
|
1295
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 font-medium capitalize", children: status.last_run_status || "—" })
|
|
1406
1296
|
] }),
|
|
1407
|
-
/* @__PURE__ */ jsxs("
|
|
1408
|
-
"
|
|
1409
|
-
/* @__PURE__ */ jsx(
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
)
|
|
1297
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1298
|
+
/* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Last success" }),
|
|
1299
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_success_at) })
|
|
1300
|
+
] }),
|
|
1301
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1302
|
+
/* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Last failure" }),
|
|
1303
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_failure_at) })
|
|
1304
|
+
] }),
|
|
1305
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1306
|
+
/* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Sessions checked" }),
|
|
1307
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: status.sessions_checked ?? 0 })
|
|
1308
|
+
] }),
|
|
1309
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1310
|
+
/* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Sessions updated" }),
|
|
1311
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: status.sessions_updated ?? 0 })
|
|
1312
|
+
] }),
|
|
1313
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1314
|
+
/* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Drift detections" }),
|
|
1315
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: status.drift_count ?? 0 })
|
|
1316
|
+
] }),
|
|
1317
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1318
|
+
/* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Last drift order" }),
|
|
1319
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: status.last_drift_order_id || "—" }),
|
|
1320
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 text-xs text-ui-fg-subtle", children: formatDate(status.last_drift_at) })
|
|
1321
|
+
] }),
|
|
1322
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 md:col-span-2", children: [
|
|
1323
|
+
/* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Last error" }),
|
|
1324
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: status.last_error || "No errors recorded." })
|
|
1418
1325
|
] }),
|
|
1419
|
-
/* @__PURE__ */ jsxs("
|
|
1420
|
-
"
|
|
1421
|
-
/* @__PURE__ */ jsx(
|
|
1422
|
-
"input",
|
|
1423
|
-
{
|
|
1424
|
-
className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base",
|
|
1425
|
-
value: filters.cart_id,
|
|
1426
|
-
onChange: (event) => setFilters((prev) => ({ ...prev, cart_id: event.target.value })),
|
|
1427
|
-
placeholder: "cart_..."
|
|
1428
|
-
}
|
|
1429
|
-
)
|
|
1430
|
-
] })
|
|
1431
|
-
] }),
|
|
1432
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-3", children: [
|
|
1433
|
-
/* @__PURE__ */ jsx(
|
|
1434
|
-
"button",
|
|
1435
|
-
{
|
|
1436
|
-
type: "submit",
|
|
1437
|
-
className: "rounded-md bg-ui-fg-base px-4 py-2 text-sm font-medium text-ui-bg-base",
|
|
1438
|
-
disabled: loading,
|
|
1439
|
-
children: loading ? "Loading..." : "Apply filters"
|
|
1440
|
-
}
|
|
1441
|
-
),
|
|
1442
|
-
/* @__PURE__ */ jsx(
|
|
1443
|
-
"button",
|
|
1444
|
-
{
|
|
1445
|
-
type: "button",
|
|
1446
|
-
className: "rounded-md border border-ui-border-base px-4 py-2 text-sm text-ui-fg-base",
|
|
1447
|
-
onClick: onReset,
|
|
1448
|
-
disabled: loading,
|
|
1449
|
-
children: "Reset"
|
|
1450
|
-
}
|
|
1451
|
-
),
|
|
1452
|
-
/* @__PURE__ */ jsxs("span", { className: "text-sm text-ui-fg-subtle", children: [
|
|
1453
|
-
"Showing ",
|
|
1454
|
-
disputes.length,
|
|
1455
|
-
" dispute",
|
|
1456
|
-
disputes.length === 1 ? "" : "s",
|
|
1457
|
-
queryString ? " (filtered)" : ""
|
|
1326
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 md:col-span-2", children: [
|
|
1327
|
+
/* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Total runs" }),
|
|
1328
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: status.runs ?? 0 })
|
|
1458
1329
|
] })
|
|
1459
|
-
] })
|
|
1460
|
-
] })
|
|
1461
|
-
] }),
|
|
1462
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
|
|
1463
|
-
/* @__PURE__ */ jsx("div", { className: "border-b border-ui-border-base p-4", children: /* @__PURE__ */ jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Dispute Records" }) }),
|
|
1464
|
-
/* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base text-sm", children: [
|
|
1465
|
-
/* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { className: "text-left text-ui-fg-subtle", children: [
|
|
1466
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 font-medium", children: "Dispute" }),
|
|
1467
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 font-medium", children: "Status" }),
|
|
1468
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 font-medium", children: "Reason" }),
|
|
1469
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 font-medium", children: "Stage" }),
|
|
1470
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 font-medium", children: "Amount" }),
|
|
1471
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 font-medium", children: "Order" }),
|
|
1472
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 font-medium", children: "Cart" }),
|
|
1473
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 font-medium", children: "Updated" })
|
|
1474
|
-
] }) }),
|
|
1475
|
-
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-base text-ui-fg-base", children: disputes.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ 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__ */ jsxs("tr", { children: [
|
|
1476
|
-
/* @__PURE__ */ jsxs("td", { className: "px-4 py-3", children: [
|
|
1477
|
-
/* @__PURE__ */ jsx("div", { className: "font-medium text-ui-fg-base", children: dispute.dispute_id }),
|
|
1478
|
-
/* @__PURE__ */ jsx("div", { className: "text-xs text-ui-fg-subtle", children: dispute.transaction_id || "No transaction" })
|
|
1479
|
-
] }),
|
|
1480
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: dispute.status || "Unknown" }),
|
|
1481
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: dispute.reason || "-" }),
|
|
1482
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: dispute.stage || "-" }),
|
|
1483
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: dispute.amount ? `${dispute.amount} ${dispute.currency_code || ""}` : "-" }),
|
|
1484
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: dispute.order_id || "-" }),
|
|
1485
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: dispute.cart_id || "-" }),
|
|
1486
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-3 text-ui-fg-subtle", children: formatDate$1(dispute.updated_at || dispute.created_at) })
|
|
1487
|
-
] }, dispute.id)) })
|
|
1488
|
-
] }) }),
|
|
1489
|
-
error ? /* @__PURE__ */ jsx("div", { className: "border-t border-ui-border-base px-4 py-3 text-sm text-ui-fg-error", children: error }) : null
|
|
1330
|
+
] }) : null
|
|
1331
|
+
] })
|
|
1490
1332
|
] })
|
|
1491
1333
|
] }) });
|
|
1492
1334
|
}
|
|
1493
|
-
function
|
|
1494
|
-
|
|
1335
|
+
async function adminFetch(path, opts = {}) {
|
|
1336
|
+
var _a;
|
|
1337
|
+
const { method = "GET", body, query } = opts;
|
|
1338
|
+
let url = path;
|
|
1339
|
+
if (query && Object.keys(query).length > 0) {
|
|
1340
|
+
const params = new URLSearchParams(query);
|
|
1341
|
+
url = `${path}?${params.toString()}`;
|
|
1342
|
+
}
|
|
1343
|
+
const headers = { Accept: "application/json" };
|
|
1344
|
+
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
1345
|
+
if (typeof window !== "undefined") {
|
|
1346
|
+
const token = (_a = window.__medusa__) == null ? void 0 : _a.token;
|
|
1347
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
1348
|
+
}
|
|
1349
|
+
const res = await fetch(url, {
|
|
1350
|
+
method,
|
|
1351
|
+
headers,
|
|
1352
|
+
credentials: "include",
|
|
1353
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
1354
|
+
});
|
|
1355
|
+
const text = await res.text().catch(() => "");
|
|
1356
|
+
if (!res.ok) {
|
|
1357
|
+
if (res.status === 401) throw new Error("Unauthorized (401) - session may have expired. Please reload and log in again.");
|
|
1358
|
+
if (res.status === 403) throw new Error("Forbidden (403) - you do not have permission to perform this action.");
|
|
1359
|
+
throw new Error(text || `Request failed with status ${res.status}`);
|
|
1360
|
+
}
|
|
1361
|
+
if (!text) return {};
|
|
1362
|
+
try {
|
|
1363
|
+
return JSON.parse(text);
|
|
1364
|
+
} catch {
|
|
1365
|
+
return {};
|
|
1366
|
+
}
|
|
1495
1367
|
}
|
|
1496
1368
|
const DISPLAY_LOCATION_OPTIONS = [
|
|
1497
1369
|
{ value: "product", label: "Product Page" },
|
|
@@ -1604,7 +1476,7 @@ function PayPalSettingsTab() {
|
|
|
1604
1476
|
const [form, setForm] = useState({
|
|
1605
1477
|
enabled: true,
|
|
1606
1478
|
title: "PayPal",
|
|
1607
|
-
description: "Pay via PayPal; you can pay with your credit card if you don
|
|
1479
|
+
description: "Pay via PayPal; you can pay with your credit card if you don't have a PayPal account",
|
|
1608
1480
|
displayOn: ["product", "cart", "express", "mini_cart"],
|
|
1609
1481
|
disableButtons: [],
|
|
1610
1482
|
buttonColor: "gold",
|
|
@@ -1623,12 +1495,9 @@ function PayPalSettingsTab() {
|
|
|
1623
1495
|
(async () => {
|
|
1624
1496
|
try {
|
|
1625
1497
|
setLoading(true);
|
|
1626
|
-
const
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
});
|
|
1630
|
-
if (!r.ok) return;
|
|
1631
|
-
const json = await r.json();
|
|
1498
|
+
const json = await adminFetch(
|
|
1499
|
+
"/admin/paypal/settings"
|
|
1500
|
+
);
|
|
1632
1501
|
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
1633
1502
|
const saved = payload == null ? void 0 : payload.paypal_settings;
|
|
1634
1503
|
if (saved && typeof saved === "object") {
|
|
@@ -1638,6 +1507,7 @@ function PayPalSettingsTab() {
|
|
|
1638
1507
|
disableButtons: filterHiddenDisableButtons(saved.disableButtons)
|
|
1639
1508
|
}));
|
|
1640
1509
|
}
|
|
1510
|
+
} catch {
|
|
1641
1511
|
} finally {
|
|
1642
1512
|
setLoading(false);
|
|
1643
1513
|
}
|
|
@@ -1650,22 +1520,13 @@ function PayPalSettingsTab() {
|
|
|
1650
1520
|
...form,
|
|
1651
1521
|
disableButtons: filterHiddenDisableButtons(form.disableButtons)
|
|
1652
1522
|
};
|
|
1653
|
-
const
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
body: JSON.stringify({ paypal_settings: cleaned })
|
|
1661
|
-
});
|
|
1662
|
-
if (!r.ok) {
|
|
1663
|
-
const t = await r.text();
|
|
1664
|
-
setToast({ type: "error", message: "Failed to save settings. " + t });
|
|
1665
|
-
window.setTimeout(() => setToast(null), 3500);
|
|
1666
|
-
return;
|
|
1667
|
-
}
|
|
1668
|
-
const json = await r.json().catch(() => null);
|
|
1523
|
+
const json = await adminFetch(
|
|
1524
|
+
"/admin/paypal/settings",
|
|
1525
|
+
{
|
|
1526
|
+
method: "POST",
|
|
1527
|
+
body: { paypal_settings: cleaned }
|
|
1528
|
+
}
|
|
1529
|
+
);
|
|
1669
1530
|
const payload = (json == null ? void 0 : json.data) ?? json;
|
|
1670
1531
|
const saved = payload == null ? void 0 : payload.paypal_settings;
|
|
1671
1532
|
if (saved && typeof saved === "object") {
|
|
@@ -1677,6 +1538,12 @@ function PayPalSettingsTab() {
|
|
|
1677
1538
|
}
|
|
1678
1539
|
setToast({ type: "success", message: "Settings saved" });
|
|
1679
1540
|
window.setTimeout(() => setToast(null), 2500);
|
|
1541
|
+
} catch (e) {
|
|
1542
|
+
setToast({
|
|
1543
|
+
type: "error",
|
|
1544
|
+
message: (e instanceof Error ? e.message : "") || "Failed to save settings."
|
|
1545
|
+
});
|
|
1546
|
+
window.setTimeout(() => setToast(null), 3500);
|
|
1680
1547
|
} finally {
|
|
1681
1548
|
setSaving(false);
|
|
1682
1549
|
}
|
|
@@ -1816,226 +1683,114 @@ function PayPalSettingsTab() {
|
|
|
1816
1683
|
] })
|
|
1817
1684
|
}
|
|
1818
1685
|
),
|
|
1819
|
-
/* @__PURE__ */
|
|
1686
|
+
/* @__PURE__ */ jsx(
|
|
1820
1687
|
SectionCard,
|
|
1821
1688
|
{
|
|
1822
1689
|
title: "Button Appearance",
|
|
1823
1690
|
description: "Control PayPal Smart Button styling (color/shape/size/label) and optionally disable specific buttons.",
|
|
1824
|
-
children: [
|
|
1825
|
-
/* @__PURE__ */
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
] }),
|
|
1906
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-6 rounded-md border border-ui-border-base bg-ui-bg-subtle p-4", children: [
|
|
1907
|
-
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium text-ui-fg-base", children: "Preview (UI only)" }),
|
|
1908
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-2 text-sm text-ui-fg-subtle", children: [
|
|
1909
|
-
"Color: ",
|
|
1910
|
-
/* @__PURE__ */ jsx("span", { className: "text-ui-fg-base", children: form.buttonColor }),
|
|
1911
|
-
" · Shape:",
|
|
1912
|
-
" ",
|
|
1913
|
-
/* @__PURE__ */ jsx("span", { className: "text-ui-fg-base", children: form.buttonShape }),
|
|
1914
|
-
" · Width:",
|
|
1915
|
-
" ",
|
|
1916
|
-
/* @__PURE__ */ jsx("span", { className: "text-ui-fg-base", children: form.buttonWidth }),
|
|
1917
|
-
" · Height:",
|
|
1918
|
-
" ",
|
|
1919
|
-
/* @__PURE__ */ jsxs("span", { className: "text-ui-fg-base", children: [
|
|
1920
|
-
form.buttonHeight,
|
|
1921
|
-
"px"
|
|
1922
|
-
] }),
|
|
1923
|
-
" · Label:",
|
|
1924
|
-
" ",
|
|
1925
|
-
/* @__PURE__ */ jsx("span", { className: "text-ui-fg-base", children: form.buttonLabel })
|
|
1926
|
-
] })
|
|
1927
|
-
] })
|
|
1928
|
-
]
|
|
1929
|
-
}
|
|
1930
|
-
)
|
|
1931
|
-
] }) });
|
|
1932
|
-
}
|
|
1933
|
-
function formatDate(value) {
|
|
1934
|
-
if (!value) {
|
|
1935
|
-
return "—";
|
|
1936
|
-
}
|
|
1937
|
-
const parsed = new Date(value);
|
|
1938
|
-
if (Number.isNaN(parsed.getTime())) {
|
|
1939
|
-
return value;
|
|
1940
|
-
}
|
|
1941
|
-
return parsed.toLocaleString();
|
|
1942
|
-
}
|
|
1943
|
-
function PayPalReconciliationStatusPage() {
|
|
1944
|
-
const [status, setStatus] = useState({});
|
|
1945
|
-
const [loading, setLoading] = useState(false);
|
|
1946
|
-
const [error, setError] = useState(null);
|
|
1947
|
-
const fetchStatus = useCallback(async () => {
|
|
1948
|
-
try {
|
|
1949
|
-
setLoading(true);
|
|
1950
|
-
setError(null);
|
|
1951
|
-
const response = await fetch("/admin/paypal/reconciliation-status", {
|
|
1952
|
-
credentials: "include",
|
|
1953
|
-
headers: {
|
|
1954
|
-
Accept: "application/json"
|
|
1955
|
-
}
|
|
1956
|
-
});
|
|
1957
|
-
if (!response.ok) {
|
|
1958
|
-
const message = await response.text().catch(() => "");
|
|
1959
|
-
throw new Error(message || "Failed to load reconciliation status.");
|
|
1691
|
+
children: /* @__PURE__ */ jsxs("div", { className: "divide-y divide-ui-border-base", children: [
|
|
1692
|
+
/* @__PURE__ */ jsx(
|
|
1693
|
+
FieldRow,
|
|
1694
|
+
{
|
|
1695
|
+
label: "Disable Specific Payment Buttons",
|
|
1696
|
+
hint: "Hide individual funding sources (ex: Card, Venmo).",
|
|
1697
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
1698
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
1699
|
+
filterHiddenDisableButtons(form.disableButtons).map((v) => {
|
|
1700
|
+
const opt = VISIBLE_DISABLE_BUTTON_OPTIONS.find((o) => o.value === v);
|
|
1701
|
+
return /* @__PURE__ */ jsx(Pill, { onRemove: () => removeMulti("disableButtons", v), children: (opt == null ? void 0 : opt.label) ?? v }, v);
|
|
1702
|
+
}),
|
|
1703
|
+
filterHiddenDisableButtons(form.disableButtons).length === 0 ? /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-subtle", children: "No buttons disabled." }) : null
|
|
1704
|
+
] }),
|
|
1705
|
+
/* @__PURE__ */ jsx("div", { className: "rounded-md border border-ui-border-base p-3", children: /* @__PURE__ */ jsx("div", { className: "grid gap-2 md:grid-cols-2", children: VISIBLE_DISABLE_BUTTON_OPTIONS.map((o) => {
|
|
1706
|
+
const checked = form.disableButtons.includes(o.value);
|
|
1707
|
+
return /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 rounded-md p-2 hover:bg-ui-bg-subtle", children: [
|
|
1708
|
+
/* @__PURE__ */ jsx(
|
|
1709
|
+
"input",
|
|
1710
|
+
{
|
|
1711
|
+
type: "checkbox",
|
|
1712
|
+
checked,
|
|
1713
|
+
onChange: () => toggleMulti("disableButtons", o.value),
|
|
1714
|
+
className: "h-4 w-4 rounded border-ui-border-base"
|
|
1715
|
+
}
|
|
1716
|
+
),
|
|
1717
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: o.label })
|
|
1718
|
+
] }, o.value);
|
|
1719
|
+
}) }) })
|
|
1720
|
+
] })
|
|
1721
|
+
}
|
|
1722
|
+
),
|
|
1723
|
+
/* @__PURE__ */ jsx(FieldRow, { label: "Button Color", children: /* @__PURE__ */ jsx(
|
|
1724
|
+
"select",
|
|
1725
|
+
{
|
|
1726
|
+
value: form.buttonColor,
|
|
1727
|
+
onChange: (e) => setForm((p) => ({ ...p, buttonColor: e.target.value })),
|
|
1728
|
+
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",
|
|
1729
|
+
children: COLOR_OPTIONS.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: o.label }, o.value))
|
|
1730
|
+
}
|
|
1731
|
+
) }),
|
|
1732
|
+
/* @__PURE__ */ jsx(FieldRow, { label: "Button Shape", children: /* @__PURE__ */ jsx(
|
|
1733
|
+
"select",
|
|
1734
|
+
{
|
|
1735
|
+
value: form.buttonShape,
|
|
1736
|
+
onChange: (e) => setForm((p) => ({ ...p, buttonShape: e.target.value })),
|
|
1737
|
+
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",
|
|
1738
|
+
children: SHAPE_OPTIONS.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: o.label }, o.value))
|
|
1739
|
+
}
|
|
1740
|
+
) }),
|
|
1741
|
+
/* @__PURE__ */ jsx(FieldRow, { label: "Button Width", children: /* @__PURE__ */ jsx(
|
|
1742
|
+
"select",
|
|
1743
|
+
{
|
|
1744
|
+
value: form.buttonWidth,
|
|
1745
|
+
onChange: (e) => setForm((p) => ({ ...p, buttonWidth: e.target.value })),
|
|
1746
|
+
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",
|
|
1747
|
+
children: WIDTH_OPTIONS.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: o.label }, o.value))
|
|
1748
|
+
}
|
|
1749
|
+
) }),
|
|
1750
|
+
/* @__PURE__ */ jsx(FieldRow, { label: "Button Height", children: /* @__PURE__ */ jsx(
|
|
1751
|
+
"select",
|
|
1752
|
+
{
|
|
1753
|
+
value: String(form.buttonHeight),
|
|
1754
|
+
onChange: (e) => setForm((p) => ({ ...p, buttonHeight: Number(e.target.value) })),
|
|
1755
|
+
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",
|
|
1756
|
+
children: HEIGHT_OPTIONS.map((h) => /* @__PURE__ */ jsxs("option", { value: h, children: [
|
|
1757
|
+
h,
|
|
1758
|
+
" px"
|
|
1759
|
+
] }, h))
|
|
1760
|
+
}
|
|
1761
|
+
) }),
|
|
1762
|
+
/* @__PURE__ */ jsx(FieldRow, { label: "Button Label", children: /* @__PURE__ */ jsx(
|
|
1763
|
+
"select",
|
|
1764
|
+
{
|
|
1765
|
+
value: form.buttonLabel,
|
|
1766
|
+
onChange: (e) => setForm((p) => ({ ...p, buttonLabel: e.target.value })),
|
|
1767
|
+
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",
|
|
1768
|
+
children: LABEL_OPTIONS.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: o.label }, o.value))
|
|
1769
|
+
}
|
|
1770
|
+
) })
|
|
1771
|
+
] })
|
|
1960
1772
|
}
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
/* @__PURE__ */ jsx("
|
|
1982
|
-
/* @__PURE__ */ jsx(
|
|
1983
|
-
"button",
|
|
1984
|
-
{
|
|
1985
|
-
type: "button",
|
|
1986
|
-
onClick: fetchStatus,
|
|
1987
|
-
className: "rounded-md border border-ui-border-base px-3 py-2 text-sm text-ui-fg-base",
|
|
1988
|
-
disabled: loading,
|
|
1989
|
-
children: loading ? "Refreshing..." : "Refresh"
|
|
1990
|
-
}
|
|
1991
|
-
)
|
|
1992
|
-
] }) }),
|
|
1993
|
-
/* @__PURE__ */ jsxs("div", { className: "p-4", children: [
|
|
1994
|
-
error ? /* @__PURE__ */ jsx("div", { className: "rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-600", children: error }) : null,
|
|
1995
|
-
!error && Object.keys(status).length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-sm text-ui-fg-subtle", children: loading ? "Loading reconciliation status..." : "No reconciliation data yet." }) : null,
|
|
1996
|
-
Object.keys(status).length > 0 ? /* @__PURE__ */ jsxs("div", { className: "grid gap-4 text-sm text-ui-fg-base md:grid-cols-2", children: [
|
|
1997
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
1998
|
-
/* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Last run" }),
|
|
1999
|
-
/* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_run_at) })
|
|
2000
|
-
] }),
|
|
2001
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
2002
|
-
/* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Last run status" }),
|
|
2003
|
-
/* @__PURE__ */ jsx("div", { className: "mt-1 font-medium capitalize", children: status.last_run_status || "—" })
|
|
2004
|
-
] }),
|
|
2005
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
2006
|
-
/* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Last success" }),
|
|
2007
|
-
/* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_success_at) })
|
|
2008
|
-
] }),
|
|
2009
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
2010
|
-
/* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Last failure" }),
|
|
2011
|
-
/* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_failure_at) })
|
|
2012
|
-
] }),
|
|
2013
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
2014
|
-
/* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Sessions checked" }),
|
|
2015
|
-
/* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: status.sessions_checked ?? 0 })
|
|
2016
|
-
] }),
|
|
2017
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
2018
|
-
/* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Sessions updated" }),
|
|
2019
|
-
/* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: status.sessions_updated ?? 0 })
|
|
2020
|
-
] }),
|
|
2021
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
2022
|
-
/* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Drift detections" }),
|
|
2023
|
-
/* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: status.drift_count ?? 0 })
|
|
2024
|
-
] }),
|
|
2025
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
|
|
2026
|
-
/* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Last drift order" }),
|
|
2027
|
-
/* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: status.last_drift_order_id || "—" }),
|
|
2028
|
-
/* @__PURE__ */ jsx("div", { className: "mt-1 text-xs text-ui-fg-subtle", children: formatDate(status.last_drift_at) })
|
|
2029
|
-
] }),
|
|
2030
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 md:col-span-2", children: [
|
|
2031
|
-
/* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Last error" }),
|
|
2032
|
-
/* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: status.last_error || "No errors recorded." })
|
|
2033
|
-
] }),
|
|
2034
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 md:col-span-2", children: [
|
|
2035
|
-
/* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Total runs" }),
|
|
2036
|
-
/* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: status.runs ?? 0 })
|
|
2037
|
-
] })
|
|
2038
|
-
] }) : null
|
|
1773
|
+
),
|
|
1774
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-6 rounded-md border border-ui-border-base bg-ui-bg-subtle p-4", children: [
|
|
1775
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium text-ui-fg-base", children: "Preview (UI only)" }),
|
|
1776
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-2 text-sm text-ui-fg-subtle", children: [
|
|
1777
|
+
"Color: ",
|
|
1778
|
+
/* @__PURE__ */ jsx("span", { className: "text-ui-fg-base", children: form.buttonColor }),
|
|
1779
|
+
" · Shape:",
|
|
1780
|
+
" ",
|
|
1781
|
+
/* @__PURE__ */ jsx("span", { className: "text-ui-fg-base", children: form.buttonShape }),
|
|
1782
|
+
" · Width:",
|
|
1783
|
+
" ",
|
|
1784
|
+
/* @__PURE__ */ jsx("span", { className: "text-ui-fg-base", children: form.buttonWidth }),
|
|
1785
|
+
" · Height:",
|
|
1786
|
+
" ",
|
|
1787
|
+
/* @__PURE__ */ jsxs("span", { className: "text-ui-fg-base", children: [
|
|
1788
|
+
form.buttonHeight,
|
|
1789
|
+
"px"
|
|
1790
|
+
] }),
|
|
1791
|
+
" · Label:",
|
|
1792
|
+
" ",
|
|
1793
|
+
/* @__PURE__ */ jsx("span", { className: "text-ui-fg-base", children: form.buttonLabel })
|
|
2039
1794
|
] })
|
|
2040
1795
|
] })
|
|
2041
1796
|
] }) });
|
|
@@ -2051,6 +1806,10 @@ const routeModule = {
|
|
|
2051
1806
|
Component: AdditionalSettingsTab,
|
|
2052
1807
|
path: "/settings/paypal/additional-settings"
|
|
2053
1808
|
},
|
|
1809
|
+
{
|
|
1810
|
+
Component: AdvancedCardPaymentsTab,
|
|
1811
|
+
path: "/settings/paypal/advanced-card-payments"
|
|
1812
|
+
},
|
|
2054
1813
|
{
|
|
2055
1814
|
Component: PayPalApplePayPage,
|
|
2056
1815
|
path: "/settings/paypal/apple-pay"
|
|
@@ -2060,8 +1819,8 @@ const routeModule = {
|
|
|
2060
1819
|
path: "/settings/paypal/connection"
|
|
2061
1820
|
},
|
|
2062
1821
|
{
|
|
2063
|
-
Component:
|
|
2064
|
-
path: "/settings/paypal/
|
|
1822
|
+
Component: PayPalDisputesPage,
|
|
1823
|
+
path: "/settings/paypal/disputes"
|
|
2065
1824
|
},
|
|
2066
1825
|
{
|
|
2067
1826
|
Component: PayPalAuditLogsPage,
|
|
@@ -2071,21 +1830,17 @@ const routeModule = {
|
|
|
2071
1830
|
Component: PayPalGooglePayPage,
|
|
2072
1831
|
path: "/settings/paypal/google-pay"
|
|
2073
1832
|
},
|
|
2074
|
-
{
|
|
2075
|
-
Component: PayPalDisputesPage,
|
|
2076
|
-
path: "/settings/paypal/disputes"
|
|
2077
|
-
},
|
|
2078
1833
|
{
|
|
2079
1834
|
Component: PayPalPayLaterMessagingPage,
|
|
2080
1835
|
path: "/settings/paypal/pay-later-messaging"
|
|
2081
1836
|
},
|
|
2082
|
-
{
|
|
2083
|
-
Component: PayPalSettingsTab,
|
|
2084
|
-
path: "/settings/paypal/paypal-settings"
|
|
2085
|
-
},
|
|
2086
1837
|
{
|
|
2087
1838
|
Component: PayPalReconciliationStatusPage,
|
|
2088
1839
|
path: "/settings/paypal/reconciliation-status"
|
|
1840
|
+
},
|
|
1841
|
+
{
|
|
1842
|
+
Component: PayPalSettingsTab,
|
|
1843
|
+
path: "/settings/paypal/paypal-settings"
|
|
2089
1844
|
}
|
|
2090
1845
|
]
|
|
2091
1846
|
};
|