Skip to content

Commit

Permalink
fix: add Verify account page
Browse files Browse the repository at this point in the history
  • Loading branch information
daledah committed Sep 17, 2024
1 parent a7c1e49 commit f7310b1
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 81 deletions.
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',
},

EXIT_SURVEY: {
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,

This comment has been minimized.

Copy link
@c3024

c3024 Dec 2, 2024

Contributor

Pay someone flow triggers the verify account modal but we still want to stay on Report Central Pane. So, this was removed here. #52456

],
[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
104 changes: 35 additions & 69 deletions src/pages/AddPersonalBankAccountPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,13 @@ import FormProvider from '@components/Form/FormProvider';
import InputWrapper from '@components/Form/InputWrapper';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import ValidateCodeActionModal from '@components/ValidateCodeActionModal';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import * as ErrorUtils from '@libs/ErrorUtils';
import getPlaidOAuthReceivedRedirectURI from '@libs/getPlaidOAuthReceivedRedirectURI';
import Navigation from '@libs/Navigation/Navigation';
import * as BankAccounts from '@userActions/BankAccounts';
import * as PaymentMethods from '@userActions/PaymentMethods';
import * as User from '@userActions/User';
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 All @@ -35,23 +31,8 @@ function AddPersonalBankAccountPage({personalBankAccount, plaidData}: AddPersona
const {translate} = useLocalize();
const [selectedPlaidAccountId, setSelectedPlaidAccountId] = useState('');
const [isUserValidated] = useOnyx(ONYXKEYS.USER, {selector: (user) => !!user?.validated});
const [isValidateCodeActionModalVisible, setIsValidateCodeActionModalVisible] = useState(!isUserValidated);
const shouldShowSuccess = personalBankAccount?.shouldShowSuccess ?? false;

const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST);
const [account] = useOnyx(ONYXKEYS.ACCOUNT);
const primaryLogin = account?.primaryLogin;
const loginData = loginList?.[primaryLogin ?? ''];
const validateLoginError = ErrorUtils.getEarliestErrorField(loginData, 'validateLogin');

const handleSubmitForm = useCallback(
(submitCode: string) => {
User.validateSecondaryLogin(loginList, primaryLogin ?? '', submitCode);
Navigation.navigate(ROUTES.SETTINGS_ADD_BANK_ACCOUNT);
},
[loginList, primaryLogin],
);

const submitBankAccountForm = useCallback(() => {
const bankAccounts = plaidData?.bankAccounts ?? [];
const selectedPlaidBankAccount = bankAccounts.find((bankAccount) => bankAccount.plaidAccountID === selectedPlaidAccountId);
Expand Down Expand Up @@ -86,58 +67,43 @@ function AddPersonalBankAccountPage({personalBankAccount, plaidData}: AddPersona
shouldShowOfflineIndicator={false}
testID={AddPersonalBankAccountPage.displayName}
>
{isUserValidated && (
<FullPageNotFoundView>
<HeaderWithBackButton
title={translate('bankAccount.addBankAccount')}
onBackButtonPress={exitFlow}
<FullPageNotFoundView shouldShow={!isUserValidated}>
<HeaderWithBackButton
title={translate('bankAccount.addBankAccount')}
onBackButtonPress={exitFlow}
/>
{shouldShowSuccess ? (
<ConfirmationPage
heading={translate('addPersonalBankAccountPage.successTitle')}
description={translate('addPersonalBankAccountPage.successMessage')}
shouldShowButton
buttonText={translate('common.continue')}
onButtonPress={() => exitFlow(true)}
/>
{shouldShowSuccess ? (
<ConfirmationPage
heading={translate('addPersonalBankAccountPage.successTitle')}
description={translate('addPersonalBankAccountPage.successMessage')}
shouldShowButton
buttonText={translate('common.continue')}
onButtonPress={() => exitFlow(true)}
) : (
<FormProvider
formID={ONYXKEYS.FORMS.PERSONAL_BANK_ACCOUNT_FORM}
isSubmitButtonVisible={(plaidData?.bankAccounts ?? []).length > 0}
submitButtonText={translate('common.saveAndContinue')}
scrollContextEnabled
onSubmit={submitBankAccountForm}
validate={BankAccounts.validatePlaidSelection}
style={[styles.mh5, styles.flex1]}
>
<InputWrapper
inputID={INPUT_IDS.BANK_INFO_STEP.SELECTED_PLAID_ACCOUNT_ID}
InputComponent={AddPlaidBankAccount}
onSelect={setSelectedPlaidAccountId}
text={translate('walletPage.chooseAccountBody')}
plaidData={plaidData}
isDisplayedInWalletFlow
onExitPlaid={() => Navigation.goBack()}
receivedRedirectURI={getPlaidOAuthReceivedRedirectURI()}
selectedPlaidAccountID={selectedPlaidAccountId}
/>
) : (
<FormProvider
formID={ONYXKEYS.FORMS.PERSONAL_BANK_ACCOUNT_FORM}
isSubmitButtonVisible={(plaidData?.bankAccounts ?? []).length > 0}
submitButtonText={translate('common.saveAndContinue')}
scrollContextEnabled
onSubmit={submitBankAccountForm}
validate={BankAccounts.validatePlaidSelection}
style={[styles.mh5, styles.flex1]}
>
<InputWrapper
inputID={INPUT_IDS.BANK_INFO_STEP.SELECTED_PLAID_ACCOUNT_ID}
InputComponent={AddPlaidBankAccount}
onSelect={setSelectedPlaidAccountId}
text={translate('walletPage.chooseAccountBody')}
plaidData={plaidData}
isDisplayedInWalletFlow
onExitPlaid={() => Navigation.goBack()}
receivedRedirectURI={getPlaidOAuthReceivedRedirectURI()}
selectedPlaidAccountID={selectedPlaidAccountId}
/>
</FormProvider>
)}
</FullPageNotFoundView>
)}
<ValidateCodeActionModal
validatePendingAction={loginList?.[primaryLogin ?? '-1']?.pendingFields?.validateLogin}
validateError={validateLoginError}
isVisible={isValidateCodeActionModalVisible}
title={translate('contacts.validateAccount')}
description={translate('contacts.featureRequiresValidate')}
onClose={() => {
setIsValidateCodeActionModalVisible(false);
exitFlow();
}}
handleSubmitForm={handleSubmitForm}
clearError={() => {}}
/>
</FormProvider>
)}
</FullPageNotFoundView>
</ScreenWrapper>
);
}
Expand Down
11 changes: 2 additions & 9 deletions src/pages/EnablePayments/AddBankAccount/SetupMethod.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,8 @@ 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,7 +25,7 @@ type SetupMethodProps = SetupMethodOnyxProps;

const plaidDesktopMessage = getPlaidDesktopMessage();

function SetupMethod({isPlaidDisabled, user}: SetupMethodProps) {
function SetupMethod({isPlaidDisabled}: SetupMethodProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();

Expand All @@ -52,7 +48,7 @@ function SetupMethod({isPlaidDisabled, user}: SetupMethodProps) {
icon={Expensicons.Bank}
text={translate('bankAccount.addBankAccount')}
onPress={() => BankAccounts.openPersonalBankAccountSetupWithPlaid()}
isDisabled={!!isPlaidDisabled || !user?.validated}
isDisabled={!!isPlaidDisabled}
style={[styles.mt4, styles.mb2]}
iconStyles={styles.buttonCTAIcon}
shouldShowRightIcon
Expand All @@ -70,7 +66,4 @@ export default withOnyx<SetupMethodProps, SetupMethodOnyxProps>({
isPlaidDisabled: {
key: ONYXKEYS.IS_PLAID_DISABLED,
},
user: {
key: ONYXKEYS.USER,
},
})(SetupMethod);
16 changes: 13 additions & 3 deletions src/pages/settings/Wallet/PaymentMethodList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import React, {useCallback, useMemo} from 'react';
import type {GestureResponderEvent, StyleProp, ViewStyle} from 'react-native';
import {FlatList, View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import {useOnyx, withOnyx} from 'react-native-onyx';
import type {SvgProps} from 'react-native-svg/lib/typescript/ReactNativeSVG';
import type {ValueOf} from 'type-fest';
import type {RenderSuggestionMenuItemProps} from '@components/AutoCompleteSuggestions/types';
Expand Down Expand Up @@ -199,6 +199,8 @@ function PaymentMethodList({
const {translate} = useLocalize();
const {isOffline} = useNetwork();

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

const getDescriptionForPolicyDomainCard = (domainName: string): string => {
// A domain name containing a policyID indicates that this is a workspace feed
const policyID = domainName.match(CONST.REGEX.EXPENSIFY_POLICY_DOMAIN_NAME)?.[1];
Expand Down Expand Up @@ -322,17 +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}
/>
),
[onPress, translate, styles.paymentMethod, listItemStyle, buttonRef],
[translate, styles.paymentMethod, listItemStyle, buttonRef, onPressItem],
);

/**
Expand Down
73 changes: 73 additions & 0 deletions src/pages/settings/Wallet/VerifyAccountPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
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 [pendingContactAction] = useOnyx(ONYXKEYS.PENDING_CONTACT_ACTION);
const contactMethod = account?.primaryLogin ?? '';
const themeStyles = useThemeStyles();
const {translate} = useLocalize();
const loginInputRef = useRef<AnimatedTextInputRef>(null);
const loginData = loginList?.[pendingContactAction?.contactMethod ?? contactMethod];
const validateLoginError = ErrorUtils.getEarliestErrorField(loginData, 'validateLogin');

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

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

useEffect(() => () => User.clearUnvalidatedNewContactMethodAction(), []);

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

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

VerifyAccountPage.displayName = 'VerifyAccountPage';

export default VerifyAccountPage;

0 comments on commit f7310b1

Please sign in to comment.