-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Refactor: Migrate BankAccountManualStep.js to function component #22245
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
Changes from all commits
ed23446
87f3acb
e2e1676
edea17a
d1f6c4d
a214f28
bc36afd
5e3e885
3d076fb
da2f288
a23ca39
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| import React from 'react'; | ||
| import React, {useCallback} from 'react'; | ||
| import _ from 'underscore'; | ||
| import {Image} from 'react-native'; | ||
| import lodashGet from 'lodash/get'; | ||
| import HeaderWithBackButton from '../../components/HeaderWithBackButton'; | ||
|
|
@@ -9,7 +10,8 @@ import TextInput from '../../components/TextInput'; | |
| import styles from '../../styles/styles'; | ||
| import CheckboxWithLabel from '../../components/CheckboxWithLabel'; | ||
| import TextLink from '../../components/TextLink'; | ||
| import withLocalize from '../../components/withLocalize'; | ||
| import useLocalize from '../../hooks/useLocalize'; | ||
| import {withLocalizePropTypes} from '../../components/withLocalize'; | ||
| import * as ValidationUtils from '../../libs/ValidationUtils'; | ||
| import ONYXKEYS from '../../ONYXKEYS'; | ||
| import exampleCheckImage from './exampleCheckImage'; | ||
|
|
@@ -19,115 +21,116 @@ import ScreenWrapper from '../../components/ScreenWrapper'; | |
| import StepPropTypes from './StepPropTypes'; | ||
|
|
||
| const propTypes = { | ||
| ...StepPropTypes, | ||
| ..._.omit(StepPropTypes, _.keys(withLocalizePropTypes)), | ||
| }; | ||
|
|
||
| class BankAccountManualStep extends React.Component { | ||
| constructor(props) { | ||
| super(props); | ||
| this.submit = this.submit.bind(this); | ||
| this.validate = this.validate.bind(this); | ||
| } | ||
|
|
||
| function BankAccountManualStep(props) { | ||
| const {translate, preferredLocale} = useLocalize(); | ||
| const {reimbursementAccount, reimbursementAccountDraft} = props; | ||
| /** | ||
| * @param {Object} values - form input values passed by the Form component | ||
| * @returns {Object} | ||
| */ | ||
| validate(values) { | ||
| const errorFields = {}; | ||
| const routingNumber = values.routingNumber && values.routingNumber.trim(); | ||
| const validate = useCallback( | ||
| (values) => { | ||
| const errorFields = {}; | ||
| const routingNumber = values.routingNumber && values.routingNumber.trim(); | ||
|
|
||
| if ( | ||
| !values.accountNumber || | ||
| (!CONST.BANK_ACCOUNT.REGEX.US_ACCOUNT_NUMBER.test(values.accountNumber.trim()) && !CONST.BANK_ACCOUNT.REGEX.MASKED_US_ACCOUNT_NUMBER.test(values.accountNumber.trim())) | ||
| ) { | ||
| errorFields.accountNumber = 'bankAccount.error.accountNumber'; | ||
| } else if (values.accountNumber === routingNumber) { | ||
| errorFields.accountNumber = this.props.translate('bankAccount.error.routingAndAccountNumberCannotBeSame'); | ||
| } | ||
| if (!routingNumber || !CONST.BANK_ACCOUNT.REGEX.SWIFT_BIC.test(routingNumber) || !ValidationUtils.isValidRoutingNumber(routingNumber)) { | ||
| errorFields.routingNumber = 'bankAccount.error.routingNumber'; | ||
| } | ||
| if (!values.acceptTerms) { | ||
| errorFields.acceptTerms = 'common.error.acceptTerms'; | ||
| } | ||
| if ( | ||
| !values.accountNumber || | ||
| (!CONST.BANK_ACCOUNT.REGEX.US_ACCOUNT_NUMBER.test(values.accountNumber.trim()) && !CONST.BANK_ACCOUNT.REGEX.MASKED_US_ACCOUNT_NUMBER.test(values.accountNumber.trim())) | ||
| ) { | ||
| errorFields.accountNumber = 'bankAccount.error.accountNumber'; | ||
| } else if (values.accountNumber === routingNumber) { | ||
| errorFields.accountNumber = translate('bankAccount.error.routingAndAccountNumberCannotBeSame'); | ||
| } | ||
| if (!routingNumber || !CONST.BANK_ACCOUNT.REGEX.SWIFT_BIC.test(routingNumber) || !ValidationUtils.isValidRoutingNumber(routingNumber)) { | ||
| errorFields.routingNumber = 'bankAccount.error.routingNumber'; | ||
| } | ||
| if (!values.acceptTerms) { | ||
| errorFields.acceptTerms = 'common.error.acceptTerms'; | ||
| } | ||
|
|
||
| return errorFields; | ||
| } | ||
| return errorFields; | ||
| }, | ||
| [translate], | ||
| ); | ||
|
|
||
| submit(values) { | ||
| BankAccounts.connectBankAccountManually( | ||
| lodashGet(this.props.reimbursementAccount, 'achData.bankAccountID') || 0, | ||
| values.accountNumber, | ||
| values.routingNumber, | ||
| lodashGet(this.props, ['reimbursementAccountDraft', 'plaidMask']), | ||
| ); | ||
| } | ||
| const submit = useCallback( | ||
| (values) => { | ||
| BankAccounts.connectBankAccountManually( | ||
| lodashGet(reimbursementAccount, ['achData.bankAccountID']) || 0, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like this line caused this regression. Why did you convert lodashGet to an array path? Regardless, this should be
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oops, I completely missed this during refactor. There is one more. |
||
| values.accountNumber, | ||
| values.routingNumber, | ||
| lodashGet(reimbursementAccountDraft, ['plaidMask']), | ||
| ); | ||
| }, | ||
| [reimbursementAccount, reimbursementAccountDraft], | ||
|
Vishrut19 marked this conversation as resolved.
|
||
| ); | ||
|
|
||
| render() { | ||
| const shouldDisableInputs = Boolean(lodashGet(this.props.reimbursementAccount, 'achData.bankAccountID')); | ||
| const shouldDisableInputs = Boolean(lodashGet(reimbursementAccount, ['achData.bankAccountID'])); | ||
|
|
||
| return ( | ||
| <ScreenWrapper includeSafeAreaPaddingBottom={false}> | ||
| <HeaderWithBackButton | ||
| title={this.props.translate('workspace.common.connectBankAccount')} | ||
| stepCounter={{step: 1, total: 5}} | ||
| shouldShowGetAssistanceButton | ||
| guidesCallTaskID={CONST.GUIDES_CALL_TASK_IDS.WORKSPACE_BANK_ACCOUNT} | ||
| onBackButtonPress={this.props.onBackButtonPress} | ||
| return ( | ||
| <ScreenWrapper includeSafeAreaPaddingBottom={false}> | ||
| <HeaderWithBackButton | ||
| title={translate('workspace.common.connectBankAccount')} | ||
| stepCounter={{step: 1, total: 5}} | ||
| shouldShowGetAssistanceButton | ||
| guidesCallTaskID={CONST.GUIDES_CALL_TASK_IDS.WORKSPACE_BANK_ACCOUNT} | ||
| onBackButtonPress={props.onBackButtonPress} | ||
| /> | ||
| <Form | ||
| formID={ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM} | ||
| onSubmit={submit} | ||
| validate={validate} | ||
| submitButtonText={translate('common.continue')} | ||
| style={[styles.mh5, styles.flexGrow1]} | ||
| > | ||
| <Text style={[styles.mb5]}>{translate('bankAccount.checkHelpLine')}</Text> | ||
| <Image | ||
| resizeMode="contain" | ||
| style={[styles.exampleCheckImage, styles.mb5]} | ||
| source={exampleCheckImage(preferredLocale)} | ||
| /> | ||
| <TextInput | ||
| autoFocus | ||
| shouldDelayFocus={shouldDelayFocus} | ||
| inputID="routingNumber" | ||
| label={translate('bankAccount.routingNumber')} | ||
| defaultValue={props.getDefaultStateForField('routingNumber', '')} | ||
| keyboardType={CONST.KEYBOARD_TYPE.NUMBER_PAD} | ||
| disabled={shouldDisableInputs} | ||
| shouldSaveDraft | ||
| shouldUseDefaultValue={shouldDisableInputs} | ||
| /> | ||
| <TextInput | ||
| inputID="accountNumber" | ||
| containerStyles={[styles.mt4]} | ||
| label={translate('bankAccount.accountNumber')} | ||
| defaultValue={props.getDefaultStateForField('accountNumber', '')} | ||
| keyboardType={CONST.KEYBOARD_TYPE.NUMBER_PAD} | ||
| disabled={shouldDisableInputs} | ||
| shouldSaveDraft | ||
| shouldUseDefaultValue={shouldDisableInputs} | ||
| /> | ||
| <CheckboxWithLabel | ||
| accessibilityLabel={`${translate('common.iAcceptThe')} ${translate('common.expensifyTermsOfService')}`} | ||
| style={styles.mt4} | ||
| inputID="acceptTerms" | ||
| LabelComponent={() => ( | ||
| <Text> | ||
| {translate('common.iAcceptThe')} | ||
| <TextLink href={CONST.TERMS_URL}>{translate('common.expensifyTermsOfService')}</TextLink> | ||
| </Text> | ||
| )} | ||
| defaultValue={props.getDefaultStateForField('acceptTerms', false)} | ||
| shouldSaveDraft | ||
| /> | ||
| <Form | ||
| formID={ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM} | ||
| onSubmit={this.submit} | ||
| validate={this.validate} | ||
| submitButtonText={this.props.translate('common.continue')} | ||
| style={[styles.mh5, styles.flexGrow1]} | ||
| > | ||
| <Text style={[styles.mb5]}>{this.props.translate('bankAccount.checkHelpLine')}</Text> | ||
| <Image | ||
| resizeMode="contain" | ||
| style={[styles.exampleCheckImage, styles.mb5]} | ||
| source={exampleCheckImage(this.props.preferredLocale)} | ||
| /> | ||
| <TextInput | ||
| autoFocus | ||
| shouldDelayFocus={shouldDelayFocus} | ||
| inputID="routingNumber" | ||
| label={this.props.translate('bankAccount.routingNumber')} | ||
| defaultValue={this.props.getDefaultStateForField('routingNumber', '')} | ||
| keyboardType={CONST.KEYBOARD_TYPE.NUMBER_PAD} | ||
| disabled={shouldDisableInputs} | ||
| shouldSaveDraft | ||
| shouldUseDefaultValue={shouldDisableInputs} | ||
| /> | ||
| <TextInput | ||
| inputID="accountNumber" | ||
| containerStyles={[styles.mt4]} | ||
| label={this.props.translate('bankAccount.accountNumber')} | ||
| defaultValue={this.props.getDefaultStateForField('accountNumber', '')} | ||
| keyboardType={CONST.KEYBOARD_TYPE.NUMBER_PAD} | ||
| disabled={shouldDisableInputs} | ||
| shouldSaveDraft | ||
| shouldUseDefaultValue={shouldDisableInputs} | ||
| /> | ||
| <CheckboxWithLabel | ||
| accessibilityLabel={`${this.props.translate('common.iAcceptThe')} ${this.props.translate('common.expensifyTermsOfService')}`} | ||
| style={styles.mt4} | ||
| inputID="acceptTerms" | ||
| LabelComponent={() => ( | ||
| <Text> | ||
| {this.props.translate('common.iAcceptThe')} | ||
| <TextLink href={CONST.TERMS_URL}>{this.props.translate('common.expensifyTermsOfService')}</TextLink> | ||
| </Text> | ||
| )} | ||
| defaultValue={this.props.getDefaultStateForField('acceptTerms', false)} | ||
| shouldSaveDraft | ||
| /> | ||
| </Form> | ||
| </ScreenWrapper> | ||
| ); | ||
| } | ||
| </Form> | ||
| </ScreenWrapper> | ||
| ); | ||
| } | ||
|
|
||
| BankAccountManualStep.propTypes = propTypes; | ||
| export default withLocalize(BankAccountManualStep); | ||
| BankAccountManualStep.displayName = 'BankAccountManualStep'; | ||
| export default BankAccountManualStep; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we removing the withLocalizePropTypes in prop types?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We moved to useLocalize from HOC so no such props will be passed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then could we not include it in StepPropTypes? Or is that too big of a refactor
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't remove it yet from StepPropTyped as that is still used in many other components so when last of that component is refactored to function, we can safely refactor all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool cool, thanks for the context