@doujins/payments-ui 0.1.15 → 0.1.17-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1137 -371
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +306 -68
- package/dist/index.d.ts +306 -68
- package/dist/index.js +975 -213
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import
|
|
1
|
+
import * as React4 from 'react';
|
|
2
|
+
import React4__default, { createContext, useMemo, useState, useEffect, useCallback, useRef, useContext } from 'react';
|
|
3
3
|
import { useQueryClient, useQuery, useMutation, QueryClient, QueryClientProvider, useInfiniteQuery } from '@tanstack/react-query';
|
|
4
4
|
import { ConnectionProvider, WalletProvider, useWallet, useConnection } from '@solana/wallet-adapter-react';
|
|
5
5
|
import { WalletModalProvider } from '@solana/wallet-adapter-react-ui';
|
|
@@ -11,7 +11,7 @@ import { SolflareWalletAdapter } from '@solana/wallet-adapter-solflare';
|
|
|
11
11
|
import { TrustWalletAdapter } from '@solana/wallet-adapter-trust';
|
|
12
12
|
import { CoinbaseWalletAdapter } from '@solana/wallet-adapter-coinbase';
|
|
13
13
|
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
14
|
-
import { ChevronDown, ChevronUp, Check, Loader2, CheckCircle, AlertCircle, Wallet, Ban, TriangleAlert, CreditCard, Trash2, Shield, UserRound, Calendar, KeyRound, XIcon, XCircle, RotateCcw
|
|
14
|
+
import { ChevronDown, ChevronUp, Check, Pencil, Loader2, CheckCircle, AlertCircle, Wallet, Ban, TriangleAlert, CreditCard, Trash2, WalletCards, RefreshCw, Shield, UserRound, Calendar, KeyRound, XIcon, XCircle, RotateCcw } from 'lucide-react';
|
|
15
15
|
import clsx2, { clsx } from 'clsx';
|
|
16
16
|
import { twMerge } from 'tailwind-merge';
|
|
17
17
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
@@ -248,6 +248,7 @@ var createClient = (config) => {
|
|
|
248
248
|
return normalizeList(result);
|
|
249
249
|
},
|
|
250
250
|
createPaymentMethod(payload) {
|
|
251
|
+
console.log("Creating payment method with payload:", payload);
|
|
251
252
|
return request("POST", "/me/payment-methods", {
|
|
252
253
|
body: payload
|
|
253
254
|
});
|
|
@@ -265,10 +266,10 @@ var createClient = (config) => {
|
|
|
265
266
|
},
|
|
266
267
|
checkout(payload, idempotencyKey) {
|
|
267
268
|
const key = idempotencyKey ?? crypto.randomUUID();
|
|
268
|
-
return request("POST", "/
|
|
269
|
+
return request("POST", "/checkout", {
|
|
269
270
|
body: payload,
|
|
270
271
|
headers: {
|
|
271
|
-
"Idempotency-Key": key
|
|
272
|
+
"X-Idempotency-Key": key
|
|
272
273
|
}
|
|
273
274
|
});
|
|
274
275
|
},
|
|
@@ -277,6 +278,36 @@ var createClient = (config) => {
|
|
|
277
278
|
body: feedback ? { feedback } : void 0
|
|
278
279
|
});
|
|
279
280
|
},
|
|
281
|
+
async listSubscriptions(params) {
|
|
282
|
+
const result = await request(
|
|
283
|
+
"GET",
|
|
284
|
+
"/me/subscriptions",
|
|
285
|
+
{
|
|
286
|
+
query: {
|
|
287
|
+
status: params?.status,
|
|
288
|
+
limit: params?.limit,
|
|
289
|
+
offset: params?.offset
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
);
|
|
293
|
+
return normalizeList(result);
|
|
294
|
+
},
|
|
295
|
+
updateSubscriptionPaymentMethod(payload) {
|
|
296
|
+
return request("PUT", "/me/subscriptions/payment-method", {
|
|
297
|
+
body: {
|
|
298
|
+
subscription_id: payload.subscription_id,
|
|
299
|
+
payment_method_id: payload.payment_method_id
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
},
|
|
303
|
+
resumeSubscription() {
|
|
304
|
+
return request("POST", "/me/subscriptions/resume");
|
|
305
|
+
},
|
|
306
|
+
changeSubscription(payload) {
|
|
307
|
+
return request("POST", "/me/subscriptions/change", {
|
|
308
|
+
body: payload
|
|
309
|
+
});
|
|
310
|
+
},
|
|
280
311
|
async getPaymentHistory(params) {
|
|
281
312
|
const result = await request("GET", "/me/payments", {
|
|
282
313
|
query: {
|
|
@@ -422,6 +453,19 @@ function DialogHeader({ className, ...props }) {
|
|
|
422
453
|
}
|
|
423
454
|
);
|
|
424
455
|
}
|
|
456
|
+
function DialogFooter({ className, ...props }) {
|
|
457
|
+
return /* @__PURE__ */ jsx(
|
|
458
|
+
"div",
|
|
459
|
+
{
|
|
460
|
+
"data-slot": "dialog-footer",
|
|
461
|
+
className: cn(
|
|
462
|
+
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
|
463
|
+
className
|
|
464
|
+
),
|
|
465
|
+
...props
|
|
466
|
+
}
|
|
467
|
+
);
|
|
468
|
+
}
|
|
425
469
|
function DialogTitle({
|
|
426
470
|
className,
|
|
427
471
|
...props
|
|
@@ -488,7 +532,7 @@ var buttonVariants = cva(
|
|
|
488
532
|
}
|
|
489
533
|
}
|
|
490
534
|
);
|
|
491
|
-
var Button =
|
|
535
|
+
var Button = React4.forwardRef(
|
|
492
536
|
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
493
537
|
const Comp = asChild ? Slot : "button";
|
|
494
538
|
return /* @__PURE__ */ jsx(
|
|
@@ -502,7 +546,7 @@ var Button = React15.forwardRef(
|
|
|
502
546
|
}
|
|
503
547
|
);
|
|
504
548
|
Button.displayName = "Button";
|
|
505
|
-
var Input =
|
|
549
|
+
var Input = React4.forwardRef(
|
|
506
550
|
({ className, type, ...props }, ref) => {
|
|
507
551
|
return /* @__PURE__ */ jsx(
|
|
508
552
|
"input",
|
|
@@ -522,7 +566,7 @@ Input.displayName = "Input";
|
|
|
522
566
|
var labelVariants = cva(
|
|
523
567
|
"text-sm font-medium leading-none text-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
|
524
568
|
);
|
|
525
|
-
var Label =
|
|
569
|
+
var Label = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
526
570
|
LabelPrimitive.Root,
|
|
527
571
|
{
|
|
528
572
|
ref,
|
|
@@ -531,9 +575,9 @@ var Label = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
|
|
|
531
575
|
}
|
|
532
576
|
));
|
|
533
577
|
Label.displayName = LabelPrimitive.Root.displayName;
|
|
534
|
-
var Select =
|
|
578
|
+
var Select = SelectPrimitive.Root;
|
|
535
579
|
var SelectValue = SelectPrimitive.Value;
|
|
536
|
-
var SelectTrigger =
|
|
580
|
+
var SelectTrigger = React4.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
537
581
|
SelectPrimitive.Trigger,
|
|
538
582
|
{
|
|
539
583
|
ref,
|
|
@@ -549,7 +593,7 @@ var SelectTrigger = React15.forwardRef(({ className, children, ...props }, ref)
|
|
|
549
593
|
}
|
|
550
594
|
));
|
|
551
595
|
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
552
|
-
var SelectScrollUpButton =
|
|
596
|
+
var SelectScrollUpButton = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
553
597
|
SelectPrimitive.ScrollUpButton,
|
|
554
598
|
{
|
|
555
599
|
ref,
|
|
@@ -562,7 +606,7 @@ var SelectScrollUpButton = React15.forwardRef(({ className, ...props }, ref) =>
|
|
|
562
606
|
}
|
|
563
607
|
));
|
|
564
608
|
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
|
565
|
-
var SelectScrollDownButton =
|
|
609
|
+
var SelectScrollDownButton = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
566
610
|
SelectPrimitive.ScrollDownButton,
|
|
567
611
|
{
|
|
568
612
|
ref,
|
|
@@ -575,39 +619,61 @@ var SelectScrollDownButton = React15.forwardRef(({ className, ...props }, ref) =
|
|
|
575
619
|
}
|
|
576
620
|
));
|
|
577
621
|
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
|
|
578
|
-
var SelectContent =
|
|
579
|
-
(
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
...props
|
|
587
|
-
}, ref) => {
|
|
588
|
-
const popperProps = position === "popper" ? { side, sideOffset, align } : {};
|
|
589
|
-
return /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
|
|
590
|
-
SelectPrimitive.Content,
|
|
591
|
-
{
|
|
592
|
-
ref,
|
|
593
|
-
className: cn(
|
|
594
|
-
"z-[200] max-h-64 w-[var(--radix-select-trigger-width)] overflow-y-auto overflow-x-hidden rounded-md border border-white/20 bg-background-regular text-foreground shadow-lg backdrop-blur-xl data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
595
|
-
className
|
|
596
|
-
),
|
|
597
|
-
position,
|
|
598
|
-
...popperProps,
|
|
599
|
-
...props,
|
|
600
|
-
children: [
|
|
601
|
-
/* @__PURE__ */ jsx(SelectScrollUpButton, {}),
|
|
602
|
-
/* @__PURE__ */ jsx(SelectPrimitive.Viewport, { className: "p-1", children }),
|
|
603
|
-
/* @__PURE__ */ jsx(SelectScrollDownButton, {})
|
|
604
|
-
]
|
|
622
|
+
var SelectContent = React4.forwardRef(({ className, children, position = "popper", ...props }, ref) => {
|
|
623
|
+
const viewportRef = React4.useRef(null);
|
|
624
|
+
const contentRef = React4.useCallback((node) => {
|
|
625
|
+
if (node) {
|
|
626
|
+
node.style.setProperty("max-height", "40vh", "important");
|
|
627
|
+
const anchorWidth = window.getComputedStyle(node).getPropertyValue("--radix-popper-anchor-width");
|
|
628
|
+
if (anchorWidth) {
|
|
629
|
+
node.style.setProperty("width", anchorWidth, "important");
|
|
605
630
|
}
|
|
606
|
-
|
|
607
|
-
}
|
|
608
|
-
)
|
|
631
|
+
}
|
|
632
|
+
}, []);
|
|
633
|
+
const combinedRef = React4.useCallback((node) => {
|
|
634
|
+
contentRef(node);
|
|
635
|
+
if (typeof ref === "function") {
|
|
636
|
+
ref(node);
|
|
637
|
+
} else if (ref) {
|
|
638
|
+
ref.current = node;
|
|
639
|
+
}
|
|
640
|
+
}, [contentRef, ref]);
|
|
641
|
+
React4.useEffect(() => {
|
|
642
|
+
if (viewportRef.current) {
|
|
643
|
+
viewportRef.current.style.setProperty("max-height", "40vh", "important");
|
|
644
|
+
}
|
|
645
|
+
});
|
|
646
|
+
return /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
|
|
647
|
+
SelectPrimitive.Content,
|
|
648
|
+
{
|
|
649
|
+
ref: combinedRef,
|
|
650
|
+
className: cn(
|
|
651
|
+
"relative z-50 min-w-[8rem] overflow-hidden rounded-md border border-white/20 bg-background-regular text-foreground shadow-lg backdrop-blur-xl data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
652
|
+
position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
653
|
+
className
|
|
654
|
+
),
|
|
655
|
+
position,
|
|
656
|
+
...props,
|
|
657
|
+
children: [
|
|
658
|
+
/* @__PURE__ */ jsx(SelectScrollUpButton, {}),
|
|
659
|
+
/* @__PURE__ */ jsx(
|
|
660
|
+
SelectPrimitive.Viewport,
|
|
661
|
+
{
|
|
662
|
+
ref: viewportRef,
|
|
663
|
+
className: cn(
|
|
664
|
+
"p-1 overflow-y-auto",
|
|
665
|
+
position === "popper" && "w-full min-w-[var(--radix-select-trigger-width)]"
|
|
666
|
+
),
|
|
667
|
+
children
|
|
668
|
+
}
|
|
669
|
+
),
|
|
670
|
+
/* @__PURE__ */ jsx(SelectScrollDownButton, {})
|
|
671
|
+
]
|
|
672
|
+
}
|
|
673
|
+
) });
|
|
674
|
+
});
|
|
609
675
|
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
610
|
-
var SelectLabel =
|
|
676
|
+
var SelectLabel = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
611
677
|
SelectPrimitive.Label,
|
|
612
678
|
{
|
|
613
679
|
ref,
|
|
@@ -616,7 +682,7 @@ var SelectLabel = React15.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
616
682
|
}
|
|
617
683
|
));
|
|
618
684
|
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
619
|
-
var SelectItem =
|
|
685
|
+
var SelectItem = React4.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
620
686
|
SelectPrimitive.Item,
|
|
621
687
|
{
|
|
622
688
|
ref,
|
|
@@ -632,7 +698,7 @@ var SelectItem = React15.forwardRef(({ className, children, ...props }, ref) =>
|
|
|
632
698
|
}
|
|
633
699
|
));
|
|
634
700
|
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
635
|
-
var SelectSeparator =
|
|
701
|
+
var SelectSeparator = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
636
702
|
SelectPrimitive.Separator,
|
|
637
703
|
{
|
|
638
704
|
ref,
|
|
@@ -654,6 +720,28 @@ var defaultBillingDetails = {
|
|
|
654
720
|
email: "",
|
|
655
721
|
provider: "mobius"
|
|
656
722
|
};
|
|
723
|
+
var defaultCardDetailsFormTranslations = {
|
|
724
|
+
firstName: "First name",
|
|
725
|
+
lastName: "Last name",
|
|
726
|
+
email: "Email",
|
|
727
|
+
address: "Address",
|
|
728
|
+
city: "City",
|
|
729
|
+
state: "State / Region",
|
|
730
|
+
postalCode: "Postal code",
|
|
731
|
+
country: "Country",
|
|
732
|
+
cardNumber: "Card number",
|
|
733
|
+
expiry: "Expiry",
|
|
734
|
+
cvv: "CVV",
|
|
735
|
+
submit: "Submit",
|
|
736
|
+
processing: "Processing\u2026",
|
|
737
|
+
errorRequiredFields: "Please complete all required billing fields.",
|
|
738
|
+
errorTokenization: "Payment tokenization failed. Please try again.",
|
|
739
|
+
errorFormNotReady: "Payment form is not ready. Please try again later.",
|
|
740
|
+
infoSecure: "Your payment information is encrypted and processed securely.",
|
|
741
|
+
cancel: "Cancel",
|
|
742
|
+
editEmail: "Edit email",
|
|
743
|
+
selectCountry: "Select a country"
|
|
744
|
+
};
|
|
657
745
|
var buildSelector = (prefix, field) => `#${prefix}-${field}`;
|
|
658
746
|
var CardDetailsForm = ({
|
|
659
747
|
visible,
|
|
@@ -665,8 +753,10 @@ var CardDetailsForm = ({
|
|
|
665
753
|
collectPrefix = "card-form",
|
|
666
754
|
className,
|
|
667
755
|
onBillingChange,
|
|
668
|
-
submitDisabled = false
|
|
756
|
+
submitDisabled = false,
|
|
757
|
+
translations
|
|
669
758
|
}) => {
|
|
759
|
+
const t = { ...defaultCardDetailsFormTranslations, ...translations };
|
|
670
760
|
const { config } = usePaymentContext();
|
|
671
761
|
const defaultValuesKey = useMemo(() => JSON.stringify(defaultValues ?? {}), [defaultValues]);
|
|
672
762
|
const mergedDefaults = useMemo(
|
|
@@ -685,6 +775,7 @@ var CardDetailsForm = ({
|
|
|
685
775
|
const [postalCode, setPostalCode] = useState(mergedDefaults.postalCode);
|
|
686
776
|
const [country, setCountry] = useState(mergedDefaults.country);
|
|
687
777
|
const [email, setEmail] = useState(mergedDefaults.email ?? "");
|
|
778
|
+
const [isEditingEmail, setIsEditingEmail] = useState(false);
|
|
688
779
|
const [localError, setLocalError] = useState(null);
|
|
689
780
|
const [isTokenizing, setIsTokenizing] = useState(false);
|
|
690
781
|
const [collectReady, setCollectReady] = useState(
|
|
@@ -706,8 +797,11 @@ var CardDetailsForm = ({
|
|
|
706
797
|
if (!visible) {
|
|
707
798
|
setLocalError(null);
|
|
708
799
|
setIsTokenizing(false);
|
|
800
|
+
if (typeof window !== "undefined" && window.__doujinsCollectConfigured && collectPrefix) {
|
|
801
|
+
window.__doujinsCollectConfigured[collectPrefix] = false;
|
|
802
|
+
}
|
|
709
803
|
}
|
|
710
|
-
}, [visible]);
|
|
804
|
+
}, [visible, collectPrefix]);
|
|
711
805
|
useEffect(() => {
|
|
712
806
|
if (!visible) return;
|
|
713
807
|
setFirstName(mergedDefaults.firstName);
|
|
@@ -769,6 +863,8 @@ var CardDetailsForm = ({
|
|
|
769
863
|
setLocalError("Payment tokenization failed. Please try again.");
|
|
770
864
|
return;
|
|
771
865
|
}
|
|
866
|
+
let rawExp = response.card?.exp;
|
|
867
|
+
let formattedExp = rawExp && rawExp.length === 4 ? `${rawExp.slice(0, 2)}/${rawExp.slice(2)}` : rawExp;
|
|
772
868
|
const billing = {
|
|
773
869
|
firstName,
|
|
774
870
|
lastName,
|
|
@@ -778,7 +874,10 @@ var CardDetailsForm = ({
|
|
|
778
874
|
postalCode,
|
|
779
875
|
country,
|
|
780
876
|
email,
|
|
781
|
-
provider: mergedDefaults.provider ?? "mobius"
|
|
877
|
+
provider: mergedDefaults.provider ?? "mobius",
|
|
878
|
+
last_four: response.card?.number,
|
|
879
|
+
card_type: response.card?.type,
|
|
880
|
+
expiry_date: formattedExp
|
|
782
881
|
};
|
|
783
882
|
onTokenize(response.token, billing);
|
|
784
883
|
};
|
|
@@ -818,9 +917,8 @@ var CardDetailsForm = ({
|
|
|
818
917
|
visible
|
|
819
918
|
]);
|
|
820
919
|
const validate = () => {
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
setLocalError("Please complete all required billing fields.");
|
|
920
|
+
if (!firstName.trim() || !lastName.trim() || !address1.trim() || !city.trim() || !postalCode.trim() || !country.trim() || !email.trim()) {
|
|
921
|
+
setLocalError(t.errorRequiredFields);
|
|
824
922
|
return false;
|
|
825
923
|
}
|
|
826
924
|
setLocalError(null);
|
|
@@ -830,7 +928,7 @@ var CardDetailsForm = ({
|
|
|
830
928
|
event.preventDefault();
|
|
831
929
|
if (!validate()) return;
|
|
832
930
|
if (!window.CollectJS) {
|
|
833
|
-
setLocalError(
|
|
931
|
+
setLocalError(t.errorFormNotReady);
|
|
834
932
|
return;
|
|
835
933
|
}
|
|
836
934
|
setIsTokenizing(true);
|
|
@@ -838,7 +936,8 @@ var CardDetailsForm = ({
|
|
|
838
936
|
};
|
|
839
937
|
const errorMessage = localError ?? externalError;
|
|
840
938
|
const collectFieldClass = "relative flex h-9 w-full items-center overflow-hidden rounded-md border border-white/30 bg-transparent px-3 text-sm text-foreground";
|
|
841
|
-
const
|
|
939
|
+
const hasDefaultEmail = Boolean(defaultValues?.email || config.defaultUser?.email);
|
|
940
|
+
const showEmailInput = !hasDefaultEmail || isEditingEmail;
|
|
842
941
|
return /* @__PURE__ */ jsxs(
|
|
843
942
|
"form",
|
|
844
943
|
{
|
|
@@ -849,7 +948,7 @@ var CardDetailsForm = ({
|
|
|
849
948
|
errorMessage && /* @__PURE__ */ jsx("div", { className: "rounded-md border border-red-500/40 bg-red-500/10 px-4 py-2 text-sm text-red-400", children: errorMessage }),
|
|
850
949
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 md:flex-row", children: [
|
|
851
950
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-2", children: [
|
|
852
|
-
/* @__PURE__ */ jsx(Label, { htmlFor: "firstName", children:
|
|
951
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "firstName", children: t.firstName }),
|
|
853
952
|
/* @__PURE__ */ jsx(
|
|
854
953
|
Input,
|
|
855
954
|
{
|
|
@@ -861,7 +960,7 @@ var CardDetailsForm = ({
|
|
|
861
960
|
)
|
|
862
961
|
] }),
|
|
863
962
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-2", children: [
|
|
864
|
-
/* @__PURE__ */ jsx(Label, { htmlFor: "lastName", children:
|
|
963
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "lastName", children: t.lastName }),
|
|
865
964
|
/* @__PURE__ */ jsx(
|
|
866
965
|
Input,
|
|
867
966
|
{
|
|
@@ -873,21 +972,50 @@ var CardDetailsForm = ({
|
|
|
873
972
|
)
|
|
874
973
|
] })
|
|
875
974
|
] }),
|
|
876
|
-
|
|
877
|
-
/* @__PURE__ */ jsx(Label, { htmlFor: "email", children:
|
|
878
|
-
/* @__PURE__ */
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
975
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
976
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "email", children: t.email }),
|
|
977
|
+
showEmailInput ? /* @__PURE__ */ jsxs("div", { className: "flex gap-2 items-center", children: [
|
|
978
|
+
/* @__PURE__ */ jsx(
|
|
979
|
+
Input,
|
|
980
|
+
{
|
|
981
|
+
id: "email",
|
|
982
|
+
type: "email",
|
|
983
|
+
value: email,
|
|
984
|
+
onChange: (e) => setEmail(e.target.value),
|
|
985
|
+
required: true,
|
|
986
|
+
className: "flex-1"
|
|
987
|
+
}
|
|
988
|
+
),
|
|
989
|
+
hasDefaultEmail && /* @__PURE__ */ jsx(
|
|
990
|
+
Button,
|
|
991
|
+
{
|
|
992
|
+
type: "button",
|
|
993
|
+
variant: "ghost",
|
|
994
|
+
size: "sm",
|
|
995
|
+
onClick: () => {
|
|
996
|
+
setIsEditingEmail(false);
|
|
997
|
+
setEmail(mergedDefaults.email ?? "");
|
|
998
|
+
},
|
|
999
|
+
className: "px-3 text-xs text-muted-foreground hover:text-foreground",
|
|
1000
|
+
children: t.cancel
|
|
1001
|
+
}
|
|
1002
|
+
)
|
|
1003
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between h-9 w-full rounded-md border border-white/30 bg-transparent px-3 text-sm text-foreground", children: [
|
|
1004
|
+
/* @__PURE__ */ jsx("span", { children: email }),
|
|
1005
|
+
/* @__PURE__ */ jsx(
|
|
1006
|
+
"button",
|
|
1007
|
+
{
|
|
1008
|
+
type: "button",
|
|
1009
|
+
onClick: () => setIsEditingEmail(true),
|
|
1010
|
+
className: "text-muted-foreground hover:text-foreground transition-colors",
|
|
1011
|
+
"aria-label": t.editEmail,
|
|
1012
|
+
children: /* @__PURE__ */ jsx(Pencil, { className: "h-4 w-4" })
|
|
1013
|
+
}
|
|
1014
|
+
)
|
|
1015
|
+
] })
|
|
888
1016
|
] }),
|
|
889
1017
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
890
|
-
/* @__PURE__ */ jsx(Label, { htmlFor: "address1", children:
|
|
1018
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "address1", children: t.address }),
|
|
891
1019
|
/* @__PURE__ */ jsx(
|
|
892
1020
|
Input,
|
|
893
1021
|
{
|
|
@@ -900,7 +1028,7 @@ var CardDetailsForm = ({
|
|
|
900
1028
|
] }),
|
|
901
1029
|
/* @__PURE__ */ jsxs("div", { className: "grid gap-2 md:grid-cols-2", children: [
|
|
902
1030
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
903
|
-
/* @__PURE__ */ jsx(Label, { htmlFor: "city", children:
|
|
1031
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "city", children: t.city }),
|
|
904
1032
|
/* @__PURE__ */ jsx(
|
|
905
1033
|
Input,
|
|
906
1034
|
{
|
|
@@ -912,7 +1040,7 @@ var CardDetailsForm = ({
|
|
|
912
1040
|
)
|
|
913
1041
|
] }),
|
|
914
1042
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
915
|
-
/* @__PURE__ */ jsx(Label, { htmlFor: "state", children:
|
|
1043
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "state", children: t.state }),
|
|
916
1044
|
/* @__PURE__ */ jsx(
|
|
917
1045
|
Input,
|
|
918
1046
|
{
|
|
@@ -925,7 +1053,7 @@ var CardDetailsForm = ({
|
|
|
925
1053
|
] }),
|
|
926
1054
|
/* @__PURE__ */ jsxs("div", { className: "grid gap-2 md:grid-cols-2", children: [
|
|
927
1055
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
928
|
-
/* @__PURE__ */ jsx(Label, { htmlFor: "postal", children:
|
|
1056
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "postal", children: t.postalCode }),
|
|
929
1057
|
/* @__PURE__ */ jsx(
|
|
930
1058
|
Input,
|
|
931
1059
|
{
|
|
@@ -937,24 +1065,24 @@ var CardDetailsForm = ({
|
|
|
937
1065
|
)
|
|
938
1066
|
] }),
|
|
939
1067
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
940
|
-
/* @__PURE__ */ jsx(Label, { children:
|
|
1068
|
+
/* @__PURE__ */ jsx(Label, { children: t.country }),
|
|
941
1069
|
/* @__PURE__ */ jsxs(Select, { value: country, onValueChange: setCountry, children: [
|
|
942
|
-
/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder:
|
|
943
|
-
/* @__PURE__ */ jsx(SelectContent, {
|
|
1070
|
+
/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: t.selectCountry }) }),
|
|
1071
|
+
/* @__PURE__ */ jsx(SelectContent, { children: countries.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.code, children: option.name }, option.code)) })
|
|
944
1072
|
] })
|
|
945
1073
|
] })
|
|
946
1074
|
] }),
|
|
947
1075
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
948
|
-
/* @__PURE__ */ jsx(Label, { children:
|
|
1076
|
+
/* @__PURE__ */ jsx(Label, { children: t.cardNumber }),
|
|
949
1077
|
/* @__PURE__ */ jsx("div", { id: buildSelector(collectPrefix, "ccnumber").slice(1), className: collectFieldClass })
|
|
950
1078
|
] }),
|
|
951
1079
|
/* @__PURE__ */ jsxs("div", { className: "grid gap-2 md:grid-cols-2", children: [
|
|
952
1080
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
953
|
-
/* @__PURE__ */ jsx(Label, { children:
|
|
1081
|
+
/* @__PURE__ */ jsx(Label, { children: t.expiry }),
|
|
954
1082
|
/* @__PURE__ */ jsx("div", { id: buildSelector(collectPrefix, "ccexp").slice(1), className: collectFieldClass })
|
|
955
1083
|
] }),
|
|
956
1084
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
957
|
-
/* @__PURE__ */ jsx(Label, { children:
|
|
1085
|
+
/* @__PURE__ */ jsx(Label, { children: t.cvv }),
|
|
958
1086
|
/* @__PURE__ */ jsx("div", { id: buildSelector(collectPrefix, "cvv").slice(1), className: collectFieldClass })
|
|
959
1087
|
] })
|
|
960
1088
|
] }),
|
|
@@ -966,11 +1094,12 @@ var CardDetailsForm = ({
|
|
|
966
1094
|
disabled: submitting || submitDisabled || isTokenizing,
|
|
967
1095
|
children: submitting || isTokenizing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
968
1096
|
/* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
|
|
969
|
-
"
|
|
970
|
-
|
|
1097
|
+
" ",
|
|
1098
|
+
t.processing
|
|
1099
|
+
] }) : submitLabel || t.submit
|
|
971
1100
|
}
|
|
972
1101
|
),
|
|
973
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-white/60", children:
|
|
1102
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-white/60", children: t.infoSecure })
|
|
974
1103
|
]
|
|
975
1104
|
}
|
|
976
1105
|
);
|
|
@@ -1007,7 +1136,9 @@ var usePaymentMethods = () => {
|
|
|
1007
1136
|
zip: billing.postalCode,
|
|
1008
1137
|
country: billing.country,
|
|
1009
1138
|
email: billing.email,
|
|
1010
|
-
provider: billing.provider
|
|
1139
|
+
provider: billing.provider,
|
|
1140
|
+
last_four: billing.last_four,
|
|
1141
|
+
card_type: billing.card_type
|
|
1011
1142
|
};
|
|
1012
1143
|
return client.createPaymentMethod(payload);
|
|
1013
1144
|
},
|
|
@@ -1046,7 +1177,7 @@ var badgeVariants = cva(
|
|
|
1046
1177
|
function Badge({ className, variant, ...props }) {
|
|
1047
1178
|
return /* @__PURE__ */ jsx("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
1048
1179
|
}
|
|
1049
|
-
var ScrollArea =
|
|
1180
|
+
var ScrollArea = React4.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
1050
1181
|
ScrollAreaPrimitive.Root,
|
|
1051
1182
|
{
|
|
1052
1183
|
ref,
|
|
@@ -1060,7 +1191,7 @@ var ScrollArea = React15.forwardRef(({ className, children, ...props }, ref) =>
|
|
|
1060
1191
|
}
|
|
1061
1192
|
));
|
|
1062
1193
|
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
|
|
1063
|
-
var ScrollBar =
|
|
1194
|
+
var ScrollBar = React4.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1064
1195
|
ScrollAreaPrimitive.ScrollAreaScrollbar,
|
|
1065
1196
|
{
|
|
1066
1197
|
ref,
|
|
@@ -1076,21 +1207,34 @@ var ScrollBar = React15.forwardRef(({ className, orientation = "vertical", ...pr
|
|
|
1076
1207
|
}
|
|
1077
1208
|
));
|
|
1078
1209
|
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
|
|
1210
|
+
var defaultTranslations = {
|
|
1211
|
+
loadingCards: "Loading cards...",
|
|
1212
|
+
noSavedMethods: "No saved payment methods yet.",
|
|
1213
|
+
selectedLabel: "Selected",
|
|
1214
|
+
useCardLabel: "Use card"
|
|
1215
|
+
};
|
|
1079
1216
|
var formatCardLabel = (method) => {
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1217
|
+
if (method.card) {
|
|
1218
|
+
const brand = method.card.brand ? method.card.brand.toUpperCase() : "CARD";
|
|
1219
|
+
const lastFour = method.card.last4 ? `\u2022\u2022\u2022\u2022 ${method.card.last4}` : "";
|
|
1220
|
+
const exp = method.card.exp_month && method.card.exp_year ? ` \u2022 ${String(method.card.exp_month).padStart(2, "0")}/${String(method.card.exp_year).slice(-2)}` : "";
|
|
1221
|
+
return `${brand} ${lastFour}${exp}`.trim();
|
|
1222
|
+
}
|
|
1223
|
+
return "CARD";
|
|
1083
1224
|
};
|
|
1084
1225
|
var StoredPaymentMethods = ({
|
|
1085
1226
|
selectedMethodId,
|
|
1086
|
-
onMethodSelect
|
|
1227
|
+
onMethodSelect,
|
|
1228
|
+
translations
|
|
1087
1229
|
}) => {
|
|
1088
1230
|
const { listQuery } = usePaymentMethods();
|
|
1089
1231
|
const payments = useMemo(() => listQuery.data?.data ?? [], [listQuery.data]);
|
|
1232
|
+
const t = { ...defaultTranslations, ...translations };
|
|
1090
1233
|
return /* @__PURE__ */ jsx("div", { className: "space-y-4", children: listQuery.isLoading ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center py-4 text-sm text-muted-foreground", children: [
|
|
1091
1234
|
/* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
|
|
1092
|
-
"
|
|
1093
|
-
|
|
1235
|
+
" ",
|
|
1236
|
+
t.loadingCards
|
|
1237
|
+
] }) : payments.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center text-sm text-muted-foreground", children: t.noSavedMethods }) : /* @__PURE__ */ jsx(ScrollArea, { className: "max-h-[320px] pr-2", children: /* @__PURE__ */ jsx("div", { className: "space-y-3", children: payments.map((method) => {
|
|
1094
1238
|
const isSelected = selectedMethodId === method.id;
|
|
1095
1239
|
return /* @__PURE__ */ jsxs(
|
|
1096
1240
|
"div",
|
|
@@ -1113,7 +1257,7 @@ var StoredPaymentMethods = ({
|
|
|
1113
1257
|
disabled: isSelected,
|
|
1114
1258
|
onClick: () => onMethodSelect(method),
|
|
1115
1259
|
className: clsx2("px-3", { "bg-muted/90": !isSelected, "bg-inherit": isSelected }),
|
|
1116
|
-
children: isSelected ?
|
|
1260
|
+
children: isSelected ? t.selectedLabel : t.useCardLabel
|
|
1117
1261
|
}
|
|
1118
1262
|
)
|
|
1119
1263
|
] })
|
|
@@ -1123,6 +1267,26 @@ var StoredPaymentMethods = ({
|
|
|
1123
1267
|
);
|
|
1124
1268
|
}) }) }) });
|
|
1125
1269
|
};
|
|
1270
|
+
|
|
1271
|
+
// src/utils/errorMessages.ts
|
|
1272
|
+
var resolveErrorMessageByCode = (error, translationErrors, fallbackMessage) => {
|
|
1273
|
+
const errors = translationErrors ?? {};
|
|
1274
|
+
const defaultMessage = fallbackMessage ?? (error instanceof Error ? error.message : typeof error === "string" ? error : "An unexpected error occurred");
|
|
1275
|
+
if (error instanceof ClientApiError) {
|
|
1276
|
+
const payload = error.body;
|
|
1277
|
+
const code = payload?.code ?? payload?.error?.code;
|
|
1278
|
+
if (code && errors[code]) return errors[code];
|
|
1279
|
+
if (typeof payload?.error?.message === "string") return payload.error.message;
|
|
1280
|
+
return error.message;
|
|
1281
|
+
}
|
|
1282
|
+
if (typeof error === "object" && error !== null && "code" in error) {
|
|
1283
|
+
const code = error.code;
|
|
1284
|
+
if (typeof code === "string" && errors[code]) return errors[code];
|
|
1285
|
+
}
|
|
1286
|
+
if (error instanceof Error) return error.message;
|
|
1287
|
+
if (typeof error === "string") return error;
|
|
1288
|
+
return defaultMessage;
|
|
1289
|
+
};
|
|
1126
1290
|
function Tabs({
|
|
1127
1291
|
className,
|
|
1128
1292
|
...props
|
|
@@ -1145,7 +1309,7 @@ function TabsList({
|
|
|
1145
1309
|
{
|
|
1146
1310
|
"data-slot": "tabs-list",
|
|
1147
1311
|
className: cn(
|
|
1148
|
-
"bg-
|
|
1312
|
+
"bg-transparent border border-white/30 text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-1",
|
|
1149
1313
|
className
|
|
1150
1314
|
),
|
|
1151
1315
|
...props
|
|
@@ -1156,12 +1320,32 @@ function TabsTrigger({
|
|
|
1156
1320
|
className,
|
|
1157
1321
|
...props
|
|
1158
1322
|
}) {
|
|
1323
|
+
const triggerRef = React4.useRef(null);
|
|
1324
|
+
React4.useEffect(() => {
|
|
1325
|
+
const element = triggerRef.current;
|
|
1326
|
+
if (!element) return;
|
|
1327
|
+
const updateStyles = () => {
|
|
1328
|
+
const isActive = element.getAttribute("data-state") === "active";
|
|
1329
|
+
if (isActive) {
|
|
1330
|
+
element.style.setProperty("background-color", "rgba(255, 255, 255, 0.3)", "important");
|
|
1331
|
+
element.style.setProperty("border-color", "transparent", "important");
|
|
1332
|
+
} else {
|
|
1333
|
+
element.style.removeProperty("background-color");
|
|
1334
|
+
element.style.removeProperty("border-color");
|
|
1335
|
+
}
|
|
1336
|
+
};
|
|
1337
|
+
updateStyles();
|
|
1338
|
+
const observer = new MutationObserver(updateStyles);
|
|
1339
|
+
observer.observe(element, { attributes: true, attributeFilter: ["data-state"] });
|
|
1340
|
+
return () => observer.disconnect();
|
|
1341
|
+
}, []);
|
|
1159
1342
|
return /* @__PURE__ */ jsx(
|
|
1160
1343
|
TabsPrimitive.Trigger,
|
|
1161
1344
|
{
|
|
1345
|
+
ref: triggerRef,
|
|
1162
1346
|
"data-slot": "tabs-trigger",
|
|
1163
1347
|
className: cn(
|
|
1164
|
-
"data-[state=active]:
|
|
1348
|
+
"data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground/70 inline-flex h-[calc(100%-0.5rem)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow,background-color,border-color] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm hover:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
1165
1349
|
className
|
|
1166
1350
|
),
|
|
1167
1351
|
...props
|
|
@@ -1405,7 +1589,7 @@ var useSolanaQrPayment = (options) => {
|
|
|
1405
1589
|
refresh
|
|
1406
1590
|
};
|
|
1407
1591
|
};
|
|
1408
|
-
var Card =
|
|
1592
|
+
var Card = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1409
1593
|
"div",
|
|
1410
1594
|
{
|
|
1411
1595
|
ref,
|
|
@@ -1417,7 +1601,7 @@ var Card = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
|
|
|
1417
1601
|
}
|
|
1418
1602
|
));
|
|
1419
1603
|
Card.displayName = "Card";
|
|
1420
|
-
var CardHeader =
|
|
1604
|
+
var CardHeader = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1421
1605
|
"div",
|
|
1422
1606
|
{
|
|
1423
1607
|
ref,
|
|
@@ -1426,7 +1610,7 @@ var CardHeader = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE
|
|
|
1426
1610
|
}
|
|
1427
1611
|
));
|
|
1428
1612
|
CardHeader.displayName = "CardHeader";
|
|
1429
|
-
var CardTitle =
|
|
1613
|
+
var CardTitle = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1430
1614
|
"div",
|
|
1431
1615
|
{
|
|
1432
1616
|
ref,
|
|
@@ -1438,7 +1622,7 @@ var CardTitle = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE_
|
|
|
1438
1622
|
}
|
|
1439
1623
|
));
|
|
1440
1624
|
CardTitle.displayName = "CardTitle";
|
|
1441
|
-
var CardDescription =
|
|
1625
|
+
var CardDescription = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1442
1626
|
"div",
|
|
1443
1627
|
{
|
|
1444
1628
|
ref,
|
|
@@ -1447,9 +1631,9 @@ var CardDescription = React15.forwardRef(({ className, ...props }, ref) => /* @_
|
|
|
1447
1631
|
}
|
|
1448
1632
|
));
|
|
1449
1633
|
CardDescription.displayName = "CardDescription";
|
|
1450
|
-
var CardContent =
|
|
1634
|
+
var CardContent = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
|
|
1451
1635
|
CardContent.displayName = "CardContent";
|
|
1452
|
-
var CardFooter =
|
|
1636
|
+
var CardFooter = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1453
1637
|
"div",
|
|
1454
1638
|
{
|
|
1455
1639
|
ref,
|
|
@@ -1464,7 +1648,7 @@ var QRCodePayment = ({
|
|
|
1464
1648
|
onPaymentError,
|
|
1465
1649
|
onPaymentSuccess
|
|
1466
1650
|
}) => {
|
|
1467
|
-
const handleQrSuccess =
|
|
1651
|
+
const handleQrSuccess = React4__default.useCallback(
|
|
1468
1652
|
(paymentId, txId) => {
|
|
1469
1653
|
if (!paymentId && !txId) {
|
|
1470
1654
|
onPaymentError("Missing payment confirmation details");
|
|
@@ -1898,20 +2082,45 @@ var SolanaPaymentView = ({
|
|
|
1898
2082
|
renderBody()
|
|
1899
2083
|
] });
|
|
1900
2084
|
};
|
|
2085
|
+
var defaultPaymentExperienceTranslations = {
|
|
2086
|
+
...defaultCardDetailsFormTranslations,
|
|
2087
|
+
useSavedCardTab: "Use saved card",
|
|
2088
|
+
addNewCardTab: "Add new card",
|
|
2089
|
+
savedUnavailable: "Saved payment methods are unavailable right now. Add a new card to get started.",
|
|
2090
|
+
payWithSavedCard: "Pay with selected card",
|
|
2091
|
+
processingSavedCard: "Processing...",
|
|
2092
|
+
savedErrorFallback: "Unable to complete payment with saved card",
|
|
2093
|
+
newCardUnavailable: "Select a subscription plan to add a new card.",
|
|
2094
|
+
payNow: "Pay now",
|
|
2095
|
+
storedLoadingCards: "Loading cards...",
|
|
2096
|
+
storedNoSavedMethods: "No saved payment methods yet.",
|
|
2097
|
+
storedSelectedLabel: "Selected",
|
|
2098
|
+
storedUseCardLabel: "Use card",
|
|
2099
|
+
payWithCcbill: "Pay with CCBill",
|
|
2100
|
+
processingCcbill: "Redirecting...",
|
|
2101
|
+
errors: {}
|
|
2102
|
+
};
|
|
1901
2103
|
var PaymentExperience = ({
|
|
1902
2104
|
priceId,
|
|
1903
2105
|
usdAmount,
|
|
1904
2106
|
onNewCardPayment,
|
|
1905
2107
|
onSavedMethodPayment,
|
|
2108
|
+
onCcbillPayment,
|
|
1906
2109
|
enableNewCard = true,
|
|
1907
2110
|
enableStoredMethods = true,
|
|
1908
2111
|
enableSolanaPay = true,
|
|
1909
2112
|
onSolanaSuccess,
|
|
1910
2113
|
onSolanaError,
|
|
1911
|
-
initialMode = "cards"
|
|
2114
|
+
initialMode = "cards",
|
|
2115
|
+
translations
|
|
1912
2116
|
}) => {
|
|
2117
|
+
const t = {
|
|
2118
|
+
...defaultPaymentExperienceTranslations,
|
|
2119
|
+
...translations
|
|
2120
|
+
};
|
|
1913
2121
|
const showNewCard = enableNewCard && Boolean(onNewCardPayment);
|
|
1914
2122
|
const showStored = enableStoredMethods && Boolean(onSavedMethodPayment);
|
|
2123
|
+
const showCcbill = showNewCard && Boolean(onCcbillPayment);
|
|
1915
2124
|
const defaultTab = showStored ? "saved" : "new";
|
|
1916
2125
|
const [activeTab, setActiveTab] = useState(defaultTab);
|
|
1917
2126
|
const [mode, setMode] = useState(
|
|
@@ -1922,6 +2131,9 @@ var PaymentExperience = ({
|
|
|
1922
2131
|
const [savedError, setSavedError] = useState(null);
|
|
1923
2132
|
const [newCardStatus, setNewCardStatus] = useState("idle");
|
|
1924
2133
|
const [newCardError, setNewCardError] = useState(null);
|
|
2134
|
+
const [billingDetails, setBillingDetails] = useState(null);
|
|
2135
|
+
const [ccbillStatus, setCcbillStatus] = useState("idle");
|
|
2136
|
+
const [ccbillError, setCcbillError] = useState(null);
|
|
1925
2137
|
const { notifyStatus, notifyError } = usePaymentNotifications();
|
|
1926
2138
|
useEffect(() => {
|
|
1927
2139
|
setActiveTab(showStored ? "saved" : "new");
|
|
@@ -1937,6 +2149,24 @@ var PaymentExperience = ({
|
|
|
1937
2149
|
setMode("cards");
|
|
1938
2150
|
}
|
|
1939
2151
|
}, [enableSolanaPay, initialMode]);
|
|
2152
|
+
useEffect(() => {
|
|
2153
|
+
if (!showNewCard) {
|
|
2154
|
+
setBillingDetails(null);
|
|
2155
|
+
setCcbillStatus("idle");
|
|
2156
|
+
setCcbillError(null);
|
|
2157
|
+
}
|
|
2158
|
+
}, [showNewCard]);
|
|
2159
|
+
const handleBillingChange = useCallback((billing) => {
|
|
2160
|
+
setBillingDetails(billing);
|
|
2161
|
+
setCcbillError(null);
|
|
2162
|
+
setCcbillStatus("idle");
|
|
2163
|
+
}, []);
|
|
2164
|
+
const isBillingComplete = useCallback((billing) => {
|
|
2165
|
+
if (!billing) return false;
|
|
2166
|
+
return Boolean(
|
|
2167
|
+
billing.firstName.trim() && billing.lastName.trim() && billing.address1.trim() && billing.city.trim() && billing.postalCode.trim() && billing.country.trim() && billing.email.trim()
|
|
2168
|
+
);
|
|
2169
|
+
}, []);
|
|
1940
2170
|
const handleMethodSelect = useCallback((method) => {
|
|
1941
2171
|
setSelectedMethodId(method.id);
|
|
1942
2172
|
setSavedStatus("idle");
|
|
@@ -1955,13 +2185,17 @@ var PaymentExperience = ({
|
|
|
1955
2185
|
setSavedStatus("success");
|
|
1956
2186
|
notifyStatus("success", { source: "saved-payment" });
|
|
1957
2187
|
} catch (error) {
|
|
1958
|
-
const message =
|
|
2188
|
+
const message = resolveErrorMessageByCode(
|
|
2189
|
+
error,
|
|
2190
|
+
t.errors,
|
|
2191
|
+
t.savedErrorFallback
|
|
2192
|
+
);
|
|
1959
2193
|
setSavedStatus("error");
|
|
1960
2194
|
setSavedError(message);
|
|
1961
2195
|
notifyStatus("error", { source: "saved-payment" });
|
|
1962
2196
|
notifyError(message);
|
|
1963
2197
|
}
|
|
1964
|
-
}, [notifyError, notifyStatus, onSavedMethodPayment, selectedMethodId, usdAmount]);
|
|
2198
|
+
}, [notifyError, notifyStatus, onSavedMethodPayment, selectedMethodId, t, usdAmount]);
|
|
1965
2199
|
const handleNewCardTokenize = useCallback(
|
|
1966
2200
|
async (token, billing) => {
|
|
1967
2201
|
if (!onNewCardPayment) return;
|
|
@@ -1973,15 +2207,56 @@ var PaymentExperience = ({
|
|
|
1973
2207
|
setNewCardStatus("success");
|
|
1974
2208
|
notifyStatus("success", { source: "new-card" });
|
|
1975
2209
|
} catch (error) {
|
|
1976
|
-
const message =
|
|
2210
|
+
const message = resolveErrorMessageByCode(
|
|
2211
|
+
error,
|
|
2212
|
+
t.errors,
|
|
2213
|
+
"Unable to complete payment"
|
|
2214
|
+
);
|
|
1977
2215
|
setNewCardStatus("error");
|
|
1978
2216
|
setNewCardError(message);
|
|
1979
2217
|
notifyStatus("error", { source: "new-card" });
|
|
1980
2218
|
notifyError(message);
|
|
1981
2219
|
}
|
|
1982
2220
|
},
|
|
1983
|
-
[notifyError, notifyStatus, onNewCardPayment]
|
|
2221
|
+
[notifyError, notifyStatus, onNewCardPayment, t]
|
|
1984
2222
|
);
|
|
2223
|
+
const handleCcbillPayment = useCallback(async () => {
|
|
2224
|
+
if (!onCcbillPayment) return;
|
|
2225
|
+
if (!billingDetails || !isBillingComplete(billingDetails)) {
|
|
2226
|
+
const message = t.errorRequiredFields;
|
|
2227
|
+
setActiveTab("new");
|
|
2228
|
+
setCcbillStatus("error");
|
|
2229
|
+
setCcbillError(message);
|
|
2230
|
+
notifyStatus("error", { source: "ccbill" });
|
|
2231
|
+
notifyError(message);
|
|
2232
|
+
return;
|
|
2233
|
+
}
|
|
2234
|
+
try {
|
|
2235
|
+
setCcbillStatus("processing");
|
|
2236
|
+
setCcbillError(null);
|
|
2237
|
+
notifyStatus("processing", { source: "ccbill" });
|
|
2238
|
+
await onCcbillPayment({ billing: billingDetails });
|
|
2239
|
+
setCcbillStatus("success");
|
|
2240
|
+
notifyStatus("success", { source: "ccbill" });
|
|
2241
|
+
} catch (error) {
|
|
2242
|
+
const message = resolveErrorMessageByCode(
|
|
2243
|
+
error,
|
|
2244
|
+
t.errors,
|
|
2245
|
+
"Unable to start CCBill checkout"
|
|
2246
|
+
);
|
|
2247
|
+
setCcbillStatus("error");
|
|
2248
|
+
setCcbillError(message);
|
|
2249
|
+
notifyStatus("error", { source: "ccbill" });
|
|
2250
|
+
notifyError(message);
|
|
2251
|
+
}
|
|
2252
|
+
}, [
|
|
2253
|
+
billingDetails,
|
|
2254
|
+
isBillingComplete,
|
|
2255
|
+
notifyError,
|
|
2256
|
+
notifyStatus,
|
|
2257
|
+
onCcbillPayment,
|
|
2258
|
+
t
|
|
2259
|
+
]);
|
|
1985
2260
|
useCallback(() => {
|
|
1986
2261
|
if (!enableSolanaPay) return;
|
|
1987
2262
|
setMode("solana");
|
|
@@ -2004,14 +2279,20 @@ var PaymentExperience = ({
|
|
|
2004
2279
|
);
|
|
2005
2280
|
const renderSavedTab = () => {
|
|
2006
2281
|
if (!showStored) {
|
|
2007
|
-
return /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children:
|
|
2282
|
+
return /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t.savedUnavailable });
|
|
2008
2283
|
}
|
|
2009
2284
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
2010
2285
|
/* @__PURE__ */ jsx(
|
|
2011
2286
|
StoredPaymentMethods,
|
|
2012
2287
|
{
|
|
2013
2288
|
selectedMethodId,
|
|
2014
|
-
onMethodSelect: handleMethodSelect
|
|
2289
|
+
onMethodSelect: handleMethodSelect,
|
|
2290
|
+
translations: {
|
|
2291
|
+
loadingCards: t.storedLoadingCards,
|
|
2292
|
+
noSavedMethods: t.storedNoSavedMethods,
|
|
2293
|
+
selectedLabel: t.storedSelectedLabel,
|
|
2294
|
+
useCardLabel: t.storedUseCardLabel
|
|
2295
|
+
}
|
|
2015
2296
|
}
|
|
2016
2297
|
),
|
|
2017
2298
|
/* @__PURE__ */ jsx(
|
|
@@ -2020,7 +2301,7 @@ var PaymentExperience = ({
|
|
|
2020
2301
|
className: "w-full",
|
|
2021
2302
|
disabled: !selectedMethodId || savedStatus === "processing",
|
|
2022
2303
|
onClick: handleSavedPayment,
|
|
2023
|
-
children: savedStatus === "processing" ?
|
|
2304
|
+
children: savedStatus === "processing" ? t.processingSavedCard : t.payWithSavedCard
|
|
2024
2305
|
}
|
|
2025
2306
|
),
|
|
2026
2307
|
savedError && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: savedError })
|
|
@@ -2028,29 +2309,50 @@ var PaymentExperience = ({
|
|
|
2028
2309
|
};
|
|
2029
2310
|
const renderNewTab = () => {
|
|
2030
2311
|
if (!showNewCard) {
|
|
2031
|
-
return /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children:
|
|
2312
|
+
return /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t.newCardUnavailable });
|
|
2032
2313
|
}
|
|
2033
2314
|
return /* @__PURE__ */ jsx(
|
|
2034
2315
|
CardDetailsForm,
|
|
2035
2316
|
{
|
|
2036
2317
|
visible: true,
|
|
2037
|
-
submitLabel:
|
|
2318
|
+
submitLabel: t.payNow,
|
|
2038
2319
|
externalError: newCardError,
|
|
2039
2320
|
onTokenize: handleNewCardTokenize,
|
|
2040
|
-
submitting: newCardStatus === "processing"
|
|
2321
|
+
submitting: newCardStatus === "processing",
|
|
2322
|
+
onBillingChange: handleBillingChange,
|
|
2323
|
+
translations: t
|
|
2041
2324
|
}
|
|
2042
2325
|
);
|
|
2043
2326
|
};
|
|
2044
2327
|
const renderCardExperience = () => /* @__PURE__ */ jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, children: [
|
|
2045
2328
|
/* @__PURE__ */ jsxs(TabsList, { className: "w-full rounded-md mb-4", children: [
|
|
2046
|
-
/* @__PURE__ */ jsx(TabsTrigger, { className:
|
|
2047
|
-
/* @__PURE__ */ jsx(TabsTrigger, { className:
|
|
2329
|
+
/* @__PURE__ */ jsx(TabsTrigger, { className: "cursor-pointer", value: "saved", children: t.useSavedCardTab }),
|
|
2330
|
+
/* @__PURE__ */ jsx(TabsTrigger, { className: "cursor-pointer", value: "new", children: t.addNewCardTab })
|
|
2048
2331
|
] }),
|
|
2049
2332
|
/* @__PURE__ */ jsx(TabsContent, { value: "saved", children: renderSavedTab() }),
|
|
2050
2333
|
/* @__PURE__ */ jsx(TabsContent, { value: "new", children: renderNewTab() })
|
|
2051
2334
|
] });
|
|
2335
|
+
const renderCcbillAction = () => {
|
|
2336
|
+
if (!showCcbill) return null;
|
|
2337
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-2 border-t border-white/10 pt-4", children: [
|
|
2338
|
+
/* @__PURE__ */ jsx(
|
|
2339
|
+
Button,
|
|
2340
|
+
{
|
|
2341
|
+
className: "w-full",
|
|
2342
|
+
variant: "outline",
|
|
2343
|
+
disabled: ccbillStatus === "processing",
|
|
2344
|
+
onClick: handleCcbillPayment,
|
|
2345
|
+
children: ccbillStatus === "processing" ? t.processingCcbill : t.payWithCcbill
|
|
2346
|
+
}
|
|
2347
|
+
),
|
|
2348
|
+
ccbillError && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: ccbillError })
|
|
2349
|
+
] });
|
|
2350
|
+
};
|
|
2052
2351
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-6 pt-4", children: [
|
|
2053
|
-
mode === "cards" &&
|
|
2352
|
+
mode === "cards" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2353
|
+
renderCardExperience(),
|
|
2354
|
+
renderCcbillAction()
|
|
2355
|
+
] }),
|
|
2054
2356
|
mode === "solana" && enableSolanaPay && /* @__PURE__ */ jsx(
|
|
2055
2357
|
SolanaPaymentView,
|
|
2056
2358
|
{
|
|
@@ -2102,17 +2404,17 @@ var useSubscriptionActions = () => {
|
|
|
2102
2404
|
const subscribeWithCard = useCallback(
|
|
2103
2405
|
async ({
|
|
2104
2406
|
priceId,
|
|
2105
|
-
processor = "
|
|
2407
|
+
processor = "mobius",
|
|
2106
2408
|
provider,
|
|
2107
2409
|
paymentToken,
|
|
2108
2410
|
billing,
|
|
2109
2411
|
idempotencyKey
|
|
2110
2412
|
}) => {
|
|
2111
|
-
|
|
2112
|
-
|
|
2413
|
+
if (processor !== "ccbill" && !paymentToken) {
|
|
2414
|
+
throw new Error("payments-ui: payment token is required for card checkout");
|
|
2415
|
+
}
|
|
2416
|
+
const payment = {
|
|
2113
2417
|
processor,
|
|
2114
|
-
provider,
|
|
2115
|
-
payment_token: paymentToken,
|
|
2116
2418
|
email: billing.email,
|
|
2117
2419
|
first_name: billing.firstName,
|
|
2118
2420
|
last_name: billing.lastName,
|
|
@@ -2122,6 +2424,17 @@ var useSubscriptionActions = () => {
|
|
|
2122
2424
|
zip: billing.postalCode,
|
|
2123
2425
|
country: billing.country
|
|
2124
2426
|
};
|
|
2427
|
+
if (paymentToken) {
|
|
2428
|
+
payment.payment_token = paymentToken;
|
|
2429
|
+
payment.last_four = billing.last_four;
|
|
2430
|
+
payment.card_type = billing.card_type;
|
|
2431
|
+
payment.expiry_date = billing.expiry_date;
|
|
2432
|
+
}
|
|
2433
|
+
const payload = {
|
|
2434
|
+
price_id: ensurePrice(priceId),
|
|
2435
|
+
provider,
|
|
2436
|
+
payment
|
|
2437
|
+
};
|
|
2125
2438
|
return client.checkout(payload, idempotencyKey);
|
|
2126
2439
|
},
|
|
2127
2440
|
[client]
|
|
@@ -2129,7 +2442,7 @@ var useSubscriptionActions = () => {
|
|
|
2129
2442
|
const subscribeWithSavedMethod = useCallback(
|
|
2130
2443
|
async ({
|
|
2131
2444
|
priceId,
|
|
2132
|
-
processor = "
|
|
2445
|
+
processor = "mobius",
|
|
2133
2446
|
provider,
|
|
2134
2447
|
paymentMethodId,
|
|
2135
2448
|
email,
|
|
@@ -2137,10 +2450,12 @@ var useSubscriptionActions = () => {
|
|
|
2137
2450
|
}) => {
|
|
2138
2451
|
const payload = {
|
|
2139
2452
|
price_id: ensurePrice(priceId),
|
|
2140
|
-
processor,
|
|
2141
2453
|
provider,
|
|
2142
|
-
|
|
2143
|
-
|
|
2454
|
+
payment: {
|
|
2455
|
+
processor,
|
|
2456
|
+
payment_method_id: paymentMethodId,
|
|
2457
|
+
email
|
|
2458
|
+
}
|
|
2144
2459
|
};
|
|
2145
2460
|
return client.checkout(payload, idempotencyKey);
|
|
2146
2461
|
},
|
|
@@ -2159,12 +2474,14 @@ var useSubscriptionActions = () => {
|
|
|
2159
2474
|
}) => {
|
|
2160
2475
|
const payload = {
|
|
2161
2476
|
price_id: ensurePrice(priceId),
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2477
|
+
payment: {
|
|
2478
|
+
processor,
|
|
2479
|
+
email,
|
|
2480
|
+
first_name: firstName,
|
|
2481
|
+
last_name: lastName,
|
|
2482
|
+
zip: zipCode,
|
|
2483
|
+
country
|
|
2484
|
+
}
|
|
2168
2485
|
};
|
|
2169
2486
|
return client.checkout(payload, idempotencyKey);
|
|
2170
2487
|
},
|
|
@@ -2176,6 +2493,11 @@ var useSubscriptionActions = () => {
|
|
|
2176
2493
|
subscribeWithCCBill
|
|
2177
2494
|
};
|
|
2178
2495
|
};
|
|
2496
|
+
var defaultTranslations2 = {
|
|
2497
|
+
...defaultPaymentExperienceTranslations,
|
|
2498
|
+
title: "Checkout",
|
|
2499
|
+
selectPlanMessage: "Select a subscription plan to continue."
|
|
2500
|
+
};
|
|
2179
2501
|
var SubscriptionCheckoutModal = ({
|
|
2180
2502
|
open,
|
|
2181
2503
|
onOpenChange,
|
|
@@ -2190,11 +2512,16 @@ var SubscriptionCheckoutModal = ({
|
|
|
2190
2512
|
enableSolanaPay = true,
|
|
2191
2513
|
onSolanaSuccess,
|
|
2192
2514
|
onSolanaError,
|
|
2193
|
-
initialMode = "cards"
|
|
2515
|
+
initialMode = "cards",
|
|
2516
|
+
translations
|
|
2194
2517
|
}) => {
|
|
2195
2518
|
const [showSuccess, setShowSuccess] = useState(false);
|
|
2196
2519
|
const [idempotencyKey, setIdempotencyKey] = useState(() => crypto.randomUUID());
|
|
2197
2520
|
const { subscribeWithCard, subscribeWithSavedMethod } = useSubscriptionActions();
|
|
2521
|
+
const t = {
|
|
2522
|
+
...defaultTranslations2,
|
|
2523
|
+
...translations
|
|
2524
|
+
};
|
|
2198
2525
|
useEffect(() => {
|
|
2199
2526
|
if (open) {
|
|
2200
2527
|
setIdempotencyKey(crypto.randomUUID());
|
|
@@ -2218,13 +2545,31 @@ var SubscriptionCheckoutModal = ({
|
|
|
2218
2545
|
console.debug("[payments-ui] subscription success", result);
|
|
2219
2546
|
}
|
|
2220
2547
|
};
|
|
2221
|
-
const
|
|
2222
|
-
if (status === "blocked") {
|
|
2223
|
-
throw new Error(message || "This subscription cannot be completed right now.");
|
|
2548
|
+
const handleCheckoutResponse = (response) => {
|
|
2549
|
+
if (response.status === "blocked") {
|
|
2550
|
+
throw new Error(response.message || "This subscription cannot be completed right now.");
|
|
2224
2551
|
}
|
|
2225
|
-
|
|
2226
|
-
|
|
2552
|
+
const nextAction = response.next_action;
|
|
2553
|
+
if (nextAction?.type === "redirect_to_url") {
|
|
2554
|
+
const redirectUrl = nextAction.redirect_to_url?.url || response.payment?.redirect_url;
|
|
2555
|
+
if (!redirectUrl) {
|
|
2556
|
+
throw new Error(response.message || "Checkout requires a redirect URL.");
|
|
2557
|
+
}
|
|
2558
|
+
if (typeof window !== "undefined") {
|
|
2559
|
+
window.location.assign(redirectUrl);
|
|
2560
|
+
}
|
|
2561
|
+
return;
|
|
2227
2562
|
}
|
|
2563
|
+
if (response.payment?.redirect_url) {
|
|
2564
|
+
if (typeof window !== "undefined") {
|
|
2565
|
+
window.location.assign(response.payment.redirect_url);
|
|
2566
|
+
}
|
|
2567
|
+
return;
|
|
2568
|
+
}
|
|
2569
|
+
if (nextAction && nextAction.type !== "none") {
|
|
2570
|
+
throw new Error(response.message || "Unsupported checkout action.");
|
|
2571
|
+
}
|
|
2572
|
+
notifySuccess();
|
|
2228
2573
|
};
|
|
2229
2574
|
const handleNewCardPayment = async ({ token, billing }) => {
|
|
2230
2575
|
const response = await subscribeWithCard({
|
|
@@ -2234,8 +2579,7 @@ var SubscriptionCheckoutModal = ({
|
|
|
2234
2579
|
paymentToken: token,
|
|
2235
2580
|
priceId: ensurePrice()
|
|
2236
2581
|
});
|
|
2237
|
-
|
|
2238
|
-
notifySuccess();
|
|
2582
|
+
handleCheckoutResponse(response);
|
|
2239
2583
|
};
|
|
2240
2584
|
const handleSavedMethodPayment = async ({ paymentMethodId }) => {
|
|
2241
2585
|
const response = await subscribeWithSavedMethod({
|
|
@@ -2245,8 +2589,16 @@ var SubscriptionCheckoutModal = ({
|
|
|
2245
2589
|
email: userEmail ?? "",
|
|
2246
2590
|
idempotencyKey
|
|
2247
2591
|
});
|
|
2248
|
-
|
|
2249
|
-
|
|
2592
|
+
handleCheckoutResponse(response);
|
|
2593
|
+
};
|
|
2594
|
+
const handleCcbillPayment = async ({ billing }) => {
|
|
2595
|
+
const response = await subscribeWithCard({
|
|
2596
|
+
billing,
|
|
2597
|
+
idempotencyKey,
|
|
2598
|
+
processor: "ccbill",
|
|
2599
|
+
priceId: ensurePrice()
|
|
2600
|
+
});
|
|
2601
|
+
handleCheckoutResponse(response);
|
|
2250
2602
|
};
|
|
2251
2603
|
const solanaSuccess = (result) => {
|
|
2252
2604
|
notifySuccess(result);
|
|
@@ -2262,11 +2614,11 @@ var SubscriptionCheckoutModal = ({
|
|
|
2262
2614
|
{
|
|
2263
2615
|
className: "z-[100] max-w-xl max-h-[90vh] overflow-y-auto border border-white/20 p-6 backdrop-blur-xl bg-background-regular rounded-md [&::-webkit-scrollbar]:hidden",
|
|
2264
2616
|
children: [
|
|
2265
|
-
/* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { className: "flex items-center gap-2 text-foreground", children:
|
|
2617
|
+
/* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { className: "flex items-center gap-2 text-foreground", children: t.title }) }),
|
|
2266
2618
|
/* @__PURE__ */ jsx("div", { className: "space-y-4", children: !priceId ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-center px-3 py-2 text-sm text-destructive", children: [
|
|
2267
2619
|
/* @__PURE__ */ jsx(AlertCircle, { className: "h-4 w-4" }),
|
|
2268
2620
|
" ",
|
|
2269
|
-
/* @__PURE__ */ jsx("span", { children:
|
|
2621
|
+
/* @__PURE__ */ jsx("span", { children: t.selectPlanMessage })
|
|
2270
2622
|
] }) : /* @__PURE__ */ jsx(
|
|
2271
2623
|
PaymentExperience,
|
|
2272
2624
|
{
|
|
@@ -2279,7 +2631,9 @@ var SubscriptionCheckoutModal = ({
|
|
|
2279
2631
|
enableStoredMethods: Boolean(priceId),
|
|
2280
2632
|
enableSolanaPay: enableSolanaPay && Boolean(priceId),
|
|
2281
2633
|
onNewCardPayment: priceId ? handleNewCardPayment : void 0,
|
|
2282
|
-
onSavedMethodPayment: priceId ? handleSavedMethodPayment : void 0
|
|
2634
|
+
onSavedMethodPayment: priceId ? handleSavedMethodPayment : void 0,
|
|
2635
|
+
onCcbillPayment: priceId ? handleCcbillPayment : void 0,
|
|
2636
|
+
translations: t
|
|
2283
2637
|
}
|
|
2284
2638
|
) })
|
|
2285
2639
|
]
|
|
@@ -2289,7 +2643,9 @@ var SubscriptionCheckoutModal = ({
|
|
|
2289
2643
|
SubscriptionSuccessDialog,
|
|
2290
2644
|
{
|
|
2291
2645
|
open: showSuccess,
|
|
2292
|
-
onClose: () =>
|
|
2646
|
+
onClose: () => {
|
|
2647
|
+
setShowSuccess(false);
|
|
2648
|
+
},
|
|
2293
2649
|
planName,
|
|
2294
2650
|
amountLabel: amountLabel ?? `$${usdAmount.toFixed(2)}`,
|
|
2295
2651
|
billingPeriodLabel
|
|
@@ -2524,7 +2880,7 @@ var SolanaPaymentSelector = ({
|
|
|
2524
2880
|
}) => {
|
|
2525
2881
|
return /* @__PURE__ */ jsx(Dialog, { open: isOpen, onOpenChange: (value) => value ? void 0 : onClose(), children: /* @__PURE__ */ jsx(DialogContent, { className: "w-full max-w-2xl max-h-[90vh] overflow-y-auto rounded-md border bg-background/95 p-0 shadow-2xl [&::-webkit-scrollbar]:hidden", children: /* @__PURE__ */ jsx(SolanaPaymentView, { ...props, onClose }) }) });
|
|
2526
2882
|
};
|
|
2527
|
-
var Table =
|
|
2883
|
+
var Table = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ jsx(
|
|
2528
2884
|
"table",
|
|
2529
2885
|
{
|
|
2530
2886
|
ref,
|
|
@@ -2533,9 +2889,9 @@ var Table = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
|
|
|
2533
2889
|
}
|
|
2534
2890
|
) }));
|
|
2535
2891
|
Table.displayName = "Table";
|
|
2536
|
-
var TableHeader =
|
|
2892
|
+
var TableHeader = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("thead", { ref, className: cn("[&_tr]:border-b", className), ...props }));
|
|
2537
2893
|
TableHeader.displayName = "TableHeader";
|
|
2538
|
-
var TableBody =
|
|
2894
|
+
var TableBody = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2539
2895
|
"tbody",
|
|
2540
2896
|
{
|
|
2541
2897
|
ref,
|
|
@@ -2544,7 +2900,7 @@ var TableBody = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE_
|
|
|
2544
2900
|
}
|
|
2545
2901
|
));
|
|
2546
2902
|
TableBody.displayName = "TableBody";
|
|
2547
|
-
var TableFooter =
|
|
2903
|
+
var TableFooter = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2548
2904
|
"tfoot",
|
|
2549
2905
|
{
|
|
2550
2906
|
ref,
|
|
@@ -2556,7 +2912,7 @@ var TableFooter = React15.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
2556
2912
|
}
|
|
2557
2913
|
));
|
|
2558
2914
|
TableFooter.displayName = "TableFooter";
|
|
2559
|
-
var TableRow =
|
|
2915
|
+
var TableRow = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2560
2916
|
"tr",
|
|
2561
2917
|
{
|
|
2562
2918
|
ref,
|
|
@@ -2568,7 +2924,7 @@ var TableRow = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__
|
|
|
2568
2924
|
}
|
|
2569
2925
|
));
|
|
2570
2926
|
TableRow.displayName = "TableRow";
|
|
2571
|
-
var TableHead =
|
|
2927
|
+
var TableHead = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2572
2928
|
"th",
|
|
2573
2929
|
{
|
|
2574
2930
|
ref,
|
|
@@ -2580,7 +2936,7 @@ var TableHead = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE_
|
|
|
2580
2936
|
}
|
|
2581
2937
|
));
|
|
2582
2938
|
TableHead.displayName = "TableHead";
|
|
2583
|
-
var TableCell =
|
|
2939
|
+
var TableCell = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2584
2940
|
"td",
|
|
2585
2941
|
{
|
|
2586
2942
|
ref,
|
|
@@ -2589,7 +2945,7 @@ var TableCell = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE_
|
|
|
2589
2945
|
}
|
|
2590
2946
|
));
|
|
2591
2947
|
TableCell.displayName = "TableCell";
|
|
2592
|
-
var TableCaption =
|
|
2948
|
+
var TableCaption = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2593
2949
|
"caption",
|
|
2594
2950
|
{
|
|
2595
2951
|
ref,
|
|
@@ -2601,7 +2957,7 @@ TableCaption.displayName = "TableCaption";
|
|
|
2601
2957
|
var AlertDialog = AlertDialogPrimitive.Root;
|
|
2602
2958
|
var AlertDialogTrigger = AlertDialogPrimitive.Trigger;
|
|
2603
2959
|
var AlertDialogPortal = AlertDialogPrimitive.Portal;
|
|
2604
|
-
var AlertDialogOverlay =
|
|
2960
|
+
var AlertDialogOverlay = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2605
2961
|
AlertDialogPrimitive.Overlay,
|
|
2606
2962
|
{
|
|
2607
2963
|
className: cn(
|
|
@@ -2613,7 +2969,7 @@ var AlertDialogOverlay = React15.forwardRef(({ className, ...props }, ref) => /*
|
|
|
2613
2969
|
}
|
|
2614
2970
|
));
|
|
2615
2971
|
AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
|
|
2616
|
-
var AlertDialogContent =
|
|
2972
|
+
var AlertDialogContent = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs(AlertDialogPortal, { children: [
|
|
2617
2973
|
/* @__PURE__ */ jsx(AlertDialogOverlay, {}),
|
|
2618
2974
|
/* @__PURE__ */ jsx(
|
|
2619
2975
|
AlertDialogPrimitive.Content,
|
|
@@ -2656,7 +3012,7 @@ var AlertDialogFooter = ({
|
|
|
2656
3012
|
}
|
|
2657
3013
|
);
|
|
2658
3014
|
AlertDialogFooter.displayName = "AlertDialogFooter";
|
|
2659
|
-
var AlertDialogTitle =
|
|
3015
|
+
var AlertDialogTitle = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2660
3016
|
AlertDialogPrimitive.Title,
|
|
2661
3017
|
{
|
|
2662
3018
|
ref,
|
|
@@ -2665,7 +3021,7 @@ var AlertDialogTitle = React15.forwardRef(({ className, ...props }, ref) => /* @
|
|
|
2665
3021
|
}
|
|
2666
3022
|
));
|
|
2667
3023
|
AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
|
|
2668
|
-
var AlertDialogDescription =
|
|
3024
|
+
var AlertDialogDescription = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2669
3025
|
AlertDialogPrimitive.Description,
|
|
2670
3026
|
{
|
|
2671
3027
|
ref,
|
|
@@ -2674,7 +3030,7 @@ var AlertDialogDescription = React15.forwardRef(({ className, ...props }, ref) =
|
|
|
2674
3030
|
}
|
|
2675
3031
|
));
|
|
2676
3032
|
AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;
|
|
2677
|
-
var AlertDialogAction =
|
|
3033
|
+
var AlertDialogAction = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2678
3034
|
AlertDialogPrimitive.Action,
|
|
2679
3035
|
{
|
|
2680
3036
|
ref,
|
|
@@ -2683,7 +3039,7 @@ var AlertDialogAction = React15.forwardRef(({ className, ...props }, ref) => /*
|
|
|
2683
3039
|
}
|
|
2684
3040
|
));
|
|
2685
3041
|
AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
|
|
2686
|
-
var AlertDialogCancel =
|
|
3042
|
+
var AlertDialogCancel = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2687
3043
|
AlertDialogPrimitive.Cancel,
|
|
2688
3044
|
{
|
|
2689
3045
|
ref,
|
|
@@ -2696,7 +3052,7 @@ var AlertDialogCancel = React15.forwardRef(({ className, ...props }, ref) => /*
|
|
|
2696
3052
|
}
|
|
2697
3053
|
));
|
|
2698
3054
|
AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
|
|
2699
|
-
var Textarea =
|
|
3055
|
+
var Textarea = React4.forwardRef(({ className, ...props }, ref) => {
|
|
2700
3056
|
return /* @__PURE__ */ jsx(
|
|
2701
3057
|
"textarea",
|
|
2702
3058
|
{
|
|
@@ -2714,7 +3070,7 @@ var notifyDefault = (payload) => {
|
|
|
2714
3070
|
const level = payload.status === "destructive" ? "error" : "info";
|
|
2715
3071
|
console[level === "error" ? "error" : "log"]("[payments-ui] cancellation", payload);
|
|
2716
3072
|
};
|
|
2717
|
-
var
|
|
3073
|
+
var defaultTranslations3 = {
|
|
2718
3074
|
buttonLabel: "Cancel Membership",
|
|
2719
3075
|
title: "Confirm Membership Cancellation",
|
|
2720
3076
|
description: "You are about to cancel your membership. Please review the consequences:",
|
|
@@ -2736,23 +3092,33 @@ var CancelMembershipDialog = ({
|
|
|
2736
3092
|
minReasonLength = 15,
|
|
2737
3093
|
onCancelled,
|
|
2738
3094
|
onNotify,
|
|
2739
|
-
translations: customTranslations
|
|
3095
|
+
translations: customTranslations,
|
|
3096
|
+
open,
|
|
3097
|
+
onOpenChange
|
|
2740
3098
|
}) => {
|
|
2741
3099
|
const { client } = usePaymentContext();
|
|
2742
3100
|
const notify = onNotify ?? notifyDefault;
|
|
2743
|
-
const t = { ...
|
|
3101
|
+
const t = { ...defaultTranslations3, ...customTranslations };
|
|
2744
3102
|
const [cancelReason, setCancelReason] = useState("");
|
|
2745
|
-
const [
|
|
3103
|
+
const [internalOpen, setInternalOpen] = useState(false);
|
|
2746
3104
|
const [isReasonValid, setIsReasonValid] = useState(false);
|
|
2747
3105
|
const [hasInteracted, setHasInteracted] = useState(false);
|
|
2748
3106
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
3107
|
+
const isControlled = typeof open === "boolean";
|
|
3108
|
+
const isOpen = isControlled ? open : internalOpen;
|
|
3109
|
+
const setOpen = (next) => {
|
|
3110
|
+
if (!isControlled) {
|
|
3111
|
+
setInternalOpen(next);
|
|
3112
|
+
}
|
|
3113
|
+
onOpenChange?.(next);
|
|
3114
|
+
};
|
|
2749
3115
|
useEffect(() => {
|
|
2750
3116
|
const trimmed = cancelReason.trim();
|
|
2751
3117
|
setIsReasonValid(trimmed.length >= minReasonLength);
|
|
2752
3118
|
}, [cancelReason, minReasonLength]);
|
|
2753
|
-
const handleOpenChange = (
|
|
2754
|
-
|
|
2755
|
-
if (!
|
|
3119
|
+
const handleOpenChange = (open2) => {
|
|
3120
|
+
setOpen(open2);
|
|
3121
|
+
if (!open2) {
|
|
2756
3122
|
setCancelReason("");
|
|
2757
3123
|
setIsReasonValid(false);
|
|
2758
3124
|
setHasInteracted(false);
|
|
@@ -2789,7 +3155,7 @@ var CancelMembershipDialog = ({
|
|
|
2789
3155
|
};
|
|
2790
3156
|
const showError = hasInteracted && !isReasonValid;
|
|
2791
3157
|
return /* @__PURE__ */ jsxs(AlertDialog, { open: isOpen, onOpenChange: handleOpenChange, children: [
|
|
2792
|
-
/* @__PURE__ */ jsx(AlertDialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, {
|
|
3158
|
+
/* @__PURE__ */ jsx(AlertDialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { className: "bg-destructive text-destructive-foreground border-destructive/50 hover:bg-destructive/90", children: [
|
|
2793
3159
|
/* @__PURE__ */ jsx(Ban, { className: "mr-2 h-4 w-4" }),
|
|
2794
3160
|
" ",
|
|
2795
3161
|
t.buttonLabel
|
|
@@ -2856,7 +3222,7 @@ var notifyDefault2 = (payload) => {
|
|
|
2856
3222
|
const level = payload.status === "destructive" ? "error" : "info";
|
|
2857
3223
|
console[level === "error" ? "error" : "log"]("[payments-ui] billing", payload);
|
|
2858
3224
|
};
|
|
2859
|
-
var
|
|
3225
|
+
var defaultTranslations4 = {
|
|
2860
3226
|
title: "Transaction History",
|
|
2861
3227
|
description: "Record of billing history",
|
|
2862
3228
|
reviewActivity: "Review your account activity below",
|
|
@@ -2878,7 +3244,7 @@ var BillingHistory = ({
|
|
|
2878
3244
|
}) => {
|
|
2879
3245
|
const { client } = usePaymentContext();
|
|
2880
3246
|
const notify = onNotify ?? notifyDefault2;
|
|
2881
|
-
const t = { ...
|
|
3247
|
+
const t = { ...defaultTranslations4, ...customTranslations };
|
|
2882
3248
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
2883
3249
|
const observerRef = useRef(null);
|
|
2884
3250
|
const loadMoreRef = useRef(null);
|
|
@@ -2987,15 +3353,21 @@ var BillingHistory = ({
|
|
|
2987
3353
|
] }) });
|
|
2988
3354
|
};
|
|
2989
3355
|
var formatCardLabel2 = (method) => {
|
|
2990
|
-
|
|
2991
|
-
|
|
3356
|
+
if (method.card) {
|
|
3357
|
+
const brand2 = method.card.brand ? method.card.brand.toUpperCase() : "CARD";
|
|
3358
|
+
const lastFour2 = method.card.last4 ? `\u2022\u2022\u2022\u2022 ${method.card.last4}` : "";
|
|
3359
|
+
const exp = method.card.exp_month && method.card.exp_year ? ` \u2022 ${String(method.card.exp_month).padStart(2, "0")}/${String(method.card.exp_year).slice(-2)}` : "";
|
|
3360
|
+
return `${brand2} ${lastFour2}${exp}`.trim();
|
|
3361
|
+
}
|
|
3362
|
+
const brand = "CARD";
|
|
3363
|
+
const lastFour = "";
|
|
2992
3364
|
return `${brand} ${lastFour}`.trim();
|
|
2993
3365
|
};
|
|
2994
3366
|
var notifyDefault3 = (payload) => {
|
|
2995
3367
|
const level = payload.status === "destructive" ? "error" : "info";
|
|
2996
3368
|
console[level === "error" ? "error" : "log"]("[payments-ui] notification", payload);
|
|
2997
3369
|
};
|
|
2998
|
-
var
|
|
3370
|
+
var defaultTranslations5 = {
|
|
2999
3371
|
title: "Payment Methods",
|
|
3000
3372
|
description: "Manage your saved billing cards",
|
|
3001
3373
|
addCard: "Add card",
|
|
@@ -3016,7 +3388,11 @@ var defaultTranslations3 = {
|
|
|
3016
3388
|
cardUpdated: "Card updated",
|
|
3017
3389
|
unableToRemoveCard: "Unable to remove card",
|
|
3018
3390
|
defaultPaymentMethodUpdated: "Default payment method updated",
|
|
3019
|
-
unableToSetDefault: "Unable to set default payment method"
|
|
3391
|
+
unableToSetDefault: "Unable to set default payment method",
|
|
3392
|
+
errors: {},
|
|
3393
|
+
activeSubscriptions: "Active subscriptions",
|
|
3394
|
+
showSubscriptions: "Show",
|
|
3395
|
+
hideSubscriptions: "Hide"
|
|
3020
3396
|
};
|
|
3021
3397
|
var PaymentMethodsSection = ({
|
|
3022
3398
|
isAuthenticated = true,
|
|
@@ -3027,8 +3403,7 @@ var PaymentMethodsSection = ({
|
|
|
3027
3403
|
onNotify,
|
|
3028
3404
|
translations: customTranslations
|
|
3029
3405
|
}) => {
|
|
3030
|
-
const { client } = usePaymentContext();
|
|
3031
|
-
const queryClient = useQueryClient();
|
|
3406
|
+
const { client, queryClient } = usePaymentContext();
|
|
3032
3407
|
const paymentMethods = {
|
|
3033
3408
|
list: (params) => client.listPaymentMethods({ limit: params.pageSize }),
|
|
3034
3409
|
create: (payload) => client.createPaymentMethod(payload),
|
|
@@ -3038,13 +3413,15 @@ var PaymentMethodsSection = ({
|
|
|
3038
3413
|
};
|
|
3039
3414
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
3040
3415
|
const [deletingId, setDeletingId] = useState(null);
|
|
3416
|
+
const [createErrorMessage, setCreateErrorMessage] = useState(null);
|
|
3417
|
+
const [expandedSubscriptions, setExpandedSubscriptions] = useState({});
|
|
3041
3418
|
const notify = onNotify ?? notifyDefault3;
|
|
3042
|
-
const t = { ...
|
|
3419
|
+
const t = { ...defaultTranslations5, ...customTranslations };
|
|
3043
3420
|
const queryKey = ["payments-ui", "payment-methods"];
|
|
3044
3421
|
const paymentQuery = useQuery({
|
|
3045
3422
|
queryKey,
|
|
3046
3423
|
queryFn: () => paymentMethods.list({ pageSize: 50 }),
|
|
3047
|
-
enabled: isAuthenticated,
|
|
3424
|
+
enabled: isAuthenticated && !!client,
|
|
3048
3425
|
staleTime: 3e4
|
|
3049
3426
|
});
|
|
3050
3427
|
const createMutation = useMutation({
|
|
@@ -3053,11 +3430,14 @@ var PaymentMethodsSection = ({
|
|
|
3053
3430
|
notify({ title: t.cardAddedSuccess, status: "success" });
|
|
3054
3431
|
setIsModalOpen(false);
|
|
3055
3432
|
void queryClient.invalidateQueries({ queryKey });
|
|
3433
|
+
setCreateErrorMessage(null);
|
|
3056
3434
|
},
|
|
3057
3435
|
onError: (error) => {
|
|
3436
|
+
const message = resolveErrorMessageByCode(error, t.errors, error.message);
|
|
3437
|
+
setCreateErrorMessage(message);
|
|
3058
3438
|
notify({
|
|
3059
3439
|
title: t.unableToAddCard,
|
|
3060
|
-
description:
|
|
3440
|
+
description: message,
|
|
3061
3441
|
status: "destructive"
|
|
3062
3442
|
});
|
|
3063
3443
|
}
|
|
@@ -3068,6 +3448,9 @@ var PaymentMethodsSection = ({
|
|
|
3068
3448
|
onSuccess: () => {
|
|
3069
3449
|
notify({ title: t.cardRemoved, status: "success" });
|
|
3070
3450
|
void queryClient.invalidateQueries({ queryKey });
|
|
3451
|
+
if (paymentQuery.refetch) {
|
|
3452
|
+
paymentQuery.refetch();
|
|
3453
|
+
}
|
|
3071
3454
|
},
|
|
3072
3455
|
onError: (error) => {
|
|
3073
3456
|
notify({
|
|
@@ -3078,7 +3461,7 @@ var PaymentMethodsSection = ({
|
|
|
3078
3461
|
},
|
|
3079
3462
|
onSettled: () => setDeletingId(null)
|
|
3080
3463
|
});
|
|
3081
|
-
|
|
3464
|
+
useMutation({
|
|
3082
3465
|
mutationFn: (id) => paymentMethods.activate(id),
|
|
3083
3466
|
onSuccess: () => {
|
|
3084
3467
|
notify({ title: t.defaultPaymentMethodUpdated, status: "success" });
|
|
@@ -3095,8 +3478,14 @@ var PaymentMethodsSection = ({
|
|
|
3095
3478
|
useEffect(() => {
|
|
3096
3479
|
if (!isModalOpen) {
|
|
3097
3480
|
createMutation.reset();
|
|
3481
|
+
setCreateErrorMessage(null);
|
|
3482
|
+
}
|
|
3483
|
+
}, [isModalOpen]);
|
|
3484
|
+
useEffect(() => {
|
|
3485
|
+
if (!isModalOpen && paymentQuery.refetch) {
|
|
3486
|
+
paymentQuery.refetch();
|
|
3098
3487
|
}
|
|
3099
|
-
}, [
|
|
3488
|
+
}, [isModalOpen]);
|
|
3100
3489
|
const payments = useMemo(() => paymentQuery.data?.data ?? [], [paymentQuery.data]);
|
|
3101
3490
|
const loading = paymentQuery.isLoading || paymentQuery.isFetching;
|
|
3102
3491
|
const buildPayload = (token, billing) => ({
|
|
@@ -3110,9 +3499,13 @@ var PaymentMethodsSection = ({
|
|
|
3110
3499
|
zip: billing.postalCode,
|
|
3111
3500
|
country: billing.country,
|
|
3112
3501
|
email: billing.email,
|
|
3113
|
-
provider: billing.provider
|
|
3502
|
+
provider: billing.provider,
|
|
3503
|
+
last_four: billing.last_four,
|
|
3504
|
+
card_type: billing.card_type,
|
|
3505
|
+
expiry_date: billing.expiry_date
|
|
3114
3506
|
});
|
|
3115
3507
|
const handleCardTokenize = (token, billing) => {
|
|
3508
|
+
setCreateErrorMessage(null);
|
|
3116
3509
|
createMutation.mutate(buildPayload(token, billing));
|
|
3117
3510
|
};
|
|
3118
3511
|
return /* @__PURE__ */ jsxs(Card, { className: "border-0 bg-black/30 shadow-2xl backdrop-blur-xl", children: [
|
|
@@ -3131,32 +3524,19 @@ var PaymentMethodsSection = ({
|
|
|
3131
3524
|
/* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" }),
|
|
3132
3525
|
" ",
|
|
3133
3526
|
t.loadingCards
|
|
3134
|
-
] }) : payments.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-6 text-sm text-center", children: t.noPaymentMethods }) : /* @__PURE__ */ jsx("div", { className: "space-y-3", children: payments.map((method) =>
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3527
|
+
] }) : payments.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-6 text-sm text-center", children: t.noPaymentMethods }) : /* @__PURE__ */ jsx("div", { className: "space-y-3", children: payments.map((method) => {
|
|
3528
|
+
(method.subscriptions?.length ?? 0) > 0;
|
|
3529
|
+
expandedSubscriptions[method.id] ?? false;
|
|
3530
|
+
return /* @__PURE__ */ jsxs(
|
|
3531
|
+
"div",
|
|
3532
|
+
{
|
|
3533
|
+
className: "rounded-lg border bg-white/5 p-4 shadow-sm",
|
|
3534
|
+
children: [
|
|
3535
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
3536
|
+
/* @__PURE__ */ jsx("div", { className: "flex justify-between", children: /* @__PURE__ */ jsx("div", { className: "text-base font-medium text-white", children: formatCardLabel2(method) }) }),
|
|
3537
|
+
/* @__PURE__ */ jsx("div", { children: method.failure_reason && /* @__PURE__ */ jsx(Badge, { variant: "destructive", children: method.failure_reason }) })
|
|
3143
3538
|
] }),
|
|
3144
|
-
/* @__PURE__ */ jsx("div", {
|
|
3145
|
-
] }),
|
|
3146
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-3 flex flex-wrap gap-2", children: [
|
|
3147
|
-
/* @__PURE__ */ jsxs(
|
|
3148
|
-
Button,
|
|
3149
|
-
{
|
|
3150
|
-
variant: "outline",
|
|
3151
|
-
disabled: method.is_active || activateMutation.isPending,
|
|
3152
|
-
onClick: () => activateMutation.mutate(method.id),
|
|
3153
|
-
children: [
|
|
3154
|
-
activateMutation.isPending ? /* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : null,
|
|
3155
|
-
method.is_active ? t.defaultMethod : t.makeDefault
|
|
3156
|
-
]
|
|
3157
|
-
}
|
|
3158
|
-
),
|
|
3159
|
-
/* @__PURE__ */ jsxs(
|
|
3539
|
+
/* @__PURE__ */ jsx("div", { className: "mt-3 flex flex-wrap gap-2", children: /* @__PURE__ */ jsxs(
|
|
3160
3540
|
Button,
|
|
3161
3541
|
{
|
|
3162
3542
|
variant: "ghost",
|
|
@@ -3168,12 +3548,12 @@ var PaymentMethodsSection = ({
|
|
|
3168
3548
|
t.remove
|
|
3169
3549
|
]
|
|
3170
3550
|
}
|
|
3171
|
-
)
|
|
3172
|
-
]
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
)
|
|
3551
|
+
) })
|
|
3552
|
+
]
|
|
3553
|
+
},
|
|
3554
|
+
method.id
|
|
3555
|
+
);
|
|
3556
|
+
}) }) }),
|
|
3177
3557
|
/* @__PURE__ */ jsx(Dialog, { open: isModalOpen, onOpenChange: setIsModalOpen, children: /* @__PURE__ */ jsxs(
|
|
3178
3558
|
DialogContent,
|
|
3179
3559
|
{
|
|
@@ -3191,12 +3571,13 @@ var PaymentMethodsSection = ({
|
|
|
3191
3571
|
collectPrefix,
|
|
3192
3572
|
onTokenize: handleCardTokenize,
|
|
3193
3573
|
submitting: createMutation.isPending,
|
|
3574
|
+
translations: t,
|
|
3194
3575
|
defaultValues: {
|
|
3195
3576
|
provider,
|
|
3196
3577
|
email: userEmail ?? "",
|
|
3197
3578
|
country: defaultCountry
|
|
3198
3579
|
},
|
|
3199
|
-
externalError:
|
|
3580
|
+
externalError: createErrorMessage
|
|
3200
3581
|
}
|
|
3201
3582
|
)
|
|
3202
3583
|
]
|
|
@@ -3204,7 +3585,388 @@ var PaymentMethodsSection = ({
|
|
|
3204
3585
|
) })
|
|
3205
3586
|
] });
|
|
3206
3587
|
};
|
|
3207
|
-
var
|
|
3588
|
+
var notifyDefault4 = (payload) => {
|
|
3589
|
+
const level = payload.status === "destructive" ? "error" : "info";
|
|
3590
|
+
console[level === "error" ? "error" : "log"]("[payments-ui] notification", payload);
|
|
3591
|
+
};
|
|
3592
|
+
var defaultTranslations6 = {
|
|
3593
|
+
title: "Subscriptions",
|
|
3594
|
+
description: "Manage your active and recent subscriptions.",
|
|
3595
|
+
loading: "Loading subscriptions...",
|
|
3596
|
+
noSubscriptions: "No subscriptions found.",
|
|
3597
|
+
status: "Status",
|
|
3598
|
+
active: "Active",
|
|
3599
|
+
cancelled: "Cancelled",
|
|
3600
|
+
pastDue: "Past due",
|
|
3601
|
+
pending: "Pending",
|
|
3602
|
+
paymentMethodLabel: "Payment method",
|
|
3603
|
+
changePaymentMethod: "Change payment method",
|
|
3604
|
+
paymentMethodUpdated: "Payment method updated",
|
|
3605
|
+
paymentMethodUpdateFailed: "Unable to update payment method",
|
|
3606
|
+
resume: "Resume subscription",
|
|
3607
|
+
changePlan: "Change plan",
|
|
3608
|
+
changePlanPlaceholder: "Enter a new price ID",
|
|
3609
|
+
planChanged: "Subscription updated",
|
|
3610
|
+
planChangeFailed: "Unable to update subscription",
|
|
3611
|
+
planChangeUnavailable: "Plan changes are unavailable for this subscription.",
|
|
3612
|
+
resumeSuccess: "Resume requested",
|
|
3613
|
+
resumeFailed: "Unable to resume subscription",
|
|
3614
|
+
update: "Update",
|
|
3615
|
+
product: "Product",
|
|
3616
|
+
price: "Price",
|
|
3617
|
+
currentPeriod: "Current period",
|
|
3618
|
+
refresh: "Refresh",
|
|
3619
|
+
manage: "Manage",
|
|
3620
|
+
close: "Close",
|
|
3621
|
+
paymentMethodTab: "Payment method",
|
|
3622
|
+
changePlanTab: "Change plan",
|
|
3623
|
+
statusTab: "Details",
|
|
3624
|
+
cancelTab: "Cancel/Resume"
|
|
3625
|
+
};
|
|
3626
|
+
var formatCardLabel3 = (method) => {
|
|
3627
|
+
if (method.card) {
|
|
3628
|
+
const brand2 = method.card.brand ? method.card.brand.toUpperCase() : "CARD";
|
|
3629
|
+
const lastFour2 = method.card.last4 ? `\u2022\u2022\u2022\u2022 ${method.card.last4}` : "";
|
|
3630
|
+
const exp = method.card.exp_month && method.card.exp_year ? ` \u2022 ${String(method.card.exp_month).padStart(2, "0")}/${String(method.card.exp_year).slice(-2)}` : "";
|
|
3631
|
+
return `${brand2} ${lastFour2}${exp}`.trim();
|
|
3632
|
+
}
|
|
3633
|
+
const brand = "CARD";
|
|
3634
|
+
const lastFour = "";
|
|
3635
|
+
return `${brand} ${lastFour}`.trim();
|
|
3636
|
+
};
|
|
3637
|
+
var SubscriptionsSection = ({
|
|
3638
|
+
isAuthenticated = true,
|
|
3639
|
+
translations: customTranslations,
|
|
3640
|
+
onNotify,
|
|
3641
|
+
statusFilter,
|
|
3642
|
+
cancelDialogTranslations,
|
|
3643
|
+
onCancelled
|
|
3644
|
+
}) => {
|
|
3645
|
+
const { client, queryClient } = usePaymentContext();
|
|
3646
|
+
const notify = onNotify ?? notifyDefault4;
|
|
3647
|
+
const t = { ...defaultTranslations6, ...customTranslations };
|
|
3648
|
+
const cancelTranslations = cancelDialogTranslations ?? defaultTranslations3;
|
|
3649
|
+
const [paymentSelections, setPaymentSelections] = useState({});
|
|
3650
|
+
const [priceInputs, setPriceInputs] = useState({});
|
|
3651
|
+
const [activeSubId, setActiveSubId] = useState(null);
|
|
3652
|
+
const [cancelDialogOpen, setCancelDialogOpen] = useState(false);
|
|
3653
|
+
const [sectionsOpen, setSectionsOpen] = useState({
|
|
3654
|
+
status: true,
|
|
3655
|
+
payment: false,
|
|
3656
|
+
plan: false,
|
|
3657
|
+
cancel: false
|
|
3658
|
+
});
|
|
3659
|
+
const normalizedStatusFilter = statusFilter ?? "all";
|
|
3660
|
+
const subscriptionsQueryKey = ["payments-ui", "subscriptions", normalizedStatusFilter];
|
|
3661
|
+
const paymentMethodsQueryKey = ["payments-ui", "payment-methods"];
|
|
3662
|
+
const subscriptionsQuery = useQuery({
|
|
3663
|
+
queryKey: subscriptionsQueryKey,
|
|
3664
|
+
queryFn: () => client.listSubscriptions({
|
|
3665
|
+
status: normalizedStatusFilter,
|
|
3666
|
+
limit: 50
|
|
3667
|
+
}),
|
|
3668
|
+
enabled: isAuthenticated && !!client,
|
|
3669
|
+
staleTime: 3e4
|
|
3670
|
+
});
|
|
3671
|
+
const paymentMethodsQuery = useQuery({
|
|
3672
|
+
queryKey: paymentMethodsQueryKey,
|
|
3673
|
+
queryFn: () => client.listPaymentMethods({ limit: 50 }),
|
|
3674
|
+
enabled: isAuthenticated && !!client,
|
|
3675
|
+
staleTime: 3e4
|
|
3676
|
+
});
|
|
3677
|
+
const subscriptions = useMemo(() => subscriptionsQuery.data?.data ?? [], [subscriptionsQuery.data]);
|
|
3678
|
+
const paymentMethods = useMemo(() => paymentMethodsQuery.data?.data ?? [], [paymentMethodsQuery.data]);
|
|
3679
|
+
const activeSubscription = useMemo(
|
|
3680
|
+
() => subscriptions.find((sub) => sub.id === activeSubId),
|
|
3681
|
+
[subscriptions, activeSubId]
|
|
3682
|
+
);
|
|
3683
|
+
useEffect(() => {
|
|
3684
|
+
setPaymentSelections((prev) => {
|
|
3685
|
+
const next = {};
|
|
3686
|
+
subscriptions.forEach((sub) => {
|
|
3687
|
+
next[sub.id] = prev[sub.id] ?? "";
|
|
3688
|
+
});
|
|
3689
|
+
return next;
|
|
3690
|
+
});
|
|
3691
|
+
}, [subscriptions]);
|
|
3692
|
+
useEffect(() => {
|
|
3693
|
+
setCancelDialogOpen(false);
|
|
3694
|
+
}, [activeSubId]);
|
|
3695
|
+
const updatePaymentMethodMutation = useMutation({
|
|
3696
|
+
mutationFn: (payload) => client.updateSubscriptionPaymentMethod({
|
|
3697
|
+
subscription_id: payload.subscriptionId,
|
|
3698
|
+
payment_method_id: payload.paymentMethodId
|
|
3699
|
+
}),
|
|
3700
|
+
onSuccess: () => {
|
|
3701
|
+
notify({ title: t.paymentMethodUpdated, status: "success" });
|
|
3702
|
+
void queryClient.invalidateQueries({ queryKey: subscriptionsQueryKey });
|
|
3703
|
+
},
|
|
3704
|
+
onError: (error) => {
|
|
3705
|
+
notify({
|
|
3706
|
+
title: t.paymentMethodUpdateFailed,
|
|
3707
|
+
description: resolveErrorMessageByCode(error, {}, error.message),
|
|
3708
|
+
status: "destructive"
|
|
3709
|
+
});
|
|
3710
|
+
}
|
|
3711
|
+
});
|
|
3712
|
+
const resumeSubscriptionMutation = useMutation({
|
|
3713
|
+
mutationFn: () => client.resumeSubscription(),
|
|
3714
|
+
onSuccess: () => {
|
|
3715
|
+
notify({ title: t.resumeSuccess, status: "success" });
|
|
3716
|
+
void queryClient.invalidateQueries({ queryKey: subscriptionsQueryKey });
|
|
3717
|
+
},
|
|
3718
|
+
onError: (error) => {
|
|
3719
|
+
notify({
|
|
3720
|
+
title: t.resumeFailed,
|
|
3721
|
+
description: resolveErrorMessageByCode(error, {}, error.message),
|
|
3722
|
+
status: "destructive"
|
|
3723
|
+
});
|
|
3724
|
+
}
|
|
3725
|
+
});
|
|
3726
|
+
useMutation({
|
|
3727
|
+
mutationFn: (payload) => client.changeSubscription({ price_id: payload.priceId }),
|
|
3728
|
+
onSuccess: () => {
|
|
3729
|
+
notify({ title: t.planChanged, status: "success" });
|
|
3730
|
+
void queryClient.invalidateQueries({ queryKey: subscriptionsQueryKey });
|
|
3731
|
+
},
|
|
3732
|
+
onError: (error) => {
|
|
3733
|
+
notify({
|
|
3734
|
+
title: t.planChangeFailed,
|
|
3735
|
+
description: resolveErrorMessageByCode(error, {}, error.message),
|
|
3736
|
+
status: "destructive"
|
|
3737
|
+
});
|
|
3738
|
+
}
|
|
3739
|
+
});
|
|
3740
|
+
const isLoading = subscriptionsQuery.isLoading || subscriptionsQuery.isFetching;
|
|
3741
|
+
const isError = subscriptionsQuery.isError;
|
|
3742
|
+
const errorMessage = subscriptionsQuery.error instanceof Error ? subscriptionsQuery.error.message : void 0;
|
|
3743
|
+
useEffect(() => {
|
|
3744
|
+
if (subscriptionsQuery.refetch) {
|
|
3745
|
+
void subscriptionsQuery.refetch();
|
|
3746
|
+
}
|
|
3747
|
+
}, []);
|
|
3748
|
+
const formatPrice = (sub) => {
|
|
3749
|
+
const price = sub.price;
|
|
3750
|
+
if (!price) return t.price;
|
|
3751
|
+
const amount = (price.amount / 100).toFixed(2);
|
|
3752
|
+
const currency = price.currency ? price.currency?.toUpperCase() : "";
|
|
3753
|
+
return `${price.display_name ?? t.price} \u2014 ${currency} ${amount}`;
|
|
3754
|
+
};
|
|
3755
|
+
const renderStatusBadge = (status) => {
|
|
3756
|
+
const normalized = status.toLowerCase();
|
|
3757
|
+
const label = normalized === "active" ? t.active : normalized === "past_due" ? t.pastDue : normalized === "pending" ? t.pending : t.cancelled;
|
|
3758
|
+
const variant = normalized === "active" ? "default" : normalized === "past_due" ? "destructive" : normalized === "pending" ? "outline" : "secondary";
|
|
3759
|
+
return /* @__PURE__ */ jsx(Badge, { variant, children: label });
|
|
3760
|
+
};
|
|
3761
|
+
const handleUpdatePaymentMethod = (subscriptionId) => {
|
|
3762
|
+
const paymentMethodId = paymentSelections[subscriptionId];
|
|
3763
|
+
const currentPaymentMethodId = "pm_" + subscriptions.find((s) => s.id === subscriptionId)?.payment_method_id;
|
|
3764
|
+
if (!paymentMethodId) return;
|
|
3765
|
+
if (currentPaymentMethodId && paymentMethodId === currentPaymentMethodId) {
|
|
3766
|
+
notify({
|
|
3767
|
+
title: t.paymentMethodUpdateFailed,
|
|
3768
|
+
description: t.paymentMethodUpdateFailed,
|
|
3769
|
+
status: "destructive"
|
|
3770
|
+
});
|
|
3771
|
+
return;
|
|
3772
|
+
}
|
|
3773
|
+
updatePaymentMethodMutation.mutate({ subscriptionId, paymentMethodId });
|
|
3774
|
+
};
|
|
3775
|
+
const toggleSection = (key) => {
|
|
3776
|
+
setSectionsOpen((prev) => ({
|
|
3777
|
+
...prev,
|
|
3778
|
+
[key]: !prev[key]
|
|
3779
|
+
}));
|
|
3780
|
+
};
|
|
3781
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3782
|
+
/* @__PURE__ */ jsxs(Card, { className: "border-0 bg-black/30 shadow-2xl backdrop-blur-xl", children: [
|
|
3783
|
+
/* @__PURE__ */ jsxs(CardHeader, { className: "flex flex-col gap-4 md:flex-row md:items-center md:justify-between", children: [
|
|
3784
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
3785
|
+
/* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center gap-2", children: [
|
|
3786
|
+
/* @__PURE__ */ jsx(WalletCards, { className: "h-5 w-5" }),
|
|
3787
|
+
t.title
|
|
3788
|
+
] }),
|
|
3789
|
+
/* @__PURE__ */ jsx(CardDescription, { children: t.description })
|
|
3790
|
+
] }),
|
|
3791
|
+
/* @__PURE__ */ jsxs(
|
|
3792
|
+
Button,
|
|
3793
|
+
{
|
|
3794
|
+
variant: "ghost",
|
|
3795
|
+
size: "sm",
|
|
3796
|
+
onClick: () => subscriptionsQuery.refetch?.(),
|
|
3797
|
+
disabled: subscriptionsQuery.isFetching,
|
|
3798
|
+
children: [
|
|
3799
|
+
/* @__PURE__ */ jsx(RefreshCw, { className: "mr-2 h-4 w-4" }),
|
|
3800
|
+
" ",
|
|
3801
|
+
subscriptionsQuery.isFetching ? t.loading : t.refresh
|
|
3802
|
+
]
|
|
3803
|
+
}
|
|
3804
|
+
)
|
|
3805
|
+
] }),
|
|
3806
|
+
/* @__PURE__ */ jsx(CardContent, { className: "space-y-4", children: isLoading ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center py-10 text-white/60", children: [
|
|
3807
|
+
/* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" }),
|
|
3808
|
+
" ",
|
|
3809
|
+
t.loading
|
|
3810
|
+
] }) : isError ? /* @__PURE__ */ jsx("div", { className: "rounded-md border border-red-500/30 bg-red-500/10 p-4 text-sm text-red-100", children: errorMessage ?? "Unable to load subscriptions." }) : subscriptions.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-6 text-sm text-center", children: t.noSubscriptions }) : /* @__PURE__ */ jsx("div", { className: "space-y-3", children: subscriptions.map((subscription) => {
|
|
3811
|
+
return /* @__PURE__ */ jsx(
|
|
3812
|
+
"div",
|
|
3813
|
+
{
|
|
3814
|
+
className: "rounded-lg border bg-white/5 p-4 shadow-sm",
|
|
3815
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4", children: [
|
|
3816
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
3817
|
+
/* @__PURE__ */ jsx("div", { className: "text-base font-semibold text-white", children: subscription.product?.display_name ?? t.product }),
|
|
3818
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm text-white/80", children: formatPrice(subscription) })
|
|
3819
|
+
] }),
|
|
3820
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3821
|
+
renderStatusBadge(subscription.status),
|
|
3822
|
+
/* @__PURE__ */ jsx(
|
|
3823
|
+
Button,
|
|
3824
|
+
{
|
|
3825
|
+
variant: "default",
|
|
3826
|
+
size: "sm",
|
|
3827
|
+
className: "rounded-full bg-foreground/10 text-muted-foreground hover:bg-foreground/20 hover:text-foreground",
|
|
3828
|
+
onClick: () => setActiveSubId(subscription.id),
|
|
3829
|
+
children: t.update
|
|
3830
|
+
}
|
|
3831
|
+
)
|
|
3832
|
+
] })
|
|
3833
|
+
] })
|
|
3834
|
+
},
|
|
3835
|
+
subscription.id
|
|
3836
|
+
);
|
|
3837
|
+
}) }) })
|
|
3838
|
+
] }),
|
|
3839
|
+
/* @__PURE__ */ jsx(Dialog, { open: !!activeSubscription, onOpenChange: (open) => setActiveSubId(open ? activeSubId : null), children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-2xl min-h-[300px] border border-white/20 bg-background-regular p-6 text-foreground", children: [
|
|
3840
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
3841
|
+
/* @__PURE__ */ jsx(DialogTitle, { className: "flex items-center gap-2", children: activeSubscription?.product?.display_name ?? t.product }),
|
|
3842
|
+
/* @__PURE__ */ jsx(DialogDescription, { className: "text-white/70", children: activeSubscription ? formatPrice(activeSubscription) : null })
|
|
3843
|
+
] }),
|
|
3844
|
+
activeSubscription && /* @__PURE__ */ jsxs("div", { className: "mt-4 space-y-3", children: [
|
|
3845
|
+
/* @__PURE__ */ jsxs("div", { className: "overflow-hidden rounded-lg border border-white/15 bg-white/5", children: [
|
|
3846
|
+
/* @__PURE__ */ jsxs(
|
|
3847
|
+
"button",
|
|
3848
|
+
{
|
|
3849
|
+
type: "button",
|
|
3850
|
+
className: "flex w-full items-center justify-between px-4 py-3 text-left text-white hover:bg-white/10",
|
|
3851
|
+
onClick: () => toggleSection("status"),
|
|
3852
|
+
children: [
|
|
3853
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold", children: t.statusTab }),
|
|
3854
|
+
/* @__PURE__ */ jsx(
|
|
3855
|
+
ChevronDown,
|
|
3856
|
+
{
|
|
3857
|
+
className: `h-4 w-4 transition-transform ${sectionsOpen.status ? "rotate-180" : ""}`
|
|
3858
|
+
}
|
|
3859
|
+
)
|
|
3860
|
+
]
|
|
3861
|
+
}
|
|
3862
|
+
),
|
|
3863
|
+
sectionsOpen.status ? /* @__PURE__ */ jsxs("div", { className: "space-y-3 border-t border-white/10 px-4 py-3", children: [
|
|
3864
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between rounded-lg border border-white/10 bg-white/5 p-3", children: [
|
|
3865
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium text-white/80", children: t.status }),
|
|
3866
|
+
renderStatusBadge(activeSubscription.status)
|
|
3867
|
+
] }),
|
|
3868
|
+
/* @__PURE__ */ jsxs("div", { className: "text-xs text-white/60", children: [
|
|
3869
|
+
t.currentPeriod,
|
|
3870
|
+
": ",
|
|
3871
|
+
activeSubscription.started_at ? new Date(activeSubscription.started_at).toLocaleDateString() : "\u2014",
|
|
3872
|
+
" \u2192",
|
|
3873
|
+
" ",
|
|
3874
|
+
activeSubscription.current_period_ends_at ?? "\u2014"
|
|
3875
|
+
] }),
|
|
3876
|
+
activeSubscription.status.toLowerCase() === "cancelled" ? /* @__PURE__ */ jsxs(
|
|
3877
|
+
Button,
|
|
3878
|
+
{
|
|
3879
|
+
variant: "secondary",
|
|
3880
|
+
onClick: () => resumeSubscriptionMutation.mutate(),
|
|
3881
|
+
disabled: resumeSubscriptionMutation.isPending,
|
|
3882
|
+
className: "rounded-full px-4",
|
|
3883
|
+
children: [
|
|
3884
|
+
resumeSubscriptionMutation.isPending ? /* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : null,
|
|
3885
|
+
t.resume
|
|
3886
|
+
]
|
|
3887
|
+
}
|
|
3888
|
+
) : null
|
|
3889
|
+
] }) : null
|
|
3890
|
+
] }),
|
|
3891
|
+
/* @__PURE__ */ jsxs("div", { className: "overflow-hidden rounded-lg border border-white/15 bg-white/5", children: [
|
|
3892
|
+
/* @__PURE__ */ jsxs(
|
|
3893
|
+
"button",
|
|
3894
|
+
{
|
|
3895
|
+
type: "button",
|
|
3896
|
+
className: "flex w-full items-center justify-between px-4 py-3 text-left text-white hover:bg-white/10",
|
|
3897
|
+
onClick: () => toggleSection("payment"),
|
|
3898
|
+
children: [
|
|
3899
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold", children: t.paymentMethodTab }),
|
|
3900
|
+
/* @__PURE__ */ jsx(
|
|
3901
|
+
ChevronDown,
|
|
3902
|
+
{
|
|
3903
|
+
className: `h-4 w-4 transition-transform ${sectionsOpen.payment ? "rotate-180" : ""}`
|
|
3904
|
+
}
|
|
3905
|
+
)
|
|
3906
|
+
]
|
|
3907
|
+
}
|
|
3908
|
+
),
|
|
3909
|
+
sectionsOpen.payment ? /* @__PURE__ */ jsxs("div", { className: "space-y-2 border-t border-white/10 px-4 py-3", children: [
|
|
3910
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs uppercase tracking-wide text-white/60", children: t.paymentMethodLabel }),
|
|
3911
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:gap-2", children: [
|
|
3912
|
+
/* @__PURE__ */ jsxs(
|
|
3913
|
+
Select,
|
|
3914
|
+
{
|
|
3915
|
+
value: paymentSelections[activeSubscription.id] || "pm_" + activeSubscription.payment_method_id || "",
|
|
3916
|
+
onValueChange: (value) => setPaymentSelections((prev) => ({ ...prev, [activeSubscription.id]: value })),
|
|
3917
|
+
disabled: paymentMethodsQuery.isLoading || paymentMethods.length === 0,
|
|
3918
|
+
children: [
|
|
3919
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "w-full md:w-64 text-white", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: paymentMethodsQuery.isLoading ? t.loading : "" }) }),
|
|
3920
|
+
/* @__PURE__ */ jsx(SelectContent, { children: paymentMethods.filter((method) => method.id !== activeSubscription.payment_method_id).map((method) => /* @__PURE__ */ jsx(SelectItem, { value: method.id, children: formatCardLabel3(method) }, method.id)) })
|
|
3921
|
+
]
|
|
3922
|
+
}
|
|
3923
|
+
),
|
|
3924
|
+
/* @__PURE__ */ jsxs(
|
|
3925
|
+
Button,
|
|
3926
|
+
{
|
|
3927
|
+
size: "sm",
|
|
3928
|
+
onClick: () => handleUpdatePaymentMethod(activeSubscription.id),
|
|
3929
|
+
disabled: updatePaymentMethodMutation.isPending || !paymentSelections[activeSubscription.id] || paymentSelections[activeSubscription.id] === activeSubscription.payment_method_id,
|
|
3930
|
+
className: "border-0 bg-green-bg text-white hover:bg-green-bg/80 disabled:opacity-50",
|
|
3931
|
+
children: [
|
|
3932
|
+
updatePaymentMethodMutation.isPending ? /* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : null,
|
|
3933
|
+
t.update
|
|
3934
|
+
]
|
|
3935
|
+
}
|
|
3936
|
+
)
|
|
3937
|
+
] })
|
|
3938
|
+
] }) : null
|
|
3939
|
+
] })
|
|
3940
|
+
] }),
|
|
3941
|
+
/* @__PURE__ */ jsxs(DialogFooter, { className: "flex flex-wrap gap-2", children: [
|
|
3942
|
+
/* @__PURE__ */ jsx(
|
|
3943
|
+
CancelMembershipDialog,
|
|
3944
|
+
{
|
|
3945
|
+
translations: cancelTranslations,
|
|
3946
|
+
onNotify,
|
|
3947
|
+
open: cancelDialogOpen,
|
|
3948
|
+
onOpenChange: (openState) => setCancelDialogOpen(openState),
|
|
3949
|
+
onCancelled: () => {
|
|
3950
|
+
void queryClient.invalidateQueries({ queryKey: subscriptionsQueryKey });
|
|
3951
|
+
onCancelled?.();
|
|
3952
|
+
setActiveSubId(null);
|
|
3953
|
+
}
|
|
3954
|
+
}
|
|
3955
|
+
),
|
|
3956
|
+
/* @__PURE__ */ jsx(
|
|
3957
|
+
Button,
|
|
3958
|
+
{
|
|
3959
|
+
variant: "secondary",
|
|
3960
|
+
onClick: () => setActiveSubId(null),
|
|
3961
|
+
className: "border-white/20 bg-transparent text-foreground hover:bg-foreground/10 hover:text-foreground",
|
|
3962
|
+
children: t.close
|
|
3963
|
+
}
|
|
3964
|
+
)
|
|
3965
|
+
] })
|
|
3966
|
+
] }) })
|
|
3967
|
+
] });
|
|
3968
|
+
};
|
|
3969
|
+
var Checkbox = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
3208
3970
|
CheckboxPrimitive.Root,
|
|
3209
3971
|
{
|
|
3210
3972
|
ref,
|
|
@@ -3719,6 +4481,6 @@ var usePaymentStatus = (options = {}) => {
|
|
|
3719
4481
|
};
|
|
3720
4482
|
};
|
|
3721
4483
|
|
|
3722
|
-
export { BillingHistory, CancelMembershipDialog, CardDetailsForm, ClientApiError, PaymentContext, PaymentExperience, PaymentMethodsSection, PaymentProvider, PaymentsDialogProvider, SolanaPaymentSelector, SolanaPaymentView, StoredPaymentMethods, SubscriptionCheckoutModal, SubscriptionSuccessDialog, WalletDialog, WalletModal, createClient, usePaymentContext, usePaymentDialogs, usePaymentMethods, usePaymentNotifications, usePaymentStatus, useSolanaQrPayment, useSubscriptionActions, useSupportedTokens, useTokenBalance };
|
|
4484
|
+
export { BillingHistory, CancelMembershipDialog, CardDetailsForm, ClientApiError, PaymentContext, PaymentExperience, PaymentMethodsSection, PaymentProvider, PaymentsDialogProvider, SolanaPaymentSelector, SolanaPaymentView, StoredPaymentMethods, SubscriptionCheckoutModal, SubscriptionSuccessDialog, SubscriptionsSection, WalletDialog, WalletModal, createClient, defaultCardDetailsFormTranslations, defaultPaymentExperienceTranslations, defaultTranslations3 as defaultTranslations, usePaymentContext, usePaymentDialogs, usePaymentMethods, usePaymentNotifications, usePaymentStatus, useSolanaQrPayment, useSubscriptionActions, useSupportedTokens, useTokenBalance };
|
|
3723
4485
|
//# sourceMappingURL=index.js.map
|
|
3724
4486
|
//# sourceMappingURL=index.js.map
|