Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: requires validate when opening bank account #49230

Merged
merged 16 commits into from
Oct 2, 2024
Merged
1 change: 1 addition & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ const ROUTES = {
SETTINGS_ABOUT: 'settings/about',
SETTINGS_APP_DOWNLOAD_LINKS: 'settings/about/app-download-links',
SETTINGS_WALLET: 'settings/wallet',
SETTINGS_WALLET_VERIFY_ACCOUNT: {route: 'settings/wallet/verify', getRoute: (backTo?: string) => getUrlWithBackToParam('settings/wallet/verify', backTo)},
SETTINGS_WALLET_DOMAINCARD: {
route: 'settings/wallet/card/:cardID?',
getRoute: (cardID: string) => `settings/wallet/card/${cardID}` as const,
Expand Down
1 change: 1 addition & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ const SCREENS = {
CARD_ACTIVATE: 'Settings_Wallet_Card_Activate',
REPORT_VIRTUAL_CARD_FRAUD: 'Settings_Wallet_ReportVirtualCardFraud',
CARDS_DIGITAL_DETAILS_UPDATE_ADDRESS: 'Settings_Wallet_Cards_Digital_Details_Update_Address',
VERIFY_ACCOUNT: 'Settings_Wallet_Verify_Account',
daledah marked this conversation as resolved.
Show resolved Hide resolved
},

EXIT_SURVEY: {
Expand Down
2 changes: 2 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,8 @@ export default {
contacts: {
contactMethod: 'Contact method',
contactMethods: 'Contact methods',
featureRequiresValidate: 'This feature requires you to validate your account.',
validateAccount: 'Validate your account',
helpTextBeforeEmail: 'Add more ways for people to find you, and forward receipts to ',
helpTextAfterEmail: ' from multiple email addresses.',
pleaseVerify: 'Please verify this contact method',
Expand Down
2 changes: 2 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,8 @@ export default {
contacts: {
contactMethod: 'Método de contacto',
contactMethods: 'Métodos de contacto',
featureRequiresValidate: 'Esta función requiere que valides tu cuenta.',
validateAccount: 'Valida tu cuenta',
helpTextBeforeEmail: 'Añade más formas de que la gente te encuentre y reenvía los recibos a ',
helpTextAfterEmail: ' desde varias direcciones de correo electrónico.',
pleaseVerify: 'Por favor, verifica este método de contacto',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
[SCREENS.SETTINGS.WALLET.TRANSFER_BALANCE]: () => require<ReactComponentModule>('../../../../pages/settings/Wallet/TransferBalancePage').default,
[SCREENS.SETTINGS.WALLET.CHOOSE_TRANSFER_ACCOUNT]: () => require<ReactComponentModule>('../../../../pages/settings/Wallet/ChooseTransferAccountPage').default,
[SCREENS.SETTINGS.WALLET.ENABLE_PAYMENTS]: () => require<ReactComponentModule>('../../../../pages/EnablePayments/EnablePayments').default,
[SCREENS.SETTINGS.WALLET.VERIFY_ACCOUNT]: () => require<ReactComponentModule>('../../../../pages/settings/Wallet/VerifyAccountPage').default,
[SCREENS.SETTINGS.ADD_DEBIT_CARD]: () => require<ReactComponentModule>('../../../../pages/settings/Wallet/AddDebitCardPage').default,
[SCREENS.SETTINGS.ADD_BANK_ACCOUNT]: () => require<ReactComponentModule>('../../../../pages/AddPersonalBankAccountPage').default,
[SCREENS.SETTINGS.PROFILE.STATUS]: () => require<ReactComponentModule>('../../../../pages/settings/Profile/CustomStatus/StatusPage').default,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const CENTRAL_PANE_TO_RHP_MAPPING: Partial<Record<CentralPaneName, string[]>> =
SCREENS.SETTINGS.WALLET.CARD_ACTIVATE,
SCREENS.SETTINGS.WALLET.REPORT_VIRTUAL_CARD_FRAUD,
SCREENS.SETTINGS.WALLET.CARDS_DIGITAL_DETAILS_UPDATE_ADDRESS,
SCREENS.SETTINGS.WALLET.VERIFY_ACCOUNT,
],
[SCREENS.SETTINGS.SECURITY]: [
SCREENS.SETTINGS.TWO_FACTOR_AUTH,
Expand Down
4 changes: 4 additions & 0 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
path: ROUTES.SETTINGS_CLOSE,
exact: true,
},
[SCREENS.SETTINGS.WALLET.VERIFY_ACCOUNT]: {
path: ROUTES.SETTINGS_WALLET_VERIFY_ACCOUNT.route,
exact: true,
},
[SCREENS.SETTINGS.WALLET.DOMAIN_CARD]: {
path: ROUTES.SETTINGS_WALLET_DOMAINCARD.route,
exact: true,
Expand Down
5 changes: 3 additions & 2 deletions src/pages/AddPersonalBankAccountPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import Navigation from '@libs/Navigation/Navigation';
import * as BankAccounts from '@userActions/BankAccounts';
import * as PaymentMethods from '@userActions/PaymentMethods';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import INPUT_IDS from '@src/types/form/ReimbursementAccountForm';
import type {PersonalBankAccount, PlaidData} from '@src/types/onyx';

Expand Down Expand Up @@ -52,7 +53,7 @@ function AddPersonalBankAccountPage({personalBankAccount, plaidData}: AddPersona
} else if (shouldContinue && onSuccessFallbackRoute) {
PaymentMethods.continueSetup(onSuccessFallbackRoute);
} else {
Navigation.goBack();
Navigation.navigate(ROUTES.SETTINGS_WALLET);
daledah marked this conversation as resolved.
Show resolved Hide resolved
}
},
[personalBankAccount],
Expand Down Expand Up @@ -97,7 +98,7 @@ function AddPersonalBankAccountPage({personalBankAccount, plaidData}: AddPersona
text={translate('walletPage.chooseAccountBody')}
plaidData={plaidData}
isDisplayedInWalletFlow
onExitPlaid={() => Navigation.goBack()}
onExitPlaid={() => Navigation.navigate(ROUTES.SETTINGS_WALLET)}
receivedRedirectURI={getPlaidOAuthReceivedRedirectURI()}
selectedPlaidAccountID={selectedPlaidAccountId}
/>
Expand Down
23 changes: 12 additions & 11 deletions src/pages/EnablePayments/AddBankAccount/SetupMethod.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import {useOnyx, withOnyx} from 'react-native-onyx';
import type {OnyxEntry} from 'react-native-onyx';
import Button from '@components/Button';
import * as Expensicons from '@components/Icon/Expensicons';
Expand All @@ -11,16 +11,13 @@ import TextLink from '@components/TextLink';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import getPlaidDesktopMessage from '@libs/getPlaidDesktopMessage';
import Navigation from '@libs/Navigation/Navigation';
import * as BankAccounts from '@userActions/BankAccounts';
import * as Link from '@userActions/Link';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {User} from '@src/types/onyx';

type SetupMethodOnyxProps = {
/** The user's data */
user: OnyxEntry<User>;

/** Whether Plaid is disabled */
isPlaidDisabled: OnyxEntry<boolean>;
};
Expand All @@ -29,9 +26,10 @@ type SetupMethodProps = SetupMethodOnyxProps;

const plaidDesktopMessage = getPlaidDesktopMessage();

function SetupMethod({isPlaidDisabled, user}: SetupMethodProps) {
function SetupMethod({isPlaidDisabled}: SetupMethodProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const [isUserValidated] = useOnyx(ONYXKEYS.USER, {selector: (user) => !!user?.validated});

return (
<View>
Expand All @@ -51,8 +49,14 @@ function SetupMethod({isPlaidDisabled, user}: SetupMethodProps) {
<Button
icon={Expensicons.Bank}
text={translate('bankAccount.addBankAccount')}
onPress={() => BankAccounts.openPersonalBankAccountSetupWithPlaid()}
isDisabled={!!isPlaidDisabled || !user?.validated}
onPress={() => {
if (!isUserValidated) {
Navigation.navigate(ROUTES.SETTINGS_WALLET_VERIFY_ACCOUNT.getRoute(ROUTES.SETTINGS_ENABLE_PAYMENTS));
return;
}
BankAccounts.openPersonalBankAccountSetupWithPlaid();
}}
isDisabled={!!isPlaidDisabled}
style={[styles.mt4, styles.mb2]}
iconStyles={styles.buttonCTAIcon}
shouldShowRightIcon
Expand All @@ -70,7 +74,4 @@ export default withOnyx<SetupMethodProps, SetupMethodOnyxProps>({
isPlaidDisabled: {
key: ONYXKEYS.IS_PLAID_DISABLED,
},
user: {
key: ONYXKEYS.USER,
},
})(SetupMethod);
15 changes: 11 additions & 4 deletions src/pages/settings/Wallet/PaymentMethodList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ function PaymentMethodList({
const StyleUtils = useStyleUtils();
const {translate} = useLocalize();
const {isOffline} = useNetwork();

const [isUserValidated] = useOnyx(ONYXKEYS.USER, {selector: (user) => !!user?.validated});

const getDescriptionForPolicyDomainCard = (domainName: string): string => {
Expand Down Expand Up @@ -323,19 +324,25 @@ function PaymentMethodList({
*/
const renderListEmptyComponent = () => <Text style={styles.popoverMenuItem}>{translate('paymentMethodList.addFirstPaymentMethod')}</Text>;

const onPressItem = useCallback(() => {
if (!isUserValidated) {
Navigation.navigate(ROUTES.SETTINGS_WALLET_VERIFY_ACCOUNT.getRoute(ROUTES.SETTINGS_ADD_BANK_ACCOUNT));
return;
}
onPress();
}, [isUserValidated, onPress]);

const renderListFooterComponent = useCallback(
() => (
<MenuItem
onPress={onPress}
onPress={onPressItem}
title={translate('walletPage.addBankAccount')}
icon={Expensicons.Plus}
wrapperStyle={[styles.paymentMethod, listItemStyle]}
ref={buttonRef}
disabled={!isUserValidated}
/>
),

[onPress, translate, styles.paymentMethod, listItemStyle, buttonRef, isUserValidated],
[translate, styles.paymentMethod, listItemStyle, buttonRef, onPressItem],
);

/**
Expand Down
86 changes: 86 additions & 0 deletions src/pages/settings/Wallet/VerifyAccountPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import type {StackScreenProps} from '@react-navigation/stack';
import React, {useCallback, useEffect, useRef} from 'react';
import {View} from 'react-native';
import {useOnyx} from 'react-native-onyx';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import type {AnimatedTextInputRef} from '@components/RNTextInput';
import ScreenWrapper from '@components/ScreenWrapper';
import Text from '@components/Text';
import ValidateCodeForm from '@components/ValidateCodeActionModal/ValidateCodeForm';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import * as ErrorUtils from '@libs/ErrorUtils';
import Navigation from '@libs/Navigation/Navigation';
import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
import * as User from '@userActions/User';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type SCREENS from '@src/SCREENS';

type VerifyAccountPageProps = StackScreenProps<SettingsNavigatorParamList, typeof SCREENS.SETTINGS.PROFILE.NEW_CONTACT_METHOD>;

function VerifyAccountPage({route}: VerifyAccountPageProps) {
const [account] = useOnyx(ONYXKEYS.ACCOUNT);
const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST);
const contactMethod = account?.primaryLogin ?? '';
const themeStyles = useThemeStyles();
const {translate} = useLocalize();
const loginInputRef = useRef<AnimatedTextInputRef>(null);
const firstRenderRef = useRef(true);
const loginData = loginList?.[contactMethod];
const validateLoginError = ErrorUtils.getEarliestErrorField(loginData, 'validateLogin');
const [isUserValidated] = useOnyx(ONYXKEYS.USER, {selector: (user) => !!user?.validated});

const [validateCodeAction] = useOnyx(ONYXKEYS.VALIDATE_ACTION_CODE);

const navigateBackTo = route?.params?.backTo ?? ROUTES.SETTINGS_WALLET;

useEffect(() => {
if (firstRenderRef.current) {
daledah marked this conversation as resolved.
Show resolved Hide resolved
firstRenderRef.current = false;
User.requestValidateCodeAction();
}
return () => User.clearUnvalidatedNewContactMethodAction();
}, []);

const handleSubmitForm = useCallback(
(submitCode: string) => {
User.validateSecondaryLogin(loginList, contactMethod ?? '', submitCode);
},
[loginList, contactMethod],
);

useEffect(() => {
if (!isUserValidated) {
return;
}
Navigation.navigate(navigateBackTo);
}, [isUserValidated, navigateBackTo]);

return (
<ScreenWrapper
onEntryTransitionEnd={() => loginInputRef.current?.focus()}
includeSafeAreaPaddingBottom={false}
shouldEnableMaxHeight
testID={VerifyAccountPage.displayName}
>
<HeaderWithBackButton
title={translate('contacts.validateAccount')}
onBackButtonPress={() => Navigation.goBack(ROUTES.SETTINGS_WALLET)}
/>
<View style={[themeStyles.ph5, themeStyles.mt3, themeStyles.mb7]}>
<Text style={[themeStyles.mb3]}>{translate('contacts.featureRequiresValidate')}</Text>
<ValidateCodeForm
validateCodeAction={validateCodeAction}
validateError={validateLoginError}
handleSubmitForm={handleSubmitForm}
clearError={() => User.clearContactMethodErrors(contactMethod, 'validateLogin')}
/>
</View>
</ScreenWrapper>
);
}

VerifyAccountPage.displayName = 'VerifyAccountPage';

export default VerifyAccountPage;
Loading