@easypayment/medusa-paypal 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/.medusa/server/src/admin/index.js +622 -622
  2. package/.medusa/server/src/admin/index.mjs +622 -622
  3. package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.d.ts.map +1 -1
  4. package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.js +2 -3
  5. package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.js.map +1 -1
  6. package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.d.ts.map +1 -1
  7. package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.js +10 -18
  8. package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.js.map +1 -1
  9. package/.medusa/server/src/modules/paypal/payment-provider/service.d.ts.map +1 -1
  10. package/.medusa/server/src/modules/paypal/payment-provider/service.js +2 -15
  11. package/.medusa/server/src/modules/paypal/payment-provider/service.js.map +1 -1
  12. package/.medusa/server/src/modules/paypal/utils/provider-ids.d.ts +0 -4
  13. package/.medusa/server/src/modules/paypal/utils/provider-ids.d.ts.map +1 -1
  14. package/.medusa/server/src/modules/paypal/utils/provider-ids.js +1 -37
  15. package/.medusa/server/src/modules/paypal/utils/provider-ids.js.map +1 -1
  16. package/LICENSE +21 -21
  17. package/README.md +102 -102
  18. package/package.json +75 -76
  19. package/src/admin/routes/settings/paypal/page.tsx +17 -17
  20. package/src/api/admin/payment-collections/[id]/payment-sessions/route.ts +3 -4
  21. package/src/api/store/payment-collections/[id]/payment-sessions/route.ts +12 -22
  22. package/src/index.ts +1 -1
  23. package/src/modules/paypal/payment-provider/service.ts +1016 -1036
  24. package/src/modules/paypal/utils/provider-ids.ts +12 -55
  25. package/src/providers/paypal/index.ts +10 -10
  26. package/src/providers/paypal_card/index.ts +10 -10
  27. package/tsconfig.json +30 -30
  28. package/postcss.config.cjs +0 -3
@@ -334,302 +334,6 @@ function AdvancedCardPaymentsTab() {
334
334
  )
335
335
  ] }) });
336
336
  }
337
- const DEFAULT_FORM = {
338
- paymentAction: "capture",
339
- brandName: "PayPal",
340
- landingPage: "no_preference",
341
- requireInstantPayment: false,
342
- useShippingAsBilling: true,
343
- sendItemDetails: true,
344
- skipOrderReviewPage: true,
345
- invoicePrefix: "WC-",
346
- creditCardStatementName: "PayPal",
347
- enableLogging: true,
348
- logPath: "/uploads/wc-logs/"
349
- };
350
- function mergeWithDefaults(saved) {
351
- if (!saved) return { ...DEFAULT_FORM };
352
- const entries = Object.entries(saved).filter(([, value]) => value !== void 0);
353
- return {
354
- ...DEFAULT_FORM,
355
- ...Object.fromEntries(entries)
356
- };
357
- }
358
- function SectionCard$1({
359
- title,
360
- description,
361
- right,
362
- children
363
- }) {
364
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
365
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4 border-b border-ui-border-base p-4", children: [
366
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
367
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: title }),
368
- description ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-sm text-ui-fg-subtle", children: description }) : null
369
- ] }),
370
- right
371
- ] }),
372
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children })
373
- ] });
374
- }
375
- function FieldRow$1({
376
- label,
377
- hint,
378
- children
379
- }) {
380
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-12 items-start gap-4 py-3", children: [
381
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-12 md:col-span-4", children: [
382
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-ui-fg-base", children: label }),
383
- hint ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-xs text-ui-fg-subtle", children: hint }) : null
384
- ] }),
385
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-12 md:col-span-8", children })
386
- ] });
387
- }
388
- function AdditionalSettingsTab() {
389
- const [form, setForm] = react.useState(() => ({ ...DEFAULT_FORM }));
390
- const [loading, setLoading] = react.useState(false);
391
- const [saving, setSaving] = react.useState(false);
392
- const didInit = react.useRef(false);
393
- react.useEffect(() => {
394
- if (didInit.current) return;
395
- didInit.current = true;
396
- (async () => {
397
- try {
398
- setLoading(true);
399
- const r = await fetch("/admin/paypal/settings", {
400
- credentials: "include",
401
- headers: { "Accept": "application/json" }
402
- });
403
- if (!r.ok) return;
404
- const json = await r.json();
405
- const payload = (json == null ? void 0 : json.data) ?? json;
406
- const saved = payload == null ? void 0 : payload.additional_settings;
407
- if (saved && typeof saved === "object") {
408
- setForm(mergeWithDefaults(saved));
409
- }
410
- } finally {
411
- setLoading(false);
412
- }
413
- })();
414
- }, []);
415
- const [toast, setToast] = react.useState(null);
416
- async function onSave() {
417
- try {
418
- setSaving(true);
419
- setToast(null);
420
- const r = await fetch("/admin/paypal/settings", {
421
- method: "POST",
422
- credentials: "include",
423
- headers: {
424
- "Content-Type": "application/json",
425
- "Accept": "application/json"
426
- },
427
- body: JSON.stringify({
428
- additional_settings: form
429
- })
430
- });
431
- if (!r.ok) {
432
- const errText = await r.text().catch(() => "");
433
- throw new Error(errText || "Failed to save settings");
434
- }
435
- const json = await r.json().catch(() => ({}));
436
- const payload = (json == null ? void 0 : json.data) ?? json;
437
- const saved = payload == null ? void 0 : payload.additional_settings;
438
- if (saved && typeof saved === "object") {
439
- setForm(mergeWithDefaults(saved));
440
- }
441
- setToast({ type: "success", message: "Settings saved" });
442
- window.setTimeout(() => setToast(null), 2500);
443
- } catch (e) {
444
- setToast({ type: "error", message: (e == null ? void 0 : e.message) || "Failed to save settings" });
445
- window.setTimeout(() => setToast(null), 3500);
446
- } finally {
447
- setSaving(false);
448
- }
449
- }
450
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
451
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-start justify-between gap-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Gateway By Easy Payment" }) }) }),
452
- /* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
453
- toast ? /* @__PURE__ */ jsxRuntime.jsx(
454
- "div",
455
- {
456
- className: "fixed right-6 top-6 z-50 rounded-md border border-ui-border-base bg-ui-bg-base px-4 py-3 text-sm shadow-lg",
457
- role: "status",
458
- "aria-live": "polite",
459
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: toast.type === "success" ? "text-ui-fg-base" : "text-ui-fg-error", children: toast.message })
460
- }
461
- ) : null,
462
- /* @__PURE__ */ jsxRuntime.jsx(
463
- SectionCard$1,
464
- {
465
- title: "Additional Settings",
466
- description: "These settings control checkout behavior, PayPal experience, and logging.",
467
- right: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
468
- /* @__PURE__ */ jsxRuntime.jsx(
469
- "button",
470
- {
471
- type: "button",
472
- onClick: onSave,
473
- disabled: saving || loading,
474
- className: "rounded-md bg-ui-button-neutral px-4 py-2 text-sm font-medium text-ui-fg-on-color shadow-sm hover:opacity-90 disabled:opacity-60",
475
- children: saving ? "Saving..." : "Save settings"
476
- }
477
- ),
478
- loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading…" }) : null
479
- ] }),
480
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-ui-border-base", children: [
481
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Payment action", children: /* @__PURE__ */ jsxRuntime.jsxs(
482
- "select",
483
- {
484
- value: form.paymentAction,
485
- onChange: (e) => setForm((p) => ({ ...p, paymentAction: e.target.value })),
486
- className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive",
487
- children: [
488
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "capture", children: "Capture" }),
489
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "authorize", children: "Authorize" })
490
- ]
491
- }
492
- ) }),
493
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Brand Name", children: /* @__PURE__ */ jsxRuntime.jsx(
494
- "input",
495
- {
496
- value: form.brandName,
497
- onChange: (e) => setForm((p) => ({ ...p, brandName: e.target.value })),
498
- className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive",
499
- placeholder: "PayPal"
500
- }
501
- ) }),
502
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Landing Page", children: /* @__PURE__ */ jsxRuntime.jsxs(
503
- "select",
504
- {
505
- value: form.landingPage,
506
- onChange: (e) => setForm((p) => ({ ...p, landingPage: e.target.value })),
507
- className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive",
508
- children: [
509
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "no_preference", children: "No Preference" }),
510
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "login", children: "Login" }),
511
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "billing", children: "Billing" })
512
- ]
513
- }
514
- ) }),
515
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Instant Payments", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
516
- /* @__PURE__ */ jsxRuntime.jsx(
517
- "input",
518
- {
519
- type: "checkbox",
520
- checked: form.requireInstantPayment,
521
- onChange: (e) => setForm((p) => ({ ...p, requireInstantPayment: e.target.checked })),
522
- className: "h-4 w-4 rounded border-ui-border-base"
523
- }
524
- ),
525
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Require Instant Payment" })
526
- ] }) }),
527
- /* @__PURE__ */ jsxRuntime.jsx(
528
- FieldRow$1,
529
- {
530
- label: "Billing Address",
531
- hint: "If the billing address is empty and PayPal provides a shipping address, the order will use the shipping address as the billing address.",
532
- children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
533
- /* @__PURE__ */ jsxRuntime.jsx(
534
- "input",
535
- {
536
- type: "checkbox",
537
- checked: form.useShippingAsBilling,
538
- onChange: (e) => setForm((p) => ({ ...p, useShippingAsBilling: e.target.checked })),
539
- className: "h-4 w-4 rounded border-ui-border-base"
540
- }
541
- ),
542
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Use PayPal Shipping Address as Billing" })
543
- ] })
544
- }
545
- ),
546
- /* @__PURE__ */ jsxRuntime.jsx(
547
- FieldRow$1,
548
- {
549
- label: "Send Item Details",
550
- hint: "Include all line item details in the payment request to PayPal so that they can be seen from the PayPal transaction details page.",
551
- children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
552
- /* @__PURE__ */ jsxRuntime.jsx(
553
- "input",
554
- {
555
- type: "checkbox",
556
- checked: form.sendItemDetails,
557
- onChange: (e) => setForm((p) => ({ ...p, sendItemDetails: e.target.checked })),
558
- className: "h-4 w-4 rounded border-ui-border-base"
559
- }
560
- ),
561
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Send line item details to PayPal" })
562
- ] })
563
- }
564
- ),
565
- /* @__PURE__ */ jsxRuntime.jsx(
566
- FieldRow$1,
567
- {
568
- label: "Order Review Page",
569
- hint: "Payments from the Product or Cart page skip the review step and go straight to the Thank You page.",
570
- children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
571
- /* @__PURE__ */ jsxRuntime.jsx(
572
- "input",
573
- {
574
- type: "checkbox",
575
- checked: form.skipOrderReviewPage,
576
- onChange: (e) => setForm((p) => ({ ...p, skipOrderReviewPage: e.target.checked })),
577
- className: "h-4 w-4 rounded border-ui-border-base"
578
- }
579
- ),
580
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Skip Order Review Page" })
581
- ] })
582
- }
583
- ),
584
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Invoice prefix", children: /* @__PURE__ */ jsxRuntime.jsx(
585
- "input",
586
- {
587
- value: form.invoicePrefix,
588
- onChange: (e) => setForm((p) => ({ ...p, invoicePrefix: e.target.value })),
589
- 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",
590
- placeholder: "WC-"
591
- }
592
- ) }),
593
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Credit Card Statement Name", children: /* @__PURE__ */ jsxRuntime.jsx(
594
- "input",
595
- {
596
- value: form.creditCardStatementName,
597
- onChange: (e) => setForm((p) => ({ ...p, creditCardStatementName: e.target.value })),
598
- className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive",
599
- placeholder: "PayPal"
600
- }
601
- ) }),
602
- /* @__PURE__ */ jsxRuntime.jsx(
603
- FieldRow$1,
604
- {
605
- label: "Debug log",
606
- hint: /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
607
- "Log PayPal events such as Webhook, Payment, Refund.",
608
- " ",
609
- form.logPath ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
610
- "Log location: ",
611
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: form.logPath })
612
- ] }) : null
613
- ] }),
614
- children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
615
- /* @__PURE__ */ jsxRuntime.jsx(
616
- "input",
617
- {
618
- type: "checkbox",
619
- checked: form.enableLogging,
620
- onChange: (e) => setForm((p) => ({ ...p, enableLogging: e.target.checked })),
621
- className: "h-4 w-4 rounded border-ui-border-base"
622
- }
623
- ),
624
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable logging" })
625
- ] })
626
- }
627
- )
628
- ] })
629
- }
630
- )
631
- ] }) });
632
- }
633
337
  const config = adminSdk.defineRouteConfig({
634
338
  label: "PayPal Connection",
635
339
  hide: true
@@ -1192,38 +896,224 @@ function PayPalConnectionPage() {
1192
896
  }
1193
897
  )
1194
898
  ] })
1195
- ] }) })
899
+ ] }) })
900
+ ] }) })
901
+ ] }),
902
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
903
+ .loader {
904
+ border: 3px solid #f3f3f3;
905
+ border-top: 3px solid #0070ba;
906
+ border-radius: 50%;
907
+ width: 18px;
908
+ height: 18px;
909
+ animation: spin 1s linear infinite;
910
+ display: inline-block;
911
+ vertical-align: middle;
912
+ margin-right: 8px;
913
+ }
914
+ @keyframes spin {
915
+ 0% { transform: rotate(0deg); }
916
+ 100% { transform: rotate(360deg); }
917
+ }
918
+ ` })
919
+ ] });
920
+ }
921
+ const EMPTY_FILTERS = {
922
+ dispute_id: "",
923
+ status: "",
924
+ order_id: "",
925
+ cart_id: ""
926
+ };
927
+ function formatDate$2(value) {
928
+ if (!value) {
929
+ return "";
930
+ }
931
+ const parsed = new Date(value);
932
+ if (Number.isNaN(parsed.getTime())) {
933
+ return value;
934
+ }
935
+ return parsed.toLocaleString();
936
+ }
937
+ function PayPalDisputesPage() {
938
+ const [filters, setFilters] = react.useState({ ...EMPTY_FILTERS });
939
+ const [disputes, setDisputes] = react.useState([]);
940
+ const [loading, setLoading] = react.useState(false);
941
+ const [error, setError] = react.useState(null);
942
+ const queryString = react.useMemo(() => {
943
+ const params = new URLSearchParams();
944
+ Object.entries(filters).forEach(([key, value]) => {
945
+ if (value.trim()) {
946
+ params.set(key, value.trim());
947
+ }
948
+ });
949
+ const qs = params.toString();
950
+ return qs ? `?${qs}` : "";
951
+ }, [filters]);
952
+ const fetchDisputes = react.useCallback(async (source) => {
953
+ try {
954
+ setLoading(true);
955
+ setError(null);
956
+ const params = new URLSearchParams();
957
+ Object.entries(source).forEach(([key, value]) => {
958
+ if (value.trim()) {
959
+ params.set(key, value.trim());
960
+ }
961
+ });
962
+ const qs = params.toString();
963
+ const resp = await fetch(`/admin/paypal/disputes${qs ? `?${qs}` : ""}`, {
964
+ credentials: "include",
965
+ headers: {
966
+ Accept: "application/json"
967
+ }
968
+ });
969
+ if (!resp.ok) {
970
+ const message = await resp.text().catch(() => "");
971
+ throw new Error(message || "Failed to load disputes");
972
+ }
973
+ const json = await resp.json().catch(() => ({}));
974
+ setDisputes((json == null ? void 0 : json.disputes) || []);
975
+ } catch (fetchError) {
976
+ setError((fetchError == null ? void 0 : fetchError.message) || "Failed to load disputes");
977
+ setDisputes([]);
978
+ } finally {
979
+ setLoading(false);
980
+ }
981
+ }, []);
982
+ react.useEffect(() => {
983
+ fetchDisputes(EMPTY_FILTERS);
984
+ }, [fetchDisputes]);
985
+ const onSubmit = (event) => {
986
+ event.preventDefault();
987
+ fetchDisputes(filters);
988
+ };
989
+ const onReset = () => {
990
+ setFilters({ ...EMPTY_FILTERS });
991
+ fetchDisputes(EMPTY_FILTERS);
992
+ };
993
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
994
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
995
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Disputes" }),
996
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-ui-fg-subtle", children: "Review PayPal dispute activity tied to your Medusa orders. This view is read-only." })
997
+ ] }),
998
+ /* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
999
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
1000
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-ui-border-base p-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Filters" }) }),
1001
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit, className: "flex flex-col gap-4", children: [
1002
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-4", children: [
1003
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
1004
+ "Dispute ID",
1005
+ /* @__PURE__ */ jsxRuntime.jsx(
1006
+ "input",
1007
+ {
1008
+ className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base",
1009
+ value: filters.dispute_id,
1010
+ onChange: (event) => setFilters((prev) => ({ ...prev, dispute_id: event.target.value })),
1011
+ placeholder: "PP-D-123"
1012
+ }
1013
+ )
1014
+ ] }),
1015
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
1016
+ "Status",
1017
+ /* @__PURE__ */ jsxRuntime.jsx(
1018
+ "input",
1019
+ {
1020
+ className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base",
1021
+ value: filters.status,
1022
+ onChange: (event) => setFilters((prev) => ({ ...prev, status: event.target.value })),
1023
+ placeholder: "OPEN"
1024
+ }
1025
+ )
1026
+ ] }),
1027
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
1028
+ "Order ID",
1029
+ /* @__PURE__ */ jsxRuntime.jsx(
1030
+ "input",
1031
+ {
1032
+ className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base",
1033
+ value: filters.order_id,
1034
+ onChange: (event) => setFilters((prev) => ({ ...prev, order_id: event.target.value })),
1035
+ placeholder: "order_..."
1036
+ }
1037
+ )
1038
+ ] }),
1039
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
1040
+ "Cart ID",
1041
+ /* @__PURE__ */ jsxRuntime.jsx(
1042
+ "input",
1043
+ {
1044
+ className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base",
1045
+ value: filters.cart_id,
1046
+ onChange: (event) => setFilters((prev) => ({ ...prev, cart_id: event.target.value })),
1047
+ placeholder: "cart_..."
1048
+ }
1049
+ )
1050
+ ] })
1051
+ ] }),
1052
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-3", children: [
1053
+ /* @__PURE__ */ jsxRuntime.jsx(
1054
+ "button",
1055
+ {
1056
+ type: "submit",
1057
+ className: "rounded-md bg-ui-fg-base px-4 py-2 text-sm font-medium text-ui-bg-base",
1058
+ disabled: loading,
1059
+ children: loading ? "Loading..." : "Apply filters"
1060
+ }
1061
+ ),
1062
+ /* @__PURE__ */ jsxRuntime.jsx(
1063
+ "button",
1064
+ {
1065
+ type: "button",
1066
+ className: "rounded-md border border-ui-border-base px-4 py-2 text-sm text-ui-fg-base",
1067
+ onClick: onReset,
1068
+ disabled: loading,
1069
+ children: "Reset"
1070
+ }
1071
+ ),
1072
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-ui-fg-subtle", children: [
1073
+ "Showing ",
1074
+ disputes.length,
1075
+ " dispute",
1076
+ disputes.length === 1 ? "" : "s",
1077
+ queryString ? " (filtered)" : ""
1078
+ ] })
1079
+ ] })
1196
1080
  ] }) })
1197
1081
  ] }),
1198
- /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
1199
- .loader {
1200
- border: 3px solid #f3f3f3;
1201
- border-top: 3px solid #0070ba;
1202
- border-radius: 50%;
1203
- width: 18px;
1204
- height: 18px;
1205
- animation: spin 1s linear infinite;
1206
- display: inline-block;
1207
- vertical-align: middle;
1208
- margin-right: 8px;
1209
- }
1210
- @keyframes spin {
1211
- 0% { transform: rotate(0deg); }
1212
- 100% { transform: rotate(360deg); }
1213
- }
1214
- ` })
1215
- ] });
1082
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
1083
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-ui-border-base p-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Dispute Records" }) }),
1084
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-ui-border-base text-sm", children: [
1085
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "text-left text-ui-fg-subtle", children: [
1086
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Dispute" }),
1087
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Status" }),
1088
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Reason" }),
1089
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Stage" }),
1090
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Amount" }),
1091
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Order" }),
1092
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Cart" }),
1093
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Updated" })
1094
+ ] }) }),
1095
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-base text-ui-fg-base", children: disputes.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-6 text-center text-ui-fg-subtle", colSpan: 8, children: loading ? "Loading disputes..." : "No disputes found." }) }) : disputes.map((dispute) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1096
+ /* @__PURE__ */ jsxRuntime.jsxs("td", { className: "px-4 py-3", children: [
1097
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-ui-fg-base", children: dispute.dispute_id }),
1098
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-ui-fg-subtle", children: dispute.transaction_id || "No transaction" })
1099
+ ] }),
1100
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.status || "Unknown" }),
1101
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.reason || "-" }),
1102
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.stage || "-" }),
1103
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.amount ? `${dispute.amount} ${dispute.currency_code || ""}` : "-" }),
1104
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.order_id || "-" }),
1105
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.cart_id || "-" }),
1106
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 text-ui-fg-subtle", children: formatDate$2(dispute.updated_at || dispute.created_at) })
1107
+ ] }, dispute.id)) })
1108
+ ] }) }),
1109
+ error ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-ui-border-base px-4 py-3 text-sm text-ui-fg-error", children: error }) : null
1110
+ ] })
1111
+ ] }) });
1216
1112
  }
1217
1113
  function PayPalApplePayPage() {
1218
1114
  return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
1219
1115
  }
1220
- const EMPTY_FILTERS = {
1221
- dispute_id: "",
1222
- status: "",
1223
- order_id: "",
1224
- cart_id: ""
1225
- };
1226
- function formatDate$2(value) {
1116
+ function formatDate$1(value) {
1227
1117
  if (!value) {
1228
1118
  return "";
1229
1119
  }
@@ -1233,188 +1123,377 @@ function formatDate$2(value) {
1233
1123
  }
1234
1124
  return parsed.toLocaleString();
1235
1125
  }
1236
- function PayPalDisputesPage() {
1237
- const [filters, setFilters] = react.useState({ ...EMPTY_FILTERS });
1238
- const [disputes, setDisputes] = react.useState([]);
1126
+ function PayPalAuditLogsPage() {
1127
+ const [logs, setLogs] = react.useState([]);
1239
1128
  const [loading, setLoading] = react.useState(false);
1240
1129
  const [error, setError] = react.useState(null);
1241
- const queryString = react.useMemo(() => {
1242
- const params = new URLSearchParams();
1243
- Object.entries(filters).forEach(([key, value]) => {
1244
- if (value.trim()) {
1245
- params.set(key, value.trim());
1246
- }
1247
- });
1248
- const qs = params.toString();
1249
- return qs ? `?${qs}` : "";
1250
- }, [filters]);
1251
- const fetchDisputes = react.useCallback(async (source) => {
1130
+ const fetchLogs = react.useCallback(async () => {
1252
1131
  try {
1253
1132
  setLoading(true);
1254
1133
  setError(null);
1255
- const params = new URLSearchParams();
1256
- Object.entries(source).forEach(([key, value]) => {
1257
- if (value.trim()) {
1258
- params.set(key, value.trim());
1259
- }
1260
- });
1261
- const qs = params.toString();
1262
- const resp = await fetch(`/admin/paypal/disputes${qs ? `?${qs}` : ""}`, {
1134
+ const response = await fetch("/admin/paypal/audit-logs?limit=50", {
1263
1135
  credentials: "include",
1264
1136
  headers: {
1265
1137
  Accept: "application/json"
1266
1138
  }
1267
1139
  });
1268
- if (!resp.ok) {
1269
- const message = await resp.text().catch(() => "");
1270
- throw new Error(message || "Failed to load disputes");
1140
+ if (!response.ok) {
1141
+ const message = await response.text().catch(() => "");
1142
+ throw new Error(message || "Failed to load audit logs.");
1271
1143
  }
1272
- const json = await resp.json().catch(() => ({}));
1273
- setDisputes((json == null ? void 0 : json.disputes) || []);
1144
+ const data = await response.json().catch(() => ({}));
1145
+ setLogs((data == null ? void 0 : data.logs) || []);
1274
1146
  } catch (fetchError) {
1275
- setError((fetchError == null ? void 0 : fetchError.message) || "Failed to load disputes");
1276
- setDisputes([]);
1147
+ setError((fetchError == null ? void 0 : fetchError.message) || "Failed to load audit logs.");
1148
+ setLogs([]);
1149
+ } finally {
1150
+ setLoading(false);
1151
+ }
1152
+ }, []);
1153
+ react.useEffect(() => {
1154
+ fetchLogs();
1155
+ }, [fetchLogs]);
1156
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
1157
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1158
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Audit Logs" }),
1159
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-ui-fg-subtle", children: "Track administrative changes and credential events for PayPal configuration." })
1160
+ ] }),
1161
+ /* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
1162
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
1163
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-ui-border-base p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-4", children: [
1164
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Latest events" }),
1165
+ /* @__PURE__ */ jsxRuntime.jsx(
1166
+ "button",
1167
+ {
1168
+ type: "button",
1169
+ onClick: fetchLogs,
1170
+ className: "rounded-md border border-ui-border-base px-3 py-2 text-sm text-ui-fg-base",
1171
+ disabled: loading,
1172
+ children: loading ? "Refreshing..." : "Refresh"
1173
+ }
1174
+ )
1175
+ ] }) }),
1176
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4", children: [
1177
+ error ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-600", children: error }) : null,
1178
+ !error && logs.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-ui-fg-subtle", children: loading ? "Loading audit logs..." : "No audit log entries found yet." }) : null,
1179
+ logs.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full text-left text-sm", children: [
1180
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "text-ui-fg-muted", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1181
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "pb-2 pr-4 font-medium", children: "Timestamp" }),
1182
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "pb-2 pr-4 font-medium", children: "Event" }),
1183
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "pb-2 font-medium", children: "Details" })
1184
+ ] }) }),
1185
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: logs.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-t border-ui-border-base", children: [
1186
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-3 pr-4 text-ui-fg-base", children: formatDate$1(entry.created_at) || "—" }),
1187
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-3 pr-4 text-ui-fg-base", children: entry.event_type || "—" }),
1188
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-3 text-ui-fg-subtle", children: /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "whitespace-pre-wrap rounded-md bg-ui-bg-subtle p-2 text-xs text-ui-fg-subtle", children: JSON.stringify(entry.metadata || {}, null, 2) }) })
1189
+ ] }, entry.id)) })
1190
+ ] }) }) : null
1191
+ ] })
1192
+ ] })
1193
+ ] }) });
1194
+ }
1195
+ function PayPalGooglePayPage() {
1196
+ return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
1197
+ }
1198
+ const DEFAULT_FORM = {
1199
+ paymentAction: "capture",
1200
+ brandName: "PayPal",
1201
+ landingPage: "no_preference",
1202
+ requireInstantPayment: false,
1203
+ useShippingAsBilling: true,
1204
+ sendItemDetails: true,
1205
+ skipOrderReviewPage: true,
1206
+ invoicePrefix: "WC-",
1207
+ creditCardStatementName: "PayPal",
1208
+ enableLogging: true,
1209
+ logPath: "/uploads/wc-logs/"
1210
+ };
1211
+ function mergeWithDefaults(saved) {
1212
+ if (!saved) return { ...DEFAULT_FORM };
1213
+ const entries = Object.entries(saved).filter(([, value]) => value !== void 0);
1214
+ return {
1215
+ ...DEFAULT_FORM,
1216
+ ...Object.fromEntries(entries)
1217
+ };
1218
+ }
1219
+ function SectionCard$1({
1220
+ title,
1221
+ description,
1222
+ right,
1223
+ children
1224
+ }) {
1225
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
1226
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4 border-b border-ui-border-base p-4", children: [
1227
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1228
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: title }),
1229
+ description ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-sm text-ui-fg-subtle", children: description }) : null
1230
+ ] }),
1231
+ right
1232
+ ] }),
1233
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children })
1234
+ ] });
1235
+ }
1236
+ function FieldRow$1({
1237
+ label,
1238
+ hint,
1239
+ children
1240
+ }) {
1241
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-12 items-start gap-4 py-3", children: [
1242
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-12 md:col-span-4", children: [
1243
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-ui-fg-base", children: label }),
1244
+ hint ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-xs text-ui-fg-subtle", children: hint }) : null
1245
+ ] }),
1246
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-12 md:col-span-8", children })
1247
+ ] });
1248
+ }
1249
+ function AdditionalSettingsTab() {
1250
+ const [form, setForm] = react.useState(() => ({ ...DEFAULT_FORM }));
1251
+ const [loading, setLoading] = react.useState(false);
1252
+ const [saving, setSaving] = react.useState(false);
1253
+ const didInit = react.useRef(false);
1254
+ react.useEffect(() => {
1255
+ if (didInit.current) return;
1256
+ didInit.current = true;
1257
+ (async () => {
1258
+ try {
1259
+ setLoading(true);
1260
+ const r = await fetch("/admin/paypal/settings", {
1261
+ credentials: "include",
1262
+ headers: { "Accept": "application/json" }
1263
+ });
1264
+ if (!r.ok) return;
1265
+ const json = await r.json();
1266
+ const payload = (json == null ? void 0 : json.data) ?? json;
1267
+ const saved = payload == null ? void 0 : payload.additional_settings;
1268
+ if (saved && typeof saved === "object") {
1269
+ setForm(mergeWithDefaults(saved));
1270
+ }
1271
+ } finally {
1272
+ setLoading(false);
1273
+ }
1274
+ })();
1275
+ }, []);
1276
+ const [toast, setToast] = react.useState(null);
1277
+ async function onSave() {
1278
+ try {
1279
+ setSaving(true);
1280
+ setToast(null);
1281
+ const r = await fetch("/admin/paypal/settings", {
1282
+ method: "POST",
1283
+ credentials: "include",
1284
+ headers: {
1285
+ "Content-Type": "application/json",
1286
+ "Accept": "application/json"
1287
+ },
1288
+ body: JSON.stringify({
1289
+ additional_settings: form
1290
+ })
1291
+ });
1292
+ if (!r.ok) {
1293
+ const errText = await r.text().catch(() => "");
1294
+ throw new Error(errText || "Failed to save settings");
1295
+ }
1296
+ const json = await r.json().catch(() => ({}));
1297
+ const payload = (json == null ? void 0 : json.data) ?? json;
1298
+ const saved = payload == null ? void 0 : payload.additional_settings;
1299
+ if (saved && typeof saved === "object") {
1300
+ setForm(mergeWithDefaults(saved));
1301
+ }
1302
+ setToast({ type: "success", message: "Settings saved" });
1303
+ window.setTimeout(() => setToast(null), 2500);
1304
+ } catch (e) {
1305
+ setToast({ type: "error", message: (e == null ? void 0 : e.message) || "Failed to save settings" });
1306
+ window.setTimeout(() => setToast(null), 3500);
1277
1307
  } finally {
1278
- setLoading(false);
1308
+ setSaving(false);
1279
1309
  }
1280
- }, []);
1281
- react.useEffect(() => {
1282
- fetchDisputes(EMPTY_FILTERS);
1283
- }, [fetchDisputes]);
1284
- const onSubmit = (event) => {
1285
- event.preventDefault();
1286
- fetchDisputes(filters);
1287
- };
1288
- const onReset = () => {
1289
- setFilters({ ...EMPTY_FILTERS });
1290
- fetchDisputes(EMPTY_FILTERS);
1291
- };
1310
+ }
1292
1311
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
1293
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1294
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Disputes" }),
1295
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-ui-fg-subtle", children: "Review PayPal dispute activity tied to your Medusa orders. This view is read-only." })
1296
- ] }),
1312
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-start justify-between gap-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Gateway By Easy Payment" }) }) }),
1297
1313
  /* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
1298
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
1299
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-ui-border-base p-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Filters" }) }),
1300
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit, className: "flex flex-col gap-4", children: [
1301
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-4", children: [
1302
- /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
1303
- "Dispute ID",
1304
- /* @__PURE__ */ jsxRuntime.jsx(
1305
- "input",
1306
- {
1307
- className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base",
1308
- value: filters.dispute_id,
1309
- onChange: (event) => setFilters((prev) => ({ ...prev, dispute_id: event.target.value })),
1310
- placeholder: "PP-D-123"
1311
- }
1312
- )
1313
- ] }),
1314
- /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
1315
- "Status",
1316
- /* @__PURE__ */ jsxRuntime.jsx(
1317
- "input",
1318
- {
1319
- className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base",
1320
- value: filters.status,
1321
- onChange: (event) => setFilters((prev) => ({ ...prev, status: event.target.value })),
1322
- placeholder: "OPEN"
1323
- }
1324
- )
1325
- ] }),
1326
- /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
1327
- "Order ID",
1328
- /* @__PURE__ */ jsxRuntime.jsx(
1329
- "input",
1330
- {
1331
- className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base",
1332
- value: filters.order_id,
1333
- onChange: (event) => setFilters((prev) => ({ ...prev, order_id: event.target.value })),
1334
- placeholder: "order_..."
1335
- }
1336
- )
1337
- ] }),
1338
- /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 text-sm text-ui-fg-subtle", children: [
1339
- "Cart ID",
1314
+ toast ? /* @__PURE__ */ jsxRuntime.jsx(
1315
+ "div",
1316
+ {
1317
+ 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",
1318
+ role: "status",
1319
+ "aria-live": "polite",
1320
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: toast.type === "success" ? "text-ui-fg-base" : "text-ui-fg-error", children: toast.message })
1321
+ }
1322
+ ) : null,
1323
+ /* @__PURE__ */ jsxRuntime.jsx(
1324
+ SectionCard$1,
1325
+ {
1326
+ title: "Additional Settings",
1327
+ description: "These settings control checkout behavior, PayPal experience, and logging.",
1328
+ right: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
1329
+ /* @__PURE__ */ jsxRuntime.jsx(
1330
+ "button",
1331
+ {
1332
+ type: "button",
1333
+ onClick: onSave,
1334
+ disabled: saving || loading,
1335
+ 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",
1336
+ children: saving ? "Saving..." : "Save settings"
1337
+ }
1338
+ ),
1339
+ loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading…" }) : null
1340
+ ] }),
1341
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-ui-border-base", children: [
1342
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Payment action", children: /* @__PURE__ */ jsxRuntime.jsxs(
1343
+ "select",
1344
+ {
1345
+ value: form.paymentAction,
1346
+ onChange: (e) => setForm((p) => ({ ...p, paymentAction: e.target.value })),
1347
+ 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",
1348
+ children: [
1349
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "capture", children: "Capture" }),
1350
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "authorize", children: "Authorize" })
1351
+ ]
1352
+ }
1353
+ ) }),
1354
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Brand Name", children: /* @__PURE__ */ jsxRuntime.jsx(
1355
+ "input",
1356
+ {
1357
+ value: form.brandName,
1358
+ onChange: (e) => setForm((p) => ({ ...p, brandName: e.target.value })),
1359
+ 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",
1360
+ placeholder: "PayPal"
1361
+ }
1362
+ ) }),
1363
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Landing Page", children: /* @__PURE__ */ jsxRuntime.jsxs(
1364
+ "select",
1365
+ {
1366
+ value: form.landingPage,
1367
+ onChange: (e) => setForm((p) => ({ ...p, landingPage: e.target.value })),
1368
+ 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",
1369
+ children: [
1370
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "no_preference", children: "No Preference" }),
1371
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "login", children: "Login" }),
1372
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "billing", children: "Billing" })
1373
+ ]
1374
+ }
1375
+ ) }),
1376
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Instant Payments", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
1340
1377
  /* @__PURE__ */ jsxRuntime.jsx(
1341
1378
  "input",
1342
1379
  {
1343
- className: "rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base",
1344
- value: filters.cart_id,
1345
- onChange: (event) => setFilters((prev) => ({ ...prev, cart_id: event.target.value })),
1346
- placeholder: "cart_..."
1380
+ type: "checkbox",
1381
+ checked: form.requireInstantPayment,
1382
+ onChange: (e) => setForm((p) => ({ ...p, requireInstantPayment: e.target.checked })),
1383
+ className: "h-4 w-4 rounded border-ui-border-base"
1347
1384
  }
1348
- )
1349
- ] })
1350
- ] }),
1351
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-3", children: [
1385
+ ),
1386
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Require Instant Payment" })
1387
+ ] }) }),
1352
1388
  /* @__PURE__ */ jsxRuntime.jsx(
1353
- "button",
1389
+ FieldRow$1,
1354
1390
  {
1355
- type: "submit",
1356
- className: "rounded-md bg-ui-fg-base px-4 py-2 text-sm font-medium text-ui-bg-base",
1357
- disabled: loading,
1358
- children: loading ? "Loading..." : "Apply filters"
1391
+ label: "Billing Address",
1392
+ hint: "If the billing address is empty and PayPal provides a shipping address, the order will use the shipping address as the billing address.",
1393
+ children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
1394
+ /* @__PURE__ */ jsxRuntime.jsx(
1395
+ "input",
1396
+ {
1397
+ type: "checkbox",
1398
+ checked: form.useShippingAsBilling,
1399
+ onChange: (e) => setForm((p) => ({ ...p, useShippingAsBilling: e.target.checked })),
1400
+ className: "h-4 w-4 rounded border-ui-border-base"
1401
+ }
1402
+ ),
1403
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Use PayPal Shipping Address as Billing" })
1404
+ ] })
1359
1405
  }
1360
1406
  ),
1361
1407
  /* @__PURE__ */ jsxRuntime.jsx(
1362
- "button",
1408
+ FieldRow$1,
1363
1409
  {
1364
- type: "button",
1365
- className: "rounded-md border border-ui-border-base px-4 py-2 text-sm text-ui-fg-base",
1366
- onClick: onReset,
1367
- disabled: loading,
1368
- children: "Reset"
1410
+ label: "Send Item Details",
1411
+ hint: "Include all line item details in the payment request to PayPal so that they can be seen from the PayPal transaction details page.",
1412
+ children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
1413
+ /* @__PURE__ */ jsxRuntime.jsx(
1414
+ "input",
1415
+ {
1416
+ type: "checkbox",
1417
+ checked: form.sendItemDetails,
1418
+ onChange: (e) => setForm((p) => ({ ...p, sendItemDetails: e.target.checked })),
1419
+ className: "h-4 w-4 rounded border-ui-border-base"
1420
+ }
1421
+ ),
1422
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Send line item details to PayPal" })
1423
+ ] })
1369
1424
  }
1370
1425
  ),
1371
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-ui-fg-subtle", children: [
1372
- "Showing ",
1373
- disputes.length,
1374
- " dispute",
1375
- disputes.length === 1 ? "" : "s",
1376
- queryString ? " (filtered)" : ""
1377
- ] })
1378
- ] })
1379
- ] }) })
1380
- ] }),
1381
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
1382
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-ui-border-base p-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Dispute Records" }) }),
1383
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-ui-border-base text-sm", children: [
1384
- /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "text-left text-ui-fg-subtle", children: [
1385
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Dispute" }),
1386
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Status" }),
1387
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Reason" }),
1388
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Stage" }),
1389
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Amount" }),
1390
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Order" }),
1391
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Cart" }),
1392
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 font-medium", children: "Updated" })
1393
- ] }) }),
1394
- /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-base text-ui-fg-base", children: disputes.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-6 text-center text-ui-fg-subtle", colSpan: 8, children: loading ? "Loading disputes..." : "No disputes found." }) }) : disputes.map((dispute) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1395
- /* @__PURE__ */ jsxRuntime.jsxs("td", { className: "px-4 py-3", children: [
1396
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-ui-fg-base", children: dispute.dispute_id }),
1397
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-ui-fg-subtle", children: dispute.transaction_id || "No transaction" })
1398
- ] }),
1399
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.status || "Unknown" }),
1400
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.reason || "-" }),
1401
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.stage || "-" }),
1402
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.amount ? `${dispute.amount} ${dispute.currency_code || ""}` : "-" }),
1403
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.order_id || "-" }),
1404
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3", children: dispute.cart_id || "-" }),
1405
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 text-ui-fg-subtle", children: formatDate$2(dispute.updated_at || dispute.created_at) })
1406
- ] }, dispute.id)) })
1407
- ] }) }),
1408
- error ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-ui-border-base px-4 py-3 text-sm text-ui-fg-error", children: error }) : null
1409
- ] })
1426
+ /* @__PURE__ */ jsxRuntime.jsx(
1427
+ FieldRow$1,
1428
+ {
1429
+ label: "Order Review Page",
1430
+ hint: "Payments from the Product or Cart page skip the review step and go straight to the Thank You page.",
1431
+ children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
1432
+ /* @__PURE__ */ jsxRuntime.jsx(
1433
+ "input",
1434
+ {
1435
+ type: "checkbox",
1436
+ checked: form.skipOrderReviewPage,
1437
+ onChange: (e) => setForm((p) => ({ ...p, skipOrderReviewPage: e.target.checked })),
1438
+ className: "h-4 w-4 rounded border-ui-border-base"
1439
+ }
1440
+ ),
1441
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Skip Order Review Page" })
1442
+ ] })
1443
+ }
1444
+ ),
1445
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Invoice prefix", children: /* @__PURE__ */ jsxRuntime.jsx(
1446
+ "input",
1447
+ {
1448
+ value: form.invoicePrefix,
1449
+ onChange: (e) => setForm((p) => ({ ...p, invoicePrefix: e.target.value })),
1450
+ 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",
1451
+ placeholder: "WC-"
1452
+ }
1453
+ ) }),
1454
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow$1, { label: "Credit Card Statement Name", children: /* @__PURE__ */ jsxRuntime.jsx(
1455
+ "input",
1456
+ {
1457
+ value: form.creditCardStatementName,
1458
+ onChange: (e) => setForm((p) => ({ ...p, creditCardStatementName: e.target.value })),
1459
+ 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",
1460
+ placeholder: "PayPal"
1461
+ }
1462
+ ) }),
1463
+ /* @__PURE__ */ jsxRuntime.jsx(
1464
+ FieldRow$1,
1465
+ {
1466
+ label: "Debug log",
1467
+ hint: /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1468
+ "Log PayPal events such as Webhook, Payment, Refund.",
1469
+ " ",
1470
+ form.logPath ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1471
+ "Log location: ",
1472
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: form.logPath })
1473
+ ] }) : null
1474
+ ] }),
1475
+ children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
1476
+ /* @__PURE__ */ jsxRuntime.jsx(
1477
+ "input",
1478
+ {
1479
+ type: "checkbox",
1480
+ checked: form.enableLogging,
1481
+ onChange: (e) => setForm((p) => ({ ...p, enableLogging: e.target.checked })),
1482
+ className: "h-4 w-4 rounded border-ui-border-base"
1483
+ }
1484
+ ),
1485
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable logging" })
1486
+ ] })
1487
+ }
1488
+ )
1489
+ ] })
1490
+ }
1491
+ )
1410
1492
  ] }) });
1411
1493
  }
1412
- function PayPalGooglePayPage() {
1413
- return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
1414
- }
1415
- function formatDate$1(value) {
1494
+ function formatDate(value) {
1416
1495
  if (!value) {
1417
- return "";
1496
+ return "";
1418
1497
  }
1419
1498
  const parsed = new Date(value);
1420
1499
  if (Number.isNaN(parsed.getTime())) {
@@ -1422,15 +1501,15 @@ function formatDate$1(value) {
1422
1501
  }
1423
1502
  return parsed.toLocaleString();
1424
1503
  }
1425
- function PayPalAuditLogsPage() {
1426
- const [logs, setLogs] = react.useState([]);
1504
+ function PayPalReconciliationStatusPage() {
1505
+ const [status, setStatus] = react.useState({});
1427
1506
  const [loading, setLoading] = react.useState(false);
1428
1507
  const [error, setError] = react.useState(null);
1429
- const fetchLogs = react.useCallback(async () => {
1508
+ const fetchStatus = react.useCallback(async () => {
1430
1509
  try {
1431
1510
  setLoading(true);
1432
1511
  setError(null);
1433
- const response = await fetch("/admin/paypal/audit-logs?limit=50", {
1512
+ const response = await fetch("/admin/paypal/reconciliation-status", {
1434
1513
  credentials: "include",
1435
1514
  headers: {
1436
1515
  Accept: "application/json"
@@ -1438,34 +1517,34 @@ function PayPalAuditLogsPage() {
1438
1517
  });
1439
1518
  if (!response.ok) {
1440
1519
  const message = await response.text().catch(() => "");
1441
- throw new Error(message || "Failed to load audit logs.");
1520
+ throw new Error(message || "Failed to load reconciliation status.");
1442
1521
  }
1443
1522
  const data = await response.json().catch(() => ({}));
1444
- setLogs((data == null ? void 0 : data.logs) || []);
1523
+ setStatus((data == null ? void 0 : data.status) || {});
1445
1524
  } catch (fetchError) {
1446
- setError((fetchError == null ? void 0 : fetchError.message) || "Failed to load audit logs.");
1447
- setLogs([]);
1525
+ setError((fetchError == null ? void 0 : fetchError.message) || "Failed to load reconciliation status.");
1526
+ setStatus({});
1448
1527
  } finally {
1449
1528
  setLoading(false);
1450
1529
  }
1451
1530
  }, []);
1452
1531
  react.useEffect(() => {
1453
- fetchLogs();
1454
- }, [fetchLogs]);
1532
+ fetchStatus();
1533
+ }, [fetchStatus]);
1455
1534
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
1456
1535
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1457
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Audit Logs" }),
1458
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-ui-fg-subtle", children: "Track administrative changes and credential events for PayPal configuration." })
1536
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Reconciliation Status" }),
1537
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-ui-fg-subtle", children: "Monitor reconciliation health and drift detection for PayPal payment sessions." })
1459
1538
  ] }),
1460
1539
  /* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
1461
1540
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
1462
1541
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-ui-border-base p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-4", children: [
1463
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Latest events" }),
1542
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Latest reconciliation run" }),
1464
1543
  /* @__PURE__ */ jsxRuntime.jsx(
1465
1544
  "button",
1466
1545
  {
1467
1546
  type: "button",
1468
- onClick: fetchLogs,
1547
+ onClick: fetchStatus,
1469
1548
  className: "rounded-md border border-ui-border-base px-3 py-2 text-sm text-ui-fg-base",
1470
1549
  disabled: loading,
1471
1550
  children: loading ? "Refreshing..." : "Refresh"
@@ -1474,19 +1553,50 @@ function PayPalAuditLogsPage() {
1474
1553
  ] }) }),
1475
1554
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4", children: [
1476
1555
  error ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-600", children: error }) : null,
1477
- !error && logs.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-ui-fg-subtle", children: loading ? "Loading audit logs..." : "No audit log entries found yet." }) : null,
1478
- logs.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full text-left text-sm", children: [
1479
- /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "text-ui-fg-muted", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1480
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "pb-2 pr-4 font-medium", children: "Timestamp" }),
1481
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "pb-2 pr-4 font-medium", children: "Event" }),
1482
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "pb-2 font-medium", children: "Details" })
1483
- ] }) }),
1484
- /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: logs.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-t border-ui-border-base", children: [
1485
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-3 pr-4 text-ui-fg-base", children: formatDate$1(entry.created_at) || "—" }),
1486
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-3 pr-4 text-ui-fg-base", children: entry.event_type || "—" }),
1487
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-3 text-ui-fg-subtle", children: /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "whitespace-pre-wrap rounded-md bg-ui-bg-subtle p-2 text-xs text-ui-fg-subtle", children: JSON.stringify(entry.metadata || {}, null, 2) }) })
1488
- ] }, entry.id)) })
1489
- ] }) }) : null
1556
+ !error && Object.keys(status).length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-ui-fg-subtle", children: loading ? "Loading reconciliation status..." : "No reconciliation data yet." }) : null,
1557
+ Object.keys(status).length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 text-sm text-ui-fg-base md:grid-cols-2", children: [
1558
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
1559
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last run" }),
1560
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_run_at) })
1561
+ ] }),
1562
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
1563
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last run status" }),
1564
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium capitalize", children: status.last_run_status || "—" })
1565
+ ] }),
1566
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
1567
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last success" }),
1568
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_success_at) })
1569
+ ] }),
1570
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
1571
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last failure" }),
1572
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_failure_at) })
1573
+ ] }),
1574
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
1575
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Sessions checked" }),
1576
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.sessions_checked ?? 0 })
1577
+ ] }),
1578
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
1579
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Sessions updated" }),
1580
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.sessions_updated ?? 0 })
1581
+ ] }),
1582
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
1583
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Drift detections" }),
1584
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.drift_count ?? 0 })
1585
+ ] }),
1586
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
1587
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last drift order" }),
1588
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.last_drift_order_id || "—" }),
1589
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-xs text-ui-fg-subtle", children: formatDate(status.last_drift_at) })
1590
+ ] }),
1591
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 md:col-span-2", children: [
1592
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last error" }),
1593
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.last_error || "No errors recorded." })
1594
+ ] }),
1595
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 md:col-span-2", children: [
1596
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Total runs" }),
1597
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.runs ?? 0 })
1598
+ ] })
1599
+ ] }) : null
1490
1600
  ] })
1491
1601
  ] })
1492
1602
  ] }) });
@@ -1931,116 +2041,6 @@ function PayPalSettingsTab() {
1931
2041
  )
1932
2042
  ] }) });
1933
2043
  }
1934
- function formatDate(value) {
1935
- if (!value) {
1936
- return "—";
1937
- }
1938
- const parsed = new Date(value);
1939
- if (Number.isNaN(parsed.getTime())) {
1940
- return value;
1941
- }
1942
- return parsed.toLocaleString();
1943
- }
1944
- function PayPalReconciliationStatusPage() {
1945
- const [status, setStatus] = react.useState({});
1946
- const [loading, setLoading] = react.useState(false);
1947
- const [error, setError] = react.useState(null);
1948
- const fetchStatus = react.useCallback(async () => {
1949
- try {
1950
- setLoading(true);
1951
- setError(null);
1952
- const response = await fetch("/admin/paypal/reconciliation-status", {
1953
- credentials: "include",
1954
- headers: {
1955
- Accept: "application/json"
1956
- }
1957
- });
1958
- if (!response.ok) {
1959
- const message = await response.text().catch(() => "");
1960
- throw new Error(message || "Failed to load reconciliation status.");
1961
- }
1962
- const data = await response.json().catch(() => ({}));
1963
- setStatus((data == null ? void 0 : data.status) || {});
1964
- } catch (fetchError) {
1965
- setError((fetchError == null ? void 0 : fetchError.message) || "Failed to load reconciliation status.");
1966
- setStatus({});
1967
- } finally {
1968
- setLoading(false);
1969
- }
1970
- }, []);
1971
- react.useEffect(() => {
1972
- fetchStatus();
1973
- }, [fetchStatus]);
1974
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
1975
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1976
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-ui-fg-base", children: "PayPal Reconciliation Status" }),
1977
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-ui-fg-subtle", children: "Monitor reconciliation health and drift detection for PayPal payment sessions." })
1978
- ] }),
1979
- /* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
1980
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: [
1981
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-ui-border-base p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-4", children: [
1982
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-ui-fg-base", children: "Latest reconciliation run" }),
1983
- /* @__PURE__ */ jsxRuntime.jsx(
1984
- "button",
1985
- {
1986
- type: "button",
1987
- onClick: fetchStatus,
1988
- className: "rounded-md border border-ui-border-base px-3 py-2 text-sm text-ui-fg-base",
1989
- disabled: loading,
1990
- children: loading ? "Refreshing..." : "Refresh"
1991
- }
1992
- )
1993
- ] }) }),
1994
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4", children: [
1995
- error ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-600", children: error }) : null,
1996
- !error && Object.keys(status).length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-ui-fg-subtle", children: loading ? "Loading reconciliation status..." : "No reconciliation data yet." }) : null,
1997
- Object.keys(status).length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 text-sm text-ui-fg-base md:grid-cols-2", children: [
1998
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
1999
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last run" }),
2000
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_run_at) })
2001
- ] }),
2002
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
2003
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last run status" }),
2004
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium capitalize", children: status.last_run_status || "—" })
2005
- ] }),
2006
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
2007
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last success" }),
2008
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_success_at) })
2009
- ] }),
2010
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
2011
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last failure" }),
2012
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: formatDate(status.last_failure_at) })
2013
- ] }),
2014
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
2015
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Sessions checked" }),
2016
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.sessions_checked ?? 0 })
2017
- ] }),
2018
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
2019
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Sessions updated" }),
2020
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.sessions_updated ?? 0 })
2021
- ] }),
2022
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
2023
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Drift detections" }),
2024
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.drift_count ?? 0 })
2025
- ] }),
2026
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3", children: [
2027
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last drift order" }),
2028
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.last_drift_order_id || "—" }),
2029
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-xs text-ui-fg-subtle", children: formatDate(status.last_drift_at) })
2030
- ] }),
2031
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 md:col-span-2", children: [
2032
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Last error" }),
2033
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.last_error || "No errors recorded." })
2034
- ] }),
2035
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 md:col-span-2", children: [
2036
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "Total runs" }),
2037
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 font-medium", children: status.runs ?? 0 })
2038
- ] })
2039
- ] }) : null
2040
- ] })
2041
- ] })
2042
- ] }) });
2043
- }
2044
2044
  const widgetModule = { widgets: [] };
2045
2045
  const routeModule = {
2046
2046
  routes: [
@@ -2052,29 +2052,33 @@ const routeModule = {
2052
2052
  Component: AdvancedCardPaymentsTab,
2053
2053
  path: "/settings/paypal/advanced-card-payments"
2054
2054
  },
2055
- {
2056
- Component: AdditionalSettingsTab,
2057
- path: "/settings/paypal/additional-settings"
2058
- },
2059
2055
  {
2060
2056
  Component: PayPalConnectionPage,
2061
2057
  path: "/settings/paypal/connection"
2062
2058
  },
2059
+ {
2060
+ Component: PayPalDisputesPage,
2061
+ path: "/settings/paypal/disputes"
2062
+ },
2063
2063
  {
2064
2064
  Component: PayPalApplePayPage,
2065
2065
  path: "/settings/paypal/apple-pay"
2066
2066
  },
2067
2067
  {
2068
- Component: PayPalDisputesPage,
2069
- path: "/settings/paypal/disputes"
2068
+ Component: PayPalAuditLogsPage,
2069
+ path: "/settings/paypal/audit-logs"
2070
2070
  },
2071
2071
  {
2072
2072
  Component: PayPalGooglePayPage,
2073
2073
  path: "/settings/paypal/google-pay"
2074
2074
  },
2075
2075
  {
2076
- Component: PayPalAuditLogsPage,
2077
- path: "/settings/paypal/audit-logs"
2076
+ Component: AdditionalSettingsTab,
2077
+ path: "/settings/paypal/additional-settings"
2078
+ },
2079
+ {
2080
+ Component: PayPalReconciliationStatusPage,
2081
+ path: "/settings/paypal/reconciliation-status"
2078
2082
  },
2079
2083
  {
2080
2084
  Component: PayPalPayLaterMessagingPage,
@@ -2083,10 +2087,6 @@ const routeModule = {
2083
2087
  {
2084
2088
  Component: PayPalSettingsTab,
2085
2089
  path: "/settings/paypal/paypal-settings"
2086
- },
2087
- {
2088
- Component: PayPalReconciliationStatusPage,
2089
- path: "/settings/paypal/reconciliation-status"
2090
2090
  }
2091
2091
  ]
2092
2092
  };