Skip to content

Commit 5d93183

Browse files
authored
Merge pull request #74481 from software-mansion-labs/feat/reimbursement-account-uses-verify-account-page
New verify account page for ReimbursementAccountPage
2 parents c56e8e2 + 0f1aa82 commit 5d93183

13 files changed

Lines changed: 91 additions & 65 deletions

File tree

src/ROUTES.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,17 +148,23 @@ const ROUTES = {
148148
REQUIRE_TWO_FACTOR_AUTH: '2fa-required',
149149

150150
BANK_ACCOUNT: 'bank-account',
151+
BANK_ACCOUNT_VERIFY_ACCOUNT: {
152+
route: `bank-account/${VERIFY_ACCOUNT}`,
153+
// eslint-disable-next-line no-restricted-syntax -- Legacy route generation
154+
getRoute: (policyID?: string, backTo?: string) => getUrlWithBackToParam(`bank-account/${VERIFY_ACCOUNT}?policyID=${policyID}`, backTo),
155+
},
151156
BANK_ACCOUNT_NEW: 'bank-account/new',
152157
BANK_ACCOUNT_PERSONAL: 'bank-account/personal',
153158
BANK_ACCOUNT_WITH_STEP_TO_OPEN: {
154159
route: 'bank-account/:stepToOpen?',
155-
getRoute: (policyID: string | undefined, stepToOpen: ReimbursementAccountStepToOpen = '', backTo?: string) => {
160+
getRoute: (policyID: string | undefined, stepToOpen: ReimbursementAccountStepToOpen = '', backTo?: string, subStepToOpen?: typeof CONST.BANK_ACCOUNT.STEP.COUNTRY) => {
156161
if (!policyID) {
157162
Log.warn('Invalid policyID is used to build the BANK_ACCOUNT_WITH_STEP_TO_OPEN route');
158163
}
159-
164+
// TODO this backTo comes from drilling it through bank account form screens
165+
// should be removed once https://github.com/Expensify/App/pull/72219 is resolved
160166
// eslint-disable-next-line no-restricted-syntax -- Legacy route generation
161-
return getUrlWithBackToParam(`bank-account/${stepToOpen}?policyID=${policyID}`, backTo);
167+
return getUrlWithBackToParam(`bank-account/${stepToOpen}?policyID=${policyID}${subStepToOpen ? `&subStep=${subStepToOpen}` : ''}`, backTo);
162168
},
163169
},
164170
BANK_ACCOUNT_ENTER_SIGNER_INFO: {
@@ -380,7 +386,7 @@ const ROUTES = {
380386
getRoute: (newContactMethod: string, backTo?: string) => {
381387
const encodedMethod = encodeURIComponent(newContactMethod);
382388
// TODO this backTo comes from drilling it through settings screens
383-
// should be removed once https://github.com/Expensify/App/pull/70980 is resolved
389+
// should be removed once https://github.com/Expensify/App/pull/72219 is resolved
384390
// eslint-disable-next-line no-restricted-syntax -- Legacy route generation
385391
return getUrlWithBackToParam(`settings/profile/contact-methods/new/${encodedMethod}/confirm-magic-code`, backTo);
386392
},

src/SCREENS.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,7 @@ const SCREENS = {
766766
ENABLE_PAYMENTS_ROOT: 'EnablePayments_Root',
767767
ADD_PERSONAL_BANK_ACCOUNT_ROOT: 'AddPersonalBankAccount_Root',
768768
REIMBURSEMENT_ACCOUNT_ROOT: 'Reimbursement_Account_Root',
769+
REIMBURSEMENT_ACCOUNT_VERIFY_ACCOUNT: 'Reimbursement_Account_Verify_Account',
769770
WALLET_STATEMENT_ROOT: 'WalletStatement_Root',
770771
SIGN_IN_ROOT: 'SignIn_Root',
771772
DETAILS_ROOT: 'Details_Root',

src/components/ValidateCodeActionModal/ValidateCodeActionContent.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ function ValidateCodeActionContent({
2525
isLoading,
2626
threeDotsMenuItems = [],
2727
onThreeDotsButtonPress = () => {},
28+
isPageModal = true,
2829
}: ValidateCodeActionContentProps) {
2930
const themeStyles = useThemeStyles();
3031
const validateCodeFormRef = useRef<ValidateCodeFormHandle>(null);
@@ -84,6 +85,7 @@ function ValidateCodeActionContent({
8485
clearError={clearError}
8586
buttonStyles={[themeStyles.justifyContentEnd, themeStyles.flex1]}
8687
ref={validateCodeFormRef}
88+
isInPageModal={isPageModal}
8789
/>
8890
</View>
8991
</ScrollView>

src/components/ValidateCodeActionModal/ValidateCodeForm/BaseValidateCodeForm.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ type ValidateCodeFormProps = {
8989

9090
/** Function to call when skip button is pressed */
9191
handleSkipButtonPress?: () => void;
92+
93+
/** Whether the modal is used as a page modal. Used to determine input auto focus timing. */
94+
isInPageModal?: boolean;
9295
};
9396

9497
function BaseValidateCodeForm({
@@ -107,6 +110,7 @@ function BaseValidateCodeForm({
107110
isLoading,
108111
shouldShowSkipButton = false,
109112
handleSkipButtonPress,
113+
isInPageModal = false,
110114
}: ValidateCodeFormProps) {
111115
const {translate} = useLocalize();
112116
const {isOffline} = useNetwork();
@@ -200,14 +204,14 @@ function BaseValidateCodeForm({
200204
}
201205
// Delay prevents the input from gaining focus before the RHP slide out animation finishes,
202206
// which would cause the wide RHP to flicker in the background.
203-
if (wideRHPRouteKeys.length > 0 && !isMobileSafari()) {
207+
if ((wideRHPRouteKeys.length > 0 && !isMobileSafari()) || isInPageModal) {
204208
focusTimeoutRef.current = setTimeout(() => {
205209
inputValidateCodeRef.current?.clear();
206210
}, CONST.ANIMATED_TRANSITION);
207211
} else {
208212
inputValidateCodeRef.current?.clear();
209213
}
210-
}, [validateCodeSent, wideRHPRouteKeys.length]);
214+
}, [validateCodeSent, wideRHPRouteKeys.length, isInPageModal]);
211215

212216
/**
213217
* Request a validate code / magic code be sent to verify this contact method

src/components/ValidateCodeActionModal/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ function ValidateCodeActionModal({
4949
threeDotsMenuItems={threeDotsMenuItems}
5050
onThreeDotsButtonPress={onThreeDotsButtonPress}
5151
isLoading={isLoading}
52+
isPageModal={false}
5253
/>
5354
</Modal>
5455
);

src/components/ValidateCodeActionModal/type.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ type ValidateCodeActionContentProps = {
4040

4141
/** Method to trigger when pressing more options button of the header */
4242
onThreeDotsButtonPress?: () => void;
43+
44+
/** Whether the modal is used as a page modal. Used to determine input auto focus timing. */
45+
isPageModal?: boolean;
4346
};
4447

4548
type ValidateCodeActionModalProps = ValidateCodeActionContentProps & {

src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,7 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
538538
[SCREENS.WORKSPACE.WORKFLOWS_CONNECT_EXISTING_BANK_ACCOUNT]: () =>
539539
require<ReactComponentModule>('../../../../pages/workspace/workflows/WorkspaceWorkflowsConnectExistingBankAccountPage').default,
540540
[SCREENS.REIMBURSEMENT_ACCOUNT]: () => require<ReactComponentModule>('../../../../pages/ReimbursementAccount/ReimbursementAccountPage').default,
541+
[SCREENS.REIMBURSEMENT_ACCOUNT_VERIFY_ACCOUNT]: () => require<ReactComponentModule>('../../../../pages/ReimbursementAccount/ReimbursementAccountVerifyAccountPage').default,
541542
[SCREENS.REIMBURSEMENT_ACCOUNT_ENTER_SIGNER_INFO]: () => require<ReactComponentModule>('../../../../pages/ReimbursementAccount/EnterSignerInfo').default,
542543
[SCREENS.SETTINGS.REPORT_CARD_LOST_OR_DAMAGED]: () => require<ReactComponentModule>('../../../../pages/settings/Wallet/ReportCardLostPage').default,
543544
[SCREENS.KEYBOARD_SHORTCUTS]: () => require<ReactComponentModule>('../../../../pages/KeyboardShortcutsPage').default,

src/libs/Navigation/linkingConfig/config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,10 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
995995
path: ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.route,
996996
exact: true,
997997
},
998+
[SCREENS.REIMBURSEMENT_ACCOUNT_VERIFY_ACCOUNT]: {
999+
path: ROUTES.BANK_ACCOUNT_VERIFY_ACCOUNT.route,
1000+
exact: true,
1001+
},
9981002
[SCREENS.REIMBURSEMENT_ACCOUNT_ENTER_SIGNER_INFO]: ROUTES.BANK_ACCOUNT_ENTER_SIGNER_INFO.route,
9991003
[SCREENS.KEYBOARD_SHORTCUTS]: {
10001004
path: ROUTES.KEYBOARD_SHORTCUTS.route,

src/libs/Navigation/types.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1926,6 +1926,14 @@ type ReimbursementAccountNavigatorParamList = {
19261926
// eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
19271927
backTo?: Routes;
19281928
policyID?: string;
1929+
subStep?: typeof CONST.BANK_ACCOUNT.STEP.COUNTRY;
1930+
};
1931+
[SCREENS.REIMBURSEMENT_ACCOUNT_VERIFY_ACCOUNT]: {
1932+
// TODO this backTo comes from drilling it through bank account form screens
1933+
// should be removed once https://github.com/Expensify/App/pull/72219 is resolved
1934+
// eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
1935+
backTo?: Routes;
1936+
policyID?: string;
19291937
};
19301938
};
19311939

src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import ReimbursementAccountLoadingIndicator from '@components/ReimbursementAccou
1212
import RenderHTML from '@components/RenderHTML';
1313
import ScreenWrapper from '@components/ScreenWrapper';
1414
import Text from '@components/Text';
15-
import useBeforeRemove from '@hooks/useBeforeRemove';
1615
import useEnvironment from '@hooks/useEnvironment';
1716
import useLocalize from '@hooks/useLocalize';
1817
import useNetwork from '@hooks/useNetwork';
@@ -69,11 +68,11 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy, navigation}:
6968
const [plaidCurrentEvent = ''] = useOnyx(ONYXKEYS.PLAID_CURRENT_EVENT, {canBeMissing: true});
7069
const [onfidoToken = ''] = useOnyx(ONYXKEYS.ONFIDO_TOKEN, {canBeMissing: true});
7170
const [isLoadingApp = false] = useOnyx(ONYXKEYS.IS_LOADING_APP, {canBeMissing: true});
72-
const [isValidateCodeActionModalVisible, setIsValidateCodeActionModalVisible] = useState(false);
7371

7472
const {isBetaEnabled} = usePermissions();
7573
const policyName = policy?.name ?? '';
7674
const policyIDParam = route.params?.policyID;
75+
const subStepParam = route.params?.subStep;
7776
const backTo = route.params.backTo;
7877
const isComingFromExpensifyCard = (backTo as string)?.includes(CONST.EXPENSIFY_CARD.ROUTE as string);
7978
const styles = useThemeStyles();
@@ -119,8 +118,9 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy, navigation}:
119118
return achData?.currentStep ?? CONST.BANK_ACCOUNT.STEP.COUNTRY;
120119
};
121120
const currentStep = getInitialCurrentStep();
122-
const [nonUSDBankAccountStep, setNonUSDBankAccountStep] = useState<string | null>(null);
123-
const [USDBankAccountStep, setUSDBankAccountStep] = useState<string | null>(null);
121+
const [nonUSDBankAccountStep, setNonUSDBankAccountStep] = useState<string | null>(subStepParam ?? null);
122+
123+
const [USDBankAccountStep, setUSDBankAccountStep] = useState<string | null>(subStepParam ?? null);
124124

125125
function getBankAccountFields(fieldNames: InputID[]): Partial<ACHDataReimbursementAccount> {
126126
return {
@@ -164,8 +164,6 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy, navigation}:
164164
}
165165
}
166166

167-
useBeforeRemove(() => setIsValidateCodeActionModalVisible(false));
168-
169167
useEffect(() => {
170168
if (isPreviousPolicy) {
171169
return;
@@ -271,7 +269,8 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy, navigation}:
271269
}
272270

273271
// Use the current page navigation object to set the param to the correct route in the stack
274-
navigation.setParams({stepToOpen: getRouteForCurrentStep(currentStep)});
272+
const stepToOpen = getRouteForCurrentStep(currentStep);
273+
navigation.setParams({stepToOpen});
275274
},
276275
// eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
277276
[isOffline, reimbursementAccount, hasACHDataBeenLoaded, shouldShowContinueSetupButton, currentStep],
@@ -414,12 +413,7 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy, navigation}:
414413
// or when data is being loaded. Don't show the loading indicator if we're offline and restarted the bank account setup process
415414
// On Android, when we open the app from the background, Onfido activity gets destroyed, so we need to reopen it.
416415
// eslint-disable-next-line react-compiler/react-compiler
417-
if (
418-
(!hasACHDataBeenLoaded || isLoading) &&
419-
shouldShowOfflineLoader &&
420-
(shouldReopenOnfido || !requestorStepRef?.current) &&
421-
!(currentStep === CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT && isValidateCodeActionModalVisible)
422-
) {
416+
if ((!hasACHDataBeenLoaded || isLoading) && shouldShowOfflineLoader && (shouldReopenOnfido || !requestorStepRef?.current)) {
423417
return <ReimbursementAccountLoadingIndicator onBackButtonPress={goBack} />;
424418
}
425419

@@ -508,9 +502,7 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy, navigation}:
508502
reimbursementAccount={reimbursementAccount}
509503
onContinuePress={isNonUSDWorkspace ? continueNonUSDVBBASetup : continueUSDVBBASetup}
510504
policyName={policyName}
511-
isValidateCodeActionModalVisible={isValidateCodeActionModalVisible}
512-
toggleValidateCodeActionModal={setIsValidateCodeActionModalVisible}
513-
onBackButtonPress={Navigation.goBack}
505+
backTo={backTo}
514506
shouldShowContinueSetupButton={shouldShowContinueSetupButton}
515507
isNonUSDWorkspace={isNonUSDWorkspace}
516508
setNonUSDBankAccountStep={setNonUSDBankAccountStep}

0 commit comments

Comments
 (0)