Skip to content

Commit

Permalink
Merge pull request #5643 from Expensify/tgolen-google-address-lookup
Browse files Browse the repository at this point in the history
[N6.1] Use Google AddressSearch component in VBA Company Step
  • Loading branch information
Luke9389 authored Oct 7, 2021
2 parents 039216a + dd9f01f commit 8b81825
Show file tree
Hide file tree
Showing 6 changed files with 187 additions and 49 deletions.
1 change: 1 addition & 0 deletions config/webpack/webpack.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const includeModules = [
'react-native-onyx',
'react-native-gesture-handler',
'react-native-flipper',
'react-native-google-places-autocomplete',
].join('|');

const webpackConfig = {
Expand Down
20 changes: 18 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
"react-native-config": "^1.4.0",
"react-native-document-picker": "^5.1.0",
"react-native-gesture-handler": "1.9.0",
"react-native-google-places-autocomplete": "^2.4.1",
"react-native-image-pan-zoom": "^2.1.12",
"react-native-image-picker": "^4.0.3",
"react-native-keyboard-spacer": "^0.4.1",
Expand Down
121 changes: 121 additions & 0 deletions src/components/AddressSearch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import _ from 'underscore';
import React from 'react';
import PropTypes from 'prop-types';
import {LogBox} from 'react-native';
import {GooglePlacesAutocomplete} from 'react-native-google-places-autocomplete';
import CONFIG from '../CONFIG';
import withLocalize, {withLocalizePropTypes} from './withLocalize';
import styles from '../styles/styles';
import ExpensiTextInput from './ExpensiTextInput';

// The error that's being thrown below will be ignored until we fork the
// react-native-google-places-autocomplete repo and replace the
// VirtualizedList component with a VirtualizedList-backed instead
LogBox.ignoreLogs(['VirtualizedLists should never be nested']);

const propTypes = {
/** The label to display for the field */
label: PropTypes.string.isRequired,

/** The value to set the field to initially */
value: PropTypes.string,

/** A callback function when the value of this field has changed */
onChangeText: PropTypes.func.isRequired,

/** Customize the ExpensiTextInput container */
containerStyles: PropTypes.arrayOf(PropTypes.object),

...withLocalizePropTypes,
};
const defaultProps = {
value: '',
containerStyles: null,
};

class AddressSearch extends React.Component {
constructor(props) {
super(props);
this.googlePlacesRef = React.createRef();
}

componentDidMount() {
this.googlePlacesRef.current?.setAddressText(this.props.value);
}

getAddressComponent(object, field, nameType) {
return _.chain(object.address_components)
.find(component => _.contains(component.types, field))
.get(nameType)
.value();
}

/**
* @param {Object} details See https://developers.google.com/maps/documentation/places/web-service/details#PlaceDetailsResponses
*/
saveLocationDetails = (details) => {
if (details.address_components) {
// Gather the values from the Google details
const streetNumber = this.getAddressComponent(details, 'street_number', 'long_name');
const streetName = this.getAddressComponent(details, 'route', 'long_name');
const city = this.getAddressComponent(details, 'locality', 'long_name');
const state = this.getAddressComponent(details, 'administrative_area_level_1', 'short_name');
const zipCode = this.getAddressComponent(details, 'postal_code', 'long_name');

// Trigger text change events for each of the individual fields being saved on the server
this.props.onChangeText('addressStreet', `${streetNumber} ${streetName}`);
this.props.onChangeText('addressCity', city);
this.props.onChangeText('addressState', state);
this.props.onChangeText('addressZipCode', zipCode);
}
}

render() {
return (
<GooglePlacesAutocomplete
ref={this.googlePlacesRef}
fetchDetails
keepResultsAfterBlur
suppressDefaultStyles
enablePoweredByContainer={false}
onPress={(data, details) => this.saveLocationDetails(details)}
query={{
key: 'AIzaSyC4axhhXtpiS-WozJEsmlL3Kg3kXucbZus',
language: this.props.preferredLocale,
}}
requestUrl={{
useOnPlatform: 'web',
url: `${CONFIG.EXPENSIFY.URL_EXPENSIFY_COM}api?command=Proxy_GooglePlaces&proxyUrl=`,
}}
textInputProps={{
InputComp: ExpensiTextInput,
label: this.props.label,
containerStyles: this.props.containerStyles,
}}
styles={{
textInputContainer: [styles.flexColumn],
listView: [
styles.borderTopRounded,
styles.borderBottomRounded,
styles.mt1,
styles.overflowAuto,
styles.borderLeft,
styles.borderRight,
],
row: [
styles.pv4,
styles.ph3,
styles.overflowAuto,
],
description: [styles.googleSearchText],
separator: [styles.googleSearchSeperator],
}}
/>
);
}
}

AddressSearch.propTypes = propTypes;
AddressSearch.defaultProps = defaultProps;

export default withLocalize(AddressSearch);
52 changes: 5 additions & 47 deletions src/pages/ReimbursementAccount/CompanyStep.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ import TextLink from '../../components/TextLink';
import StatePicker from '../../components/StatePicker';
import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize';
import {
isValidAddress, isValidDate, isValidZipCode, isRequiredFulfilled, isValidPhoneWithSpecialChars, isValidURL,
isValidDate, isRequiredFulfilled, isValidURL, isValidPhoneWithSpecialChars,
} from '../../libs/ValidationUtils';
import compose from '../../libs/compose';
import ONYXKEYS from '../../ONYXKEYS';
import ExpensiPicker from '../../components/ExpensiPicker';
import * as ReimbursementAccountUtils from '../../libs/ReimbursementAccountUtils';
import reimbursementAccountPropTypes from './reimbursementAccountPropTypes';
import ReimbursementAccountForm from './ReimbursementAccountForm';
import AddressSearch from '../../components/AddressSearch';

const propTypes = {
/** Bank account currently in setup */
Expand Down Expand Up @@ -69,10 +70,6 @@ class CompanyStep extends React.Component {
// These fields need to be filled out in order to submit the form
this.requiredFields = [
'companyName',
'addressStreet',
'addressCity',
'addressState',
'addressZipCode',
'website',
'companyTaxID',
'incorporationDate',
Expand All @@ -84,9 +81,6 @@ class CompanyStep extends React.Component {

// Map a field to the key of the error's translation
this.errorTranslationKeys = {
addressStreet: 'bankAccount.error.addressStreet',
addressCity: 'bankAccount.error.addressCity',
addressZipCode: 'bankAccount.error.zipCode',
companyName: 'bankAccount.error.companyName',
companyPhone: 'bankAccount.error.phoneNumber',
website: 'bankAccount.error.website',
Expand Down Expand Up @@ -125,13 +119,6 @@ class CompanyStep extends React.Component {
*/
validate() {
const errors = {};
if (!isValidAddress(this.state.addressStreet)) {
errors.addressStreet = true;
}

if (!isValidZipCode(this.state.addressZipCode)) {
errors.addressZipCode = true;
}

if (!isValidURL(this.state.website)) {
errors.website = true;
Expand Down Expand Up @@ -193,40 +180,11 @@ class CompanyStep extends React.Component {
disabled={shouldDisableCompanyName}
errorText={this.getErrorText('companyName')}
/>
<ExpensiTextInput
<AddressSearch
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.NUMERIC}
onChangeText={value => this.clearErrorAndSetValue('addressZipCode', value)}
value={this.state.addressZipCode}
errorText={this.getErrorText('addressZipCode')}
maxLength={CONST.BANK_ACCOUNT.MAX_LENGTH.ZIP_CODE}
value={`${this.state.addressStreet} ${this.state.addressCity} ${this.state.addressState} ${this.state.addressZipCode}`}
onChangeText={(fieldName, value) => this.clearErrorAndSetValue(fieldName, value)}
/>
<ExpensiTextInput
label={this.props.translate('common.phoneNumber')}
Expand Down
41 changes: 41 additions & 0 deletions src/styles/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -1375,6 +1375,25 @@ const styles = {
flex: 1,
},

borderTop: {
borderTopWidth: 1,
borderColor: themeColors.border,
},

borderTopRounded: {
borderTopWidth: 1,
borderColor: themeColors.border,
borderTopLeftRadius: variables.componentBorderRadiusNormal,
borderTopRightRadius: variables.componentBorderRadiusNormal,
},

borderBottomRounded: {
borderBottomWidth: 1,
borderColor: themeColors.border,
borderBottomLeftRadius: variables.componentBorderRadiusNormal,
borderBottomRightRadius: variables.componentBorderRadiusNormal,
},

borderBottom: {
borderBottomWidth: 1,
borderColor: themeColors.border,
Expand All @@ -1385,6 +1404,11 @@ const styles = {
borderColor: themeColors.border,
},

borderLeft: {
borderLeftWidth: 1,
borderColor: themeColors.border,
},

headerBar: {
overflow: 'hidden',
justifyContent: 'center',
Expand Down Expand Up @@ -2025,6 +2049,23 @@ const styles = {
{translateY},
],
}),

googleSearchTextInputContainer: {
flexDirection: 'column',
},

googleSearchSeperator: {
height: 1,
backgroundColor: themeColors.border,
},

googleSearchText: {
color: themeColors.text,
fontSize: variables.fontSizeNormal,
lineHeight: variables.fontSizeNormalHeight,
fontFamily: fontFamily.GTA,
flex: 1,
},
};

const baseCodeTagStyles = {
Expand Down

0 comments on commit 8b81825

Please sign in to comment.