order-management 0.0.57 → 0.0.58

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.
@@ -370,6 +370,504 @@ const OrderRefundContextWidget = (props) => {
370
370
  adminSdk.defineWidgetConfig({
371
371
  zone: "order.details.after"
372
372
  });
373
+ const useDebounce$3 = (value, delay) => {
374
+ const [debouncedValue, setDebouncedValue] = react.useState(value);
375
+ react.useEffect(() => {
376
+ const handler = setTimeout(() => setDebouncedValue(value), delay);
377
+ return () => clearTimeout(handler);
378
+ }, [value, delay]);
379
+ return debouncedValue;
380
+ };
381
+ const getStatusBadgeClass$7 = (status) => {
382
+ const s = status.toLowerCase();
383
+ if (s === "captured" || s === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
384
+ if (s === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
385
+ if (s === "error" || s === "canceled" || s === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
386
+ if (s === "pending" || s === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
387
+ return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
388
+ };
389
+ const PaymentsPage = () => {
390
+ const navigate = reactRouterDom.useNavigate();
391
+ const [items, setItems] = react.useState([]);
392
+ const [statusFilter, setStatusFilter] = react.useState("all");
393
+ const [orderIdSearch, setOrderIdSearch] = react.useState("");
394
+ const debouncedOrderId = useDebounce$3(orderIdSearch, 300);
395
+ const [isLoading, setIsLoading] = react.useState(true);
396
+ const [isFetchingMore, setIsFetchingMore] = react.useState(false);
397
+ const [error, setError] = react.useState(null);
398
+ const [offset, setOffset] = react.useState(0);
399
+ const [count, setCount] = react.useState(0);
400
+ const limit = 50;
401
+ const loadTransactions = react.useCallback(
402
+ async (nextOffset, replace) => {
403
+ try {
404
+ if (replace) setIsLoading(true);
405
+ else setIsFetchingMore(true);
406
+ setError(null);
407
+ const params = new URLSearchParams();
408
+ params.set("limit", String(limit));
409
+ params.set("offset", String(nextOffset));
410
+ if (statusFilter !== "all") params.set("status", statusFilter);
411
+ if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
412
+ const response = await fetch(
413
+ `/admin/payment-transactions?${params.toString()}`,
414
+ { credentials: "include" }
415
+ );
416
+ if (!response.ok) {
417
+ const text = await response.text();
418
+ throw new Error(text || "Failed to load payment transactions");
419
+ }
420
+ const payload = await response.json();
421
+ const list = payload.transactions ?? [];
422
+ setCount(payload.count ?? 0);
423
+ setOffset(nextOffset + list.length);
424
+ setItems((prev) => replace ? list : [...prev, ...list]);
425
+ } catch (e) {
426
+ setError(e instanceof Error ? e.message : "Failed to load");
427
+ } finally {
428
+ setIsLoading(false);
429
+ setIsFetchingMore(false);
430
+ }
431
+ },
432
+ [statusFilter, debouncedOrderId]
433
+ );
434
+ react.useEffect(() => {
435
+ void loadTransactions(0, true);
436
+ }, [loadTransactions]);
437
+ const hasMore = react.useMemo(() => offset < count, [offset, count]);
438
+ const displayStatus = (t) => {
439
+ const s = t.payment_id != null && t.payment_status != null && t.payment_status !== "" ? t.payment_status : t.session_status ?? "";
440
+ return s !== "" ? s : "—";
441
+ };
442
+ const displayAmount = (t) => {
443
+ const num = Number(t.amount) / 100;
444
+ const code = (t.currency_code ?? "USD").toUpperCase();
445
+ return `${code} ${num.toFixed(2)}`;
446
+ };
447
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
448
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
449
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
450
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Payments" }),
451
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "All payment attempts — completed, pending, failed, requires action" })
452
+ ] }),
453
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => loadTransactions(0, true), children: "Refresh" })
454
+ ] }),
455
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
456
+ /* @__PURE__ */ jsxRuntime.jsx(
457
+ ui.Input,
458
+ {
459
+ placeholder: "Search by Order ID",
460
+ value: orderIdSearch,
461
+ onChange: (e) => setOrderIdSearch(e.target.value),
462
+ className: "md:max-w-sm",
463
+ "aria-label": "Search by order ID"
464
+ }
465
+ ),
466
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsxRuntime.jsxs(
467
+ "select",
468
+ {
469
+ value: statusFilter,
470
+ onChange: (e) => setStatusFilter(e.target.value),
471
+ className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-xs",
472
+ "aria-label": "Filter by status",
473
+ children: [
474
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All statuses" }),
475
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "pending", children: "Pending" }),
476
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "requires_more", children: "Requires more" }),
477
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "error", children: "Error" }),
478
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "canceled", children: "Canceled" }),
479
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "authorized", children: "Authorized" }),
480
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "captured", children: "Captured" })
481
+ ]
482
+ }
483
+ ) })
484
+ ] }),
485
+ error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
486
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
487
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => loadTransactions(0, true), children: "Try again" }) })
488
+ ] }) : null,
489
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading payments…" }) }) : items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
490
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No payment transactions yet" }),
491
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Payment attempts will appear here." })
492
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
493
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
494
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
495
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Amount" }),
496
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Provider" }),
497
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
498
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Finalized" }),
499
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
500
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
501
+ ] }) }),
502
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((t) => /* @__PURE__ */ jsxRuntime.jsxs(
503
+ "tr",
504
+ {
505
+ className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
506
+ onClick: () => navigate(`/payments/${t.payment_session_id}`),
507
+ children: [
508
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: t.order_id ?? "—" }),
509
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: displayAmount(t) }),
510
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.provider_id }),
511
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
512
+ ui.Badge,
513
+ {
514
+ size: "2xsmall",
515
+ className: `uppercase ${getStatusBadgeClass$7(displayStatus(t))}`,
516
+ children: displayStatus(t) !== "—" ? displayStatus(t).replace(/_/g, " ") : "—"
517
+ }
518
+ ) }),
519
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: t.payment_id != null ? "Yes" : "No" }),
520
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(t.created_at).toLocaleDateString("en-US", {
521
+ year: "numeric",
522
+ month: "short",
523
+ day: "numeric",
524
+ hour: "numeric",
525
+ minute: "2-digit",
526
+ hour12: true
527
+ }) }),
528
+ /* @__PURE__ */ jsxRuntime.jsxs("td", { className: "px-4 py-4", children: [
529
+ /* @__PURE__ */ jsxRuntime.jsx(
530
+ ui.Button,
531
+ {
532
+ variant: "transparent",
533
+ size: "small",
534
+ onClick: (e) => {
535
+ e.stopPropagation();
536
+ navigate(`/payments/${t.payment_session_id}`);
537
+ },
538
+ children: "View details"
539
+ }
540
+ ),
541
+ t.order_id ? /* @__PURE__ */ jsxRuntime.jsx(
542
+ ui.Button,
543
+ {
544
+ variant: "transparent",
545
+ size: "small",
546
+ onClick: (e) => {
547
+ e.stopPropagation();
548
+ navigate(`/orders/${t.order_id}`);
549
+ },
550
+ children: "Order"
551
+ }
552
+ ) : null
553
+ ] })
554
+ ]
555
+ },
556
+ t.payment_session_id
557
+ )) })
558
+ ] }) }),
559
+ hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
560
+ ui.Button,
561
+ {
562
+ variant: "secondary",
563
+ isLoading: isFetchingMore,
564
+ onClick: () => loadTransactions(offset, false),
565
+ children: "Load more"
566
+ }
567
+ ) }) : null
568
+ ] }) });
569
+ };
570
+ const config$7 = adminSdk.defineRouteConfig({
571
+ label: "Payments",
572
+ icon: icons.CreditCard
573
+ });
574
+ const useDebounce$2 = (value, delay) => {
575
+ const [debouncedValue, setDebouncedValue] = react.useState(value);
576
+ react.useEffect(() => {
577
+ const handler = setTimeout(() => setDebouncedValue(value), delay);
578
+ return () => clearTimeout(handler);
579
+ }, [value, delay]);
580
+ return debouncedValue;
581
+ };
582
+ const getStatusBadgeClass$6 = (status) => {
583
+ const s = status.toLowerCase();
584
+ if (s === "captured" || s === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
585
+ if (s === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
586
+ if (s === "error" || s === "canceled" || s === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
587
+ if (s === "pending" || s === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
588
+ return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
589
+ };
590
+ const RefundsPage = () => {
591
+ const navigate = reactRouterDom.useNavigate();
592
+ const [items, setItems] = react.useState([]);
593
+ const [orderIdSearch, setOrderIdSearch] = react.useState("");
594
+ const debouncedOrderId = useDebounce$2(orderIdSearch, 300);
595
+ const [paymentStatusFilter, setPaymentStatusFilter] = react.useState("all");
596
+ const [providerSearch, setProviderSearch] = react.useState("");
597
+ const debouncedProvider = useDebounce$2(providerSearch, 300);
598
+ const [currencySearch, setCurrencySearch] = react.useState("");
599
+ const debouncedCurrency = useDebounce$2(currencySearch, 300);
600
+ const [dateFrom, setDateFrom] = react.useState("");
601
+ const [dateTo, setDateTo] = react.useState("");
602
+ const [amountMin, setAmountMin] = react.useState("");
603
+ const [amountMax, setAmountMax] = react.useState("");
604
+ const [isLoading, setIsLoading] = react.useState(true);
605
+ const [isFetchingMore, setIsFetchingMore] = react.useState(false);
606
+ const [error, setError] = react.useState(null);
607
+ const [offset, setOffset] = react.useState(0);
608
+ const [count, setCount] = react.useState(0);
609
+ const limit = 50;
610
+ const loadRefunds = react.useCallback(
611
+ async (nextOffset, replace) => {
612
+ try {
613
+ if (replace) setIsLoading(true);
614
+ else setIsFetchingMore(true);
615
+ setError(null);
616
+ const params = new URLSearchParams();
617
+ params.set("limit", String(limit));
618
+ params.set("offset", String(nextOffset));
619
+ if (debouncedOrderId.trim()) params.set("order_id", debouncedOrderId.trim());
620
+ if (paymentStatusFilter !== "all") params.set("payment_status", paymentStatusFilter);
621
+ if (debouncedProvider.trim()) params.set("provider_id", debouncedProvider.trim());
622
+ if (debouncedCurrency.trim()) params.set("currency_code", debouncedCurrency.trim());
623
+ if (dateFrom.trim()) params.set("date_from", dateFrom.trim());
624
+ if (dateTo.trim()) params.set("date_to", dateTo.trim());
625
+ const min = amountMin.trim() ? Number(amountMin) : void 0;
626
+ const max = amountMax.trim() ? Number(amountMax) : void 0;
627
+ if (min != null && !Number.isNaN(min)) params.set("amount_min", String(min));
628
+ if (max != null && !Number.isNaN(max)) params.set("amount_max", String(max));
629
+ const response = await fetch(`/admin/refunds?${params.toString()}`, {
630
+ credentials: "include"
631
+ });
632
+ if (!response.ok) {
633
+ const text = await response.text();
634
+ throw new Error(text || "Failed to load refunds");
635
+ }
636
+ const payload = await response.json();
637
+ const list = payload.refunds ?? [];
638
+ setCount(payload.count ?? 0);
639
+ setOffset(nextOffset + list.length);
640
+ setItems((prev) => replace ? list : [...prev, ...list]);
641
+ } catch (e) {
642
+ setError(e instanceof Error ? e.message : "Failed to load");
643
+ } finally {
644
+ setIsLoading(false);
645
+ setIsFetchingMore(false);
646
+ }
647
+ },
648
+ [
649
+ debouncedOrderId,
650
+ paymentStatusFilter,
651
+ debouncedProvider,
652
+ debouncedCurrency,
653
+ dateFrom,
654
+ dateTo,
655
+ amountMin,
656
+ amountMax
657
+ ]
658
+ );
659
+ react.useEffect(() => {
660
+ void loadRefunds(0, true);
661
+ }, [loadRefunds]);
662
+ const hasMore = react.useMemo(() => offset < count, [offset, count]);
663
+ const displayAmount = (r) => {
664
+ const num = Number(r.amount) / 100;
665
+ const code = (r.currency_code ?? "USD").toUpperCase();
666
+ return `${code} ${num.toFixed(2)}`;
667
+ };
668
+ const displayStatus = (r) => {
669
+ const s = r.payment_status ?? "";
670
+ return s !== "" ? s : "—";
671
+ };
672
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
673
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
674
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
675
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Refunds" }),
676
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Refund records — amount, order, payment status" })
677
+ ] }),
678
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => loadRefunds(0, true), children: "Refresh" })
679
+ ] }),
680
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
681
+ /* @__PURE__ */ jsxRuntime.jsx(
682
+ ui.Input,
683
+ {
684
+ placeholder: "Order ID",
685
+ value: orderIdSearch,
686
+ onChange: (e) => setOrderIdSearch(e.target.value),
687
+ className: "md:max-w-[180px]",
688
+ "aria-label": "Filter by order ID"
689
+ }
690
+ ),
691
+ /* @__PURE__ */ jsxRuntime.jsx(
692
+ ui.Input,
693
+ {
694
+ placeholder: "Provider",
695
+ value: providerSearch,
696
+ onChange: (e) => setProviderSearch(e.target.value),
697
+ className: "md:max-w-[140px]",
698
+ "aria-label": "Filter by provider"
699
+ }
700
+ ),
701
+ /* @__PURE__ */ jsxRuntime.jsx(
702
+ ui.Input,
703
+ {
704
+ placeholder: "Currency",
705
+ value: currencySearch,
706
+ onChange: (e) => setCurrencySearch(e.target.value),
707
+ className: "md:max-w-[100px]",
708
+ "aria-label": "Filter by currency"
709
+ }
710
+ ),
711
+ /* @__PURE__ */ jsxRuntime.jsxs(
712
+ "select",
713
+ {
714
+ value: paymentStatusFilter,
715
+ onChange: (e) => setPaymentStatusFilter(e.target.value),
716
+ className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-[160px]",
717
+ "aria-label": "Filter by payment status",
718
+ children: [
719
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All statuses" }),
720
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "pending", children: "Pending" }),
721
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "requires_more", children: "Requires more" }),
722
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "error", children: "Error" }),
723
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "canceled", children: "Canceled" }),
724
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "authorized", children: "Authorized" }),
725
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "captured", children: "Captured" })
726
+ ]
727
+ }
728
+ ),
729
+ /* @__PURE__ */ jsxRuntime.jsx(
730
+ ui.Input,
731
+ {
732
+ type: "date",
733
+ placeholder: "From",
734
+ value: dateFrom,
735
+ onChange: (e) => setDateFrom(e.target.value),
736
+ className: "md:max-w-[140px]",
737
+ "aria-label": "Date from"
738
+ }
739
+ ),
740
+ /* @__PURE__ */ jsxRuntime.jsx(
741
+ ui.Input,
742
+ {
743
+ type: "date",
744
+ placeholder: "To",
745
+ value: dateTo,
746
+ onChange: (e) => setDateTo(e.target.value),
747
+ className: "md:max-w-[140px]",
748
+ "aria-label": "Date to"
749
+ }
750
+ ),
751
+ /* @__PURE__ */ jsxRuntime.jsx(
752
+ ui.Input,
753
+ {
754
+ placeholder: "Amount min",
755
+ value: amountMin,
756
+ onChange: (e) => setAmountMin(e.target.value),
757
+ type: "number",
758
+ min: 0,
759
+ className: "md:max-w-[100px]",
760
+ "aria-label": "Refund amount minimum"
761
+ }
762
+ ),
763
+ /* @__PURE__ */ jsxRuntime.jsx(
764
+ ui.Input,
765
+ {
766
+ placeholder: "Amount max",
767
+ value: amountMax,
768
+ onChange: (e) => setAmountMax(e.target.value),
769
+ type: "number",
770
+ min: 0,
771
+ className: "md:max-w-[100px]",
772
+ "aria-label": "Refund amount maximum"
773
+ }
774
+ )
775
+ ] }) }),
776
+ error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
777
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
778
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => loadRefunds(0, true), children: "Try again" }) })
779
+ ] }) : null,
780
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading refunds…" }) }) : items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
781
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No refunds yet" }),
782
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Refund records will appear here." })
783
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
784
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
785
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Refund ID" }),
786
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
787
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Payment ID" }),
788
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Amount" }),
789
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Currency" }),
790
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Provider" }),
791
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Payment Status" }),
792
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Note" }),
793
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
794
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
795
+ ] }) }),
796
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((r) => /* @__PURE__ */ jsxRuntime.jsxs(
797
+ "tr",
798
+ {
799
+ className: "cursor-pointer hover:bg-ui-bg-subtle/60",
800
+ onClick: () => navigate(`/refunds/${r.refund_id}`),
801
+ children: [
802
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-mono text-sm text-ui-fg-base", children: r.refund_id }),
803
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: r.order_id ?? "—" }),
804
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-mono text-sm text-ui-fg-subtle", children: r.payment_id }),
805
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: displayAmount(r) }),
806
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle uppercase", children: r.currency_code || "—" }),
807
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: r.provider_id || "—" }),
808
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
809
+ ui.Badge,
810
+ {
811
+ size: "2xsmall",
812
+ className: `uppercase ${getStatusBadgeClass$6(displayStatus(r))}`,
813
+ children: displayStatus(r) !== "—" ? displayStatus(r).replace(/_/g, " ") : "—"
814
+ }
815
+ ) }),
816
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "max-w-[160px] truncate px-4 py-4 text-ui-fg-subtle", title: r.note ?? void 0, children: r.note ?? "—" }),
817
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(r.created_at).toLocaleDateString("en-US", {
818
+ year: "numeric",
819
+ month: "short",
820
+ day: "numeric",
821
+ hour: "numeric",
822
+ minute: "2-digit",
823
+ hour12: true
824
+ }) }),
825
+ /* @__PURE__ */ jsxRuntime.jsxs("td", { className: "px-4 py-4", children: [
826
+ /* @__PURE__ */ jsxRuntime.jsx(
827
+ ui.Button,
828
+ {
829
+ variant: "transparent",
830
+ size: "small",
831
+ onClick: (e) => {
832
+ e.stopPropagation();
833
+ navigate(`/refunds/${r.refund_id}`);
834
+ },
835
+ children: "View details"
836
+ }
837
+ ),
838
+ r.order_id ? /* @__PURE__ */ jsxRuntime.jsx(
839
+ ui.Button,
840
+ {
841
+ variant: "transparent",
842
+ size: "small",
843
+ onClick: (e) => {
844
+ e.stopPropagation();
845
+ navigate(`/orders/${r.order_id}`);
846
+ },
847
+ children: "Order"
848
+ }
849
+ ) : null
850
+ ] })
851
+ ]
852
+ },
853
+ r.refund_id
854
+ )) })
855
+ ] }) }),
856
+ hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
857
+ ui.Button,
858
+ {
859
+ variant: "secondary",
860
+ isLoading: isFetchingMore,
861
+ onClick: () => loadRefunds(offset, false),
862
+ children: "Load more"
863
+ }
864
+ ) }) : null
865
+ ] }) });
866
+ };
867
+ const config$6 = adminSdk.defineRouteConfig({
868
+ label: "Refunds",
869
+ icon: icons.Receipt
870
+ });
373
871
  const useDebounce$1 = (value, delay) => {
374
872
  const [debouncedValue, setDebouncedValue] = react.useState(value);
375
873
  react.useEffect(() => {
@@ -378,7 +876,7 @@ const useDebounce$1 = (value, delay) => {
378
876
  }, [value, delay]);
379
877
  return debouncedValue;
380
878
  };
381
- const getStatusBadgeClass$3 = (status) => {
879
+ const getStatusBadgeClass$5 = (status) => {
382
880
  const statusLower = status.toLowerCase();
383
881
  if (statusLower === "requested") {
384
882
  return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
@@ -549,7 +1047,7 @@ const ReturnsPage = () => {
549
1047
  ui.Badge,
550
1048
  {
551
1049
  size: "2xsmall",
552
- className: `uppercase ${getStatusBadgeClass$3(returnOrder.status)}`,
1050
+ className: `uppercase ${getStatusBadgeClass$5(returnOrder.status)}`,
553
1051
  children: returnOrder.status.replace(/_/g, " ")
554
1052
  }
555
1053
  ) }),
@@ -598,7 +1096,7 @@ const ReturnsPage = () => {
598
1096
  ) }) : null
599
1097
  ] }) });
600
1098
  };
601
- const config$3 = adminSdk.defineRouteConfig({
1099
+ const config$5 = adminSdk.defineRouteConfig({
602
1100
  label: "Return Orders",
603
1101
  icon: icons.ArrowPath
604
1102
  });
@@ -610,7 +1108,7 @@ const useDebounce = (value, delay) => {
610
1108
  }, [value, delay]);
611
1109
  return debouncedValue;
612
1110
  };
613
- const getStatusBadgeClass$2 = (status) => {
1111
+ const getStatusBadgeClass$4 = (status) => {
614
1112
  const statusLower = status.toLowerCase();
615
1113
  if (statusLower === "requested") {
616
1114
  return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
@@ -778,7 +1276,7 @@ const SwapsPage = () => {
778
1276
  ui.Badge,
779
1277
  {
780
1278
  size: "2xsmall",
781
- className: `uppercase ${getStatusBadgeClass$2(swap.status)}`,
1279
+ className: `uppercase ${getStatusBadgeClass$4(swap.status)}`,
782
1280
  children: swap.status.replace(/_/g, " ")
783
1281
  }
784
1282
  ) }),
@@ -828,10 +1326,321 @@ const SwapsPage = () => {
828
1326
  ) }) : null
829
1327
  ] }) });
830
1328
  };
831
- const config$2 = adminSdk.defineRouteConfig({
1329
+ const config$4 = adminSdk.defineRouteConfig({
832
1330
  label: "Exchanges",
833
1331
  icon: icons.ArrowPath
834
1332
  });
1333
+ const getStatusBadgeClass$3 = (status) => {
1334
+ const s = status.toLowerCase();
1335
+ if (s === "captured" || s === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
1336
+ if (s === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
1337
+ if (s === "error" || s === "canceled" || s === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
1338
+ if (s === "pending" || s === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
1339
+ return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
1340
+ };
1341
+ const PaymentDetailPage = () => {
1342
+ var _a;
1343
+ const navigate = reactRouterDom.useNavigate();
1344
+ const params = reactRouterDom.useParams();
1345
+ const id = (_a = params == null ? void 0 : params.id) == null ? void 0 : _a.trim();
1346
+ const [detail, setDetail] = react.useState(null);
1347
+ const [loading, setLoading] = react.useState(!!id);
1348
+ const [error, setError] = react.useState(null);
1349
+ react.useEffect(() => {
1350
+ if (!id) {
1351
+ setLoading(false);
1352
+ return;
1353
+ }
1354
+ let cancelled = false;
1355
+ setLoading(true);
1356
+ setError(null);
1357
+ fetch(`/admin/payment-transactions/${id}`, { credentials: "include" }).then((res) => {
1358
+ if (!res.ok) throw new Error(res.statusText || "Failed to load");
1359
+ return res.json();
1360
+ }).then((data) => {
1361
+ if (!cancelled) setDetail(data);
1362
+ }).catch((e) => {
1363
+ if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
1364
+ }).finally(() => {
1365
+ if (!cancelled) setLoading(false);
1366
+ });
1367
+ return () => {
1368
+ cancelled = true;
1369
+ };
1370
+ }, [id]);
1371
+ const displayStatus = detail ? (detail.payment_id != null && detail.payment_status != null && detail.payment_status !== "" ? detail.payment_status : detail.session_status ?? "") || "—" : "";
1372
+ const sessionStatusRaw = (detail == null ? void 0 : detail.session_status) ?? "—";
1373
+ const paymentStatusRaw = (detail == null ? void 0 : detail.payment_id) != null ? (detail == null ? void 0 : detail.payment_status) ?? "—" : "—";
1374
+ const displayAmount = detail ? `${(detail.currency_code ?? "USD").toUpperCase()} ${(Number(detail.amount) / 100).toFixed(2)}` : "";
1375
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-4xl flex-col gap-6 p-6", children: [
1376
+ /* @__PURE__ */ jsxRuntime.jsx("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
1377
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => navigate("/payments"), children: "← Payments" }),
1378
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Payment session" }),
1379
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: id ?? "—" })
1380
+ ] }) }),
1381
+ error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
1382
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
1383
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/payments"), children: "Back to list" })
1384
+ ] }) : loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading…" }) }) : detail ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
1385
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-ui-border-base p-6 flex flex-col gap-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
1386
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1387
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Order ID" }),
1388
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: detail.order_id ? /* @__PURE__ */ jsxRuntime.jsx(
1389
+ ui.Button,
1390
+ {
1391
+ variant: "transparent",
1392
+ size: "small",
1393
+ onClick: () => navigate(`/orders/${detail.order_id}`),
1394
+ children: detail.order_id
1395
+ }
1396
+ ) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "—" }) })
1397
+ ] }),
1398
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1399
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
1400
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: displayAmount })
1401
+ ] }),
1402
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1403
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
1404
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.provider_id })
1405
+ ] }),
1406
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1407
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
1408
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
1409
+ ui.Badge,
1410
+ {
1411
+ size: "2xsmall",
1412
+ className: `uppercase ${getStatusBadgeClass$3(displayStatus)}`,
1413
+ children: displayStatus !== "—" ? displayStatus.replace(/_/g, " ") : "—"
1414
+ }
1415
+ ) })
1416
+ ] }),
1417
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1418
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Session status (DB)" }),
1419
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: sessionStatusRaw })
1420
+ ] }),
1421
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1422
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Payment status (DB)" }),
1423
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: paymentStatusRaw })
1424
+ ] }),
1425
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1426
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Finalized" }),
1427
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.payment_id != null ? "Yes" : "No" })
1428
+ ] }),
1429
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1430
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created" }),
1431
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: new Date(detail.created_at).toLocaleDateString("en-US", {
1432
+ year: "numeric",
1433
+ month: "short",
1434
+ day: "numeric",
1435
+ hour: "numeric",
1436
+ minute: "2-digit",
1437
+ hour12: true
1438
+ }) })
1439
+ ] })
1440
+ ] }) }),
1441
+ Object.keys(detail.data ?? {}).length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
1442
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Provider data" }),
1443
+ /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-xs bg-ui-bg-subtle p-4 rounded-lg overflow-auto max-h-96", children: JSON.stringify(detail.data, null, 2) })
1444
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-ui-border-base p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No provider data for this session." }) })
1445
+ ] }) : null
1446
+ ] }) });
1447
+ };
1448
+ const config$3 = adminSdk.defineRouteConfig({
1449
+ label: "Payment details",
1450
+ icon: icons.CreditCard
1451
+ });
1452
+ const getStatusBadgeClass$2 = (status) => {
1453
+ const s = status.toLowerCase();
1454
+ if (s === "captured" || s === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
1455
+ if (s === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
1456
+ if (s === "error" || s === "canceled" || s === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
1457
+ if (s === "pending" || s === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
1458
+ return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
1459
+ };
1460
+ const formatAmount = (value) => {
1461
+ return (value / 100).toFixed(2);
1462
+ };
1463
+ const RefundDetailPage = () => {
1464
+ var _a, _b, _c;
1465
+ const navigate = reactRouterDom.useNavigate();
1466
+ const params = reactRouterDom.useParams();
1467
+ const id = (_a = params == null ? void 0 : params.id) == null ? void 0 : _a.trim();
1468
+ const [detail, setDetail] = react.useState(null);
1469
+ const [loading, setLoading] = react.useState(!!id);
1470
+ const [error, setError] = react.useState(null);
1471
+ const [gatewayExpanded, setGatewayExpanded] = react.useState(false);
1472
+ react.useEffect(() => {
1473
+ if (!id) {
1474
+ setLoading(false);
1475
+ return;
1476
+ }
1477
+ let cancelled = false;
1478
+ setLoading(true);
1479
+ setError(null);
1480
+ fetch(`/admin/refunds/${id}`, { credentials: "include" }).then((res) => {
1481
+ if (!res.ok) throw new Error(res.statusText || "Failed to load");
1482
+ return res.json();
1483
+ }).then((data) => {
1484
+ if (!cancelled) setDetail(data);
1485
+ }).catch((e) => {
1486
+ if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
1487
+ }).finally(() => {
1488
+ if (!cancelled) setLoading(false);
1489
+ });
1490
+ return () => {
1491
+ cancelled = true;
1492
+ };
1493
+ }, [id]);
1494
+ const paymentStatus = ((_b = detail == null ? void 0 : detail.payment) == null ? void 0 : _b.status) ?? "—";
1495
+ const hasGatewayData = ((_c = detail == null ? void 0 : detail.payment) == null ? void 0 : _c.payment_data) && typeof detail.payment.payment_data === "object" && Object.keys(detail.payment.payment_data).length > 0;
1496
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-4xl flex-col gap-6 p-6", children: [
1497
+ /* @__PURE__ */ jsxRuntime.jsx("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
1498
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => navigate("/refunds"), children: "← Refunds" }),
1499
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Refund details" }),
1500
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle font-mono", children: id ?? "—" })
1501
+ ] }) }),
1502
+ error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
1503
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
1504
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/refunds"), children: "Back to list" })
1505
+ ] }) : loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading…" }) }) : detail ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
1506
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
1507
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Refund summary" }),
1508
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
1509
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1510
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund ID" }),
1511
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.id })
1512
+ ] }),
1513
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1514
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
1515
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.refund.amount) })
1516
+ ] }),
1517
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1518
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Note" }),
1519
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.refund.note ?? "—" })
1520
+ ] }),
1521
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1522
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created at" }),
1523
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: new Date(detail.refund.created_at).toLocaleDateString("en-US", {
1524
+ year: "numeric",
1525
+ month: "short",
1526
+ day: "numeric",
1527
+ hour: "numeric",
1528
+ minute: "2-digit",
1529
+ hour12: true
1530
+ }) })
1531
+ ] }),
1532
+ detail.refund.created_by ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1533
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created by" }),
1534
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.created_by })
1535
+ ] }) : null
1536
+ ] })
1537
+ ] }),
1538
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
1539
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Payment summary" }),
1540
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
1541
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1542
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Payment amount" }),
1543
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.payment_amount) })
1544
+ ] }),
1545
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1546
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Captured amount" }),
1547
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.captured_amount) })
1548
+ ] }),
1549
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1550
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refunded amount" }),
1551
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.refunded_amount) })
1552
+ ] }),
1553
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1554
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
1555
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.payment.provider_id || "—" })
1556
+ ] }),
1557
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1558
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
1559
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
1560
+ ui.Badge,
1561
+ {
1562
+ size: "2xsmall",
1563
+ className: `uppercase ${getStatusBadgeClass$2(paymentStatus)}`,
1564
+ children: paymentStatus !== "—" ? paymentStatus.replace(/_/g, " ") : "—"
1565
+ }
1566
+ ) })
1567
+ ] }),
1568
+ detail.computed ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1569
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1570
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Full refund" }),
1571
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.computed.is_full_refund ? "Yes" : "No" })
1572
+ ] }),
1573
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1574
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Remaining refundable" }),
1575
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.computed.remaining_refundable_amount) })
1576
+ ] }),
1577
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1578
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund %" }),
1579
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "mt-1 block", children: [
1580
+ detail.computed.refund_percentage.toFixed(1),
1581
+ "%"
1582
+ ] })
1583
+ ] })
1584
+ ] }) : null
1585
+ ] })
1586
+ ] }),
1587
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
1588
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Order summary" }),
1589
+ detail.order ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
1590
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1591
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Order" }),
1592
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
1593
+ ui.Button,
1594
+ {
1595
+ variant: "transparent",
1596
+ size: "small",
1597
+ onClick: () => navigate(`/orders/${detail.order.order_id}`),
1598
+ children: detail.order.order_number ?? detail.order.order_id
1599
+ }
1600
+ ) })
1601
+ ] }),
1602
+ detail.order.total != null ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1603
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Total" }),
1604
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.order.total) })
1605
+ ] }) : null,
1606
+ detail.order.customer_id ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1607
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Customer ID" }),
1608
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.order.customer_id })
1609
+ ] }) : null,
1610
+ detail.order.region ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1611
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Region" }),
1612
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.region })
1613
+ ] }) : null,
1614
+ detail.order.fulfillment_status ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1615
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Fulfillment status" }),
1616
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.fulfillment_status })
1617
+ ] }) : null
1618
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No order linked to this refund." })
1619
+ ] }),
1620
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
1621
+ /* @__PURE__ */ jsxRuntime.jsxs(
1622
+ "button",
1623
+ {
1624
+ type: "button",
1625
+ className: "flex w-full items-center justify-between text-left",
1626
+ onClick: () => setGatewayExpanded((prev) => !prev),
1627
+ "aria-expanded": gatewayExpanded,
1628
+ "aria-label": gatewayExpanded ? "Collapse gateway data" : "Expand gateway data",
1629
+ children: [
1630
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg", children: "Gateway data" }),
1631
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: gatewayExpanded ? "Collapse" : "Expand" })
1632
+ ]
1633
+ }
1634
+ ),
1635
+ gatewayExpanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4", children: hasGatewayData ? /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-xs bg-ui-bg-subtle p-4 rounded-lg overflow-auto max-h-96", children: JSON.stringify(detail.payment.payment_data, null, 2) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No gateway payload for this payment." }) })
1636
+ ] })
1637
+ ] }) : null
1638
+ ] }) });
1639
+ };
1640
+ const config$2 = adminSdk.defineRouteConfig({
1641
+ label: "Refund details",
1642
+ icon: icons.Receipt
1643
+ });
835
1644
  const getStatusBadgeClass$1 = (status) => {
836
1645
  const statusLower = status.toLowerCase();
837
1646
  if (statusLower === "requested") {
@@ -1398,6 +2207,14 @@ const widgetModule = { widgets: [
1398
2207
  ] };
1399
2208
  const routeModule = {
1400
2209
  routes: [
2210
+ {
2211
+ Component: PaymentsPage,
2212
+ path: "/payments"
2213
+ },
2214
+ {
2215
+ Component: RefundsPage,
2216
+ path: "/refunds"
2217
+ },
1401
2218
  {
1402
2219
  Component: ReturnsPage,
1403
2220
  path: "/returns"
@@ -1406,6 +2223,14 @@ const routeModule = {
1406
2223
  Component: SwapsPage,
1407
2224
  path: "/swaps"
1408
2225
  },
2226
+ {
2227
+ Component: PaymentDetailPage,
2228
+ path: "/payments/:id"
2229
+ },
2230
+ {
2231
+ Component: RefundDetailPage,
2232
+ path: "/refunds/:id"
2233
+ },
1409
2234
  {
1410
2235
  Component: ReturnDetailPage,
1411
2236
  path: "/returns/:id"
@@ -1419,17 +2244,35 @@ const routeModule = {
1419
2244
  const menuItemModule = {
1420
2245
  menuItems: [
1421
2246
  {
1422
- label: config$3.label,
1423
- icon: config$3.icon,
2247
+ label: config$7.label,
2248
+ icon: config$7.icon,
2249
+ path: "/payments",
2250
+ nested: void 0
2251
+ },
2252
+ {
2253
+ label: config$5.label,
2254
+ icon: config$5.icon,
1424
2255
  path: "/returns",
1425
2256
  nested: void 0
1426
2257
  },
1427
2258
  {
1428
- label: config$2.label,
1429
- icon: config$2.icon,
2259
+ label: config$4.label,
2260
+ icon: config$4.icon,
1430
2261
  path: "/swaps",
1431
2262
  nested: void 0
1432
2263
  },
2264
+ {
2265
+ label: config$6.label,
2266
+ icon: config$6.icon,
2267
+ path: "/refunds",
2268
+ nested: void 0
2269
+ },
2270
+ {
2271
+ label: config$3.label,
2272
+ icon: config$3.icon,
2273
+ path: "/payments/:id",
2274
+ nested: void 0
2275
+ },
1433
2276
  {
1434
2277
  label: config$1.label,
1435
2278
  icon: config$1.icon,
@@ -1441,6 +2284,12 @@ const menuItemModule = {
1441
2284
  icon: config.icon,
1442
2285
  path: "/swaps/:id",
1443
2286
  nested: void 0
2287
+ },
2288
+ {
2289
+ label: config$2.label,
2290
+ icon: config$2.icon,
2291
+ path: "/refunds/:id",
2292
+ nested: void 0
1444
2293
  }
1445
2294
  ]
1446
2295
  };