Skip to content

Commit

Permalink
feature - added address and verify screens to kyc flow
Browse files Browse the repository at this point in the history
  • Loading branch information
tony-blockchain committed Jul 19, 2018
1 parent 8c93e49 commit e0227fb
Show file tree
Hide file tree
Showing 18 changed files with 599 additions and 193 deletions.
1 change: 1 addition & 0 deletions packages/blockchain-wallet-v4-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
"lodash.debounce": "4.0.8",
"matchmedia-polyfill": "0.3.1",
"moment": "2.22.2",
"postal-codes-js": "^1.0.0",
"prop-types": "15.6.1",
"qrcode.react": "0.8.0",
"ramda": "0.25.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import IntlTelInput from 'react-intl-tel-input'
import 'react-intl-tel-input/dist/libphonenumber.js'
import 'react-intl-tel-input/dist/main.css'
import { Text } from 'blockchain-info-components'
import { Remote } from 'blockchain-wallet-v4'

const Container = styled.div`
position: relative;
Expand Down Expand Up @@ -52,7 +53,10 @@ const PhoneNumberBox = field => {
input.onBlur(number)
}

const upperCountryCode = prop('countryCode', field).getOrElse('US')
const countryCodeField = prop('countryCode', field)
const upperCountryCode = Remote.is(countryCodeField)
? countryCodeField.getOrElse('US')
: countryCodeField || 'US'
const countryCode = upperCountryCode && toLower(upperCountryCode)

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react'
import PropTypes from 'prop-types'
import { filter, contains, isEmpty, cond, T, identity } from 'ramda'
import { FormattedMessage } from 'react-intl'
import countryRegionData from 'country-region-data'

import SelectBox from '../SelectBox'

Expand Down Expand Up @@ -54,7 +55,6 @@ const applyWhiteBlackList = (whiteList, blackList) => {
}

export const countries = [
{ text: 'Aland Islands', value: 'FI-AX' },
{ text: 'Albania', value: 'AL' },
{ text: 'Algeria', value: 'DZ' },
{ text: 'American Samoa', value: 'AS' },
Expand All @@ -68,7 +68,6 @@ export const countries = [
{ text: 'Australia', value: 'AU' },
{ text: 'Austria', value: 'AT' },
{ text: 'Azerbaijan', value: 'AZ' },
{ text: 'Azores', value: 'PT-20' },
{ text: 'Bahamas', value: 'BS' },
{ text: 'Bahrain', value: 'BH' },
{ text: 'Bangladesh', value: 'BD' },
Expand All @@ -92,7 +91,6 @@ export const countries = [
{ text: 'Cambodia', value: 'KH' },
{ text: 'Cameroon', value: 'CM' },
{ text: 'Canada', value: 'CA' },
{ text: 'Canary Islands', value: 'ES-IC' },
{ text: 'Cape Verde', value: 'CV' },
{ text: 'Cayman Islands', value: 'KY' },
{ text: 'Chad', value: 'TD' },
Expand Down Expand Up @@ -170,7 +168,6 @@ export const countries = [
{ text: 'Macao', value: 'MO' },
{ text: 'Macedonia, the Former Yugoslav Republic of', value: 'MK' },
{ text: 'Madagascar', value: 'MG' },
{ text: 'Madeira', value: 'PT-30' },
{ text: 'Malawi', value: 'MW' },
{ text: 'Malaysia', value: 'MY' },
{ text: 'Maldives', value: 'MV' },
Expand Down Expand Up @@ -245,7 +242,6 @@ export const countries = [
{ text: 'Spain', value: 'ES' },
{ text: 'Sri Lanka', value: 'LK' },
{ text: 'Suriname', value: 'SR' },
{ text: 'Svalbard and Jan Mayen', value: 'SJ' },
{ text: 'Swaziland', value: 'SZ' },
{ text: 'Sweden', value: 'SE' },
{ text: 'Switzerland', value: 'CH' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import countryRegionData from 'country-region-data'

import SelectBox from '../SelectBox'

const countriesWithStates = ['US']

export const countryHasStates = countryCode =>
countriesWithStates.includes(countryCode)

class SelectBoxRegion extends React.PureComponent {
static propTypes = {
countryCode: PropTypes.string
Expand All @@ -27,10 +32,17 @@ class SelectBoxRegion extends React.PureComponent {
return (
<SelectBox
label={
<FormattedMessage
id='components.selectboxcountry.label'
defaultMessage='Select state/region'
/>
countryHasStates(countryCode) ? (
<FormattedMessage
id='components.selectboxregion.placeholder.state'
defaultMessage='Select state'
/>
) : (
<FormattedMessage
id='components.selectboxregion.placeholder.region'
defaultMessage='Select region'
/>
)
}
elements={elements}
{...this.props}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import SelectBoxCoinifyCurrency from './SelectBoxCoinifyCurrency'
import SelectBoxCountry from './SelectBoxCountry'
import SelectBoxCurrency from './SelectBoxCurrency'
import SelectBoxLanguages from './SelectBoxLanguages'
import SelectBoxRegion from './SelectBoxRegion'
import SelectBoxTheme from './SelectBoxTheme'
import SelectBoxUSState from './SelectBoxUSState'
import TabMenuBuySellStatus from './TabMenuBuySellStatus'
Expand Down Expand Up @@ -58,6 +59,7 @@ export {
SelectBoxCountry,
SelectBoxCurrency,
SelectBoxLanguages,
SelectBoxRegion,
SelectBoxTheme,
SelectBoxUSState,
TabMenuBuySellStatus,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ export const SMS_STEPS = {
export const PERSONAL_FORM = '@KYC.personalForm'
export const EMAIL_FORM = '@KYC.emailForm'
export const SMS_NUMBER_FORM = '@KYC.smsNumberForm'
export const ADDRESS_FORM = '@KYC.addresForm'
1 change: 1 addition & 0 deletions packages/blockchain-wallet-v4-frontend/src/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
__webpack_nonce__ = 'c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM='
const index =
process.env.NODE_ENV === 'production'
? require('./index.prod')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
import React from 'react'
import PropTypes from 'prop-types'
import { compose } from 'redux'
import { connect } from 'react-redux'
import { FormattedMessage } from 'react-intl'
import { Field, reduxForm } from 'redux-form'
import styled from 'styled-components'

import { getAddressData } from './selectors'
import { required, requiredZipCode } from 'services/FormHelper'
import { ADDRESS_FORM } from 'data/components/identityVerification/model'
import media from 'services/ResponsiveService'
import { Button, Text, HeartbeatLoader } from 'blockchain-info-components'
import {
FormGroup,
FormItem,
TextBox,
SelectBoxRegion,
SelectBoxCountry
} from 'components/Form'
import { countryHasStates } from 'components/Form/SelectBoxRegion'
import {
Form,
ColLeft,
ColRight,
InputWrapper,
PartnerHeader,
PartnerSubHeader,
ColRightInner
} from 'components/IdentityVerification'
import renderFaq from 'components/FaqDropdown'

const FormContainer = styled.div`
margin-top: 25px;
`
const AddressForm = styled(Form)`
display: flex;
flex-direction: row;
${media.mobile`
flex-direction: column;
`};
`
const AddressFormGroup = styled(FormGroup)`
${media.mobile`
flex-direction: column;
div:first-of-type {
margin-bottom: 10px;
}
div:last-of-type {
div:last-of-type {
margin-bottom: 15px;
}
}
`};
`

const faqQuestions = [
{
question: (
<FormattedMessage
id='identityverification.address.faq.whycollect.question'
defaultMessage='Why do you need this information?'
/>
),
answer: (
<FormattedMessage
id='identityverification.address.faq.whycollect.answer'
defaultMessage='To comply with government regulated anti-money laundering legislation, we need to obtain additional information in order to verify your identity.'
/>
)
}
]

const Address = ({
invalid,
submitting,
handleSubmit,
countryCode,
formBusy
}) => (
<AddressForm onSubmit={handleSubmit}>
<ColLeft>
<InputWrapper>
<PartnerHeader>
<FormattedMessage
id='identityverification.address.header'
defaultMessage='Address Details'
/>
</PartnerHeader>
<PartnerSubHeader>
<FormattedMessage
id='identityverification.address.subheader'
defaultMessage="There's so much we'd love to know about you, but we only need a few things."
/>
</PartnerSubHeader>
<FormContainer>
<FormGroup>
<FormItem>
<Text size='14px' weight={400} style={{ marginBottom: '5px' }}>
<FormattedMessage
id='identityverification.address.address'
defaultMessage='Address'
/>
</Text>
<Field
name='address1'
validate={[required]}
component={TextBox}
placeholder='Street Address'
/>
</FormItem>
</FormGroup>
<FormGroup>
<FormItem>
<Text size='14px' weight={400} style={{ marginBottom: '5px' }}>
<FormattedMessage
id='identityverification.address.address2'
defaultMessage='Address 2'
/>
</Text>
<Field
name='address2'
component={TextBox}
placeholder='Apartment, unit, floor, etc..'
/>
</FormItem>
</FormGroup>
<FormGroup>
<FormItem>
<Text size='14px' weight={400} style={{ marginBottom: '5px' }}>
<FormattedMessage
id='identityverification.address.city'
defaultMessage='City'
/>
</Text>
<Field name='city' validate={[required]} component={TextBox} />
</FormItem>
</FormGroup>
<AddressFormGroup inline>
<FormItem>
<Text size='14px' weight={400} style={{ marginBottom: '5px' }}>
{countryHasStates(countryCode) ? (
<FormattedMessage
id='identityverification.address.state'
defaultMessage='State'
/>
) : (
<FormattedMessage
id='identityverification.address.region'
defaultMessage='Region'
/>
)}
</Text>
<Field
name='region'
validate={[required]}
countryCode={countryCode}
component={SelectBoxRegion}
/>
</FormItem>
<FormItem>
<Text size='14px' weight={400} style={{ marginBottom: '5px' }}>
<FormattedMessage
id='identityverification.address.zipcode'
defaultMessage='Zip Code'
/>
</Text>
<Field
name='zipCode'
validate={[requiredZipCode]}
component={TextBox}
/>
</FormItem>
</AddressFormGroup>
<FormGroup>
<FormItem>
<Text size='14px' weight={400} style={{ marginBottom: '5px' }}>
<FormattedMessage
id='identityverification.address.country'
defaultMessage='Country'
/>
</Text>
<Field
name='countryCode'
validate={[required]}
component={SelectBoxCountry}
/>
</FormItem>
</FormGroup>
</FormContainer>
</InputWrapper>
</ColLeft>
<ColRight>
<ColRightInner>
<Button
uppercase
nature='primary'
type='submit'
fullwidth
disabled={invalid || submitting || formBusy}
>
{!formBusy ? (
<FormattedMessage
id='identityverification.address.continue'
defaultMessage='Continue'
/>
) : (
<HeartbeatLoader height='20px' width='20px' color='white' />
)}
</Button>
{renderFaq(faqQuestions)}
</ColRightInner>
</ColRight>
</AddressForm>
)

Address.propTypes = {
handleSubmit: PropTypes.func.isRequired,
countryCode: PropTypes.string
}

Address.defaultProps = {
countryCode: ''
}

const enhance = compose(
connect(getAddressData),
reduxForm({
form: ADDRESS_FORM,
destroyOnUnmount: false
})
)

export default enhance(Address)

0 comments on commit e0227fb

Please sign in to comment.