Cleanup - unused files / unused exports / duplicate exports
[ProtonMail-WebClient.git] / packages / components / containers / topBanners / ReferralTopBanner.tsx
blobde28fcd12f9f742e248a547e5e2742bbff991eca
1 import { format, fromUnixTime } from 'date-fns';
2 import { c } from 'ttag';
4 import { useSubscription } from '@proton/account/subscription/hooks';
5 import { useUser } from '@proton/account/user/hooks';
6 import { InlineLinkButton } from '@proton/atoms';
7 import SettingsLink from '@proton/components/components/link/SettingsLink';
8 import SubscriptionModalProvider, {
9     useSubscriptionModal,
10 } from '@proton/components/containers/payments/subscription/SubscriptionModalProvider';
11 import { SUBSCRIPTION_STEPS } from '@proton/components/containers/payments/subscription/constants';
12 import useConfig from '@proton/components/hooks/useConfig';
13 import { PLANS, PLAN_NAMES } from '@proton/payments';
14 import type { APP_NAMES } from '@proton/shared/lib/constants';
15 import {
16     APPS,
17     CYCLE,
18     MAIL_APP_NAME,
19     OPEN_OFFER_MODAL_EVENT,
20     SHARED_UPSELL_PATHS,
21     UPSELL_COMPONENT,
22 } from '@proton/shared/lib/constants';
23 import {
24     getPlanIDs,
25     getPlanTitle,
26     isTrial,
27     isTrialExpired,
28     willTrialExpire,
29 } from '@proton/shared/lib/helpers/subscription';
30 import { addUpsellPath, getUpgradePath, getUpsellRefFromApp } from '@proton/shared/lib/helpers/upsell';
31 import { dateLocale } from '@proton/shared/lib/i18n';
33 import TopBanner from './TopBanner';
35 const ModalAction = ({ textAction, upsellRef }: { textAction: string; upsellRef: string | undefined }) => {
36     const [subscription] = useSubscription();
37     const [openSubscriptionModal] = useSubscriptionModal();
39     return (
40         <InlineLinkButton
41             className="color-inherit"
42             onClick={() => {
43                 openSubscriptionModal({
44                     step: SUBSCRIPTION_STEPS.CHECKOUT,
45                     cycle: CYCLE.YEARLY,
46                     planIDs: getPlanIDs(subscription),
47                     upsellRef,
48                     metrics: {
49                         source: 'upsells',
50                     },
51                 });
52             }}
53         >
54             {textAction}
55         </InlineLinkButton>
56     );
59 const WrappedModalAction = ({
60     fromApp,
61     ...rest
62 }: {
63     fromApp: APP_NAMES;
64     textAction: string;
65     upsellRef: string | undefined;
66 }) => {
67     return (
68         <SubscriptionModalProvider app={fromApp}>
69             <ModalAction {...rest} />
70         </SubscriptionModalProvider>
71     );
74 const TrialEndsActionButton = ({
75     refApp,
76     fromApp,
77     textAction,
78 }: {
79     refApp?: APP_NAMES;
80     fromApp: APP_NAMES;
81     textAction: string;
82 }) => {
83     const { APP_NAME } = useConfig();
84     const [user] = useUser();
85     const [subscription, subscriptionLoading] = useSubscription();
86     if (subscriptionLoading) {
87         return null;
88     }
90     const upsellRef = getUpsellRefFromApp({
91         app: refApp ?? APP_NAME,
92         fromApp,
93         component: UPSELL_COMPONENT.BANNER,
94         feature: SHARED_UPSELL_PATHS.TRIAL_WILL_END,
95     });
97     // If that's already Account or VPN settings app then we render the buton that will open the subscription modal
98     // directly
99     if (APP_NAME === APPS.PROTONACCOUNT || APP_NAME === APPS.PROTONVPN_SETTINGS) {
100         return <WrappedModalAction upsellRef={upsellRef} fromApp={fromApp} textAction={textAction} />;
101     }
103     // For all other apps we render the button that will redirect to the account app
104     const upgradePath = addUpsellPath(getUpgradePath({ user, subscription, app: APP_NAME }), upsellRef);
105     return (
106         <SettingsLink path={upgradePath} className="color-inherit">
107             {textAction}
108         </SettingsLink>
109     );
113  * Mail and account apps have an upsell modal. It's triggered by the `OPEN_OFFER_MODAL_EVENT` event.
114  * The handler component must be rendered in DOM to handle the events.
115  */
116 const UpgradeBannerLink = ({ textAction }: { textAction: string }) => {
117     const handleClick = () => document.dispatchEvent(new CustomEvent(OPEN_OFFER_MODAL_EVENT));
119     return (
120         <InlineLinkButton key="continue" className="color-inherit" onClick={handleClick}>
121             {textAction}
122         </InlineLinkButton>
123     );
126 const TrialEndsActionButtonSwitcher = ({ fromApp }: { fromApp: APP_NAMES }) => {
127     const [subscription] = useSubscription();
129     if (isTrial(subscription, PLANS.MAIL)) {
130         const textAction = c('Button').t`Continue using ${MAIL_APP_NAME}.`;
131         return <UpgradeBannerLink textAction={textAction} />;
132     }
134     if (isTrial(subscription, PLANS.BUNDLE)) {
135         const planTitle = PLAN_NAMES[PLANS.BUNDLE];
136         const textAction = c('Button').t`Continue using ${planTitle}`;
137         return <TrialEndsActionButton fromApp={fromApp} textAction={textAction} />;
138     }
140     // a catch-all for all other cases
141     if (subscription && isTrial(subscription)) {
142         const planTitle = getPlanTitle(subscription);
143         let textAction = c('Button').t`Continue using ${planTitle}`;
144         if (!planTitle) {
145             textAction = c('Button').t`Continue your subscription`;
146         }
148         return <TrialEndsActionButton fromApp={fromApp} textAction={textAction} />;
149     }
151     return null;
154 const ReferralTopBanner = ({ fromApp }: { fromApp: APP_NAMES }) => {
155     const [subscription, loadingSubscription] = useSubscription();
156     const { APP_NAME } = useConfig();
157     const isVpn = APP_NAME === APPS.PROTONVPN_SETTINGS;
158     const trial = isTrial(subscription);
159     if (loadingSubscription || !trial || isVpn) {
160         return null;
161     }
163     const action = <TrialEndsActionButtonSwitcher key="trial-action-button" fromApp={fromApp} />;
164     const { PeriodEnd = 0 } = subscription || {};
165     const textDate = format(fromUnixTime(PeriodEnd), 'PPP', { locale: dateLocale });
167     // 1 week before the trial ends
168     const willExpire = willTrialExpire(subscription);
169     if (willExpire) {
170         const message = c('Warning').jt`Your free trial ends on ${textDate}. ${action}`;
171         return <TopBanner className="bg-warning">{message}</TopBanner>;
172     }
174     // Trial has ended
175     const isExpired = isTrialExpired(subscription);
176     if (isExpired) {
177         const message = c('Message')
178             .jt`Your free trial has ended. Access to your account will soon be disabled. ${action}`;
179         return <TopBanner className="bg-danger">{message}</TopBanner>;
180     }
182     // In trial
183     return null;
186 export default ReferralTopBanner;