1 import Loader from '@proton/components/components/loader/Loader';
2 import MozillaInfoPanel from '@proton/components/containers/account/MozillaInfoPanel';
3 import SettingsSectionExtraWide from '@proton/components/containers/account/SettingsSectionExtraWide';
4 import SettingsSectionWide from '@proton/components/containers/account/SettingsSectionWide';
5 import type { APP_NAMES } from '@proton/shared/lib/constants';
6 import { APPS, ORGANIZATION_STATE } from '@proton/shared/lib/constants';
7 import { pick } from '@proton/shared/lib/helpers/object';
8 import { getCanSubscriptionAccessDuoPlan, getHasVpnB2BPlan, isTrial } from '@proton/shared/lib/helpers/subscription';
9 import { FREE_PLAN } from '@proton/shared/lib/subscription/freePlans';
10 import clsx from '@proton/utils/clsx';
17 usePendingUserInvitations,
23 } from '../../../hooks';
24 import { useSubscriptionModal } from './SubscriptionModalProvider';
25 import { resolveUpsellsToDisplay } from './helpers';
26 import { SubscriptionPanel, UpsellPanels, UsagePanel } from './panels';
27 import PendingInvitationsPanel from './panels/PendingInvitationsPanel';
29 import './YourPlanSection.scss';
35 const YourPlanSection = ({ app }: Props) => {
36 const [user] = useUser();
37 const [plansResult, loadingPlans] = usePlans();
38 const plans = plansResult?.plans;
39 const freePlan = plansResult?.freePlan || FREE_PLAN;
40 const [addresses] = useAddresses();
41 const [calendars] = useCalendars();
42 const [subscription, loadingSubscription] = useSubscription();
43 const [organization, loadingOrganization] = useOrganization();
44 const [serversCount, serversCountLoading] = useVPNServersCount();
45 const [invites = []] = usePendingUserInvitations();
46 const [openSubscriptionModal] = useSubscriptionModal();
47 const canAccessDuoPlan = getCanSubscriptionAccessDuoPlan(subscription);
48 const { plansMap } = usePreferredPlansMap();
52 const loading = loadingSubscription || loadingOrganization || loadingPlans || serversCountLoading;
54 if (!subscription || !plans || loading) {
58 const { isManagedByMozilla } = subscription;
59 if (isManagedByMozilla) {
60 return <MozillaInfoPanel />;
63 const upsells = resolveUpsellsToDisplay({
69 openSubscriptionModal,
71 ...pick(user, ['canPay', 'isFree', 'hasPaidMail']),
74 const isVpnB2b = getHasVpnB2BPlan(subscription);
75 const isWalletEA = app === APPS.PROTONWALLET;
76 // Subscription panel is displayed for user with a free or paid plan and not in a trial
77 const shouldRenderSubscription = user.canPay || (subscription && !isTrial(subscription));
78 const shouldRenderPendingInvitation = !!invites.length;
79 // Upsell panel if the user has a subscription and is not vpn or wallet
80 const shouldRenderUpsells = !isVpnB2b && !isWalletEA && shouldRenderSubscription;
81 // Usage panel is displayed for members of B2B plans except VPN B2B
82 const shouldRenderUsagePanel =
83 (organization?.UsedMembers || 0) > 1 && !isVpnB2b && organization?.State === ORGANIZATION_STATE.ACTIVE;
85 // By default, for style consistency, we display every setting in `SettingsSectionWide`
86 // But since 3 panels don't fit in this section (or are too tightly packed),
87 // we use the extra wide one when we have > 2 panels to display
88 const panelCount = [shouldRenderSubscription, shouldRenderPendingInvitation, shouldRenderUsagePanel].filter(
91 const shouldRenderInLargeSection = panelCount + upsells.length > 2;
92 const SettingsSection = shouldRenderInLargeSection ? SettingsSectionExtraWide : SettingsSectionWide;
98 shouldRenderInLargeSection ? 'grid-column-3' : 'grid-column-2',
99 'your-plan-section-container gap-8 pt-4'
101 data-testid="dashboard-panels-container"
103 {/* Subcription details */}
104 {shouldRenderSubscription && (
107 subscription={subscription}
108 organization={organization}
110 addresses={addresses}
111 vpnServers={serversCount}
112 upsells={shouldRenderUpsells ? upsells : []}
116 {/* Usage for plans with >1 Members except VPN B2B */}
117 {shouldRenderUsagePanel && (
118 <UsagePanel addresses={addresses} calendars={calendars} organization={organization} user={user} />
120 {shouldRenderUpsells && <UpsellPanels upsells={upsells} subscription={subscription} />}
121 {shouldRenderPendingInvitation && <PendingInvitationsPanel invites={invites} />}
126 export default YourPlanSection;