@easypayment/medusa-paypal 0.2.4 → 0.2.5

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.
@@ -40,17 +40,11 @@ function PayPalTabs() {
40
40
  }) }) });
41
41
  }
42
42
  const DEFAULT_FORM$1 = {
43
- paymentAction: "capture",
44
- brandName: "PayPal",
45
- landingPage: "no_preference",
46
- requireInstantPayment: false,
47
- useShippingAsBilling: true,
48
- sendItemDetails: true,
49
- skipOrderReviewPage: true,
50
- invoicePrefix: "WC-",
51
- creditCardStatementName: "PayPal",
52
- enableLogging: true,
53
- logPath: "/uploads/wc-logs/"
43
+ enabled: true,
44
+ title: "Credit or Debit Card",
45
+ disabledCards: [],
46
+ threeDS: "when_required",
47
+ cardSaveEnabled: false
54
48
  };
55
49
  function mergeWithDefaults$1(saved) {
56
50
  if (!saved) return { ...DEFAULT_FORM$1 };
@@ -60,6 +54,53 @@ function mergeWithDefaults$1(saved) {
60
54
  ...Object.fromEntries(entries)
61
55
  };
62
56
  }
57
+ const CARD_BRANDS = [
58
+ { value: "visa", label: "Visa" },
59
+ { value: "mastercard", label: "Mastercard" },
60
+ { value: "amex", label: "American Express" },
61
+ { value: "discover", label: "Discover" },
62
+ { value: "diners", label: "Diners Club" },
63
+ { value: "jcb", label: "JCB" },
64
+ { value: "unionpay", label: "UnionPay" }
65
+ ];
66
+ const THREE_DS_OPTIONS = [
67
+ {
68
+ value: "when_required",
69
+ label: "3D Secure when required",
70
+ hint: "Triggers 3DS only when the card / issuer requires it."
71
+ },
72
+ {
73
+ value: "sli",
74
+ label: "3D Secure (SCA) / liability shift (recommended)",
75
+ hint: "Attempts to optimize for liability shift while remaining compliant."
76
+ },
77
+ {
78
+ value: "always",
79
+ label: "Always request 3D Secure",
80
+ hint: "Forces 3DS challenge whenever possible (may reduce conversion)."
81
+ }
82
+ ];
83
+ function cx$1(...parts) {
84
+ return parts.filter(Boolean).join(" ");
85
+ }
86
+ function Pill$1({
87
+ children,
88
+ onRemove
89
+ }) {
90
+ 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: [
91
+ children,
92
+ onRemove ? /* @__PURE__ */ jsx(
93
+ "button",
94
+ {
95
+ type: "button",
96
+ onClick: onRemove,
97
+ className: "ml-1 rounded px-1 text-ui-fg-subtle hover:text-ui-fg-base",
98
+ "aria-label": "Remove",
99
+ children: "×"
100
+ }
101
+ ) : null
102
+ ] });
103
+ }
63
104
  function SectionCard$2({
64
105
  title,
65
106
  description,
@@ -90,10 +131,12 @@ function FieldRow$2({
90
131
  /* @__PURE__ */ jsx("div", { className: "col-span-12 md:col-span-8", children })
91
132
  ] });
92
133
  }
93
- function AdditionalSettingsTab() {
134
+ function AdvancedCardPaymentsTab() {
135
+ var _a, _b;
94
136
  const [form, setForm] = useState(() => ({ ...DEFAULT_FORM$1 }));
95
137
  const [loading, setLoading] = useState(false);
96
138
  const [saving, setSaving] = useState(false);
139
+ const [toast, setToast] = useState(null);
97
140
  const didInit = useRef(false);
98
141
  useEffect(() => {
99
142
  if (didInit.current) return;
@@ -108,7 +151,7 @@ function AdditionalSettingsTab() {
108
151
  if (!r.ok) return;
109
152
  const json = await r.json();
110
153
  const payload = (json == null ? void 0 : json.data) ?? json;
111
- const saved = payload == null ? void 0 : payload.additional_settings;
154
+ const saved = payload == null ? void 0 : payload.advanced_card_payments;
112
155
  if (saved && typeof saved === "object") {
113
156
  setForm(mergeWithDefaults$1(saved));
114
157
  }
@@ -117,11 +160,9 @@ function AdditionalSettingsTab() {
117
160
  }
118
161
  })();
119
162
  }, []);
120
- const [toast, setToast] = useState(null);
121
163
  async function onSave() {
122
164
  try {
123
165
  setSaving(true);
124
- setToast(null);
125
166
  const r = await fetch("/admin/paypal/settings", {
126
167
  method: "POST",
127
168
  credentials: "include",
@@ -129,29 +170,42 @@ function AdditionalSettingsTab() {
129
170
  "Content-Type": "application/json",
130
171
  "Accept": "application/json"
131
172
  },
132
- body: JSON.stringify({
133
- additional_settings: form
134
- })
173
+ body: JSON.stringify({ advanced_card_payments: form })
135
174
  });
136
175
  if (!r.ok) {
137
- const errText = await r.text().catch(() => "");
138
- throw new Error(errText || "Failed to save settings");
176
+ const t = await r.text();
177
+ setToast({ type: "error", message: "Failed to save settings. " + t });
178
+ window.setTimeout(() => setToast(null), 3500);
179
+ return;
139
180
  }
140
- const json = await r.json().catch(() => ({}));
181
+ const json = await r.json().catch(() => null);
141
182
  const payload = (json == null ? void 0 : json.data) ?? json;
142
- const saved = payload == null ? void 0 : payload.additional_settings;
183
+ const saved = payload == null ? void 0 : payload.advanced_card_payments;
143
184
  if (saved && typeof saved === "object") {
144
185
  setForm(mergeWithDefaults$1(saved));
145
186
  }
146
187
  setToast({ type: "success", message: "Settings saved" });
147
188
  window.setTimeout(() => setToast(null), 2500);
148
- } catch (e) {
149
- setToast({ type: "error", message: (e == null ? void 0 : e.message) || "Failed to save settings" });
150
- window.setTimeout(() => setToast(null), 3500);
151
189
  } finally {
152
190
  setSaving(false);
153
191
  }
154
192
  }
193
+ const disabledSet = useMemo(() => new Set(form.disabledCards), [form.disabledCards]);
194
+ function toggleDisabledCard(value) {
195
+ setForm((prev) => {
196
+ const exists = prev.disabledCards.includes(value);
197
+ return {
198
+ ...prev,
199
+ disabledCards: exists ? prev.disabledCards.filter((v) => v !== value) : [...prev.disabledCards, value]
200
+ };
201
+ });
202
+ }
203
+ function removeDisabledCard(value) {
204
+ setForm((prev) => ({
205
+ ...prev,
206
+ disabledCards: prev.disabledCards.filter((v) => v !== value)
207
+ }));
208
+ }
155
209
  return /* @__PURE__ */ jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
156
210
  /* @__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
211
  /* @__PURE__ */ jsx(PayPalTabs, {}),
@@ -167,8 +221,8 @@ function AdditionalSettingsTab() {
167
221
  /* @__PURE__ */ jsx(
168
222
  SectionCard$2,
169
223
  {
170
- title: "Additional Settings",
171
- description: "These settings control checkout behavior, PayPal experience, and logging.",
224
+ title: "Advanced Card Payments",
225
+ description: "Control card checkout settings, 3D Secure behavior, and card saving.",
172
226
  right: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
173
227
  /* @__PURE__ */ jsx(
174
228
  "button",
@@ -183,164 +237,114 @@ function AdditionalSettingsTab() {
183
237
  loading ? /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading…" }) : null
184
238
  ] }),
185
239
  children: /* @__PURE__ */ jsxs("div", { className: "divide-y divide-ui-border-base", children: [
186
- /* @__PURE__ */ jsx(FieldRow$2, { label: "Payment action", children: /* @__PURE__ */ jsxs(
187
- "select",
188
- {
189
- value: form.paymentAction,
190
- onChange: (e) => setForm((p) => ({ ...p, paymentAction: e.target.value })),
191
- 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",
192
- children: [
193
- /* @__PURE__ */ jsx("option", { value: "capture", children: "Capture" }),
194
- /* @__PURE__ */ jsx("option", { value: "authorize", children: "Authorize" })
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
- ) }),
220
- /* @__PURE__ */ jsx(FieldRow$2, { label: "Instant Payments", children: /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2", children: [
240
+ /* @__PURE__ */ jsx(FieldRow$2, { label: "Enable/Disable", children: /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2", children: [
221
241
  /* @__PURE__ */ jsx(
222
242
  "input",
223
243
  {
224
244
  type: "checkbox",
225
- checked: form.requireInstantPayment,
226
- onChange: (e) => setForm((p) => ({ ...p, requireInstantPayment: e.target.checked })),
245
+ checked: form.enabled,
246
+ onChange: (e) => setForm((p) => ({ ...p, enabled: e.target.checked })),
227
247
  className: "h-4 w-4 rounded border-ui-border-base"
228
248
  }
229
249
  ),
230
- /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Require Instant Payment" })
250
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable Advanced Credit/Debit Card" })
231
251
  ] }) }),
232
- /* @__PURE__ */ jsx(
233
- FieldRow$2,
252
+ /* @__PURE__ */ jsx(FieldRow$2, { label: "Title", children: /* @__PURE__ */ jsx(
253
+ "input",
234
254
  {
235
- label: "Billing Address",
236
- hint: "If the billing address is empty and PayPal provides a shipping address, the order will use the shipping address as the billing address.",
237
- children: /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2", children: [
238
- /* @__PURE__ */ jsx(
239
- "input",
240
- {
241
- type: "checkbox",
242
- checked: form.useShippingAsBilling,
243
- onChange: (e) => setForm((p) => ({ ...p, useShippingAsBilling: e.target.checked })),
244
- className: "h-4 w-4 rounded border-ui-border-base"
245
- }
246
- ),
247
- /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Use PayPal Shipping Address as Billing" })
248
- ] })
255
+ value: form.title,
256
+ onChange: (e) => setForm((p) => ({ ...p, title: e.target.value })),
257
+ 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",
258
+ placeholder: "Credit or Debit Card"
249
259
  }
250
- ),
260
+ ) }),
251
261
  /* @__PURE__ */ jsx(
252
262
  FieldRow$2,
253
263
  {
254
- label: "Send Item Details",
255
- hint: "Include all line item details in the payment request to PayPal so that they can be seen from the PayPal transaction details page.",
256
- children: /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2", children: [
257
- /* @__PURE__ */ jsx(
258
- "input",
259
- {
260
- type: "checkbox",
261
- checked: form.sendItemDetails,
262
- onChange: (e) => setForm((p) => ({ ...p, sendItemDetails: e.target.checked })),
263
- className: "h-4 w-4 rounded border-ui-border-base"
264
- }
265
- ),
266
- /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Send line item details to PayPal" })
264
+ label: "Disable specific credit cards",
265
+ hint: "Select card brands to hide from the card form.",
266
+ children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
267
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: form.disabledCards.length ? form.disabledCards.map((v) => {
268
+ var _a2;
269
+ const label = ((_a2 = CARD_BRANDS.find((b) => b.value === v)) == null ? void 0 : _a2.label) ?? v;
270
+ return /* @__PURE__ */ jsx(Pill$1, { onRemove: () => removeDisabledCard(v), children: label }, v);
271
+ }) : /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-subtle", children: "No card brands disabled." }) }),
272
+ /* @__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) => {
273
+ const checked = disabledSet.has(b.value);
274
+ return /* @__PURE__ */ jsxs(
275
+ "label",
276
+ {
277
+ className: cx$1(
278
+ "flex items-center gap-2 rounded-md p-2",
279
+ "hover:bg-ui-bg-subtle"
280
+ ),
281
+ children: [
282
+ /* @__PURE__ */ jsx(
283
+ "input",
284
+ {
285
+ type: "checkbox",
286
+ checked,
287
+ onChange: () => toggleDisabledCard(b.value),
288
+ className: "h-4 w-4 rounded border-ui-border-base"
289
+ }
290
+ ),
291
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: b.label })
292
+ ]
293
+ },
294
+ b.value
295
+ );
296
+ }) }) })
267
297
  ] })
268
298
  }
269
299
  ),
270
300
  /* @__PURE__ */ jsx(
271
301
  FieldRow$2,
272
302
  {
273
- label: "Order Review Page",
274
- hint: "Payments from the Product or Cart page skip the review step and go straight to the Thank You page.",
275
- children: /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2", children: [
303
+ label: "Contingency for 3D Secure",
304
+ hint: "Choose when 3D Secure should be triggered during card payments.",
305
+ children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
276
306
  /* @__PURE__ */ jsx(
277
- "input",
307
+ "select",
278
308
  {
279
- type: "checkbox",
280
- checked: form.skipOrderReviewPage,
281
- onChange: (e) => setForm((p) => ({ ...p, skipOrderReviewPage: e.target.checked })),
282
- className: "h-4 w-4 rounded border-ui-border-base"
309
+ value: form.threeDS,
310
+ onChange: (e) => setForm((p) => ({ ...p, threeDS: e.target.value })),
311
+ 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",
312
+ children: THREE_DS_OPTIONS.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: o.label }, o.value))
283
313
  }
284
314
  ),
285
- /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Skip Order Review Page" })
315
+ ((_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
286
316
  ] })
287
317
  }
288
318
  ),
289
- /* @__PURE__ */ jsx(FieldRow$2, { label: "Invoice prefix", children: /* @__PURE__ */ jsx(
290
- "input",
291
- {
292
- value: form.invoicePrefix,
293
- onChange: (e) => setForm((p) => ({ ...p, invoicePrefix: e.target.value })),
294
- 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",
295
- placeholder: "WC-"
296
- }
297
- ) }),
298
- /* @__PURE__ */ jsx(FieldRow$2, { label: "Credit Card Statement Name", children: /* @__PURE__ */ jsx(
299
- "input",
300
- {
301
- value: form.creditCardStatementName,
302
- onChange: (e) => setForm((p) => ({ ...p, creditCardStatementName: e.target.value })),
303
- 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",
304
- placeholder: "PayPal"
305
- }
306
- ) }),
307
- /* @__PURE__ */ jsx(
308
- FieldRow$2,
309
- {
310
- label: "Debug log",
311
- hint: /* @__PURE__ */ jsxs("span", { children: [
312
- "Log PayPal events such as Webhook, Payment, Refund.",
313
- " ",
314
- form.logPath ? /* @__PURE__ */ jsxs(Fragment, { children: [
315
- "Log location: ",
316
- /* @__PURE__ */ jsx("span", { className: "font-mono", children: form.logPath })
317
- ] }) : null
318
- ] }),
319
- children: /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2", children: [
320
- /* @__PURE__ */ jsx(
321
- "input",
322
- {
323
- type: "checkbox",
324
- checked: form.enableLogging,
325
- onChange: (e) => setForm((p) => ({ ...p, enableLogging: e.target.checked })),
326
- className: "h-4 w-4 rounded border-ui-border-base"
327
- }
328
- ),
329
- /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable logging" })
330
- ] })
331
- }
332
- )
319
+ /* @__PURE__ */ jsx(FieldRow$2, { 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: [
320
+ /* @__PURE__ */ jsx(
321
+ "input",
322
+ {
323
+ type: "checkbox",
324
+ checked: form.cardSaveEnabled,
325
+ onChange: (e) => setForm((p) => ({ ...p, cardSaveEnabled: e.target.checked })),
326
+ className: "h-4 w-4 rounded border-ui-border-base"
327
+ }
328
+ ),
329
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable card saving at checkout" })
330
+ ] }) })
333
331
  ] })
334
332
  }
335
333
  )
336
334
  ] }) });
337
335
  }
338
336
  const DEFAULT_FORM = {
339
- enabled: true,
340
- title: "Credit or Debit Card",
341
- disabledCards: [],
342
- threeDS: "when_required",
343
- cardSaveEnabled: false
337
+ paymentAction: "capture",
338
+ brandName: "PayPal",
339
+ landingPage: "no_preference",
340
+ requireInstantPayment: false,
341
+ useShippingAsBilling: true,
342
+ sendItemDetails: true,
343
+ skipOrderReviewPage: true,
344
+ invoicePrefix: "WC-",
345
+ creditCardStatementName: "PayPal",
346
+ enableLogging: true,
347
+ logPath: "/uploads/wc-logs/"
344
348
  };
345
349
  function mergeWithDefaults(saved) {
346
350
  if (!saved) return { ...DEFAULT_FORM };
@@ -350,53 +354,6 @@ function mergeWithDefaults(saved) {
350
354
  ...Object.fromEntries(entries)
351
355
  };
352
356
  }
353
- const CARD_BRANDS = [
354
- { value: "visa", label: "Visa" },
355
- { value: "mastercard", label: "Mastercard" },
356
- { value: "amex", label: "American Express" },
357
- { value: "discover", label: "Discover" },
358
- { value: "diners", label: "Diners Club" },
359
- { value: "jcb", label: "JCB" },
360
- { value: "unionpay", label: "UnionPay" }
361
- ];
362
- const THREE_DS_OPTIONS = [
363
- {
364
- value: "when_required",
365
- label: "3D Secure when required",
366
- hint: "Triggers 3DS only when the card / issuer requires it."
367
- },
368
- {
369
- value: "sli",
370
- label: "3D Secure (SCA) / liability shift (recommended)",
371
- hint: "Attempts to optimize for liability shift while remaining compliant."
372
- },
373
- {
374
- value: "always",
375
- label: "Always request 3D Secure",
376
- hint: "Forces 3DS challenge whenever possible (may reduce conversion)."
377
- }
378
- ];
379
- function cx$1(...parts) {
380
- return parts.filter(Boolean).join(" ");
381
- }
382
- function Pill$1({
383
- children,
384
- onRemove
385
- }) {
386
- 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: [
387
- children,
388
- onRemove ? /* @__PURE__ */ jsx(
389
- "button",
390
- {
391
- type: "button",
392
- onClick: onRemove,
393
- className: "ml-1 rounded px-1 text-ui-fg-subtle hover:text-ui-fg-base",
394
- "aria-label": "Remove",
395
- children: "×"
396
- }
397
- ) : null
398
- ] });
399
- }
400
357
  function SectionCard$1({
401
358
  title,
402
359
  description,
@@ -427,12 +384,10 @@ function FieldRow$1({
427
384
  /* @__PURE__ */ jsx("div", { className: "col-span-12 md:col-span-8", children })
428
385
  ] });
429
386
  }
430
- function AdvancedCardPaymentsTab() {
431
- var _a, _b;
387
+ function AdditionalSettingsTab() {
432
388
  const [form, setForm] = useState(() => ({ ...DEFAULT_FORM }));
433
389
  const [loading, setLoading] = useState(false);
434
390
  const [saving, setSaving] = useState(false);
435
- const [toast, setToast] = useState(null);
436
391
  const didInit = useRef(false);
437
392
  useEffect(() => {
438
393
  if (didInit.current) return;
@@ -447,7 +402,7 @@ function AdvancedCardPaymentsTab() {
447
402
  if (!r.ok) return;
448
403
  const json = await r.json();
449
404
  const payload = (json == null ? void 0 : json.data) ?? json;
450
- const saved = payload == null ? void 0 : payload.advanced_card_payments;
405
+ const saved = payload == null ? void 0 : payload.additional_settings;
451
406
  if (saved && typeof saved === "object") {
452
407
  setForm(mergeWithDefaults(saved));
453
408
  }
@@ -456,9 +411,11 @@ function AdvancedCardPaymentsTab() {
456
411
  }
457
412
  })();
458
413
  }, []);
414
+ const [toast, setToast] = useState(null);
459
415
  async function onSave() {
460
416
  try {
461
417
  setSaving(true);
418
+ setToast(null);
462
419
  const r = await fetch("/admin/paypal/settings", {
463
420
  method: "POST",
464
421
  credentials: "include",
@@ -466,42 +423,29 @@ function AdvancedCardPaymentsTab() {
466
423
  "Content-Type": "application/json",
467
424
  "Accept": "application/json"
468
425
  },
469
- body: JSON.stringify({ advanced_card_payments: form })
426
+ body: JSON.stringify({
427
+ additional_settings: form
428
+ })
470
429
  });
471
430
  if (!r.ok) {
472
- const t = await r.text();
473
- setToast({ type: "error", message: "Failed to save settings. " + t });
474
- window.setTimeout(() => setToast(null), 3500);
475
- return;
431
+ const errText = await r.text().catch(() => "");
432
+ throw new Error(errText || "Failed to save settings");
476
433
  }
477
- const json = await r.json().catch(() => null);
434
+ const json = await r.json().catch(() => ({}));
478
435
  const payload = (json == null ? void 0 : json.data) ?? json;
479
- const saved = payload == null ? void 0 : payload.advanced_card_payments;
436
+ const saved = payload == null ? void 0 : payload.additional_settings;
480
437
  if (saved && typeof saved === "object") {
481
438
  setForm(mergeWithDefaults(saved));
482
439
  }
483
440
  setToast({ type: "success", message: "Settings saved" });
484
441
  window.setTimeout(() => setToast(null), 2500);
442
+ } catch (e) {
443
+ setToast({ type: "error", message: (e == null ? void 0 : e.message) || "Failed to save settings" });
444
+ window.setTimeout(() => setToast(null), 3500);
485
445
  } finally {
486
446
  setSaving(false);
487
447
  }
488
448
  }
489
- const disabledSet = useMemo(() => new Set(form.disabledCards), [form.disabledCards]);
490
- function toggleDisabledCard(value) {
491
- setForm((prev) => {
492
- const exists = prev.disabledCards.includes(value);
493
- return {
494
- ...prev,
495
- disabledCards: exists ? prev.disabledCards.filter((v) => v !== value) : [...prev.disabledCards, value]
496
- };
497
- });
498
- }
499
- function removeDisabledCard(value) {
500
- setForm((prev) => ({
501
- ...prev,
502
- disabledCards: prev.disabledCards.filter((v) => v !== value)
503
- }));
504
- }
505
449
  return /* @__PURE__ */ jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
506
450
  /* @__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" }) }) }),
507
451
  /* @__PURE__ */ jsx(PayPalTabs, {}),
@@ -517,8 +461,8 @@ function AdvancedCardPaymentsTab() {
517
461
  /* @__PURE__ */ jsx(
518
462
  SectionCard$1,
519
463
  {
520
- title: "Advanced Card Payments",
521
- description: "Control card checkout settings, 3D Secure behavior, and card saving.",
464
+ title: "Additional Settings",
465
+ description: "These settings control checkout behavior, PayPal experience, and logging.",
522
466
  right: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
523
467
  /* @__PURE__ */ jsx(
524
468
  "button",
@@ -530,187 +474,161 @@ function AdvancedCardPaymentsTab() {
530
474
  children: saving ? "Saving..." : "Save settings"
531
475
  }
532
476
  ),
533
- loading ? /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading…" }) : null
534
- ] }),
535
- children: /* @__PURE__ */ jsxs("div", { className: "divide-y divide-ui-border-base", children: [
536
- /* @__PURE__ */ jsx(FieldRow$1, { label: "Enable/Disable", children: /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2", children: [
537
- /* @__PURE__ */ jsx(
538
- "input",
539
- {
540
- type: "checkbox",
541
- checked: form.enabled,
542
- onChange: (e) => setForm((p) => ({ ...p, enabled: e.target.checked })),
543
- className: "h-4 w-4 rounded border-ui-border-base"
544
- }
545
- ),
546
- /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable Advanced Credit/Debit Card" })
547
- ] }) }),
548
- /* @__PURE__ */ jsx(FieldRow$1, { label: "Title", children: /* @__PURE__ */ jsx(
477
+ loading ? /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading…" }) : null
478
+ ] }),
479
+ children: /* @__PURE__ */ jsxs("div", { className: "divide-y divide-ui-border-base", children: [
480
+ /* @__PURE__ */ jsx(FieldRow$1, { label: "Payment action", children: /* @__PURE__ */ jsxs(
481
+ "select",
482
+ {
483
+ value: form.paymentAction,
484
+ onChange: (e) => setForm((p) => ({ ...p, paymentAction: e.target.value })),
485
+ 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",
486
+ children: [
487
+ /* @__PURE__ */ jsx("option", { value: "capture", children: "Capture" }),
488
+ /* @__PURE__ */ jsx("option", { value: "authorize", children: "Authorize" })
489
+ ]
490
+ }
491
+ ) }),
492
+ /* @__PURE__ */ jsx(FieldRow$1, { label: "Brand Name", children: /* @__PURE__ */ jsx(
493
+ "input",
494
+ {
495
+ value: form.brandName,
496
+ onChange: (e) => setForm((p) => ({ ...p, brandName: e.target.value })),
497
+ 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",
498
+ placeholder: "PayPal"
499
+ }
500
+ ) }),
501
+ /* @__PURE__ */ jsx(FieldRow$1, { label: "Landing Page", children: /* @__PURE__ */ jsxs(
502
+ "select",
503
+ {
504
+ value: form.landingPage,
505
+ onChange: (e) => setForm((p) => ({ ...p, landingPage: e.target.value })),
506
+ 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",
507
+ children: [
508
+ /* @__PURE__ */ jsx("option", { value: "no_preference", children: "No Preference" }),
509
+ /* @__PURE__ */ jsx("option", { value: "login", children: "Login" }),
510
+ /* @__PURE__ */ jsx("option", { value: "billing", children: "Billing" })
511
+ ]
512
+ }
513
+ ) }),
514
+ /* @__PURE__ */ jsx(FieldRow$1, { label: "Instant Payments", children: /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2", children: [
515
+ /* @__PURE__ */ jsx(
516
+ "input",
517
+ {
518
+ type: "checkbox",
519
+ checked: form.requireInstantPayment,
520
+ onChange: (e) => setForm((p) => ({ ...p, requireInstantPayment: e.target.checked })),
521
+ className: "h-4 w-4 rounded border-ui-border-base"
522
+ }
523
+ ),
524
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Require Instant Payment" })
525
+ ] }) }),
526
+ /* @__PURE__ */ jsx(
527
+ FieldRow$1,
528
+ {
529
+ label: "Billing Address",
530
+ hint: "If the billing address is empty and PayPal provides a shipping address, the order will use the shipping address as the billing address.",
531
+ children: /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2", children: [
532
+ /* @__PURE__ */ jsx(
533
+ "input",
534
+ {
535
+ type: "checkbox",
536
+ checked: form.useShippingAsBilling,
537
+ onChange: (e) => setForm((p) => ({ ...p, useShippingAsBilling: e.target.checked })),
538
+ className: "h-4 w-4 rounded border-ui-border-base"
539
+ }
540
+ ),
541
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Use PayPal Shipping Address as Billing" })
542
+ ] })
543
+ }
544
+ ),
545
+ /* @__PURE__ */ jsx(
546
+ FieldRow$1,
547
+ {
548
+ label: "Send Item Details",
549
+ hint: "Include all line item details in the payment request to PayPal so that they can be seen from the PayPal transaction details page.",
550
+ children: /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2", children: [
551
+ /* @__PURE__ */ jsx(
552
+ "input",
553
+ {
554
+ type: "checkbox",
555
+ checked: form.sendItemDetails,
556
+ onChange: (e) => setForm((p) => ({ ...p, sendItemDetails: e.target.checked })),
557
+ className: "h-4 w-4 rounded border-ui-border-base"
558
+ }
559
+ ),
560
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Send line item details to PayPal" })
561
+ ] })
562
+ }
563
+ ),
564
+ /* @__PURE__ */ jsx(
565
+ FieldRow$1,
566
+ {
567
+ label: "Order Review Page",
568
+ hint: "Payments from the Product or Cart page skip the review step and go straight to the Thank You page.",
569
+ children: /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2", children: [
570
+ /* @__PURE__ */ jsx(
571
+ "input",
572
+ {
573
+ type: "checkbox",
574
+ checked: form.skipOrderReviewPage,
575
+ onChange: (e) => setForm((p) => ({ ...p, skipOrderReviewPage: e.target.checked })),
576
+ className: "h-4 w-4 rounded border-ui-border-base"
577
+ }
578
+ ),
579
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Skip Order Review Page" })
580
+ ] })
581
+ }
582
+ ),
583
+ /* @__PURE__ */ jsx(FieldRow$1, { label: "Invoice prefix", children: /* @__PURE__ */ jsx(
549
584
  "input",
550
585
  {
551
- value: form.title,
552
- onChange: (e) => setForm((p) => ({ ...p, title: e.target.value })),
586
+ value: form.invoicePrefix,
587
+ onChange: (e) => setForm((p) => ({ ...p, invoicePrefix: e.target.value })),
553
588
  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",
554
- placeholder: "Credit or Debit Card"
589
+ placeholder: "WC-"
555
590
  }
556
591
  ) }),
557
- /* @__PURE__ */ jsx(
558
- FieldRow$1,
592
+ /* @__PURE__ */ jsx(FieldRow$1, { label: "Credit Card Statement Name", children: /* @__PURE__ */ jsx(
593
+ "input",
559
594
  {
560
- label: "Disable specific credit cards",
561
- hint: "Select card brands to hide from the card form.",
562
- children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
563
- /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: form.disabledCards.length ? form.disabledCards.map((v) => {
564
- var _a2;
565
- const label = ((_a2 = CARD_BRANDS.find((b) => b.value === v)) == null ? void 0 : _a2.label) ?? v;
566
- return /* @__PURE__ */ jsx(Pill$1, { onRemove: () => removeDisabledCard(v), children: label }, v);
567
- }) : /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-subtle", children: "No card brands disabled." }) }),
568
- /* @__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) => {
569
- const checked = disabledSet.has(b.value);
570
- return /* @__PURE__ */ jsxs(
571
- "label",
572
- {
573
- className: cx$1(
574
- "flex items-center gap-2 rounded-md p-2",
575
- "hover:bg-ui-bg-subtle"
576
- ),
577
- children: [
578
- /* @__PURE__ */ jsx(
579
- "input",
580
- {
581
- type: "checkbox",
582
- checked,
583
- onChange: () => toggleDisabledCard(b.value),
584
- className: "h-4 w-4 rounded border-ui-border-base"
585
- }
586
- ),
587
- /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: b.label })
588
- ]
589
- },
590
- b.value
591
- );
592
- }) }) })
593
- ] })
595
+ value: form.creditCardStatementName,
596
+ onChange: (e) => setForm((p) => ({ ...p, creditCardStatementName: e.target.value })),
597
+ 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",
598
+ placeholder: "PayPal"
594
599
  }
595
- ),
600
+ ) }),
596
601
  /* @__PURE__ */ jsx(
597
602
  FieldRow$1,
598
603
  {
599
- label: "Contingency for 3D Secure",
600
- hint: "Choose when 3D Secure should be triggered during card payments.",
601
- children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
604
+ label: "Debug log",
605
+ hint: /* @__PURE__ */ jsxs("span", { children: [
606
+ "Log PayPal events such as Webhook, Payment, Refund.",
607
+ " ",
608
+ form.logPath ? /* @__PURE__ */ jsxs(Fragment, { children: [
609
+ "Log location: ",
610
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: form.logPath })
611
+ ] }) : null
612
+ ] }),
613
+ children: /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2", children: [
602
614
  /* @__PURE__ */ jsx(
603
- "select",
615
+ "input",
604
616
  {
605
- value: form.threeDS,
606
- onChange: (e) => setForm((p) => ({ ...p, threeDS: e.target.value })),
607
- 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",
608
- children: THREE_DS_OPTIONS.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: o.label }, o.value))
617
+ type: "checkbox",
618
+ checked: form.enableLogging,
619
+ onChange: (e) => setForm((p) => ({ ...p, enableLogging: e.target.checked })),
620
+ className: "h-4 w-4 rounded border-ui-border-base"
609
621
  }
610
622
  ),
611
- ((_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
623
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable logging" })
612
624
  ] })
613
625
  }
614
- ),
615
- /* @__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: [
616
- /* @__PURE__ */ jsx(
617
- "input",
618
- {
619
- type: "checkbox",
620
- checked: form.cardSaveEnabled,
621
- onChange: (e) => setForm((p) => ({ ...p, cardSaveEnabled: e.target.checked })),
622
- className: "h-4 w-4 rounded border-ui-border-base"
623
- }
624
- ),
625
- /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable card saving at checkout" })
626
- ] }) })
626
+ )
627
627
  ] })
628
628
  }
629
629
  )
630
630
  ] }) });
631
631
  }
632
- function PayPalApplePayPage() {
633
- return /* @__PURE__ */ jsx(Navigate, { to: "/settings/paypal/connection", replace: true });
634
- }
635
- function formatDate$2(value) {
636
- if (!value) {
637
- return "";
638
- }
639
- const parsed = new Date(value);
640
- if (Number.isNaN(parsed.getTime())) {
641
- return value;
642
- }
643
- return parsed.toLocaleString();
644
- }
645
- function PayPalAuditLogsPage() {
646
- const [logs, setLogs] = useState([]);
647
- const [loading, setLoading] = useState(false);
648
- const [error, setError] = useState(null);
649
- const fetchLogs = useCallback(async () => {
650
- try {
651
- setLoading(true);
652
- setError(null);
653
- const response = await fetch("/admin/paypal/audit-logs?limit=50", {
654
- credentials: "include",
655
- headers: {
656
- Accept: "application/json"
657
- }
658
- });
659
- if (!response.ok) {
660
- const message = await response.text().catch(() => "");
661
- throw new Error(message || "Failed to load audit logs.");
662
- }
663
- const data = await response.json().catch(() => ({}));
664
- setLogs((data == null ? void 0 : data.logs) || []);
665
- } catch (fetchError) {
666
- setError((fetchError == null ? void 0 : fetchError.message) || "Failed to load audit logs.");
667
- setLogs([]);
668
- } finally {
669
- setLoading(false);
670
- }
671
- }, []);
672
- useEffect(() => {
673
- fetchLogs();
674
- }, [fetchLogs]);
675
- return /* @__PURE__ */ jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
676
- /* @__PURE__ */ jsxs("div", { children: [
677
- /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Audit Logs" }),
678
- /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-ui-fg-subtle", children: "Track administrative changes and credential events for PayPal configuration." })
679
- ] }),
680
- /* @__PURE__ */ jsx(PayPalTabs, {}),
681
- /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
682
- /* @__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: [
683
- /* @__PURE__ */ jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Latest events" }),
684
- /* @__PURE__ */ jsx(
685
- "button",
686
- {
687
- type: "button",
688
- onClick: fetchLogs,
689
- className: "rounded-md border border-ui-border-base px-3 py-2 text-sm text-ui-fg-base",
690
- disabled: loading,
691
- children: loading ? "Refreshing..." : "Refresh"
692
- }
693
- )
694
- ] }) }),
695
- /* @__PURE__ */ jsxs("div", { className: "p-4", children: [
696
- error ? /* @__PURE__ */ jsx("div", { className: "rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-600", children: error }) : null,
697
- !error && logs.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-sm text-ui-fg-subtle", children: loading ? "Loading audit logs..." : "No audit log entries found yet." }) : null,
698
- logs.length > 0 ? /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full text-left text-sm", children: [
699
- /* @__PURE__ */ jsx("thead", { className: "text-ui-fg-muted", children: /* @__PURE__ */ jsxs("tr", { children: [
700
- /* @__PURE__ */ jsx("th", { className: "pb-2 pr-4 font-medium", children: "Timestamp" }),
701
- /* @__PURE__ */ jsx("th", { className: "pb-2 pr-4 font-medium", children: "Event" }),
702
- /* @__PURE__ */ jsx("th", { className: "pb-2 font-medium", children: "Details" })
703
- ] }) }),
704
- /* @__PURE__ */ jsx("tbody", { children: logs.map((entry) => /* @__PURE__ */ jsxs("tr", { className: "border-t border-ui-border-base", children: [
705
- /* @__PURE__ */ jsx("td", { className: "py-3 pr-4 text-ui-fg-base", children: formatDate$2(entry.created_at) || "—" }),
706
- /* @__PURE__ */ jsx("td", { className: "py-3 pr-4 text-ui-fg-base", children: entry.event_type || "—" }),
707
- /* @__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) }) })
708
- ] }, entry.id)) })
709
- ] }) }) : null
710
- ] })
711
- ] })
712
- ] }) });
713
- }
714
632
  const config = defineRouteConfig({
715
633
  label: "PayPal Connection",
716
634
  hide: true
@@ -1295,6 +1213,88 @@ function PayPalConnectionPage() {
1295
1213
  ` })
1296
1214
  ] });
1297
1215
  }
1216
+ function formatDate$2(value) {
1217
+ if (!value) {
1218
+ return "";
1219
+ }
1220
+ const parsed = new Date(value);
1221
+ if (Number.isNaN(parsed.getTime())) {
1222
+ return value;
1223
+ }
1224
+ return parsed.toLocaleString();
1225
+ }
1226
+ function PayPalAuditLogsPage() {
1227
+ const [logs, setLogs] = useState([]);
1228
+ const [loading, setLoading] = useState(false);
1229
+ const [error, setError] = useState(null);
1230
+ const fetchLogs = useCallback(async () => {
1231
+ try {
1232
+ setLoading(true);
1233
+ setError(null);
1234
+ const response = await fetch("/admin/paypal/audit-logs?limit=50", {
1235
+ credentials: "include",
1236
+ headers: {
1237
+ Accept: "application/json"
1238
+ }
1239
+ });
1240
+ if (!response.ok) {
1241
+ const message = await response.text().catch(() => "");
1242
+ throw new Error(message || "Failed to load audit logs.");
1243
+ }
1244
+ const data = await response.json().catch(() => ({}));
1245
+ setLogs((data == null ? void 0 : data.logs) || []);
1246
+ } catch (fetchError) {
1247
+ setError((fetchError == null ? void 0 : fetchError.message) || "Failed to load audit logs.");
1248
+ setLogs([]);
1249
+ } finally {
1250
+ setLoading(false);
1251
+ }
1252
+ }, []);
1253
+ useEffect(() => {
1254
+ fetchLogs();
1255
+ }, [fetchLogs]);
1256
+ return /* @__PURE__ */ jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
1257
+ /* @__PURE__ */ jsxs("div", { children: [
1258
+ /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Audit Logs" }),
1259
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-ui-fg-subtle", children: "Track administrative changes and credential events for PayPal configuration." })
1260
+ ] }),
1261
+ /* @__PURE__ */ jsx(PayPalTabs, {}),
1262
+ /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
1263
+ /* @__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: [
1264
+ /* @__PURE__ */ jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Latest events" }),
1265
+ /* @__PURE__ */ jsx(
1266
+ "button",
1267
+ {
1268
+ type: "button",
1269
+ onClick: fetchLogs,
1270
+ className: "rounded-md border border-ui-border-base px-3 py-2 text-sm text-ui-fg-base",
1271
+ disabled: loading,
1272
+ children: loading ? "Refreshing..." : "Refresh"
1273
+ }
1274
+ )
1275
+ ] }) }),
1276
+ /* @__PURE__ */ jsxs("div", { className: "p-4", children: [
1277
+ error ? /* @__PURE__ */ jsx("div", { className: "rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-600", children: error }) : null,
1278
+ !error && logs.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-sm text-ui-fg-subtle", children: loading ? "Loading audit logs..." : "No audit log entries found yet." }) : null,
1279
+ logs.length > 0 ? /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full text-left text-sm", children: [
1280
+ /* @__PURE__ */ jsx("thead", { className: "text-ui-fg-muted", children: /* @__PURE__ */ jsxs("tr", { children: [
1281
+ /* @__PURE__ */ jsx("th", { className: "pb-2 pr-4 font-medium", children: "Timestamp" }),
1282
+ /* @__PURE__ */ jsx("th", { className: "pb-2 pr-4 font-medium", children: "Event" }),
1283
+ /* @__PURE__ */ jsx("th", { className: "pb-2 font-medium", children: "Details" })
1284
+ ] }) }),
1285
+ /* @__PURE__ */ jsx("tbody", { children: logs.map((entry) => /* @__PURE__ */ jsxs("tr", { className: "border-t border-ui-border-base", children: [
1286
+ /* @__PURE__ */ jsx("td", { className: "py-3 pr-4 text-ui-fg-base", children: formatDate$2(entry.created_at) || "—" }),
1287
+ /* @__PURE__ */ jsx("td", { className: "py-3 pr-4 text-ui-fg-base", children: entry.event_type || "—" }),
1288
+ /* @__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) }) })
1289
+ ] }, entry.id)) })
1290
+ ] }) }) : null
1291
+ ] })
1292
+ ] })
1293
+ ] }) });
1294
+ }
1295
+ function PayPalApplePayPage() {
1296
+ return /* @__PURE__ */ jsx(Navigate, { to: "/settings/paypal/connection", replace: true });
1297
+ }
1298
1298
  const EMPTY_FILTERS = {
1299
1299
  dispute_id: "",
1300
1300
  status: "",
@@ -1493,6 +1493,116 @@ function PayPalGooglePayPage() {
1493
1493
  function PayPalPayLaterMessagingPage() {
1494
1494
  return /* @__PURE__ */ jsx(Navigate, { to: "/settings/paypal/connection", replace: true });
1495
1495
  }
1496
+ function formatDate(value) {
1497
+ if (!value) {
1498
+ return "—";
1499
+ }
1500
+ const parsed = new Date(value);
1501
+ if (Number.isNaN(parsed.getTime())) {
1502
+ return value;
1503
+ }
1504
+ return parsed.toLocaleString();
1505
+ }
1506
+ function PayPalReconciliationStatusPage() {
1507
+ const [status, setStatus] = useState({});
1508
+ const [loading, setLoading] = useState(false);
1509
+ const [error, setError] = useState(null);
1510
+ const fetchStatus = useCallback(async () => {
1511
+ try {
1512
+ setLoading(true);
1513
+ setError(null);
1514
+ const response = await fetch("/admin/paypal/reconciliation-status", {
1515
+ credentials: "include",
1516
+ headers: {
1517
+ Accept: "application/json"
1518
+ }
1519
+ });
1520
+ if (!response.ok) {
1521
+ const message = await response.text().catch(() => "");
1522
+ throw new Error(message || "Failed to load reconciliation status.");
1523
+ }
1524
+ const data = await response.json().catch(() => ({}));
1525
+ setStatus((data == null ? void 0 : data.status) || {});
1526
+ } catch (fetchError) {
1527
+ setError((fetchError == null ? void 0 : fetchError.message) || "Failed to load reconciliation status.");
1528
+ setStatus({});
1529
+ } finally {
1530
+ setLoading(false);
1531
+ }
1532
+ }, []);
1533
+ useEffect(() => {
1534
+ fetchStatus();
1535
+ }, [fetchStatus]);
1536
+ return /* @__PURE__ */ jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
1537
+ /* @__PURE__ */ jsxs("div", { children: [
1538
+ /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Reconciliation Status" }),
1539
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-ui-fg-subtle", children: "Monitor reconciliation health and drift detection for PayPal payment sessions." })
1540
+ ] }),
1541
+ /* @__PURE__ */ jsx(PayPalTabs, {}),
1542
+ /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
1543
+ /* @__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: [
1544
+ /* @__PURE__ */ jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Latest reconciliation run" }),
1545
+ /* @__PURE__ */ jsx(
1546
+ "button",
1547
+ {
1548
+ type: "button",
1549
+ onClick: fetchStatus,
1550
+ className: "rounded-md border border-ui-border-base px-3 py-2 text-sm text-ui-fg-base",
1551
+ disabled: loading,
1552
+ children: loading ? "Refreshing..." : "Refresh"
1553
+ }
1554
+ )
1555
+ ] }) }),
1556
+ /* @__PURE__ */ jsxs("div", { className: "p-4", children: [
1557
+ error ? /* @__PURE__ */ jsx("div", { className: "rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-600", children: error }) : null,
1558
+ !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,
1559
+ Object.keys(status).length > 0 ? /* @__PURE__ */ jsxs("div", { className: "grid gap-4 text-sm text-ui-fg-base md:grid-cols-2", children: [
1560
+ /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
1561
+ /* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Last run" }),
1562
+ /* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_run_at) })
1563
+ ] }),
1564
+ /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
1565
+ /* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Last run status" }),
1566
+ /* @__PURE__ */ jsx("div", { className: "mt-1 font-medium capitalize", children: status.last_run_status || "—" })
1567
+ ] }),
1568
+ /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
1569
+ /* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Last success" }),
1570
+ /* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_success_at) })
1571
+ ] }),
1572
+ /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
1573
+ /* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Last failure" }),
1574
+ /* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_failure_at) })
1575
+ ] }),
1576
+ /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
1577
+ /* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Sessions checked" }),
1578
+ /* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: status.sessions_checked ?? 0 })
1579
+ ] }),
1580
+ /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
1581
+ /* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Sessions updated" }),
1582
+ /* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: status.sessions_updated ?? 0 })
1583
+ ] }),
1584
+ /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
1585
+ /* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Drift detections" }),
1586
+ /* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: status.drift_count ?? 0 })
1587
+ ] }),
1588
+ /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
1589
+ /* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Last drift order" }),
1590
+ /* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: status.last_drift_order_id || "—" }),
1591
+ /* @__PURE__ */ jsx("div", { className: "mt-1 text-xs text-ui-fg-subtle", children: formatDate(status.last_drift_at) })
1592
+ ] }),
1593
+ /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 md:col-span-2", children: [
1594
+ /* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Last error" }),
1595
+ /* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: status.last_error || "No errors recorded." })
1596
+ ] }),
1597
+ /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 md:col-span-2", children: [
1598
+ /* @__PURE__ */ jsx("div", { className: "text-ui-fg-subtle", children: "Total runs" }),
1599
+ /* @__PURE__ */ jsx("div", { className: "mt-1 font-medium", children: status.runs ?? 0 })
1600
+ ] })
1601
+ ] }) : null
1602
+ ] })
1603
+ ] })
1604
+ ] }) });
1605
+ }
1496
1606
  const DISPLAY_LOCATION_OPTIONS = [
1497
1607
  { value: "product", label: "Product Page" },
1498
1608
  { value: "cart", label: "Cart Page" },
@@ -1930,116 +2040,6 @@ function PayPalSettingsTab() {
1930
2040
  )
1931
2041
  ] }) });
1932
2042
  }
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.");
1960
- }
1961
- const data = await response.json().catch(() => ({}));
1962
- setStatus((data == null ? void 0 : data.status) || {});
1963
- } catch (fetchError) {
1964
- setError((fetchError == null ? void 0 : fetchError.message) || "Failed to load reconciliation status.");
1965
- setStatus({});
1966
- } finally {
1967
- setLoading(false);
1968
- }
1969
- }, []);
1970
- useEffect(() => {
1971
- fetchStatus();
1972
- }, [fetchStatus]);
1973
- return /* @__PURE__ */ jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
1974
- /* @__PURE__ */ jsxs("div", { children: [
1975
- /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Reconciliation Status" }),
1976
- /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-ui-fg-subtle", children: "Monitor reconciliation health and drift detection for PayPal payment sessions." })
1977
- ] }),
1978
- /* @__PURE__ */ jsx(PayPalTabs, {}),
1979
- /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
1980
- /* @__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: [
1981
- /* @__PURE__ */ jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Latest reconciliation run" }),
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
2039
- ] })
2040
- ] })
2041
- ] }) });
2042
- }
2043
2043
  const widgetModule = { widgets: [] };
2044
2044
  const routeModule = {
2045
2045
  routes: [
@@ -2047,25 +2047,25 @@ const routeModule = {
2047
2047
  Component: PayPalSettingsIndexRoute,
2048
2048
  path: "/settings/paypal"
2049
2049
  },
2050
- {
2051
- Component: AdditionalSettingsTab,
2052
- path: "/settings/paypal/additional-settings"
2053
- },
2054
2050
  {
2055
2051
  Component: AdvancedCardPaymentsTab,
2056
2052
  path: "/settings/paypal/advanced-card-payments"
2057
2053
  },
2058
2054
  {
2059
- Component: PayPalApplePayPage,
2060
- path: "/settings/paypal/apple-pay"
2055
+ Component: AdditionalSettingsTab,
2056
+ path: "/settings/paypal/additional-settings"
2057
+ },
2058
+ {
2059
+ Component: PayPalConnectionPage,
2060
+ path: "/settings/paypal/connection"
2061
2061
  },
2062
2062
  {
2063
2063
  Component: PayPalAuditLogsPage,
2064
2064
  path: "/settings/paypal/audit-logs"
2065
2065
  },
2066
2066
  {
2067
- Component: PayPalConnectionPage,
2068
- path: "/settings/paypal/connection"
2067
+ Component: PayPalApplePayPage,
2068
+ path: "/settings/paypal/apple-pay"
2069
2069
  },
2070
2070
  {
2071
2071
  Component: PayPalDisputesPage,
@@ -2079,13 +2079,13 @@ const routeModule = {
2079
2079
  Component: PayPalPayLaterMessagingPage,
2080
2080
  path: "/settings/paypal/pay-later-messaging"
2081
2081
  },
2082
- {
2083
- Component: PayPalSettingsTab,
2084
- path: "/settings/paypal/paypal-settings"
2085
- },
2086
2082
  {
2087
2083
  Component: PayPalReconciliationStatusPage,
2088
2084
  path: "/settings/paypal/reconciliation-status"
2085
+ },
2086
+ {
2087
+ Component: PayPalSettingsTab,
2088
+ path: "/settings/paypal/paypal-settings"
2089
2089
  }
2090
2090
  ]
2091
2091
  };