Advanced Tutorial: KYC Plugin web views
We will go over how to develop home and verification web views for the KYC plugin.

Step 1: Initialize the KYC plugin web view.

Run the following commands to initialize the plugin web view:
1
cd web/
2
npm run add-plugin --plugin=kyc --type=kyc
Copied!

Step 2: Install the initial plugin.

Run the following commands to build the initial plugin with a default view and install the plugin.
1
cd ..
2
npm run build --plugin=kyc
Copied!

Step 3: disable CORS error on the browser.

The web view JSON file and bundles are served on the localhost port 8080. In order to allow the kit to access them in plugin development mode, we need to disable the CORS issue on the browser. This can be achieved by using a browser extension.

Step 4: Plugin interactive development mode

To start using interactive plugin development mode, we need to run the commands of steps 5 and 6 simultaneously.

Step 5: Create, watch and serve web view bundles and the JSON file.

Run the following command on the plugin starter kit web directory:
1
npm start --plugin=kyc
Copied!

Step 6: Start Hollaex kit plugin development mode.

Run the following command on the Hollaex kit web directory:
1
npm run dev:plugin --plugin=kyc
Copied!
In order to see the plugin's changes, we need to refresh the page after every change.

Step 7: Update home Form.js component.

Then add the following component to the Form.js file.
Form.js
1
import React, { useState, useEffect } from 'react';
2
import { Tabs } from 'antd';
3
import { withKit } from 'components/KitContext';
4
import Identity from './components/Identity';
5
import Documents from './components/Documents';
6
7
const { TabPane } = Tabs;
8
const INITIAL_KYC_TAB_KEY = 'initial_kyc_tab';
9
10
const Form = ({ strings: STRINGS, setActivePageContent: setPageContent, handleBack, activeLanguage, user, getCountry, getFormatTimestamp, icons: ICONS }) => {
11
const kycTabs = [
12
{
13
key: 'identity',
14
title: STRINGS['USER_VERIFICATION.TITLE_IDENTITY'],
15
},
16
{
17
key: 'documents',
18
title: STRINGS['USER_VERIFICATION.TITLE_ID_DOCUMENTS'],
19
},
20
];
21
22
const [activeKYCTab, setActiveKYCTab] = useState('identity');
23
24
useEffect(() => {
25
const kycInitialTab = localStorage.getItem(INITIAL_KYC_TAB_KEY);
26
if (kycInitialTab && kycTabs.map(({key}) => key).includes(kycInitialTab)) {
27
setActiveKYCTab(kycInitialTab);
28
}
29
}, []);
30
31
const setActivePageContent = (key) => (page) => {
32
localStorage.setItem(INITIAL_KYC_TAB_KEY, key);
33
setPageContent(page)
34
}
35
36
const renderKYCVerificationHomeContent = (key, user, activeLanguage) => {
37
switch (key) {
38
case 'identity':
39
return (
40
<Identity
41
activeLanguage={activeLanguage}
42
user={user}
43
handleBack={handleBack}
44
setActivePageContent={setActivePageContent(key)}
45
getFormatTimestamp={getFormatTimestamp}
46
getCountry={getCountry}
47
strings={STRINGS}
48
/>
49
);
50
case 'documents':
51
return (
52
<Documents
53
user={user}
54
setActivePageContent={setActivePageContent(key)}
55
icons={ICONS}
56
strings={STRINGS}
57
/>
58
);
59
default:
60
return <div>No content</div>;
61
}
62
};
63
64
return (
65
<div>
66
<Tabs activeKey={activeKYCTab} onTabClick={setActiveKYCTab}>
67
{kycTabs.map(({ key, title }) => (
68
<TabPane tab={title} key={key}>
69
{renderKYCVerificationHomeContent(
70
key,
71
user,
72
activeLanguage
73
)}
74
</TabPane>
75
))}
76
</Tabs>
77
</div>
78
)
79
}
80
81
const mapContextToProps = ({ strings, setActivePageContent, handleBack, activeLanguage, user, getCountry, getFormatTimestamp, icons }) => ({
82
strings,
83
setActivePageContent,
84
handleBack,
85
activeLanguage,
86
user,
87
getCountry,
88
getFormatTimestamp,
89
icons,
90
});
91
92
export default withKit(mapContextToProps)(Form);
Copied!
In this component, we are getting the following common props and target-specific props from the kit context using the withKit HOC.
  • Common props: strings, activeLanguage, user, icons
  • Target-specific props: setActivePageContent, handleBack, getCountry, getFormatTimestamp
See the SmartTarget with REMOTE_COMPONENT__KYC_VERIFICATION_HOME id on the verification container component for more details about the props.

Step 8: Add home components.

1
mkdir src/plugins/kyc/views/home/components
2
touch src/plugins/kyc/views/home/components/Documents.js
3
touch src/plugins/kyc/views/home/components/Identity.js
Copied!

Documents

Documents.js
1
import React from 'react';
2
import moment from 'moment';
3
import classnames from 'classnames';
4
import { Button, PanelInformationRow, Editable as EditWrapper, Image } from 'hollaex-web-lib';
5
6
const Documents = ({
7
user,
8
setActivePageContent,
9
icons: ICONS,
10
strings: STRINGS,
11
}) => {
12
const { id_data } = user;
13
let note = '';
14
if (id_data.status === 1) {
15
note = STRINGS['USER_VERIFICATION.DOCUMENT_PENDING_NOTE'];
16
} else if (id_data.status === 2) {
17
note = id_data.note;
18
} else {
19
note = STRINGS['USER_VERIFICATION.DOCUMENT_VERIFIED_NOTE'];
20
}
21
return (
22
<div>
23
{id_data.status !== 0 && (
24
<div className="d-flex my-3">
25
<div
26
className={classnames('mr-2', 'd-flex', 'justify-content-center', 'align-items-center')}
27
title={
28
STRINGS['USER_VERIFICATION.NOTE_FROM_VERIFICATION_DEPARTMENT']
29
}
30
>
31
<Image
32
icon={ICONS['NOTE_KYC']}
33
iconId="NOTE_KYC"
34
stringId="USER_VERIFICATION.NOTE_FROM_VERIFICATION_DEPARTMENT"
35
wrapperClassName="document-note-icon"
36
/>
37
</div>
38
<PanelInformationRow
39
stringId="USER_VERIFICATION.CUSTOMER_SUPPORT_MESSAGE,USER_VERIFICATION.DOCUMENT_PENDING_NOTE,USER_VERIFICATION.DOCUMENT_VERIFIED_NOTE"
40
label={STRINGS['USER_VERIFICATION.CUSTOMER_SUPPORT_MESSAGE']}
41
information={note}
42
className="title-font"
43
disable
44
/>
45
</div>
46
)}
47
{id_data.status === 1 && (
48
<div className="my-3">
49
<PanelInformationRow
50
stringId="USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.ID_NUMBER_LABEL"
51
label={
52
STRINGS[
53
'USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.ID_NUMBER_LABEL'
54
]
55
}
56
information={id_data.number}
57
className="title-font"
58
disable
59
/>
60
<div className="d-flex">
61
<PanelInformationRow
62
stringId="USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.ISSUED_DATE_LABEL"
63
label={
64
STRINGS[
65
'USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.ISSUED_DATE_LABEL'
66
]
67
}
68
information={moment(id_data.issued_date).format('DD, MMMM, YYYY')}
69
className="title-font mr-2"
70
disable
71
/>
72
<PanelInformationRow
73
stringId="USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.EXPIRATION_DATE_LABEL"
74
label={
75
STRINGS[
76
'USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.EXPIRATION_DATE_LABEL'
77
]
78
}
79
information={moment(id_data.expiration_date).format(
80
'DD, MMMM, YYYY'
81
)}
82
className="title-font"
83
disable
84
/>
85
</div>
86
</div>
87
)}
88
{id_data.status !== 3 && (
89
<div className="my-2 btn-wrapper">
90
<div className="holla-verification-button static pt-4">
91
<EditWrapper stringId="USER_VERIFICATION.START_DOCUMENTATION_SUBMISSION,USER_VERIFICATION.START_DOCUMENTATION_RESUBMISSION" />
92
<Button
93
label={
94
id_data.status === 0
95
? STRINGS['USER_VERIFICATION.START_DOCUMENTATION_SUBMISSION']
96
: STRINGS[
97
'USER_VERIFICATION.START_DOCUMENTATION_RESUBMISSION'
98
]
99
}
100
onClick={() => setActivePageContent('kyc')}
101
/>
102
</div>
103
</div>
104
)}
105
</div>
106
);
107
};
108
109
export default Documents;
110
Copied!

Identity

Identity.js
1
import React from 'react';
2
import { Button, PanelInformationRow, Editable as EditWrapper } from 'hollaex-web-lib';
3
4
const formatBirthday = {
5
en: 'DD, MMMM, YYYY',
6
fa: 'jDD, jMMMM, jYYYY',
7
};
8
9
const Identity = ({
10
user,
11
activeLanguage,
12
setActivePageContent,
13
handleBack,
14
strings: STRINGS,
15
getCountry,
16
getFormatTimestamp,
17
}) => {
18
const { address, id_data } = user;
19
if (!address.country) {
20
return (
21
<div className="btn-wrapper">
22
<div className="holla-verification-button static pt-4">
23
<EditWrapper stringId="USER_VERIFICATION.START_IDENTITY_VERIFICATION" />
24
<Button
25
label={STRINGS['USER_VERIFICATION.START_IDENTITY_VERIFICATION']}
26
onClick={() => setActivePageContent('kyc')}
27
/>
28
</div>
29
</div>
30
);
31
} else {
32
return (
33
<div>
34
<div className="font-weight-bold text-lowercase">
35
{STRINGS.formatString(
36
STRINGS['USER_VERIFICATION.BANK_VERIFICATION_HELP_TEXT'],
37
<span
38
className="verification_link pointer"
39
onClick={(e) => handleBack('kyc', e)}
40
>
41
{STRINGS['USER_VERIFICATION.DOCUMENT_SUBMISSION']}
42
</span>
43
)}
44
<EditWrapper stringId="USER_VERIFICATION.BANK_VERIFICATION_HELP_TEXT,USER_VERIFICATION.DOCUMENT_SUBMISSION" />
45
</div>
46
<div className="my-3">
47
<PanelInformationRow
48
stringId="USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.FULL_NAME_LABEL"
49
label={
50
STRINGS[
51
'USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.FULL_NAME_LABEL'
52
]
53
}
54
information={user.full_name}
55
className="title-font"
56
disable
57
/>
58
<div className="d-flex">
59
<PanelInformationRow
60
stringId="USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.GENDER_LABEL,USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.GENDER_OPTIONS.MAN,USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.GENDER_OPTIONS.WOMAN"
61
label={
62
STRINGS[
63
'USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.GENDER_LABEL'
64
]
65
}
66
information={
67
user.gender === false
68
? STRINGS[
69
'USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.GENDER_OPTIONS.MAN'
70
]
71
: STRINGS[
72
'USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.GENDER_OPTIONS.WOMAN'
73
]
74
}
75
className="title-font divider"
76
disable
77
/>
78
<PanelInformationRow
79
stringId="USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.DOB_LABEL"
80
label={
81
STRINGS[
82
'USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.DOB_LABEL'
83
]
84
}
85
information={getFormatTimestamp(
86
user.dob,
87
formatBirthday[activeLanguage]
88
)}
89
className="title-font"
90
disable
91
/>
92
</div>
93
<PanelInformationRow
94
stringId="USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.NATIONALITY_LABEL"
95
label={
96
STRINGS[
97
'USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.NATIONALITY_LABEL'
98
]
99
}
100
information={getCountry(user.nationality).name}
101
className="title-font"
102
disable
103
/>
104
<div className="d-flex">
105
<PanelInformationRow
106
stringId="USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.COUNTRY_LABEL"
107
label={
108
STRINGS[
109
'USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.COUNTRY_LABEL'
110
]
111
}
112
information={getCountry(address.country).name}
113
className="title-font divider"
114
disable
115
/>
116
<PanelInformationRow
117
stringId="USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.CITY_LABEL"
118
label={
119
STRINGS[
120
'USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.CITY_LABEL'
121
]
122
}
123
information={address.city}
124
className="title-font"
125
disable
126
/>
127
</div>
128
<div className="d-flex">
129
<div className="w-75">
130
<PanelInformationRow
131
stringId="USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.ADDRESS_LABEL"
132
label={
133
STRINGS[
134
'USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.ADDRESS_LABEL'
135
]
136
}
137
information={address.address}
138
className="title-font divider"
139
disable
140
/>
141
</div>
142
<PanelInformationRow
143
stringId="USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.POSTAL_CODE_LABEL"
144
label={
145
STRINGS[
146
'USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.POSTAL_CODE_LABEL'
147
]
148
}
149
information={address.postal_code}
150
className="title-font"
151
disable
152
/>
153
</div>
154
</div>
155
{id_data.status === 3 ? null : (
156
<div className="btn-wrapper">
157
<div className="holla-verification-button static pt-4">
158
<EditWrapper stringId="USER_VERIFICATION.REVIEW_IDENTITY_VERIFICATION" />
159
<Button
160
label={
161
STRINGS['USER_VERIFICATION.REVIEW_IDENTITY_VERIFICATION']
162
}
163
onClick={() => setActivePageContent('kyc')}
164
/>
165
</div>
166
</div>
167
)}
168
</div>
169
);
170
}
171
};
172
173
export default Identity;
174
Copied!

Step 9: Update verification Form.js component.

Form.js
1
import React, { useState, useEffect } from 'react';
2
import { Tabs } from 'antd';
3
import { withKit } from 'components/KitContext';
4
import Identity from './components/Identity';
5
import Documents from './components/Documents';
6
7
const { TabPane } = Tabs;
8
const INITIAL_KYC_TAB_KEY = 'initial_kyc_tab';
9
10
const Form = ({ handleBack: back, strings: STRINGS, user, constants, identityInitialValues, documentInitialValues }) => {
11
const kycTabs = [
12
{
13
key: 'identity',
14
title: STRINGS['USER_VERIFICATION.TITLE_IDENTITY'],
15
},
16
{
17
key: 'documents',
18
title: STRINGS['USER_VERIFICATION.TITLE_ID_DOCUMENTS'],
19
},
20
];
21
22
const [activeKYCTab, setActiveKYCTab] = useState('identity');
23
24
useEffect(() => {
25
const kycInitialTab = localStorage.getItem(INITIAL_KYC_TAB_KEY);
26
if (kycInitialTab && kycTabs.map(({key}) => key).includes(kycInitialTab)) {
27
setActiveKYCTab(kycInitialTab);
28
}
29
}, []);
30
31
const handleBack = (key) => (params) => {
32
localStorage.setItem(INITIAL_KYC_TAB_KEY, key);
33
back(params)
34
}
35
36
const renderKYCVerificationContent = (key) => {
37
38
switch (key) {
39
case 'identity':
40
return (
41
<Identity
42
fullName={user.full_name}
43
initialValues={identityInitialValues(user, constants)}
44
handleBack={handleBack(key)}
45
/>
46
);
47
case 'documents':
48
return (
49
<Documents
50
idData={user.id_data}
51
initialValues={documentInitialValues(user)}
52
handleBack={handleBack(key)}
53
/>
54
);
55
default:
56
return <div>No content</div>;
57
}
58
};
59
60
return (
61
<div className="presentation_container apply_rtl verification_container">
62
<Tabs activeKey={activeKYCTab} onTabClick={setActiveKYCTab}>
63
{kycTabs.map(({ key, title }) => (
64
<TabPane tab={title} key={key}>
65
{renderKYCVerificationContent(key)}
66
</TabPane>
67
))}
68
</Tabs>
69
</div>
70
)
71
}
72
73
const mapContextToProps = ({ handleBack, strings, user, constants, identityInitialValues, documentInitialValues }) => ({
74
handleBack,
75
strings,
76
user,
77
constants,
78
identityInitialValues,
79
documentInitialValues
80
});
81
82
export default withKit(mapContextToProps)(Form);
Copied!
In this component, we are getting the following common and target-specific props from the kit context using the withKit HOC.
  • Common props: strings, user, constants
  • Target-specific props: handleBack, identityInitialValues, documentInitialValues
See the SmartTarget with REMOTE_COMPONENT__KYC_VERIFICATION id on the verification container component for more details about the props.

Step 10: Add verification components.

1
mkdir src/plugins/kyc/views/verification/components
2
touch src/plugins/kyc/views/verification/components/Documents.js
3
touch src/plugins/kyc/views/verification/components/Identity.js
4
touch src/plugins/kyc/views/verification/components/HeaderSection.js
Copied!

Documents

Documents.js
1
import React, { Component } from 'react';
2
import { reduxForm, SubmissionError, formValueSelector } from 'redux-form';
3
import { connect } from 'react-redux';
4
import moment from 'moment';
5
import {
6
isBefore,
7
requiredWithCustomMessage,
8
} from 'utils';
9
import { Button, IconTitle, Image, Editable } from 'hollaex-web-lib';
10
import { HeaderSection } from 'components/HeaderSection';
11
import { withKit } from 'components/KitContext';
12
import {
13
IdentificationFormSection,
14
PORSection,
15
SelfieWithPhotoId,
16
} from './HeaderSection';
17
18
import { isMobile } from 'react-device-detect';
19
const FORM_NAME = 'DocumentsVerification';
20
21
const selector = formValueSelector(FORM_NAME);
22
export const sizeLimitInMB = 6;
23
const sizeLimit = sizeLimitInMB * 1024 * 1024;
24
25
26
class Documents extends Component {
27
state = {
28
formFields: {},
29
accSize: 0,
30
};
31
32
componentDidMount() {
33
this.generateFormFields(this.props.activeLanguage);
34
}
35
36
UNSAFE_componentWillReceiveProps(nextProps) {
37
if (nextProps.activeLanguage !== this.props.activeLanguage) {
38
this.generateFormFields(nextProps.activeLanguage);
39
}
40
41
if (JSON.stringify(nextProps.files) !== JSON.stringify(this.props.files)) {
42
this.checkTotalFilesSize(nextProps.files)
43
}
44
}
45
46
getFileSize = (file) => {
47
if (file && file.size) {
48
return file.size;
49
} else {
50
return 0;
51
}
52
}
53
54
checkTotalFilesSize = (files = {}) => {
55
let accSize = 0
56
Object.entries(files).forEach(([_, file]) => {
57
accSize += this.getFileSize(file);
58
})
59
60
this.setState({ accSize });
61
}
62
63
generateFormFields = (language) => {
64
const { strings: STRINGS } = this.props;
65
const formFields = {
66
idDocument: {
67
number: {
68
type: 'text',
69
stringId:
70
'USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.ID_NUMBER_LABEL,USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.ID_NUMBER_PLACEHOLDER,USER_VERIFICATION.ID_DOCUMENTS_FORM.VALIDATIONS.ID_NUMBER',
71
label:
72
STRINGS[
73
'USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.ID_NUMBER_LABEL'
74
],
75
placeholder:
76
STRINGS[
77
'USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.ID_NUMBER_PLACEHOLDER'
78
],
79
validate: [
80
requiredWithCustomMessage(
81
STRINGS[
82
'USER_VERIFICATION.ID_DOCUMENTS_FORM.VALIDATIONS.ID_NUMBER'
83
]
84
),
85
],
86
fullWidth: isMobile,
87
ishorizontalfield: true,
88
},
89
issued_date: {
90
type: 'date-dropdown',
91
stringId:
92
'USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.ISSUED_DATE_LABEL,USER_VERIFICATION.ID_DOCUMENTS_FORM.VALIDATIONS.ISSUED_DATE',
93
label:
94
STRINGS[
95
'USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.ISSUED_DATE_LABEL'
96
],
97
validate: [
98
requiredWithCustomMessage(
99
STRINGS[
100
'USER_VERIFICATION.ID_DOCUMENTS_FORM.VALIDATIONS.ISSUED_DATE'
101
]
102
),
103
isBefore('', STRINGS['VALIDATIONS.INVALID_DATE']),
104
],
105
endDate: moment().add(1, 'days'),
106
language,
107
fullWidth: isMobile,
108
ishorizontalfield: true,
109
},
110
expiration_date: {
111
type: 'date-dropdown',
112
stringId:
113
'USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.EXPIRATION_DATE_LABEL,USER_VERIFICATION.ID_DOCUMENTS_FORM.VALIDATIONS.EXPIRATION_DATE',
114
label:
115
STRINGS[
116
'USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.EXPIRATION_DATE_LABEL'
117
],
118
validate: [
119
requiredWithCustomMessage(
120
STRINGS[
121
'USER_VERIFICATION.ID_DOCUMENTS_FORM.VALIDATIONS.EXPIRATION_DATE'
122
]
123
),
124
isBefore(moment().add(15, 'years'), STRINGS['VALIDATIONS.INVALID_DATE']),
125
],
126
endDate: moment().add(15, 'years'),
127
addYears: 15,
128
yearsBefore: 5,
129
language,
130
fullWidth: isMobile,
131
ishorizontalfield: true,
132
},
133
},
134
id: {
135
type: {
136
type: 'hidden',
137
},
138
front: {
139
type: 'file',
140
stringId:
141
'USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.FRONT_LABEL,USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.FRONT_PLACEHOLDER,USER_VERIFICATION.ID_DOCUMENTS_FORM.VALIDATIONS.FRONT',
142
label:
143
STRINGS[
144
'USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.FRONT_LABEL'
145
],
146
placeholder:
147
STRINGS[
148
'USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.FRONT_PLACEHOLDER'
149
],
150
validate: [
151
requiredWithCustomMessage(
152
STRINGS['USER_VERIFICATION.ID_DOCUMENTS_FORM.VALIDATIONS.FRONT']
153
),
154
],
155
fullWidth: isMobile,
156
ishorizontalfield: true,
157
},
158
},
159
proof_of_residency: {
160
type: {
161
type: 'hidden',
162
},
163
back: {
164
type: 'file',
165
stringId:
166
'USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.POR_LABEL,USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.POR_PLACEHOLDER,USER_VERIFICATION.ID_DOCUMENTS_FORM.VALIDATIONS.PROOF_OF_RESIDENCY',
167
label:
168
STRINGS[
169
'USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.POR_LABEL'
170
],
171
placeholder:
172
STRINGS[
173
'USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.POR_PLACEHOLDER'
174
],
175
validate: [
176
requiredWithCustomMessage(
177
STRINGS[
178
'USER_VERIFICATION.ID_DOCUMENTS_FORM.VALIDATIONS.PROOF_OF_RESIDENCY'
179
]
180
),
181
],
182
fullWidth: isMobile,
183
ishorizontalfield: true,
184
},
185
},
186
selfieWithNote: {
187
type: {
188
type: 'hidden',
189
},
190
proof_of_residency: {
191
type: 'file',
192
stringId:
193
'USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.SELFIE_PHOTO_ID_LABEL,USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.SELFIE_PHOTO_ID_PLACEHOLDER,USER_VERIFICATION.ID_DOCUMENTS_FORM.VALIDATIONS.SELFIE_PHOTO_ID',
194
label:
195
STRINGS[
196
'USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.SELFIE_PHOTO_ID_LABEL'
197
],
198
placeholder:
199
STRINGS[
200
'USER_VERIFICATION.ID_DOCUMENTS_FORM.FORM_FIELDS.SELFIE_PHOTO_ID_PLACEHOLDER'
201
],
202
validate: [
203
requiredWithCustomMessage(
204
STRINGS[
205
'USER_VERIFICATION.ID_DOCUMENTS_FORM.VALIDATIONS.SELFIE_PHOTO_ID'
206
]
207
),
208
],
209
fullWidth: isMobile,
210
ishorizontalfield: true,
211
},
212
},
213
};
214
215
this.setState({ formFields });
216
};
217
218
handleSubmit = (formValues) => {
219
const { moveToNextStep, setActivePageContent, updateDocuments } = this.props;
220
return updateDocuments(formValues)
221
.then(({ data }) => {
222
const values = {
223
type: formValues.type,
224
number: formValues.number,
225
expiration_date: formValues.expiration_date,
226
issued_date: formValues.issued_date,
227
status: 1,
228
};
229
230
moveToNextStep('documents', values);
231
setActivePageContent('email');
232
})
233
.catch((err) => {
234
const error = { _error: err.message };
235
if (err.response && err.response.data) {
236
error._error = err.response.data.message;
237
}
238
throw new SubmissionError(error);
239
});
240
};
241
242
onGoBack = () => {
243
const { setActivePageContent, handleBack } = this.props;
244
setActivePageContent('email');
245
handleBack('kyc');
246
};
247
248
render() {
249
const {
250
idData,
251
handleSubmit,
252
pristine,
253
submitting,
254
valid,
255
error,
256
// skip,
257
openContactForm,
258
icons: ICONS,
259
strings: STRINGS,
260
getErrorLocalized,
261
renderFields,
262
} = this.props;
263
const { formFields, accSize } = this.state;
264
const violated = accSize > sizeLimit;
265
return (
266
<div>
267
<IconTitle
268
stringId="USER_VERIFICATION.DOCUMENT_VERIFICATION"
269
text={STRINGS['USER_VERIFICATION.DOCUMENT_VERIFICATION']}
270
textType="title"
271
iconPath={ICONS['VERIFICATION_DOCUMENT_NEW']}
272
/>
273
<form
274
className="d-flex flex-column w-100 verification_content-form-wrapper"
275
onSubmit={this.handleSubmit}
276
>
277
<div className="verification-form-panel mt-3">
278
<HeaderSection
279
stringId="USER_VERIFICATION.DOCUMENT_PROOF_SUBMISSION"
280
title={STRINGS['USER_VERIFICATION.DOCUMENT_PROOF_SUBMISSION']}
281
openContactForm={openContactForm}
282
>
283
<IdentificationFormSection strings={STRINGS} />
284
</HeaderSection>
285
{renderFields(formFields.idDocument)}
286
{renderFields(formFields.id)}
287
</div>
288
<div className="my-4" />
289
290
<div className="verification-form-panel">
291
{formFields.proof_of_residency && (
292
<div>
293
<HeaderSection
294
stringId="USER_VERIFICATION.ID_DOCUMENTS_FORM.INFORMATION.PROOF_OF_RESIDENCY"
295
title={
296
STRINGS[
297
'USER_VERIFICATION.ID_DOCUMENTS_FORM.INFORMATION.PROOF_OF_RESIDENCY'
298
]
299
}
300
>
301
<PORSection strings={STRINGS}/>
302
</HeaderSection>
303
{renderFields(formFields.proof_of_residency)}
304
</div>
305
)}
306
</div>
307
<div className="my-4" />
308
309
<div className="verification-form-panel">
310
{formFields.selfieWithNote && (
311
<div>
312
<HeaderSection
313
stringId="USER_VERIFICATION.ID_DOCUMENTS_FORM.INFORMATION.SELFIE.TITLE"
314
title={
315
STRINGS[
316
'USER_VERIFICATION.ID_DOCUMENTS_FORM.INFORMATION.SELFIE.TITLE'
317
]
318
}
319
>
320
<SelfieWithPhotoId strings={STRINGS} />
321
</HeaderSection>
322
<div className="my-2">
323
<Image
324
alt="document-sample"
325
iconId="SELF_KYC_ID_EN"
326
icon={ICONS['SELF_KYC_ID_EN']}
327
wrapperClassName="verification_document-sample"
328
/>
329
</div>
330
{renderFields(formFields.selfieWithNote)}
331
</div>
332
)}
333
</div>
334
{error && (
335
<div className="warning_text">{getErrorLocalized(error)}</div>
336
)}
337
{
338
violated && (
339
<div className="warning_text">
340
<Editable stringId="USER_VERIFICATION.ID_DOCUMENTS_FORM.INFORMATION.ID_SECTION.VIOLATION_ERROR">
341
{STRINGS.formatString(STRINGS['USER_VERIFICATION.ID_DOCUMENTS_FORM.INFORMATION.ID_SECTION.VIOLATION_ERROR'], sizeLimitInMB)}
342
</Editable>
343
</div>
344
)
345
}
346
<div className="my-4" />
347
348
<div className="d-flex justify-content-center">
349
<div className="d-flex justify-content-end f-1 verification-buttons-wrapper">
350
<Button
351
type="button"
352
onClick={this.onGoBack}
353
label={STRINGS['USER_VERIFICATION.GO_BACK']}
354
disabled={submitting}
355
/>
356
</div>
357
<div className="