Skip to content

Commit ec5704e

Browse files
committed
Merge branch 'vit-tieredBankAccountFlow' of https://github.com/Expensify/App into feat/bank-info-step-to-ts
2 parents 85f44ee + d918cd4 commit ec5704e

File tree

15 files changed

+500
-347
lines changed

15 files changed

+500
-347
lines changed

src/CONST.ts

+8
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,14 @@ const CONST = {
260260
EXIT: 'EXIT',
261261
},
262262
},
263+
COMPLETE_VERIFICATION: {
264+
INPUT_KEY: {
265+
BANK_ACCOUNT_ID: 'bankAccountID',
266+
IS_AUTHORIZED_TO_USE_BANK_ACCOUNT: 'isAuthorizedToUseBankAccount',
267+
CERTIFY_TRUE_INFORMATION: 'certifyTrueInformation',
268+
ACCEPT_TERMS_AND_CONDITIONS: 'acceptTermsAndConditions',
269+
},
270+
},
263271
ERROR: {
264272
MISSING_ROUTING_NUMBER: '402 Missing routingNumber',
265273
MAX_ROUTING_NUMBER: '402 Maximum Size Exceeded routingNumber',

src/languages/en.ts

+21-2
Original file line numberDiff line numberDiff line change
@@ -1535,10 +1535,29 @@ export default {
15351535
confirmAgreements: 'Please confirm the agreements below.',
15361536
certifyTrueAndAccurate: 'I certify that the information provided is true and accurate',
15371537
certifyTrueAndAccurateError: 'Must certify information is true and accurate',
1538-
isControllingOfficer: 'I am authorized to use my company bank account for business spend',
1539-
isControllingOfficerError: 'You must be a controlling officer with authorization to operate the business bank account.',
1538+
isAuthorizedToUseBankAccount: 'I am authorized to use my company bank account for business spend',
1539+
isAuthorizedToUseBankAccountError: 'You must be a controlling officer with authorization to operate the business bank account.',
15401540
termsAndConditions: 'terms and conditions',
15411541
},
1542+
connectBankAccountStep: {
1543+
connectBankAccount: 'Connect bank account',
1544+
finishButtonText: 'Finish setup',
1545+
validateYourBankAccount: 'Validate your bank account',
1546+
validateButtonText: 'Validate',
1547+
validationInputLabel: 'Transaction',
1548+
maxAttemptsReached: 'Validation for this bank account has been disabled due to too many incorrect attempts.',
1549+
description: 'A day or two after you add your account to Expensify we send three (3) transactions to your account. They have a merchant line like "Expensify, Inc. Validation".',
1550+
descriptionCTA: 'Please enter each transaction amount in the fields below. Example: 1.51.',
1551+
reviewingInfo: "Thanks! We're reviewing your information, and will be in touch shortly. Please check your chat with Concierge ",
1552+
forNextSteps: ' for next steps to finish setting up your bank account.',
1553+
letsChatCTA: "Yes, let's chat",
1554+
letsChatText: 'Thanks for doing that. We need your help verifying a few pieces of information, but we can work this out quickly over chat. Ready?',
1555+
letsChatTitle: "Let's chat!",
1556+
enable2FATitle: 'Prevent fraud, enable two-factor authentication!',
1557+
enable2FAText:
1558+
'We take your security seriously, so please set up two-factor authentication for your account now. That will allow us to dispute Expensify Card digital transactions, and will reduce your risk for fraud.',
1559+
secureYourAccount: 'Secure your account',
1560+
},
15421561
reimbursementAccountLoadingAnimation: {
15431562
oneMoment: 'One moment',
15441563
explanationLine: 'We’re taking a look at your information. You will be able to continue with next steps shortly.',

src/languages/es.ts

+27-7
Original file line numberDiff line numberDiff line change
@@ -1554,13 +1554,33 @@ export default {
15541554
},
15551555
},
15561556
completeVerificationStep: {
1557-
completeVerification: 'Complete verification',
1558-
confirmAgreements: 'Please confirm the agreements below.',
1559-
certifyTrueAndAccurate: 'I certify that the information provided is true and accurate',
1560-
certifyTrueAndAccurateError: 'Must certify information is true and accurate',
1561-
isControllingOfficer: 'I am authorized to use my company bank account for business spend',
1562-
isControllingOfficerError: 'You must be a controlling officer with authorization to operate the business bank account.',
1563-
termsAndConditions: 'terms and conditions',
1557+
completeVerification: 'Completar la verificación',
1558+
confirmAgreements: 'Por favor, confirma los Acuerdos a continuación.',
1559+
certifyTrueAndAccurate: 'Certifico que la información dada es verdadera y precisa',
1560+
certifyTrueAndAccurateError: 'Debe certificar que la información es verdadera y precisa',
1561+
isAuthorizedToUseBankAccount: 'Estoy autorizado para usar la cuenta bancaria de mi empresa para gastos comerciales',
1562+
isAuthorizedToUseBankAccountError: 'Debes ser un oficial controlador con autorización para operar la cuenta bancaria de la empresa.',
1563+
termsAndConditions: 'Términos y Condiciones',
1564+
},
1565+
connectBankAccountStep: {
1566+
connectBankAccount: 'Conectar cuenta bancaria',
1567+
finishButtonText: 'Finalizar configuración',
1568+
validateYourBankAccount: 'Valida tu cuenta bancaria',
1569+
validateButtonText: 'Validar',
1570+
validationInputLabel: 'Transacción',
1571+
maxAttemptsReached: 'La validación para esta cuenta bancaria se ha desactivado debido a demasiados intentos incorrectos.',
1572+
description:
1573+
'Un día o dos después de agregar tu cuenta a Expensify, enviamos tres (3) transacciones a tu cuenta. Tienen un nombre de comerciante similar a "Expensify, Inc. Validation".',
1574+
descriptionCTA: 'Ingresa el importe de cada transacción en los campos a continuación. Ejemplo: 1.51.',
1575+
reviewingInfo: '¡Gracias! Estamos revisando tu información y nos comunicaremos contigo en breve. Consulta el chat con Concierge ',
1576+
forNextSteps: ' para conocer los próximos pasos para terminar de configurar tu cuenta bancaria.',
1577+
letsChatCTA: 'Sí, vamos a chatear',
1578+
letsChatText: 'Gracias. Necesitamos tu ayuda para verificar la información, pero podemos resolver esto rápidamente a través del chat. ¿Estás Listo?',
1579+
letsChatTitle: '¡Vamos a chatear!',
1580+
enable2FATitle: '¡Evita fraudes, habilita la autenticación de dos factores!',
1581+
enable2FAText:
1582+
'Tu seguridad es importante para nosotros. Por favor, configura ahora la autenticación de dos factores. Eso nos permitirá disputar las transacciones de la Tarjeta Expensify y reducirá tu riesgo de fraude.',
1583+
secureYourAccount: 'Asegura tu cuenta',
15641584
},
15651585
reimbursementAccountLoadingAnimation: {
15661586
oneMoment: 'Un momento',

src/pages/ReimbursementAccount/ACHContractStep.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,15 @@ const propTypes = {
1313

1414
function ACHContractStep({onBackButtonPress, onCloseButtonPress}) {
1515
const [isBeneficialOwnerInfoSet, setIsBeneficialOwnerInfoSet] = useState(false);
16+
const handleCompleteVerificationBackButtonPress = () => setIsBeneficialOwnerInfoSet(false);
1617

1718
if (isBeneficialOwnerInfoSet) {
18-
return <CompleteVerification setIsBeneficialOwnerInfoSet={setIsBeneficialOwnerInfoSet} />;
19+
return (
20+
<CompleteVerification
21+
onBackButtonPress={handleCompleteVerificationBackButtonPress}
22+
onCloseButtonPress={onCloseButtonPress}
23+
/>
24+
);
1925
}
2026

2127
return (

src/pages/ReimbursementAccount/BankInfo/substeps/Confirmation.tsx

+11-10
Original file line numberDiff line numberDiff line change
@@ -66,21 +66,23 @@ function Confirmation({reimbursementAccount, reimbursementAccountDraft, onNext}:
6666
>
6767
<ScrollView contentContainerStyle={styles.flexGrow1}>
6868
<Text style={[styles.textHeadline, styles.ph5, styles.mb6]}>{translate('bankAccount.letsDoubleCheck')}</Text>
69-
<View style={[styles.confirmBankInfoCard]}>
69+
<View style={[styles.cardSection]}>
7070
{setupType === CONST.BANK_ACCOUNT.SUBSTEP.MANUAL && (
71-
<View style={[styles.mb5]}>
71+
<View style={[styles.mb5, styles.flexRow, styles.alignItemsCenter]}>
7272
<Icon
7373
src={Expensicons.Bank}
74-
additionalStyles={[styles.confirmBankInfoCompanyIcon, styles.mb5]}
74+
additionalStyles={[styles.confirmBankInfoCompanyIcon, styles.mr3]}
7575
fill={theme.iconHovered}
7676
/>
77-
<View style={[styles.mb3]}>
78-
<Text style={[styles.mutedTextLabel, styles.mb1]}>{translate('bankAccount.routingNumber')}</Text>
79-
<Text style={styles.confirmBankInfoNumber}>{values[bankInfoStepKeys.ROUTING_NUMBER]}</Text>
80-
</View>
8177
<View>
82-
<Text style={[styles.mutedTextLabel, styles.mb1]}>{translate('bankAccount.accountNumber')}</Text>
83-
<Text style={styles.confirmBankInfoNumber}>{values[bankInfoStepKeys.ACCOUNT_NUMBER]}</Text>
78+
<View style={[styles.mb3]}>
79+
<Text style={[styles.mutedTextLabel, styles.mb1]}>{translate('bankAccount.routingNumber')}</Text>
80+
<Text style={styles.confirmBankInfoNumber}>{values[bankInfoStepKeys.ROUTING_NUMBER]}</Text>
81+
</View>
82+
<View>
83+
<Text style={[styles.mutedTextLabel, styles.mb1]}>{translate('bankAccount.accountNumber')}</Text>
84+
<Text style={styles.confirmBankInfoNumber}>{values[bankInfoStepKeys.ACCOUNT_NUMBER]}</Text>
85+
</View>
8486
</View>
8587
</View>
8688
)}
@@ -100,7 +102,6 @@ function Confirmation({reimbursementAccount, reimbursementAccountDraft, onNext}:
100102
<MenuItem
101103
icon={Expensicons.Bank}
102104
iconType={CONST.ICON_TYPE_ICON}
103-
titleStyle={styles.confirmBankInfoText}
104105
title={translate('bankAccount.connectDifferentAccount')}
105106
onPress={handleConnectDifferentAccount}
106107
shouldShowRightIcon

src/pages/ReimbursementAccount/CompleteVerification/CompleteVerification.js

+19-10
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@ const propTypes = {
2525
/** The draft values of the bank account being setup */
2626
reimbursementAccountDraft: reimbursementAccountDraftPropTypes,
2727

28-
/** Changes variable responsible for displaying step 4 or 5 */
29-
setIsBeneficialOwnerInfoSet: PropTypes.func.isRequired,
28+
/** Handles back button press */
29+
onBackButtonPress: PropTypes.func.isRequired,
30+
31+
/** Exits flow and goes back to the workspace initial page */
32+
onCloseButtonPress: PropTypes.func.isRequired,
3033
};
3134

3235
const defaultProps = {
@@ -35,29 +38,33 @@ const defaultProps = {
3538
};
3639

3740
const BODY_CONTENT = [ConfirmAgreements];
38-
const PERSONAL_INFO_STEP_KEYS = CONST.BANK_ACCOUNT.PERSONAL_INFO_STEP.INPUT_KEY;
41+
const COMPLETE_VERIFICATION_KEYS = CONST.BANK_ACCOUNT.COMPLETE_VERIFICATION.INPUT_KEY;
42+
const BENEFICIAL_OWNER_INFO_STEP_KEYS = CONST.BANK_ACCOUNT.BENEFICIAL_OWNER_INFO_STEP.INPUT_KEY;
3943

40-
// This is a mocked step to showcase full transition between steps - will be removed with next PR
41-
const CompleteVerification = forwardRef(({reimbursementAccount, reimbursementAccountDraft, setIsBeneficialOwnerInfoSet}, ref) => {
44+
const CompleteVerification = forwardRef(({reimbursementAccount, reimbursementAccountDraft, onBackButtonPress, onCloseButtonPress}, ref) => {
4245
const {translate} = useLocalize();
4346
const styles = useThemeStyles();
4447

45-
const values = useMemo(() => getSubstepValues(PERSONAL_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]);
48+
const values = useMemo(() => getSubstepValues(COMPLETE_VERIFICATION_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]);
4649

4750
const submit = useCallback(() => {
4851
const payload = {
49-
bankAccountID: getDefaultValueForReimbursementAccountField(reimbursementAccount, PERSONAL_INFO_STEP_KEYS.BANK_ACCOUNT_ID, 0),
52+
bankAccountID: getDefaultValueForReimbursementAccountField(reimbursementAccount, COMPLETE_VERIFICATION_KEYS.BANK_ACCOUNT_ID, 0),
5053
...values,
5154
};
55+
const beneficialOwnersStepValues = getSubstepValues(BENEFICIAL_OWNER_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount);
5256

53-
BankAccounts.updatePersonalInformationForBankAccount(payload);
54-
}, [reimbursementAccount, values]);
57+
BankAccounts.updateBeneficialOwnersForBankAccount({
58+
...beneficialOwnersStepValues,
59+
...payload,
60+
});
61+
}, [reimbursementAccount, reimbursementAccountDraft, values]);
5562

5663
const {componentToRender: SubStep, isEditing, screenIndex, nextScreen, prevScreen, moveTo} = useSubStep({bodyContent: BODY_CONTENT, startFrom: 0, onFinished: submit});
5764

5865
const handleBackButtonPress = () => {
5966
if (screenIndex === 0) {
60-
setIsBeneficialOwnerInfoSet(false);
67+
onBackButtonPress();
6168
} else {
6269
prevScreen();
6370
}
@@ -74,6 +81,8 @@ const CompleteVerification = forwardRef(({reimbursementAccount, reimbursementAcc
7481
<HeaderWithBackButton
7582
onBackButtonPress={handleBackButtonPress}
7683
title={translate('completeVerificationStep.completeVerification')}
84+
shouldShowCloseButton
85+
onCloseButtonPress={onCloseButtonPress}
7786
/>
7887
<View style={[styles.ph5, styles.mt3, {height: CONST.BANK_ACCOUNT.STEPS_HEADER_HEIGHT}]}>
7988
<InteractiveStepSubHeader
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React from 'react';
2+
import {withOnyx} from 'react-native-onyx';
23
import CheckboxWithLabel from '@components/CheckboxWithLabel';
34
import FormProvider from '@components/Form/FormProvider';
45
import InputWrapper from '@components/Form/InputWrapper';
@@ -8,8 +9,23 @@ import TextLink from '@components/TextLink';
89
import useLocalize from '@hooks/useLocalize';
910
import useThemeStyles from '@hooks/useThemeStyles';
1011
import * as ValidationUtils from '@libs/ValidationUtils';
12+
import {reimbursementAccountPropTypes} from '@pages/ReimbursementAccount/reimbursementAccountPropTypes';
13+
import * as ReimbursementAccountProps from '@pages/ReimbursementAccount/reimbursementAccountPropTypes';
14+
import subStepPropTypes from '@pages/ReimbursementAccount/subStepPropTypes';
15+
import getDefaultValueForReimbursementAccountField from '@pages/ReimbursementAccount/utils/getDefaultValueForReimbursementAccountField';
16+
import CONST from '@src/CONST';
1117
import ONYXKEYS from '@src/ONYXKEYS';
1218

19+
const propTypes = {
20+
/** Reimbursement account from ONYX */
21+
reimbursementAccount: reimbursementAccountPropTypes,
22+
...subStepPropTypes,
23+
};
24+
25+
const defaultProps = {
26+
reimbursementAccount: ReimbursementAccountProps.reimbursementAccountDefaultProps,
27+
};
28+
1329
const validate = (values) => {
1430
const errors = {};
1531

@@ -21,16 +37,31 @@ const validate = (values) => {
2137
errors.certifyTrueInformation = 'completeVerificationStep.certifyTrueAndAccurateError';
2238
}
2339

24-
if (!ValidationUtils.isRequiredFulfilled(values.isControllingOfficer)) {
25-
errors.isControllingOfficer = 'completeVerificationStep.isControllingOfficerError';
40+
if (!ValidationUtils.isRequiredFulfilled(values.isAuthorizedToUseBankAccount)) {
41+
errors.isAuthorizedToUseBankAccount = 'completeVerificationStep.isAuthorizedToUseBankAccountError';
2642
}
2743

2844
return errors;
2945
};
3046

31-
function ConfirmAgreements() {
47+
const COMPLETE_VERIFICATION_KEYS = CONST.BANK_ACCOUNT.COMPLETE_VERIFICATION.INPUT_KEY;
48+
49+
function ConfirmAgreements({onNext, reimbursementAccount}) {
3250
const {translate} = useLocalize();
3351
const styles = useThemeStyles();
52+
const defaultValues = {
53+
[COMPLETE_VERIFICATION_KEYS.IS_AUTHORIZED_TO_USE_BANK_ACCOUNT]: getDefaultValueForReimbursementAccountField(
54+
reimbursementAccount,
55+
COMPLETE_VERIFICATION_KEYS.IS_AUTHORIZED_TO_USE_BANK_ACCOUNT,
56+
false,
57+
),
58+
[COMPLETE_VERIFICATION_KEYS.CERTIFY_TRUE_INFORMATION]: getDefaultValueForReimbursementAccountField(reimbursementAccount, COMPLETE_VERIFICATION_KEYS.CERTIFY_TRUE_INFORMATION, false),
59+
[COMPLETE_VERIFICATION_KEYS.ACCEPT_TERMS_AND_CONDITIONS]: getDefaultValueForReimbursementAccountField(
60+
reimbursementAccount,
61+
COMPLETE_VERIFICATION_KEYS.ACCEPT_TERMS_AND_CONDITIONS,
62+
false,
63+
),
64+
};
3465

3566
return (
3667
<ScreenWrapper
@@ -42,40 +73,40 @@ function ConfirmAgreements() {
4273
<FormProvider
4374
formID={ONYXKEYS.REIMBURSEMENT_ACCOUNT}
4475
validate={validate}
45-
onSubmit={() => {}}
76+
onSubmit={onNext}
4677
submitButtonText={translate('common.saveAndContinue')}
4778
style={[styles.mh5, styles.flexGrow1]}
4879
>
4980
<InputWrapper
5081
InputComponent={CheckboxWithLabel}
51-
accessibilityLabel={translate('completeVerificationStep.isControllingOfficer')}
52-
inputID="isControllingOfficer"
82+
accessibilityLabel={translate('completeVerificationStep.isAuthorizedToUseBankAccount')}
83+
inputID={COMPLETE_VERIFICATION_KEYS.IS_AUTHORIZED_TO_USE_BANK_ACCOUNT}
5384
style={styles.mt4}
54-
LabelComponent={() => <Text>{translate('completeVerificationStep.isControllingOfficer')}</Text>}
55-
defaultValue={false}
85+
LabelComponent={() => <Text>{translate('completeVerificationStep.isAuthorizedToUseBankAccount')}</Text>}
86+
defaultValue={defaultValues[COMPLETE_VERIFICATION_KEYS.IS_AUTHORIZED_TO_USE_BANK_ACCOUNT]}
5687
shouldSaveDraft
5788
/>
5889
<InputWrapper
5990
InputComponent={CheckboxWithLabel}
6091
accessibilityLabel={translate('completeVerificationStep.certifyTrueAndAccurate')}
61-
inputID="certifyTrueInformation"
92+
inputID={COMPLETE_VERIFICATION_KEYS.CERTIFY_TRUE_INFORMATION}
6293
style={styles.mt4}
6394
LabelComponent={() => <Text>{translate('completeVerificationStep.certifyTrueAndAccurate')}</Text>}
64-
defaultValue={false}
95+
defaultValue={defaultValues[COMPLETE_VERIFICATION_KEYS.CERTIFY_TRUE_INFORMATION]}
6596
shouldSaveDraft
6697
/>
6798
<InputWrapper
6899
InputComponent={CheckboxWithLabel}
69100
accessibilityLabel={`${translate('common.iAcceptThe')} ${translate('completeVerificationStep.termsAndConditions')}`}
70-
inputID="acceptTermsAndConditions"
101+
inputID={COMPLETE_VERIFICATION_KEYS.ACCEPT_TERMS_AND_CONDITIONS}
71102
style={styles.mt4}
72103
LabelComponent={() => (
73104
<Text>
74105
{translate('common.iAcceptThe')}
75106
<TextLink href="https://use.expensify.com/achterms">{`${translate('completeVerificationStep.termsAndConditions')}`}</TextLink>
76107
</Text>
77108
)}
78-
defaultValue={false}
109+
defaultValue={defaultValues[COMPLETE_VERIFICATION_KEYS.ACCEPT_TERMS_AND_CONDITIONS]}
79110
shouldSaveDraft
80111
/>
81112
</FormProvider>
@@ -84,5 +115,11 @@ function ConfirmAgreements() {
84115
}
85116

86117
ConfirmAgreements.displayName = 'ConfirmAgreements';
118+
ConfirmAgreements.propTypes = propTypes;
119+
ConfirmAgreements.defaultProps = defaultProps;
87120

88-
export default ConfirmAgreements;
121+
export default withOnyx({
122+
reimbursementAccount: {
123+
key: ONYXKEYS.REIMBURSEMENT_ACCOUNT,
124+
},
125+
})(ConfirmAgreements);

0 commit comments

Comments
 (0)