Remove payments API routing initialization
[ProtonMail-WebClient.git] / packages / components / containers / payments / CreditsSection.tsx
blob2d3fed7b8a2c61e3f32eb3dd7b8699ac2de815d3
1 import { useEffect } from 'react';
2 import { useLocation } from 'react-router';
4 import { c } from 'ttag';
6 import { usePaymentStatus } from '@proton/account/paymentStatus/hooks';
7 import { useSubscription } from '@proton/account/subscription/hooks';
8 import { useUser } from '@proton/account/user/hooks';
9 import { Button } from '@proton/atoms';
10 import Loader from '@proton/components/components/loader/Loader';
11 import useModalState from '@proton/components/components/modalTwo/useModalState';
12 import { useModalTwoStatic } from '@proton/components/components/modalTwo/useModalTwo';
13 import Price from '@proton/components/components/price/Price';
14 import SettingsParagraph from '@proton/components/containers/account/SettingsParagraph';
15 import SettingsSection from '@proton/components/containers/account/SettingsSection';
16 import { isFreeSubscription, isSplittedUser } from '@proton/payments';
17 import { getAppHref } from '@proton/shared/lib/apps/helper';
18 import { APPS } from '@proton/shared/lib/constants';
19 import { isElectronApp } from '@proton/shared/lib/helpers/desktop';
20 import { isManagedExternally } from '@proton/shared/lib/helpers/subscription';
21 import { BillingPlatform, ChargebeeEnabled } from '@proton/shared/lib/interfaces';
23 import { openLinkInBrowser } from '../desktop/openExternalLink';
24 import CreditsModal from './CreditsModal';
25 import InAppPurchaseModal from './subscription/InAppPurchaseModal';
27 const redirectFromDesktop = '?open=credit-modal';
29 const CreditsSection = () => {
30     const location = useLocation();
31     const [user] = useUser();
32     const [subscription] = useSubscription();
33     const [creditModalProps, setCreditModalOpen, renderCreditModal] = useModalState();
34     const [externalSubscriptionModal, showExternalSubscriptionModal] = useModalTwoStatic(InAppPurchaseModal);
35     const [paymentStatus, paymentStatusLoading] = usePaymentStatus();
37     const [{ Credit, Currency, ChargebeeUser }] = useUser();
39     const openCreditModal = () => {
40         setCreditModalOpen(true);
41     };
43     useEffect(() => {
44         const searchParams = new URLSearchParams(location.search);
45         if (searchParams.get('open') === 'credit-modal') {
46             void openCreditModal();
47         }
48     }, [location.search]);
50     if (!subscription || paymentStatusLoading) {
51         return <Loader />;
52     }
54     let upcomingSubscriptionPrice: number = 0;
55     // In case of Chargebee, they don't display the balance for the upcoming subscription.
56     // Instead, they count it as already paid, and they return credits balance already taking into account
57     // the upcoming subscription.
58     if (
59         !isFreeSubscription(subscription) &&
60         subscription?.BillingPlatform !== BillingPlatform.Chargebee &&
61         subscription?.UpcomingSubscription
62     ) {
63         upcomingSubscriptionPrice =
64             subscription.UpcomingSubscription.Amount - subscription.UpcomingSubscription.Discount;
65     }
67     let availableCredits = Credit - upcomingSubscriptionPrice;
68     if (availableCredits < 0) {
69         availableCredits = 0;
70     }
72     // Splitted users can't add credits in both v4 and v5 APIs, so we hide this option for them until the migration is
73     // completed.
74     const hideAddCredits = isSplittedUser(user.ChargebeeUser, user.ChargebeeUserExists, subscription.BillingPlatform);
76     return (
77         <SettingsSection>
78             <SettingsParagraph>
79                 {c('Info')
80                     .t`When your subscription renews, we will apply any available credits before we charge the payment method above.`}
81             </SettingsParagraph>
82             {hideAddCredits ? null : (
83                 <div className="mb-7">
84                     <Button
85                         shape="outline"
86                         onClick={() => {
87                             if (isManagedExternally(subscription)) {
88                                 showExternalSubscriptionModal({
89                                     subscription,
90                                 });
91                                 return;
92                             }
94                             if (isElectronApp) {
95                                 openLinkInBrowser(getAppHref(`/dashboard${redirectFromDesktop}`, APPS.PROTONACCOUNT));
96                                 return;
97                             }
99                             void openCreditModal();
100                         }}
101                     >{c('Action').t`Add credits`}</Button>
102                 </div>
103             )}
104             <div className="px-4 mb-4 flex justify-space-between">
105                 <span className="text-bold" data-testid="unused-credits">{c('Credits').t`Available credits`}</span>
106                 <span className="text-bold" data-testid="available-credits">
107                     {ChargebeeUser === ChargebeeEnabled.CHARGEBEE_FORCED && availableCredits > 0 ? (
108                         <Price currency={Currency}>{availableCredits}</Price>
109                     ) : (
110                         availableCredits / 100
111                     )}
112                 </span>
113             </div>
114             <hr />
115             {renderCreditModal && paymentStatus && <CreditsModal status={paymentStatus} {...creditModalProps} />}
116             {externalSubscriptionModal}
117         </SettingsSection>
118     );
121 export default CreditsSection;