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

Replace AddressInput Selects #321

Merged
merged 11 commits into from
Oct 28, 2017
31 changes: 12 additions & 19 deletions src/components/AddressInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,13 @@ import PropTypes from 'prop-types';
import React from 'react';
import flow from 'lodash.flow';

import Select from './Select';
import CountryInput from './CountryInput';
Copy link

Choose a reason for hiding this comment

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

I like this a lot as it allows us to even improve the looks over time.

import StateInput from './StateInput';
Copy link

Choose a reason for hiding this comment

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

The name is slightly ambiguous. Should we call it USAStateInput ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True, idea was it might handle determining provinces for various countries, but agreed "State" is vague

import ValidatedFormGroup from './ValidatedFormGroup';
import Col from './Col';
import Input from './Input';
import Row from './Row';

// TODO Dynamic states based on country:
import states from './address/USStates.js';
import COUNTRIES from './address/Countries.js';

const US_STATES = states.map(state => ({
label: state.value,
value: state.value
}));

const readEvent = e => ({ [e.target.name]: e.target.value });

class AddressInput extends React.Component {
Expand Down Expand Up @@ -48,11 +40,11 @@ class AddressInput extends React.Component {
value: {},
};

onChange = update => {
onChange = (update) => {
this.props.onChange({ ...this.props.value, ...update });
}

propsFor = field => {
propsFor = (field) => {
if (this.props.value[field]) {
return { value: this.props.value[field] };
}
Expand All @@ -66,13 +58,14 @@ class AddressInput extends React.Component {
}

render() {
const { disabled, error, id, labels, showLabels } = this.props;
const { disabled, error, id, labels, showLabels, stacked } = this.props;

return (
<div id={id}>
<ValidatedFormGroup
label={showLabels ? labels.address1 : null}
error={error.address1}
stacked={stacked}
>
<Input
id={id ? `${id}_address1` : null}
Expand All @@ -89,6 +82,7 @@ class AddressInput extends React.Component {
<ValidatedFormGroup
label={showLabels ? labels.address2 : null}
error={error.address2}
stacked={stacked}
>
<Input
id={id ? `${id}_address2` : null}
Expand Down Expand Up @@ -126,12 +120,11 @@ class AddressInput extends React.Component {
error={error.state}
label={showLabels ? labels.state : null}
>
<Select
<StateInput
id={id ? `${id}_state` : null}
className="w-100"
inputProps={{ id: id ? `${id}_state` : null }}
name="state"
placeholder={labels.state}
options={US_STATES}
{...this.propsFor('state')}
onChange={selection => this.onChange({ state: selection && selection.value })}
disabled={disabled}
Expand Down Expand Up @@ -160,12 +153,12 @@ class AddressInput extends React.Component {
error={error.countryCode}
className="mb-0"
label={showLabels ? labels.countryCode : null}
stacked={stacked}
>
<Select
<CountryInput
className="w-100"
inputProps={{ id: id ? `${id}_countryCode` : null }}
id={id ? `${id}_countryCode` : null}
name="countryCode"
options={COUNTRIES}
placeholder={labels.countryCode}
{...this.propsFor('countryCode')}
onChange={selection => this.onChange({ countryCode: selection && selection.value })}
Expand Down
48 changes: 48 additions & 0 deletions src/components/CountryInput.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from 'react';
import PropTypes from 'prop-types';
import Input from './Input';
import COUNTRIES from './address/Countries.js';

export default class CountryInput extends React.Component {
static propTypes = {
className: PropTypes.string,
id: PropTypes.string,
locale: PropTypes.string,
name: PropTypes.string,
placeholder: PropTypes.string,
onChange: PropTypes.func,
disabled: PropTypes.bool
}

static defaultProps = {
onChange: () => {}
}

render() {
const {
className,
disabled,
id,
name,
onChange,
placeholder,
...props
} = this.props;

return (
<Input
type="select"
{...props}
className={className}
disabled={disabled}
id={id}
name={name}
onChange={e => onChange(e.target.value)}
placeholder={placeholder}
>
{COUNTRIES.map(country =>
<option value={country.value} key={country.value}>{country.label}</option>)}
</Input>
);
}
}
57 changes: 57 additions & 0 deletions src/components/StateInput.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from 'react';
import PropTypes from 'prop-types';
import Input from './Input';

// TODO Dynamic states based on country:
import states from './address/USStates.js';

const US_STATES = states.map(state => ({
label: state.value,
value: state.value
}));

export default class StateInput extends React.Component {
static propTypes = {
className: PropTypes.string,
country: PropTypes.string,
id: PropTypes.string,
name: PropTypes.string,
placeholder: PropTypes.string,
onChange: PropTypes.func,
disabled: PropTypes.bool
}

static defaultProps = {
country: 'US',
onChange: () => {}
}

render() {
const {
className,
country,
disabled,
id,
name,
onChange,
placeholder,
...props
} = this.props;

return (
<Input
type="select"
{...props}
className={className}
disabled={disabled}
id={id}
name={name}
onChange={e => onChange(e.target.value)}
placeholder={placeholder}
>
{US_STATES.map(state =>
<option value={state.value} key={state.value}>{state.label}</option>)}
</Input>
);
}
}
2 changes: 1 addition & 1 deletion src/components/address/USStates.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default [
{ label: 'California', value: 'CA' },
{ label: 'Colorado', value: 'CO' },
{ label: 'Connecticut', value: 'CT' },
{ label: 'Deleware', value: 'DE' },
{ label: 'Delaware', value: 'DE' },

Choose a reason for hiding this comment

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

👍

{ label: 'Washington, D.C.', value: 'DC' },
{ label: 'Florida', value: 'FL' },
{ label: 'Georgia', value: 'GA' },
Expand Down
4 changes: 0 additions & 4 deletions test/components/AddressInput.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,9 @@ describe('<AddressInput />', () => {

it('should have state', () => {
const input = component.find('[name="state"]');
assert.equal(input.type(), Select);
assert.equal(input.prop('placeholder'), 'State');
assert.equal(input.prop('defaultValue'), 'NJ');
assert.equal(input.prop('value'), undefined);
assert.deepEqual(input.prop('options').map(s => s.value), states.map(s => s.value));

input.simulate('change', { label: 'New York', value: 'NY' });
assert(callback.calledWith({ state: 'NY' }));

Expand All @@ -80,7 +77,6 @@ describe('<AddressInput />', () => {

it('should have country', () => {
const input = component.find('[name="countryCode"]');
assert.equal(input.type(), Select);
assert.equal(input.prop('placeholder'), 'Country');
assert.equal(input.prop('defaultValue'), 'US');
assert.equal(input.prop('value'), undefined);
Expand Down