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

Allow users to enter addresses manually when needed #6210

Merged
merged 1 commit into from
Nov 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 67 additions & 8 deletions src/pages/ReimbursementAccount/CompanyStep.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import TextLink from '../../components/TextLink';
import StatePicker from '../../components/StatePicker';
import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize';
import {
isValidDate, isRequiredFulfilled, isValidURL, isValidPhoneWithSpecialChars,
isValidDate, isRequiredFulfilled, isValidURL, isValidPhoneWithSpecialChars, isValidAddress, isValidZipCode,
} from '../../libs/ValidationUtils';
import compose from '../../libs/compose';
import ONYXKEYS from '../../ONYXKEYS';
Expand Down Expand Up @@ -145,6 +145,16 @@ class CompanyStep extends React.Component {
validate() {
const errors = {};

if (this.state.manualAddress) {
Gonals marked this conversation as resolved.
Show resolved Hide resolved
if (!isValidAddress(this.state.addressStreet)) {
errors.addressStreet = true;
}

if (!isValidZipCode(this.state.addressZipCode)) {
errors.addressZipCode = true;
}
Comment on lines +149 to +155
Copy link
Contributor

@jasperhuangg jasperhuangg Nov 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can probably condense this to the following, unless you specifically want errors.addressStreet to be undefined instead of false after this runs.

Suggested change
if (!isValidAddress(this.state.addressStreet)) {
errors.addressStreet = true;
}
if (!isValidZipCode(this.state.addressZipCode)) {
errors.addressZipCode = true;
}
errors.addressStreet = !isValidAddress(this.state.addressStreet) || !isValidZipCode(this.state.addressZipCode);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

? I'm a bit confused. Why do you want to get rid of errors.addressZipCode?

}

if (!isValidURL(this.state.website)) {
errors.website = true;
}
Expand Down Expand Up @@ -205,13 +215,62 @@ class CompanyStep extends React.Component {
disabled={shouldDisableCompanyName}
errorText={this.getErrorText('companyName')}
/>
<AddressSearch
label={this.props.translate('common.companyAddress')}
containerStyles={[styles.mt4]}
value={this.getFormattedAddressValue()}
onChangeText={(fieldName, value) => this.clearErrorAndSetValue(fieldName, value)}
errorText={this.getErrorText('addressStreet')}
/>
{!this.state.manualAddress && (
<div>
<AddressSearch
label={this.props.translate('common.companyAddress')}
containerStyles={[styles.mt4]}
value={this.getFormattedAddressValue()}
onChangeText={(fieldName, value) => this.clearErrorAndSetValue(fieldName, value)}
errorText={this.getErrorText('addressStreet')}
/>
<TextLink
style={[styles.textMicro]}
onPress={() => this.setState({manualAddress: true})}
>
Can&apos;t find your address? Enter it manually
</TextLink>
</div>
)}
{this.state.manualAddress && (
<div>
<ExpensiTextInput
label={this.props.translate('common.companyAddress')}
containerStyles={[styles.mt4]}
onChangeText={value => this.clearErrorAndSetValue('addressStreet', value)}
value={this.state.addressStreet}
errorText={this.getErrorText('addressStreet')}
/>
<Text style={[styles.mutedTextLabel, styles.mt1]}>{this.props.translate('common.noPO')}</Text>
<View style={[styles.flexRow, styles.mt4]}>
<View style={[styles.flex2, styles.mr2]}>
<ExpensiTextInput
label={this.props.translate('common.city')}
onChangeText={value => this.clearErrorAndSetValue('addressCity', value)}
value={this.state.addressCity}
errorText={this.getErrorText('addressCity')}
translateX={-14}
/>
</View>
<View style={[styles.flex1]}>
<StatePicker
onChange={value => this.clearErrorAndSetValue('addressState', value)}
value={this.state.addressState}
hasError={this.getErrors().addressState}
/>
</View>
</View>
<ExpensiTextInput
label={this.props.translate('common.zip')}
containerStyles={[styles.mt4]}
keyboardType={CONST.KEYBOARD_TYPE.PHONE_PAD}
onChangeText={value => this.clearErrorAndSetValue('addressZipCode', value)}
value={this.state.addressZipCode}
errorText={this.getErrorText('addressZipCode')}
/>
</div>
)}
jasperhuangg marked this conversation as resolved.
Show resolved Hide resolved

Gonals marked this conversation as resolved.
Show resolved Hide resolved
<ExpensiTextInput
label={this.props.translate('common.phoneNumber')}
containerStyles={[styles.mt4]}
Expand Down
73 changes: 65 additions & 8 deletions src/pages/ReimbursementAccount/IdentityForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import styles from '../../styles/styles';
import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize';
import CONST from '../../CONST';
import DatePicker from '../../components/DatePicker';
import TextLink from '../../components/TextLink';
import StatePicker from '../../components/StatePicker';
import Text from '../../components/Text';


const propTypes = {
Expand Down Expand Up @@ -41,6 +44,9 @@ const propTypes = {

/** Last 4 digits of SSN */
ssnLast4: PropTypes.string,

/** Whether the address pieces should be entered manually */
manualAddress: PropTypes.bool,
Gonals marked this conversation as resolved.
Show resolved Hide resolved
}),

/** Any errors that can arise from form validation */
Expand All @@ -60,6 +66,7 @@ const defaultProps = {
zipCode: '',
dob: '',
ssnLast4: '',
manualAddress: false,
},
errors: {},
};
Expand All @@ -69,7 +76,7 @@ const IdentityForm = ({
translate, values, onFieldChange, style, errors,
}) => {
const {
firstName, lastName, street, city, state, zipCode, dob, ssnLast4,
firstName, lastName, street, city, state, zipCode, dob, ssnLast4, manualAddress,
} = values;

// dob field has multiple validations/errors, we are handling it temporarily like this.
Expand Down Expand Up @@ -132,13 +139,63 @@ const IdentityForm = ({
errorText={errors.ssnLast4 ? translate('bankAccount.error.ssnLast4') : ''}
maxLength={CONST.BANK_ACCOUNT.MAX_LENGTH.SSN}
/>
<AddressSearch
label={translate('common.personalAddress')}
containerStyles={[styles.mt4]}
value={getFormattedAddressValue()}
onChangeText={(fieldName, value) => onFieldChange(fieldName, value)}
errorText={errors.street ? translate('bankAccount.error.addressStreet') : ''}
/>
{!manualAddress && (
<div>
<AddressSearch
label={translate('common.personalAddress')}
containerStyles={[styles.mt4]}
value={getFormattedAddressValue()}
onChangeText={(fieldName, value) => onFieldChange(fieldName, value)}
errorText={errors.street ? translate('bankAccount.error.addressStreet') : ''}
/>
<TextLink
style={[styles.textMicro]}
onPress={() => onFieldChange('manualAddress', true)}
>
Can&apos;t find your address? Enter it manually
</TextLink>
</div>
)}
{manualAddress && (
<div>
<ExpensiTextInput
label={translate('common.personalAddress')}
containerStyles={[styles.mt4]}
value={street}
onChangeText={value => onFieldChange('addressStreet', value)}
errorText={errors.street ? translate('bankAccount.error.address') : ''}
/>
<Text style={[styles.mutedTextLabel, styles.mt1]}>{translate('common.noPO')}</Text>
<View style={[styles.flexRow, styles.mt4]}>
<View style={[styles.flex2, styles.mr2]}>
<ExpensiTextInput
label={translate('common.city')}
value={city}
onChangeText={value => onFieldChange('addressCity', value)}
errorText={errors.city ? translate('bankAccount.error.addressCity') : ''}
translateX={-14}
/>
</View>
<View style={[styles.flex1]}>
<StatePicker
value={state}
onChange={value => onFieldChange('addressState', value)}
errorText={errors.state ? translate('bankAccount.error.addressState') : ''}
hasError={Boolean(errors.state)}
/>
</View>
</View>
<ExpensiTextInput
label={translate('common.zip')}
containerStyles={[styles.mt4]}
keyboardType={CONST.KEYBOARD_TYPE.NUMERIC}
value={zipCode}
onChangeText={value => onFieldChange('addressZipCode', value)}
errorText={errors.zipCode ? translate('bankAccount.error.zipCode') : ''}
maxLength={CONST.BANK_ACCOUNT.MAX_LENGTH.ZIP_CODE}
/>
</div>
)}
jasperhuangg marked this conversation as resolved.
Show resolved Hide resolved
</View>
);
};
Expand Down
37 changes: 22 additions & 15 deletions src/pages/ReimbursementAccount/RequestorStep.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,25 +85,31 @@ class RequestorStep extends React.Component {
* Clear the error associated to inputKey if found and store the inputKey new value in the state.
*
* @param {String} inputKey
* @param {String} value
* @param {String|Boolean} value
*/
clearErrorAndSetValue(inputKey, value) {
const renamedFields = {
addressStreet: 'requestorAddressStreet',
addressCity: 'requestorAddressCity',
addressState: 'requestorAddressState',
addressZipCode: 'requestorAddressZipCode',
};
const renamedInputKey = lodashGet(renamedFields, inputKey, inputKey);
const newState = {[renamedInputKey]: value};
this.setState(newState);
updateReimbursementAccountDraft(newState);
if (inputKey === 'manualAddress') {
this.setState({
manualAddress: value,
});
} else {
const renamedFields = {
addressStreet: 'requestorAddressStreet',
addressCity: 'requestorAddressCity',
addressState: 'requestorAddressState',
addressZipCode: 'requestorAddressZipCode',
};
const renamedInputKey = lodashGet(renamedFields, inputKey, inputKey);
const newState = {[renamedInputKey]: value};
this.setState(newState);
updateReimbursementAccountDraft(newState);
Gonals marked this conversation as resolved.
Show resolved Hide resolved

// dob field has multiple validations/errors, we are handling it temporarily like this.
if (inputKey === 'dob') {
this.clearError('dobAge');
// dob field has multiple validations/errors, we are handling it temporarily like this.
if (inputKey === 'dob') {
this.clearError('dobAge');
}
this.clearError(inputKey);
}
this.clearError(inputKey);
}

/**
Expand Down Expand Up @@ -210,6 +216,7 @@ class RequestorStep extends React.Component {
zipCode: this.state.requestorAddressZipCode,
dob: this.state.dob,
ssnLast4: this.state.ssnLast4,
manualAddress: this.state.manualAddress,
Gonals marked this conversation as resolved.
Show resolved Hide resolved
}}
errors={this.props.reimbursementAccount.errors}
/>
Expand Down