@easypayment/medusa-paypal 0.2.6 → 0.2.7

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