mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-27 09:13:14 +10:00
Implement PayoutDetailsForm
This commit is contained in:
parent
ee1cdd859c
commit
0fdce2b0fd
5 changed files with 310 additions and 0 deletions
23
src/containers/PayoutDetailsForm/PayoutDetailsForm.css
Normal file
23
src/containers/PayoutDetailsForm/PayoutDetailsForm.css
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
.root {
|
||||
|
||||
}
|
||||
|
||||
.countries {
|
||||
border: 1px solid #979797;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.formTitle {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.subTitle {
|
||||
margin-top: 60px;
|
||||
}
|
||||
|
||||
.submitButton {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import PayoutDetailsForm from './PayoutDetailsForm';
|
||||
|
||||
export const USD = {
|
||||
component: PayoutDetailsForm,
|
||||
props: {
|
||||
currency: 'USD',
|
||||
onSubmit: values => {
|
||||
console.log('submit payout details:', values); // eslint-disable-line
|
||||
},
|
||||
},
|
||||
};
|
||||
251
src/containers/PayoutDetailsForm/PayoutDetailsForm.js
Normal file
251
src/containers/PayoutDetailsForm/PayoutDetailsForm.js
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
import React, { Component, PropTypes } from 'react';
|
||||
import { compose } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
|
||||
import { Field, reduxForm, formValueSelector, propTypes as formPropTypes } from 'redux-form';
|
||||
import config from '../../config';
|
||||
import {
|
||||
Button,
|
||||
StripeBankAccountToken,
|
||||
Select,
|
||||
BirthdayInput,
|
||||
LocationAutocompleteInput,
|
||||
} from '../../components';
|
||||
import * as validators from '../../util/validators';
|
||||
import { enhancedField } from '../../util/forms';
|
||||
|
||||
import css from './PayoutDetailsForm.css';
|
||||
|
||||
const supportedCountries = config.stripe.supportedCountries.map(c => c.code);
|
||||
|
||||
const requiresAddress = countryCode => {
|
||||
const country = config.stripe.supportedCountries.find(c => c.code === countryCode);
|
||||
if (!country) {
|
||||
throw new Error(`Country code not found in Stripe config ${countryCode}`);
|
||||
}
|
||||
return country.payoutAddressRequired;
|
||||
};
|
||||
|
||||
const CountriesSelect = props => {
|
||||
const { input } = props;
|
||||
return (
|
||||
<Select className={css.countries} {...input}>
|
||||
<option />
|
||||
{supportedCountries.map(c => <option key={c} value={c}>{c}</option>)}
|
||||
</Select>
|
||||
);
|
||||
};
|
||||
|
||||
const { string, bool, object } = PropTypes;
|
||||
|
||||
CountriesSelect.propTypes = {
|
||||
input: object.isRequired,
|
||||
};
|
||||
|
||||
class PayoutDetailsFormComponent extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.EnhancedInput = enhancedField('input', {
|
||||
errorClassName: css.error,
|
||||
});
|
||||
this.EnhancedCountriesDropdown = enhancedField(CountriesSelect, {
|
||||
errorClassName: css.error,
|
||||
});
|
||||
this.EnhancedBirthdayInput = enhancedField(BirthdayInput, {
|
||||
errorClassName: css.error,
|
||||
});
|
||||
this.EnhancedLocationAutocompleteInput = enhancedField(LocationAutocompleteInput, {
|
||||
errorClassName: css.error,
|
||||
});
|
||||
}
|
||||
render() {
|
||||
const { country, currency, handleSubmit, pristine, submitting, inProgress, intl } = this.props;
|
||||
|
||||
const nameLabel = intl.formatMessage({ id: 'PayoutDetailsForm.nameLabel' });
|
||||
const nameRequired = validators.required(
|
||||
intl.formatMessage({
|
||||
id: 'PayoutDetailsForm.nameRequired',
|
||||
})
|
||||
);
|
||||
|
||||
const birthdayLabel = intl.formatMessage({ id: 'PayoutDetailsForm.birthdayLabel' });
|
||||
const birthdayRequired = validators.required(
|
||||
intl.formatMessage({
|
||||
id: 'PayoutDetailsForm.birthdayRequired',
|
||||
})
|
||||
);
|
||||
|
||||
const countryLabel = intl.formatMessage({ id: 'PayoutDetailsForm.countryLabel' });
|
||||
const countryRequired = validators.required(
|
||||
intl.formatMessage({
|
||||
id: 'PayoutDetailsForm.countryRequired',
|
||||
})
|
||||
);
|
||||
|
||||
const streetAddressLabel = intl.formatMessage({ id: 'PayoutDetailsForm.streetAddressLabel' });
|
||||
const streetAddressPlaceholder = intl.formatMessage({
|
||||
id: 'PayoutDetailsForm.streetAddressPlaceholder',
|
||||
});
|
||||
const streetAddressRequiredMessage = intl.formatMessage({
|
||||
id: 'PayoutDetailsForm.streetAddressRequired',
|
||||
});
|
||||
const streetAddressNotRecognizedMessage = intl.formatMessage({
|
||||
id: 'PayoutDetailsForm.streetAddressNotRecognized',
|
||||
});
|
||||
const validateStreetAddress = [
|
||||
validators.autocompleteSearchRequired(streetAddressRequiredMessage),
|
||||
validators.autocompletePlaceSelected(streetAddressNotRecognizedMessage),
|
||||
];
|
||||
|
||||
const postalCodeLabel = intl.formatMessage({ id: 'PayoutDetailsForm.postalCodeLabel' });
|
||||
const postalCodePlaceholder = intl.formatMessage({
|
||||
id: 'PayoutDetailsForm.postalCodePlaceholder',
|
||||
});
|
||||
const postalCodeRequired = validators.required(
|
||||
intl.formatMessage({
|
||||
id: 'PayoutDetailsForm.postalCodeRequired',
|
||||
})
|
||||
);
|
||||
|
||||
const cityLabel = intl.formatMessage({ id: 'PayoutDetailsForm.cityLabel' });
|
||||
const cityPlaceholder = intl.formatMessage({ id: 'PayoutDetailsForm.cityPlaceholder' });
|
||||
const cityRequired = validators.required(
|
||||
intl.formatMessage({
|
||||
id: 'PayoutDetailsForm.cityRequired',
|
||||
})
|
||||
);
|
||||
|
||||
const showAddressFields = country && requiresAddress(country);
|
||||
const addressSection = showAddressFields
|
||||
? <div>
|
||||
<Field
|
||||
name="streetAddress"
|
||||
type="text"
|
||||
label={streetAddressLabel}
|
||||
placeholder={streetAddressPlaceholder}
|
||||
format={null}
|
||||
component={this.EnhancedLocationAutocompleteInput}
|
||||
validate={validateStreetAddress}
|
||||
clearOnUnmount
|
||||
/>
|
||||
<Field
|
||||
name="postalCode"
|
||||
type="text"
|
||||
label={postalCodeLabel}
|
||||
placeholder={postalCodePlaceholder}
|
||||
component={this.EnhancedInput}
|
||||
validate={postalCodeRequired}
|
||||
clearOnUnmount
|
||||
/>
|
||||
<Field
|
||||
name="city"
|
||||
type="text"
|
||||
label={cityLabel}
|
||||
placeholder={cityPlaceholder}
|
||||
component={this.EnhancedInput}
|
||||
validate={cityRequired}
|
||||
clearOnUnmount
|
||||
/>
|
||||
</div>
|
||||
: null;
|
||||
|
||||
const bankAccountRequired = validators.required(
|
||||
intl.formatMessage({
|
||||
id: 'PayoutDetailsForm.bankAccountRequired',
|
||||
})
|
||||
);
|
||||
|
||||
const bankAccountSection = country
|
||||
? <div>
|
||||
<h2 className={css.subTitle}>
|
||||
<FormattedMessage id="PayoutDetailsForm.bankDetails" />
|
||||
</h2>
|
||||
<Field
|
||||
name="bankAccountToken"
|
||||
component={StripeBankAccountToken}
|
||||
props={{ country, currency }}
|
||||
validate={bankAccountRequired}
|
||||
clearOnUnmount
|
||||
/>
|
||||
</div>
|
||||
: null;
|
||||
|
||||
const submitDisabled = pristine || submitting || inProgress;
|
||||
|
||||
return (
|
||||
<form className={css.root} onSubmit={handleSubmit}>
|
||||
<h2 className={css.formTitle}>
|
||||
<FormattedMessage id="PayoutDetailsForm.title" />
|
||||
</h2>
|
||||
<p>
|
||||
<FormattedMessage id="PayoutDetailsForm.information" />
|
||||
</p>
|
||||
<h2 className={css.subTitle}>
|
||||
<FormattedMessage id="PayoutDetailsForm.personalDetailsTitle" />
|
||||
</h2>
|
||||
<Field
|
||||
name="name"
|
||||
type="text"
|
||||
label={nameLabel}
|
||||
component={this.EnhancedInput}
|
||||
validate={nameRequired}
|
||||
/>
|
||||
<Field
|
||||
name="birthday"
|
||||
type="text"
|
||||
label={birthdayLabel}
|
||||
format={null}
|
||||
component={this.EnhancedBirthdayInput}
|
||||
validate={birthdayRequired}
|
||||
/>
|
||||
<h2 className={css.subTitle}>
|
||||
<FormattedMessage id="PayoutDetailsForm.addressTitle" />
|
||||
</h2>
|
||||
<Field
|
||||
name="country"
|
||||
type="text"
|
||||
label={countryLabel}
|
||||
component={this.EnhancedCountriesDropdown}
|
||||
validate={countryRequired}
|
||||
/>
|
||||
{addressSection}
|
||||
{bankAccountSection}
|
||||
<Button className={css.submitButton} type="submit" disabled={submitDisabled}>
|
||||
<FormattedMessage id="PayoutDetailsForm.submitButtonText" />
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
PayoutDetailsFormComponent.defaultProps = { country: null, inProgress: false };
|
||||
|
||||
PayoutDetailsFormComponent.propTypes = {
|
||||
...formPropTypes,
|
||||
inProgress: bool,
|
||||
currency: string.isRequired,
|
||||
|
||||
// from mapStateToProps
|
||||
country: string,
|
||||
|
||||
// from injectIntl
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
const formName = 'PayoutDetailsForm';
|
||||
|
||||
const selector = formValueSelector(formName);
|
||||
const mapStateToProps = state => {
|
||||
const country = selector(state, 'country');
|
||||
return { country };
|
||||
};
|
||||
|
||||
const formOptions = {
|
||||
form: formName,
|
||||
};
|
||||
|
||||
const PayoutDetailsForm = compose(connect(mapStateToProps), reduxForm(formOptions), injectIntl)(
|
||||
PayoutDetailsFormComponent
|
||||
);
|
||||
|
||||
export default PayoutDetailsForm;
|
||||
|
|
@ -35,6 +35,7 @@ import * as SearchForm from './containers/SearchForm/SearchForm.example';
|
|||
import * as LoginForm from './containers/LoginForm/LoginForm.example';
|
||||
import * as PasswordForgottenForm
|
||||
from './containers/PasswordForgottenForm/PasswordForgottenForm.example';
|
||||
import * as PayoutDetailsForm from './containers/PayoutDetailsForm/PayoutDetailsForm.example';
|
||||
import * as SignupForm from './containers/SignupForm/SignupForm.example';
|
||||
import * as StripePaymentForm from './containers/StripePaymentForm/StripePaymentForm.example';
|
||||
|
||||
|
|
@ -61,6 +62,7 @@ export {
|
|||
NamedLink,
|
||||
PaginationLinks,
|
||||
PasswordForgottenForm,
|
||||
PayoutDetailsForm,
|
||||
SearchForm,
|
||||
SignupForm,
|
||||
StripeBankAccountToken,
|
||||
|
|
|
|||
|
|
@ -94,6 +94,29 @@
|
|||
"PageLayout.logoutFailed": "Logout failed. Please try again.",
|
||||
"PaginationLinks.next": "Next page",
|
||||
"PaginationLinks.previous": "Previous page",
|
||||
"PayoutDetailsForm.addressTitle": "Address",
|
||||
"PayoutDetailsForm.bankAccountRequired": "Bank account information is required",
|
||||
"PayoutDetailsForm.bankDetails": "Bank details",
|
||||
"PayoutDetailsForm.birthdayLabel": "Date of birth",
|
||||
"PayoutDetailsForm.birthdayRequired": "This field is required",
|
||||
"PayoutDetailsForm.cityLabel": "City",
|
||||
"PayoutDetailsForm.cityPlaceholder": "Enter your city...",
|
||||
"PayoutDetailsForm.cityRequired": "This field is required",
|
||||
"PayoutDetailsForm.countryLabel": "Country",
|
||||
"PayoutDetailsForm.countryRequired": "This field is required",
|
||||
"PayoutDetailsForm.information": "Since this was the first listing you created, we need to know bit more information about you in order to send you money. We only ask these once.",
|
||||
"PayoutDetailsForm.nameLabel": "First and Last name",
|
||||
"PayoutDetailsForm.nameRequired": "This field is required",
|
||||
"PayoutDetailsForm.personalDetailsTitle": "Personal details",
|
||||
"PayoutDetailsForm.postalCodeLabel": "Postal code",
|
||||
"PayoutDetailsForm.postalCodePlaceholder": "Enter your postal code...",
|
||||
"PayoutDetailsForm.postalCodeRequired": "This field is required",
|
||||
"PayoutDetailsForm.streetAddressLabel": "Street address",
|
||||
"PayoutDetailsForm.streetAddressPlaceholder": "Start typing...",
|
||||
"PayoutDetailsForm.streetAddressNotRecognized": "We didn't recognize this address. Please try another address.",
|
||||
"PayoutDetailsForm.streetAddressRequired": "This field is required",
|
||||
"PayoutDetailsForm.submitButtonText": "Save details & publish listing",
|
||||
"PayoutDetailsForm.title": "One more thing: payout preferences",
|
||||
"SaleDetailsPanel.listingAcceptedTitle": "{customerName} has booked {title}.",
|
||||
"SaleDetailsPanel.listingRejectedTitle": "{customerName} requested to book {title}.",
|
||||
"SaleDetailsPanel.listingRequestedTitle": "{customerName} has requested to book {title}.",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue