Add additional owners to company account if required

This commit is contained in:
Jenni Nurmi 2018-12-20 16:45:35 +02:00
parent 9d8d211677
commit 9c31f3e0ea
9 changed files with 199 additions and 36 deletions

View file

@ -408,6 +408,7 @@ export const createStripeAccount = payoutDetails => (dispatch, getState, sdk) =>
companyName,
companyTaxId,
personalAddress,
additionalOwners,
} = payoutDetailValues;
const hasProvince = address.province && !address.state;
@ -433,6 +434,22 @@ export const createStripeAccount = payoutDetails => (dispatch, getState, sdk) =>
};
}
const additionalOwnersValue = additionalOwners
? additionalOwners.map(owner => {
return {
first_name: owner.firstName,
last_name: owner.lastName,
dob: owner.birthDate,
address: {
city: owner.city,
line1: owner.streetAddress,
postal_code: owner.postalCode,
state: hasProvince ? owner.province : owner.state ? owner.state : '',
},
};
})
: [];
const idNumber =
country === 'US' ? { ssn_last_4: personalIdNumber } : { personal_id_number: personalIdNumber };
@ -447,13 +464,14 @@ export const createStripeAccount = payoutDetails => (dispatch, getState, sdk) =>
business_name: companyName,
business_tax_id: companyTaxId,
personal_address: personalAddressValue,
additional_owners: additionalOwnersValue,
...idNumber,
},
tos_shown_and_accepted: true,
};
let accountResponse;
return stripe
.createToken('account', params)
.then(response => {

View file

@ -24,16 +24,20 @@ const CANADIAN_PROVINCES = [
];
const PayoutDetailsAddress = props => {
const { country, intl, disabled, form, fieldId } = props;
const { className, country, intl, disabled, form, fieldId } = props;
const countryConfig = country ? stripeCountryConfigs(country).addressConfig : null;
const isRequired = (countryConfig, field) => {
return countryConfig[field];
};
const showTitle =
fieldId === 'company.address' ||
fieldId === 'individual' ||
fieldId === 'company.personalAddress';
const addressTitle = intl.formatMessage({
id:
fieldId === 'company'
fieldId === 'company.address'
? 'PayoutDetailsForm.companyAddressTitle'
: 'PayoutDetailsForm.streetAddressLabel',
});
@ -97,8 +101,8 @@ const PayoutDetailsAddress = props => {
);
return (
<div className={css.sectionContainer}>
<h3 className={css.subTitle}>{addressTitle}</h3>
<div className={className ? className : css.sectionContainer}>
{showTitle ? <h3 className={css.subTitle}>{addressTitle}</h3> : null}
{showAddressLine ? (
<FieldTextInput

View file

@ -109,3 +109,56 @@
.bankDetailsStripeField p {
@apply --marketplaceH4FontStyles;
}
.personalAddressContainer {
margin-bottom: 28px;
}
.fieldArrayAdd {
@apply --marketplaceLinkStyles;
@apply --marketplaceSearchFilterSublabelFontStyles;
font-weight: var(--fontWeightMedium);
margin-bottom: 2px;
}
.fieldArrayRemove {
@apply --marketplaceH5FontStyles;
color: var(--matterColorAnti);
float: right;
line-height: 20px;
&:hover {
color: var(--matterColor);
}
}
.closeIcon {
@apply --marketplaceModalCloseIcon;
}
.additionalOwnerWrapper {
margin-bottom: 35px;
@media (--viewportMedium) {
margin-bottom: 56px;
}
}
.additionalOwnerWrapper .sectionContainer {
margin-bottom: 24px;
}
.additionalOwnerLabel {
display: inline-block;
}
.closeIcon {
margin-right: 5px;
}
.addIcon {
margin-right: 7px;
display: inline-block;
height: 18px;
padding-top: 1px;
}

View file

@ -3,6 +3,7 @@ import { bool, object, string } from 'prop-types';
import { compose } from 'redux';
import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
import { Form as FinalForm } from 'react-final-form';
import arrayMutators from 'final-form-arrays';
import classNames from 'classnames';
import config from '../../config';
import { Button, ExternalLink, FieldRadioButton, FieldSelect, Form } from '../../components';
@ -27,6 +28,9 @@ export const stripeCountryConfigs = countryCode => {
const PayoutDetailsFormComponent = props => (
<FinalForm
{...props}
mutators={{
...arrayMutators,
}}
render={fieldRenderProps => {
const {
className,
@ -93,8 +97,6 @@ const PayoutDetailsFormComponent = props => (
</ExternalLink>
);
console.log('Values', JSON.stringify(values, null, ' '));
return (
<Form className={classes} onSubmit={handleSubmit}>
<div className={css.sectionContainer}>

View file

@ -1,8 +1,9 @@
import React from 'react';
import { bool, object, string } from 'prop-types';
import { bool, string } from 'prop-types';
import { compose } from 'redux';
import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
import { FieldTextInput } from '../../components';
import { FieldArray } from 'react-final-form-arrays';
import { FieldTextInput, IconAdd, IconClose, InlineTextButton } from '../../components';
import * as validators from '../../util/validators';
import PayoutDetailsAddress from './PayoutDetailsAddress';
@ -11,8 +12,21 @@ import PayoutDetailsPersonalDetails from './PayoutDetailsPersonalDetails';
import { stripeCountryConfigs } from './PayoutDetailsForm';
import css from './PayoutDetailsForm.css';
const PayoutDetailsFormCompanyComponent = ({ fieldRenderProps, country }) => {
const { disabled, form, intl, values } = fieldRenderProps;
// In EU, there can be a maximum of 4 additional owners
const MAX_NUMBER_OF_ADDITIONAL_OWNERS = 4;
const PayoutDetailsFormCompanyComponent = ({ fieldRenderProps }) => {
const {
id,
disabled,
form,
intl,
values,
form: {
mutators: { push },
},
} = fieldRenderProps;
const { country } = values;
const companyNameLabel = intl.formatMessage({ id: 'PayoutDetailsForm.companyNameLabel' });
const companyNamePlaceholder = intl.formatMessage({
@ -51,6 +65,15 @@ const PayoutDetailsFormCompanyComponent = ({ fieldRenderProps, country }) => {
stripeCountryConfigs(country).companyConfig &&
stripeCountryConfigs(country).companyConfig.personalAddress;
const showAdditionalOwnersField =
country &&
stripeCountryConfigs(country).companyConfig &&
stripeCountryConfigs(country).companyConfig.additionalOwners;
const hasAdditionalOwners = values.company && values.company.additionalOwners;
const hasMaxNumberOfAdditionalOwners =
hasAdditionalOwners &&
values.company.additionalOwners.length >= MAX_NUMBER_OF_ADDITIONAL_OWNERS;
return (
<React.Fragment>
{country ? (
@ -100,8 +123,10 @@ const PayoutDetailsFormCompanyComponent = ({ fieldRenderProps, country }) => {
country={country}
fieldId="company"
/>
{showPersonalAddressField ? (
<PayoutDetailsAddress
className={css.personalAddressContainer}
country={country}
intl={intl}
disabled={disabled}
@ -109,6 +134,59 @@ const PayoutDetailsFormCompanyComponent = ({ fieldRenderProps, country }) => {
fieldId="company.personalAddress"
/>
) : null}
{showAdditionalOwnersField ? (
<div className={css.additionalOwnerWrapper}>
<FieldArray id={id} name={'company.additionalOwners'}>
{({ fields }) =>
fields.map((name, index) => (
<div className={css.additionalOwnerWrapper} key={name}>
<div
className={css.fieldArrayRemove}
onClick={() => fields.remove(index)}
style={{ cursor: 'pointer' }}
>
<span className={css.additionalOwnerLabel}>
<IconClose rootClassName={css.closeIcon} size="small" />
<FormattedMessage id="PayoutDetailsForm.additionalOwnerRemove" />
</span>
</div>
<PayoutDetailsPersonalDetails
intl={intl}
disabled={disabled}
values={values}
country={country}
fieldId={`company.additionalOwners.${index}`}
/>
{showPersonalAddressField ? (
<PayoutDetailsAddress
className={css.personalAddressContainer}
country={country}
intl={intl}
disabled={disabled}
form={form}
fieldId={`company.additionalOwners.${index}`}
/>
) : null}
</div>
))
}
</FieldArray>
{!hasAdditionalOwners || !hasMaxNumberOfAdditionalOwners ? (
<InlineTextButton
type="button"
className={css.fieldArrayAdd}
onClick={() => push('company.additionalOwners', undefined)}
>
<span className={css.additionalOwnerLabel}>
<IconAdd rootClassName={css.addIcon} />
<FormattedMessage id="PayoutDetailsForm.additionalOwnerLabel" />
</span>
</InlineTextButton>
) : null}
</div>
) : null}
</React.Fragment>
) : null}
</React.Fragment>
@ -116,28 +194,13 @@ const PayoutDetailsFormCompanyComponent = ({ fieldRenderProps, country }) => {
};
PayoutDetailsFormCompanyComponent.defaultProps = {
className: null,
country: null,
createStripeAccountError: null,
id: null,
disabled: false,
<<<<<<< HEAD
inProgress: false,
ready: false,
submitButtonText: null,
=======
>>>>>>> 70cd0720... Merge to add personal address
};
PayoutDetailsFormCompanyComponent.propTypes = {
className: string,
createStripeAccountError: object,
id: string,
disabled: bool,
<<<<<<< HEAD
inProgress: bool,
ready: bool,
submitButtonText: string,
=======
>>>>>>> 70cd0720... Merge to add personal address
// from injectIntl
intl: intlShape.isRequired,

View file

@ -1,5 +1,5 @@
import React from 'react';
import { bool, object } from 'prop-types';
import { bool } from 'prop-types';
import { compose } from 'redux';
import { injectIntl, intlShape } from 'react-intl';
@ -18,15 +18,16 @@ const PayoutDetailsFormIndividualComponent = ({ fieldRenderProps }) => {
disabled={disabled}
values={values}
country={country}
fieldId="individual"
/>
<PayoutDetailsAddress
country={country}
intl={intl}
disabled={disabled}
form={form}
fieldId="individual"
fieldId="individual.address"
/>
<PayoutDetailsBankDetails country={country} disabled={disabled} />
<PayoutDetailsBankDetails country={country} disabled={disabled} fieldId="individual" />
</React.Fragment>
);
};
@ -37,7 +38,6 @@ PayoutDetailsFormIndividualComponent.defaultProps = {
PayoutDetailsFormIndividualComponent.propTypes = {
disabled: bool,
form: object.isRequired,
// from injectIntl
intl: intlShape.isRequired,

View file

@ -1,6 +1,5 @@
import React from 'react';
import { bool, string } from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { FieldBirthdayInput, FieldTextInput } from '../../components';
import * as validators from '../../util/validators';
import { intlShape } from 'react-intl';
@ -13,6 +12,13 @@ const MIN_STRIPE_ACCOUNT_AGE = 18;
const PayoutDetailsPersonalDetails = props => {
const { intl, disabled, values, country, fieldId } = props;
const personalDetailsTitle = intl.formatMessage({
id:
fieldId === 'company' || fieldId === 'individual'
? 'PayoutDetailsForm.personalDetailsTitle'
: 'PayoutDetailsForm.personalDetailsAdditionalOwnerTitle',
});
const firstNameLabel = intl.formatMessage({ id: 'PayoutDetailsForm.firstNameLabel' });
const firstNamePlaceholder = intl.formatMessage({
id: 'PayoutDetailsForm.firstNamePlaceholder',
@ -100,9 +106,7 @@ const PayoutDetailsPersonalDetails = props => {
return (
<div className={css.sectionContainer}>
<h3 className={css.subTitle}>
<FormattedMessage id="PayoutDetailsForm.personalDetailsTitle" />
</h3>
<h3 className={css.subTitle}>{personalDetailsTitle}</h3>
<div className={css.formRow}>
<FieldTextInput
id={`${fieldId}.firstName`}

View file

@ -40,6 +40,7 @@ export const stripeSupportedCountries = [
},
companyConfig: {
personalAddress: true,
additionalOwners: true,
},
},
{
@ -56,6 +57,7 @@ export const stripeSupportedCountries = [
},
companyConfig: {
personalAddress: true,
additionalOwners: true,
},
},
{
@ -88,6 +90,7 @@ export const stripeSupportedCountries = [
},
companyConfig: {
personalAddress: true,
additionalOwners: true,
},
},
{
@ -104,6 +107,7 @@ export const stripeSupportedCountries = [
},
companyConfig: {
personalAddress: true,
additionalOwners: true,
},
},
{
@ -120,6 +124,7 @@ export const stripeSupportedCountries = [
},
companyConfig: {
personalAddress: true,
additionalOwners: true,
},
},
{
@ -136,6 +141,7 @@ export const stripeSupportedCountries = [
},
companyConfig: {
personalAddress: true,
additionalOwners: true,
},
},
{
@ -170,6 +176,7 @@ export const stripeSupportedCountries = [
},
companyConfig: {
personalAddress: true,
additionalOwners: true,
},
},
{
@ -186,6 +193,7 @@ export const stripeSupportedCountries = [
},
companyConfig: {
personalAddress: true,
additionalOwners: true,
},
},
{
@ -202,6 +210,7 @@ export const stripeSupportedCountries = [
},
companyConfig: {
personalAddress: true,
additionalOwners: true,
},
},
{
@ -218,6 +227,7 @@ export const stripeSupportedCountries = [
},
companyConfig: {
personalAddress: true,
additionalOwners: true,
},
},
{
@ -247,6 +257,7 @@ export const stripeSupportedCountries = [
},
companyConfig: {
personalAddress: true,
additionalOwners: true,
},
},
{
@ -263,6 +274,7 @@ export const stripeSupportedCountries = [
},
companyConfig: {
personalAddress: true,
additionalOwners: true,
},
},
{
@ -279,6 +291,7 @@ export const stripeSupportedCountries = [
},
companyConfig: {
personalAddress: true,
additionalOwners: true,
},
},
{
@ -295,6 +308,7 @@ export const stripeSupportedCountries = [
},
companyConfig: {
personalAddress: true,
additionalOwners: true,
},
},
{
@ -311,6 +325,7 @@ export const stripeSupportedCountries = [
},
companyConfig: {
personalAddress: true,
additionalOwners: true,
},
},
{
@ -328,6 +343,7 @@ export const stripeSupportedCountries = [
},
companyConfig: {
personalAddress: true,
additionalOwners: true,
},
},
{

View file

@ -453,6 +453,8 @@
"PasswordResetPage.resetFailed": "Reset failed. Please try again.",
"PasswordResetPage.title": "Reset password",
"PayoutDetailsForm.accountTypeTitle": "Account type",
"PayoutDetailsForm.additionalOwnerLabel": "Add additional owner",
"PayoutDetailsForm.additionalOwnerRemove": "Remove additional owner",
"PayoutDetailsForm.addressTitle": "Address",
"PayoutDetailsForm.bankDetails": "Bank details",
"PayoutDetailsForm.birthdayDatePlaceholder": "dd",
@ -545,6 +547,7 @@
"PayoutDetailsForm.lastNameLabel": "Last name",
"PayoutDetailsForm.lastNamePlaceholder": "Doe",
"PayoutDetailsForm.lastNameRequired": "This field is required",
"PayoutDetailsForm.personalDetailsAdditionalOwnerTitle": "Additional owner details",
"PayoutDetailsForm.personalDetailsTitle": "Personal details",
"PayoutDetailsForm.personalIdNumberTitle": "Personal id number",
"PayoutDetailsForm.personalIdNumberLabel.HK": "Hong Kong Identity Card Number (HKID)",