Skip to content

Commit c7ef5a1

Browse files
committed
show blocking screen for work email which has 2FA enabled
1 parent de3f8af commit c7ef5a1

4 files changed

Lines changed: 158 additions & 117 deletions

File tree

src/CONST/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7226,6 +7226,8 @@ const CONST = {
72267226
REGISTER_FOR_WEBINAR: 'registerForWebinar',
72277227
},
72287228

7229+
ONBOARDING_2FA_REQUIRED_ERROR_MESSAGE: '401 work account uses 2FA',
7230+
72297231
SCHEDULE_CALL_STATUS: {
72307232
CREATED: 'created',
72317233
RESCHEDULED: 'rescheduled',
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import React from 'react';
2+
import useLocalize from '@hooks/useLocalize';
3+
import useThemeStyles from '@hooks/useThemeStyles';
4+
import Navigation from '@libs/Navigation/Navigation';
5+
import variables from '@styles/variables';
6+
import {setOnboardingErrorMessage} from '@userActions/Welcome';
7+
import ROUTES from '@src/ROUTES';
8+
import BlockingView from './BlockingViews/BlockingView';
9+
import Button from './Button';
10+
import {ToddBehindCloud} from './Icon/Illustrations';
11+
12+
type OnboardingMergingAccountBlockedProps = {
13+
// Work email to display in the subtitle
14+
workEmail: string | undefined;
15+
isVsb: boolean | undefined;
16+
};
17+
function OnboardingMergingAccountBlocked({workEmail, isVsb}: OnboardingMergingAccountBlockedProps) {
18+
const styles = useThemeStyles();
19+
const {translate} = useLocalize();
20+
return (
21+
<>
22+
<BlockingView
23+
icon={ToddBehindCloud}
24+
iconWidth={variables.modalTopIconWidth}
25+
iconHeight={variables.modalTopIconHeight}
26+
title={translate('onboarding.mergeBlockScreen.title')}
27+
subtitle={translate('onboarding.mergeBlockScreen.subtitle', {workEmail})}
28+
subtitleStyle={[styles.colorMuted]}
29+
/>
30+
<Button
31+
success
32+
large
33+
style={[styles.mb5]}
34+
text={translate('common.buttonConfirm')}
35+
onPress={() => {
36+
setOnboardingErrorMessage('');
37+
if (isVsb) {
38+
Navigation.navigate(ROUTES.ONBOARDING_ACCOUNTING.getRoute());
39+
return;
40+
}
41+
Navigation.navigate(ROUTES.ONBOARDING_PURPOSE.getRoute());
42+
}}
43+
/>
44+
</>
45+
);
46+
}
47+
48+
export default OnboardingMergingAccountBlocked;

src/pages/OnboardingWorkEmail/BaseOnboardingWorkEmail.tsx

Lines changed: 104 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
1212
import Icon from '@components/Icon';
1313
import * as Illustrations from '@components/Icon/Illustrations';
1414
import OfflineWithFeedback from '@components/OfflineWithFeedback';
15+
import OnboardingMergingAccountBlocked from '@components/OnboardingMergingAccountBlocked';
1516
import ScreenWrapper from '@components/ScreenWrapper';
1617
import Text from '@components/Text';
1718
import TextInput from '@components/TextInput';
@@ -122,6 +123,8 @@ function BaseOnboardingWorkEmail({shouldUseNativeStyles}: BaseOnboardingWorkEmai
122123
},
123124
];
124125

126+
const isMergingAccountBlocked = onboardingErrorMessage === CONST.ONBOARDING_2FA_REQUIRED_ERROR_MESSAGE;
127+
125128
return (
126129
<ScreenWrapper
127130
shouldEnableMaxHeight
@@ -133,103 +136,112 @@ function BaseOnboardingWorkEmail({shouldUseNativeStyles}: BaseOnboardingWorkEmai
133136
progressBarPercentage={10}
134137
shouldShowBackButton={false}
135138
/>
136-
<FormProvider
137-
style={[styles.flexGrow1, onboardingIsMediumOrLargerScreenWidth && styles.mt5, onboardingIsMediumOrLargerScreenWidth ? styles.mh8 : styles.mh5]}
138-
formID={ONYXKEYS.FORMS.ONBOARDING_WORK_EMAIL_FORM}
139-
validate={validate}
140-
onSubmit={submitWorkEmail}
141-
submitButtonText={translate('onboarding.workEmail.addWorkEmail')}
142-
enabledWhenOffline
143-
submitFlexEnabled
144-
shouldValidateOnBlur={false}
145-
shouldValidateOnChange={shouldValidateOnChange}
146-
shouldTrimValues={false}
147-
footerContent={
148-
<View style={styles.mb2}>
149-
<OfflineWithFeedback
150-
shouldDisplayErrorAbove
151-
errors={onboardingErrorMessage ? {addWorkEmailError: onboardingErrorMessage} : undefined}
152-
errorRowStyles={[styles.mt2, styles.textWrap]}
153-
onClose={() => setOnboardingErrorMessage('')}
154-
>
155-
<Button
156-
large
157-
text={translate('common.skip')}
158-
testID="onboardingPrivateEmailSkipButton"
159-
onPress={() => {
160-
setOnboardingErrorMessage('');
161-
162-
setOnboardingMergeAccountStepValue(true);
163-
// Once we skip the private email step, we need to force replace the screen
164-
// so that we don't navigate back on back button press
165-
if (isVsb) {
166-
Navigation.navigate(ROUTES.ONBOARDING_ACCOUNTING.getRoute(), {forceReplace: true});
167-
return;
168-
}
169-
Navigation.navigate(ROUTES.ONBOARDING_PURPOSE.getRoute(), {forceReplace: true});
170-
}}
171-
/>
172-
</OfflineWithFeedback>
173-
</View>
174-
}
175-
shouldRenderFooterAboveSubmit
176-
shouldHideFixErrorsAlert
177-
>
178-
<View>
179-
<View style={[onboardingIsMediumOrLargerScreenWidth ? styles.flexRow : styles.flexColumn, styles.mb3]}>
180-
<Text style={styles.textHeadlineH1}>{translate('onboarding.workEmail.title')}</Text>
181-
</View>
182-
<View style={styles.mb2}>
183-
<Text style={[styles.textNormal, styles.colorMuted]}>{translate('onboarding.workEmail.subtitle')}</Text>
184-
</View>
139+
{isMergingAccountBlocked ? (
140+
<View style={[styles.flex1, onboardingIsMediumOrLargerScreenWidth && styles.mt5, onboardingIsMediumOrLargerScreenWidth ? styles.mh8 : styles.mh5]}>
141+
<OnboardingMergingAccountBlocked
142+
workEmail={workEmail}
143+
isVsb={isVsb}
144+
/>
145+
</View>
146+
) : (
147+
<FormProvider
148+
style={[styles.flexGrow1, onboardingIsMediumOrLargerScreenWidth && styles.mt5, onboardingIsMediumOrLargerScreenWidth ? styles.mh8 : styles.mh5]}
149+
formID={ONYXKEYS.FORMS.ONBOARDING_WORK_EMAIL_FORM}
150+
validate={validate}
151+
onSubmit={submitWorkEmail}
152+
submitButtonText={translate('onboarding.workEmail.addWorkEmail')}
153+
enabledWhenOffline
154+
submitFlexEnabled
155+
shouldValidateOnBlur={false}
156+
shouldValidateOnChange={shouldValidateOnChange}
157+
shouldTrimValues={false}
158+
footerContent={
159+
<View style={styles.mb2}>
160+
<OfflineWithFeedback
161+
shouldDisplayErrorAbove
162+
errors={onboardingErrorMessage ? {addWorkEmailError: onboardingErrorMessage} : undefined}
163+
errorRowStyles={[styles.mt2, styles.textWrap]}
164+
onClose={() => setOnboardingErrorMessage('')}
165+
>
166+
<Button
167+
large
168+
text={translate('common.skip')}
169+
testID="onboardingPrivateEmailSkipButton"
170+
onPress={() => {
171+
setOnboardingErrorMessage('');
172+
173+
setOnboardingMergeAccountStepValue(true);
174+
// Once we skip the private email step, we need to force replace the screen
175+
// so that we don't navigate back on back button press
176+
if (isVsb) {
177+
Navigation.navigate(ROUTES.ONBOARDING_ACCOUNTING.getRoute(), {forceReplace: true});
178+
return;
179+
}
180+
Navigation.navigate(ROUTES.ONBOARDING_PURPOSE.getRoute(), {forceReplace: true});
181+
}}
182+
/>
183+
</OfflineWithFeedback>
184+
</View>
185+
}
186+
shouldRenderFooterAboveSubmit
187+
shouldHideFixErrorsAlert
188+
>
185189
<View>
186-
{section.map((item) => {
187-
return (
188-
<View
189-
key={item.titleTranslationKey}
190-
style={[styles.mt2, styles.mb3]}
191-
>
192-
<View style={[styles.flexRow, styles.alignItemsCenter, styles.flex1]}>
193-
<Icon
194-
src={item.icon}
195-
height={ICON_SIZE}
196-
width={ICON_SIZE}
197-
additionalStyles={[styles.mr3]}
198-
/>
199-
<View style={[styles.flexColumn, styles.flex1]}>
200-
{item.shouldRenderEmail ? (
201-
<AutoEmailLink
202-
style={[styles.textStrong, styles.lh20]}
203-
text={translate(item.titleTranslationKey)}
204-
/>
205-
) : (
206-
<Text style={[styles.textStrong, styles.lh20]}>{translate(item.titleTranslationKey)}</Text>
207-
)}
190+
<View style={[onboardingIsMediumOrLargerScreenWidth ? styles.flexRow : styles.flexColumn, styles.mb3]}>
191+
<Text style={styles.textHeadlineH1}>{translate('onboarding.workEmail.title')}</Text>
192+
</View>
193+
<View style={styles.mb2}>
194+
<Text style={[styles.textNormal, styles.colorMuted]}>{translate('onboarding.workEmail.subtitle')}</Text>
195+
</View>
196+
<View>
197+
{section.map((item) => {
198+
return (
199+
<View
200+
key={item.titleTranslationKey}
201+
style={[styles.mt2, styles.mb3]}
202+
>
203+
<View style={[styles.flexRow, styles.alignItemsCenter, styles.flex1]}>
204+
<Icon
205+
src={item.icon}
206+
height={ICON_SIZE}
207+
width={ICON_SIZE}
208+
additionalStyles={[styles.mr3]}
209+
/>
210+
<View style={[styles.flexColumn, styles.flex1]}>
211+
{item.shouldRenderEmail ? (
212+
<AutoEmailLink
213+
style={[styles.textStrong, styles.lh20]}
214+
text={translate(item.titleTranslationKey)}
215+
/>
216+
) : (
217+
<Text style={[styles.textStrong, styles.lh20]}>{translate(item.titleTranslationKey)}</Text>
218+
)}
219+
</View>
208220
</View>
209221
</View>
210-
</View>
211-
);
212-
})}
222+
);
223+
})}
224+
</View>
213225
</View>
214-
</View>
215226

216-
<View style={[styles.mb4, styles.pt3]}>
217-
<InputWrapper
218-
InputComponent={TextInput}
219-
// We do not want to auto-focus for mobile platforms
220-
ref={operatingSystem !== CONST.OS.ANDROID && operatingSystem !== CONST.OS.IOS ? inputCallbackRef : undefined}
221-
name="fname"
222-
inputID={INPUT_IDS.ONBOARDING_WORK_EMAIL}
223-
label={translate('common.workEmail')}
224-
aria-label={translate('common.workEmail')}
225-
role={CONST.ROLE.PRESENTATION}
226-
defaultValue={workEmail ?? ''}
227-
shouldSaveDraft
228-
maxLength={CONST.LOGIN_CHARACTER_LIMIT}
229-
spellCheck={false}
230-
/>
231-
</View>
232-
</FormProvider>
227+
<View style={[styles.mb4, styles.pt3]}>
228+
<InputWrapper
229+
InputComponent={TextInput}
230+
// We do not want to auto-focus for mobile platforms
231+
ref={operatingSystem !== CONST.OS.ANDROID && operatingSystem !== CONST.OS.IOS ? inputCallbackRef : undefined}
232+
name="fname"
233+
inputID={INPUT_IDS.ONBOARDING_WORK_EMAIL}
234+
label={translate('common.workEmail')}
235+
aria-label={translate('common.workEmail')}
236+
role={CONST.ROLE.PRESENTATION}
237+
defaultValue={workEmail ?? ''}
238+
shouldSaveDraft
239+
maxLength={CONST.LOGIN_CHARACTER_LIMIT}
240+
spellCheck={false}
241+
/>
242+
</View>
243+
</FormProvider>
244+
)}
233245
</ScreenWrapper>
234246
);
235247
}

src/pages/OnboardingWorkEmailValidation/BaseOnboardingWorkEmailValidation.tsx

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ import {useIsFocused} from '@react-navigation/native';
22
import React, {useCallback, useEffect} from 'react';
33
import {View} from 'react-native';
44
import {useOnyx} from 'react-native-onyx';
5-
import BlockingView from '@components/BlockingViews/BlockingView';
6-
import Button from '@components/Button';
75
import HeaderWithBackButton from '@components/HeaderWithBackButton';
8-
import * as Illustrations from '@components/Icon/Illustrations';
6+
import OnboardingMergingAccountBlocked from '@components/OnboardingMergingAccountBlocked';
97
import ScreenWrapper from '@components/ScreenWrapper';
108
import Text from '@components/Text';
119
import ValidateCodeForm from '@components/ValidateCodeActionModal/ValidateCodeForm';
@@ -16,7 +14,6 @@ import AccountUtils from '@libs/AccountUtils';
1614
import {openOldDotLink} from '@libs/actions/Link';
1715
import {setOnboardingErrorMessage, setOnboardingMergeAccountStepValue, updateOnboardingValuesAndNavigation} from '@libs/actions/Welcome';
1816
import Navigation from '@libs/Navigation/Navigation';
19-
import variables from '@styles/variables';
2017
import {MergeIntoAccountAndLogin} from '@userActions/Session';
2118
import {resendValidateCode} from '@userActions/User';
2219
import CONST from '@src/CONST';
@@ -89,27 +86,9 @@ function BaseOnboardingWorkEmailValidation({shouldUseNativeStyles}: BaseOnboardi
8986
/>
9087
{onboardingValues?.isMergingAccountBlocked ? (
9188
<View style={[styles.flex1, onboardingIsMediumOrLargerScreenWidth && styles.mt5, onboardingIsMediumOrLargerScreenWidth ? styles.mh8 : styles.mh5]}>
92-
<BlockingView
93-
icon={Illustrations.ToddBehindCloud}
94-
iconWidth={variables.modalTopIconWidth}
95-
iconHeight={variables.modalTopIconHeight}
96-
title={translate('onboarding.mergeBlockScreen.title')}
97-
subtitle={translate('onboarding.mergeBlockScreen.subtitle', {workEmail})}
98-
subtitleStyle={[styles.colorMuted]}
99-
/>
100-
<Button
101-
success={onboardingValues?.isMergingAccountBlocked}
102-
large
103-
style={[styles.mb5]}
104-
text={translate('common.buttonConfirm')}
105-
onPress={() => {
106-
setOnboardingErrorMessage('');
107-
if (isVsb) {
108-
Navigation.navigate(ROUTES.ONBOARDING_ACCOUNTING.getRoute());
109-
return;
110-
}
111-
Navigation.navigate(ROUTES.ONBOARDING_PURPOSE.getRoute());
112-
}}
89+
<OnboardingMergingAccountBlocked
90+
workEmail={workEmail}
91+
isVsb={isVsb}
11392
/>
11493
</View>
11594
) : (

0 commit comments

Comments
 (0)