Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / applications / drive / src / app / components / modals / DriveOnboardingV2Modal / DriveOnboardingV2Modal.tsx
blob430902a7bd71fdcbc7fea4ed5c3d988af6d7b9c0
1 import type { ReactNode } from 'react';
2 import { type FC, useEffect, useMemo, useState } from 'react';
4 import { useUserSettings, useWelcomeFlags } from '@proton/account';
5 import type { ModalStateProps } from '@proton/components';
6 import { Loader, ModalTwo, ModalTwoContent, ModalTwoFooter, useApi, useDrivePlan } from '@proton/components';
7 import { updateFlags, updateWelcomeFlags } from '@proton/shared/lib/api/settings';
8 import { isMobile } from '@proton/shared/lib/helpers/browser';
9 import isTruthy from '@proton/utils/isTruthy';
10 import noop from '@proton/utils/noop';
12 import { useDesktopDownloads } from '../../../hooks/drive/useDesktopDownloads';
13 import { Actions, countActionWithTelemetry } from '../../../utils/telemetry';
14 import { useOnboarding } from '../../onboarding/useOnboarding';
15 import { Header } from './Header';
16 import { B2BInviteStep, B2BInviteStepButtons } from './steps/B2BInviteStep';
17 import { DesktopAppStep, DesktopAppStepButtons } from './steps/DesktopAppStep';
18 import { MobileAppStep, MobileAppStepButtons } from './steps/MobileAppStep';
19 import { PendingInvitationStep, PendingInvitationStepButtons } from './steps/PendingInvitationStep';
20 import { ThemeStep, ThemeStepButtons } from './steps/ThemeStep';
21 import { UploadStep, UploadStepButtons } from './steps/UploadStep';
22 import { WelcomeStep, WelcomeStepButtons } from './steps/WelcomeStep';
24 export const DriveOnboardingV2Modal: FC<ModalStateProps> = (props) => {
25     const api = useApi();
26     const { welcomeFlags, setDone: setWelcomeFlagsDone } = useWelcomeFlags();
27     const [userSettings] = useUserSettings();
29     const { isLoading: isOnboardingLoading, hasPendingExternalInvitations } = useOnboarding();
30     const { isB2B, isAdmin } = useDrivePlan();
32     const { downloads: desktopDownloads, isLoading: isDesktopDownloadsLoading } = useDesktopDownloads();
33     const isLoading = isOnboardingLoading || isDesktopDownloadsLoading;
34     const preferredPlatform = useMemo(
35         () => desktopDownloads.find((platform) => platform.isPreferred()),
36         [desktopDownloads]
37     );
39     const [step, setStep] = useState(0);
41     // Only show the B2B invite step to admins
42     const showB2BInviteStep = isB2B && isAdmin;
43     // Only show the desktop app step if there is a platform, and on desktop
44     const showDesktopAppStep = !!preferredPlatform && !isMobile();
45     // Only show if we have pending invitations
46     const showPendingInvitationsStep = !showB2BInviteStep && hasPendingExternalInvitations;
47     // Only show upload step on desktop
48     const showUploadStep = !isMobile();
50     useEffect(() => {
51         if (props.open) {
52             countActionWithTelemetry(Actions.OnboardingV2Shown);
53         }
54     }, [props.open]);
56     if (isLoading) {
57         return (
58             <ModalTwo open fullscreenOnMobile blurBackdrop size="xlarge">
59                 <ModalTwoContent className="my-8">
60                     <div className="flex flex-column items-center">
61                         <Loader size="medium" className="my-4" />
62                     </div>
63                 </ModalTwoContent>
64             </ModalTwo>
65         );
66     }
68     const steps = [
69         [WelcomeStep, WelcomeStepButtons],
70         [ThemeStep, ThemeStepButtons],
71         showDesktopAppStep && [
72             DesktopAppStep,
73             DesktopAppStepButtons,
74             {
75                 download: preferredPlatform.startDownload,
76                 platform: preferredPlatform.platform,
77             },
78         ],
79         [MobileAppStep, MobileAppStepButtons],
80         showB2BInviteStep && [B2BInviteStep, B2BInviteStepButtons],
81         showPendingInvitationsStep && [PendingInvitationStep, PendingInvitationStepButtons],
82         showUploadStep && [UploadStep, UploadStepButtons],
83     ].filter(isTruthy) as [() => ReactNode, () => ReactNode, any][];
85     const [Container, Buttons, extraProps] = steps[step] || [];
87     const onNext = () => {
88         if (step < steps.length - 1) {
89             setStep((step) => step + 1);
90         } else {
91             if (welcomeFlags.isWelcomeFlow) {
92                 api(updateFlags({ Welcomed: 1 })).catch(noop);
93             }
94             if (!userSettings.WelcomeFlag) {
95                 api(updateWelcomeFlags()).catch(noop);
96             }
97             setWelcomeFlagsDone();
99             props.onClose?.();
100         }
101     };
103     return (
104         <ModalTwo {...props} fullscreenOnMobile blurBackdrop size="xlarge" data-testid="drive-onboarding-v2">
105             <ModalTwoContent className="my-8">
106                 <Header
107                     currentStep={step}
108                     maxSteps={steps.length}
109                     onBack={step > 0 ? () => setStep((step) => step - 1) : undefined}
110                 />
111                 <Container {...extraProps} onNext={onNext} />
112             </ModalTwoContent>
114             <ModalTwoFooter>
115                 <Buttons {...extraProps} onNext={onNext} />
116             </ModalTwoFooter>
117         </ModalTwo>
118     );