· 6 years ago · Mar 05, 2020, 08:18 AM
1import { Radio, Layout, Row, Col, Upload, Button, Icon, Spin, Form,Input, notification, Typography, Dropdown, Menu } from 'antd'
2import moment from 'moment'
3import React from 'react'
4import axios from 'axios'
5const { Header, Footer, Content} = Layout
6const { Title } = Typography
7const api_feedback = 'https://endpointh.eyeq.tech'
8const api = api_feedback
9
10
11const menu = (
12 <Menu>
13 <Menu.Item>
14 <a target="_blank" rel="noopener noreferrer" href="https://ekycdemo.eyeq.tech/?utm_source=ocrdemo.eyeq.tech&utm_medium=cpc&utm_campaign=websitetraffictracking">
15 eKYC Demo
16 </a>
17 </Menu.Item>
18 <Menu.Item>
19 <a target="_blank" rel="noopener noreferrer" href="https://ocrdemo.eyeq.tech/?utm_source=ocrdemo.eyeq.tech&utm_medium=cpc&utm_campaign=websitetraffictracking">
20 OCR Demo
21 </a>
22 </Menu.Item>
23 <Menu.Item>
24 <a target="_blank" rel="noopener noreferrer" href="https://ekycbatch.eyeq.tech/?utm_source=ocrdemo.eyeq.tech&utm_medium=cpc&utm_campaign=websitetraffictracking">
25 eKYC Batch
26 </a>
27 </Menu.Item>
28 </Menu>
29 );
30
31export default class Home extends React.Component {
32 isValidDate = (str) => {
33 var d = moment(str,'D/M/YYYY');
34 if(d == null || !d.isValid()) return false;
35
36 return str.indexOf(d.format('D/M/YYYY')) >= 0
37 || str.indexOf(d.format('DD/MM/YYYY')) >= 0
38 || str.indexOf(d.format('D/M/YY')) >= 0
39 || str.indexOf(d.format('DD/MM/YY')) >= 0;
40 }
41 isAllNum = (str) => {
42 for (var i = 0; i < str.length; i++) {
43 if (!('0' <= str[i] && str[i] <= '9')) {
44 return false;
45 }
46 }
47 return true;
48 }
49 validData = (data) => {
50 var errors = ''
51 if (data['id'] && !((data['id'].length == 9 || data['id'].length == 12) && this.isAllNum(data['id']))) {
52 errors += 'id, '
53 }
54 if (data['birthday'] && !this.isValidDate(data['birthday'].replace(new RegExp('-', 'g'),'/'))) {
55 errors += 'birthday, '
56 }
57 if (data['issue_date'] && !this.isValidDate(data['issue_date'].replace(new RegExp('-', 'g'),'/'))) {
58 errors += 'issue_date, '
59 }
60 if (errors.length > 0) {
61 errors = errors.slice(0, errors.length - 2)
62 }
63 return errors
64
65 }
66 constructor(props) {
67 super(props)
68 this.state = {
69 uploadingFront: false,
70 uploadingBack: false,
71 frontImage: 'https://ispyvisuals.com/wp-content/themes/ispy/images/placeholder-image.png',
72 backImage: 'https://ispyvisuals.com/wp-content/themes/ispy/images/placeholder-image.png',
73 documentFront: 'OLD ID',
74 documentBack: 'OLD ID',
75 document: 'OLD ID',
76 frontFace: null,
77 backFace: null,
78 currentDBidFront: null,
79 currentDBidBack: null,
80 res: {address: '', birthday: '', district: '', ethnicity: '', expiry: '', id: '', id_type: '', idconf: '', issue_by: '', issue_date: '', name: '', precinct: '', religion: '', sex:'', street: '', street_name: ''},
81 client: {address: '', birthday: '', district: '', ethnicity: '', expiry: '', id: '', id_type: '', idconf: '', issue_by: '', issue_date: '', name: '', precinct: '', religion: '', sex:'', street: '', street_name: ''}
82 }
83 }
84
85 getBase64 = (file, cb) => {
86 let reader = new FileReader();
87 reader.readAsDataURL(file);
88 reader.onload = function () {
89 cb(reader.result)
90 };
91 reader.onerror = function (error) {
92 console.log('Error: ', error);
93 };
94 }
95 handleBeforeUploadFront = (e) => {
96 this.setState({uploadingFront: true})
97 this.getBase64(e, (res) => this.setState({frontImage: res}))
98 }
99 handleBeforeUploadBack = (e) => {
100 this.setState({uploadingBack: true})
101 this.getBase64(e, (res) => this.setState({backImage: res}))
102 }
103 handleChange = (e) => {
104 // console.log(e)
105 if (e.file.status != 'done') return
106 var new_data = e.file.response.data.data
107 var id = e.file.response.id
108 var current_state=this.state.res
109 var current_client=this.state.client
110 for (var key in new_data) {
111 if (new_data[key] != 'N/A') {
112 current_state[key] = new_data[key]
113 current_client[key] = new_data[key]
114 }
115 }
116 if (e.file.response.data.data.id_type == 0) {
117 this.setState({currentDBidFront: id})
118 } else {
119 this.setState({currentDBidBack: id})
120 }
121 this.setState({client: current_client, res: current_state})
122 }
123 handleChangeFront = (e) => {
124 // console.log(e)
125 if (e.file.status != 'done') {
126 var newRes = this.state.res
127 var newCli = this.state.client
128 var frontSideAttr = ['id', 'name', 'birthday', 'sex', 'expiry', 'address']
129 frontSideAttr.forEach(v => {
130 newRes[v] = ''
131 newCli[v] = ''
132 })
133 this.setState({res: newRes, client: newCli, currentDBidFront: null})
134 return
135 }
136
137 this.setState({uploadingFront: false})
138
139 if (e.file.response.message == 'failed') {
140 notification["error"]({
141 message: 'Error',
142 description:
143 "Can't detect the card.\nPlease try zooming in/out or cropping the image.",
144 });
145 return
146 }
147
148 var id_type = e.file.response.data.data.id_type
149 if (id_type != 0) {
150 notification["error"]({
151 message: 'Error',
152 description:
153 'The file you uploaded is not the front side ! Please upload it in the right section !',
154 });
155 return
156 }
157 var new_data = e.file.response.data.data
158 var id = e.file.response.id
159 var current_state=this.state.res
160 var current_client=this.state.client
161 for (var key in new_data) {
162 if (new_data[key] != 'N/A') {
163 current_state[key] = new_data[key]
164 current_client[key] = new_data[key]
165 }
166 }
167
168 this.setState({currentDBidFront: id, documentFront: e.file.response.data.document})
169 this.setState({client: current_client, res: current_state})
170 }
171 handleChangeBack = (e) => {
172 // console.log(e)
173 if (e.file.status != 'done') {
174 var newRes = this.state.res
175 var newCli = this.state.client
176 var backSideAttr = ['issue_by', 'issue_date', 'ethnicity', 'religion']
177 backSideAttr.forEach(v => {
178 newRes[v] = ''
179 newCli[v] = ''
180 })
181
182 this.setState({res: newRes, client: newCli, currentDBidBack: null})
183 return
184 }
185
186 this.setState({uploadingBack: false})
187
188 if (e.file.response.message == 'failed') {
189 notification["error"]({
190 message: 'Error',
191 description:
192 "Can't detect the card. Please try again ! (zoom in the card).",
193 });
194 return
195 }
196
197 var id_type = e.file.response.data.data.id_type
198 if (id_type != 1) {
199 notification["error"]({
200 message: 'Error',
201 description:
202 'The file you uploaded is not the back side ! Please upload it in the right section !',
203 });
204 return
205 }
206 var new_data = e.file.response.data.data
207 var id = e.file.response.id
208 var current_state=this.state.res
209 var current_client=this.state.client
210 for (var key in new_data) {
211 if (new_data[key] != 'N/A') {
212 current_state[key] = new_data[key]
213 current_client[key] = new_data[key]
214 }
215 }
216 this.setState({currentDBidBack: id, documentBack: e.file.response.data.document})
217 this.setState({client: current_client, res: current_state})
218 }
219 handleRadioGroupChangeFront = (e) => {
220 this.setState({documentFront: e.target.value})
221 }
222 handleRadioGroupChangeBack = (e) => {
223 this.setState({documentBack: e.target.value})
224 }
225 handleInputChange = (e) => {
226 var inputValue = e.target.value
227 var inputName = e.target.name
228 var new_client_result = this.state.client
229 new_client_result[inputName] = inputValue
230 this.setState({client: new_client_result})
231 }
232 handleSubmitClientFront = (e) => {
233 if (!this.state.currentDBidFront) {
234 notification["error"]({
235 message: 'Error',
236 description:
237 'Please upload front side image!',
238 });
239 return
240 }
241 const {id, name, birthday, address, sex, expiry} = this.state.client
242 var data = {id: id, name: name, birthday: birthday, address: address}
243 if (sex && expiry) {
244 data.sex = sex
245 data.expiry = expiry
246 }
247 var errors = this.validData(data)
248 if (errors.length == 0) {
249 axios.post(api_feedback + '/ocr/feedback', {id: this.state.currentDBidFront, client_result: data})
250 .then(res => {
251 if (res.data === 'OK') {
252 notification["success"]({
253 message: 'Success',
254 description:
255 'Saved',
256 });
257 } else {
258 notification["error"]({
259 message: 'Lỗi',
260 description:
261 'Đã có lỗi',
262 });
263 }
264 })
265 } else {
266 notification["error"]({
267 message: 'Lỗi',
268 description:
269 `These fields is invalid: ${errors}`,
270 });
271 }
272 }
273 handleSubmitClientBack = (e) => {
274 if (!this.state.currentDBidBack) {
275 notification["error"]({
276 message: 'Error',
277 description:
278 'Please upload back side image !',
279 });
280 return
281 }
282 const {religion, ethnicity, issue_by, issue_date} = this.state.client
283 var data = {religion: religion, ethnicity: ethnicity, issue_by: issue_by, issue_date: issue_date}
284 axios.post(api_feedback + '/ocr/feedback', {id: this.state.currentDBidBack, client_result: data})
285 .then(res => {
286 if (res.data === 'OK') {
287 notification["success"]({
288 message: 'Thành công',
289 description:
290 'Đã lưu',
291 });
292 } else {
293 notification["error"]({
294 message: 'Lỗi',
295 description:
296 'Đã có lỗi',
297 });
298 }
299 })
300 }
301 render () {
302 return (
303 <div>
304 <Layout style={{marginBottom: '12px'}}>
305 <Header style={{backgroundColor: '#2194EA', display: 'flex', flexDirection: 'row', alignItems: 'center'}}>
306 <Dropdown overlay={menu} placement="bottomLeft">
307 <Icon style={{ fontSize: '25px', color: '#fff', marginRight: `30px` }} type="menu" />
308 </Dropdown>
309 <img src="https://eyeq.tech/wp-content/themes/eyeq-theme/img/logo_white.svg" height="60%"></img>
310 </Header>
311 <Content style={{ padding: '50px' }}>
312 <Layout style={{ padding: '24px', background: '#fff' }}>
313 <Row gutter={32}>
314 <Col md={8}>
315 <Title level={2}>Front Side</Title>
316 <Radio.Group defaultValue={this.state.documentFront} buttonStyle="solid" onChange={this.handleRadioGroupChangeFront}>
317 <Radio.Button value="OLD ID">CMND</Radio.Button>
318 <Radio.Button value="NEW ID">Căn cước công dân</Radio.Button>
319 </Radio.Group>
320 <img style={{width: '100%', marginBottom: '10px', marginTop: '10px'}} src={this.state.frontImage}></img>
321 <Upload
322 disabled={this.state.uploadingFront}
323 showUploadList = {false}
324 beforeUpload={this.handleBeforeUploadFront}
325 action={api + '/ocr'}
326 name="front"
327 data={{caller: 'ocr', document: this.state.document}}
328 onChange = {this.handleChangeFront}
329 >
330 <Button>
331 <Icon type="upload" /> Upload
332 </Button>
333 </Upload>
334 {this.state.uploadingFront && <Spin style={{marginLeft: `10px`}}/>}
335 </Col>
336 <Col md={8}>
337 <Title level={2}>AI's Result</Title>
338 <Title level={4}>Result from our AI. </Title>
339 <Form>
340 <Form.Item label="Số CMND">
341 <Input disabled={true} value={this.state.res.id}/>
342 </Form.Item>
343 <Row gutter={8}>
344 <Col span={16}>
345 <Form.Item label="Họ và tên">
346 <Input disabled={true} value={this.state.res.name} />
347 </Form.Item>
348 </Col>
349 <Col span={8}>
350 <Form.Item label="Ngày sinh">
351 <Input disabled={true} value={this.state.res.birthday}/>
352 </Form.Item>
353 </Col>
354 </Row>
355 {this.state.documentFront === 'NEW ID' &&
356 <Row gutter={8}>
357 <Col span={12}>
358 <Form.Item label="Giới tính">
359 <Input disabled={true} value={this.state.res.sex}/>
360 </Form.Item>
361 </Col>
362 <Col span={12}>
363 <Form.Item label="Ngày hết hạn">
364 <Input disabled={true} value={this.state.res.expiry}/>
365 </Form.Item>
366 </Col>
367 </Row>
368 }
369 <Form.Item label="Nơi ĐKHKTT">
370 <Input disabled={true} value={this.state.res.address}/>
371 </Form.Item>
372 </Form>
373 </Col>
374 <Col md={8}>
375 <Title level={2}>Wrong Results ?</Title>
376 <Title level={4}>Please help us by filling the form below. </Title>
377 <Form>
378 <Form.Item label="Số CMND">
379 <Input value={this.state.client.id} onChange={this.handleInputChange} name="id"/>
380 </Form.Item>
381 <Row gutter={8}>
382 <Col span={16}>
383 <Form.Item label="Họ và tên">
384 <Input value={this.state.client.name} onChange={this.handleInputChange} name="name"/>
385 </Form.Item>
386 </Col>
387 <Col span={8}>
388 <Form.Item label="Ngày sinh">
389 <Input value={this.state.client.birthday} onChange={this.handleInputChange} name="birthday"/>
390 </Form.Item>
391 </Col>
392 </Row>
393 {this.state.documentFront === 'NEW ID' &&
394 <Row gutter={8}>
395 <Col span={12}>
396 <Form.Item label="Giới tính">
397 <Input value={this.state.client.sex} onChange={this.handleInputChange} name="sex"/>
398 </Form.Item>
399 </Col>
400 <Col span={12}>
401 <Form.Item label="Ngày hết hạn">
402 <Input value={this.state.res.expiry}/>
403 </Form.Item>
404 </Col>
405 </Row>
406 }
407 <Form.Item label="Nơi ĐKHKTT">
408 <Input value={this.state.client.address} onChange={this.handleInputChange} name="address"/>
409 </Form.Item>
410 <Button disabled={!this.state.currentDBidFront} type="primary" onClick={this.handleSubmitClientFront}>Save</Button>
411 </Form>
412 </Col>
413 </Row>
414 </Layout>
415 <Layout style={{ padding: '24px', marginTop: '16px', background: '#fff' }}>
416 <Row gutter={32}>
417 <Col md={8}>
418 <Title level={2}>Back Side</Title>
419 <Radio.Group defaultValue={this.state.documentBack} buttonStyle="solid" onChange={this.handleRadioGroupChangeBack}>
420 <Radio.Button value="OLD ID">CMND</Radio.Button>
421 <Radio.Button value="NEW ID">Căn cước công dân</Radio.Button>
422 </Radio.Group>
423 <img style={{width: '100%', marginBottom: '10px', marginTop: '10px'}} src={this.state.backImage}></img>
424 <Upload
425 disabled={this.state.uploadingBack}
426 showUploadList = {false}
427 beforeUpload={this.handleBeforeUploadBack}
428 action={api + '/ocr'}
429 name="back"
430 data={{caller: 'ocr', document: this.state.document}}
431 onChange = {this.handleChangeBack}
432 >
433 <Button>
434 <Icon type="upload" /> Upload
435 </Button>
436 </Upload>
437 {this.state.uploadingBack && <Spin style={{marginLeft: `10px`}}/>}
438 </Col>
439 <Col md={8}>
440 <Title level={2}>AI's Result</Title>
441 <Title level={4}>Result from our AI.</Title>
442 <Form>
443 {/* <Row gutter={8}>
444 <Col span={12}>
445 <Form.Item label="Dân tộc">
446 <Input disabled={true} value={this.state.res.ethnicity}/>
447 </Form.Item>
448 </Col>
449 <Col span={12}>
450 <Form.Item label="Tôn giáo">
451 <Input disabled={true} value={this.state.res.religion}/>
452 </Form.Item>
453 </Col>
454 </Row> */}
455 <Row gutter={8}>
456 <Col span={12}>
457 <Form.Item label="Cấp bởi">
458 <Input disabled={true} value={this.state.res.issue_by}/>
459 </Form.Item>
460 </Col>
461 <Col span={12}>
462 <Form.Item label="Ngày cấp">
463 <Input disabled={true} value={this.state.res.issue_date}/>
464 </Form.Item>
465 </Col>
466 </Row>
467 </Form>
468 </Col>
469 <Col md={8}>
470 <Title level={2}>Wrong Results ?</Title>
471 <Title level={4}>Please help us by filling the form below. </Title>
472 <Form>
473 {/* <Row gutter={8}>
474 <Col span={12}>
475 <Form.Item label="Dân tộc">
476 <Input value={this.state.client.ethnicity} onChange={this.handleInputChange} name="ethnicity"/>
477 </Form.Item>
478 </Col>
479 <Col span={12}>
480 <Form.Item label="Tôn giáo">
481 <Input value={this.state.client.religion} onChange={this.handleInputChange} name="religion"/>
482 </Form.Item>
483 </Col>
484 </Row> */}
485 <Row gutter={8}>
486 <Col span={12}>
487 <Form.Item label="Cấp bởi">
488 <Input value={this.state.client.issue_by} onChange={this.handleInputChange} name="issue_by"/>
489 </Form.Item>
490 </Col>
491 <Col span={12}>
492 <Form.Item label="Ngày cấp">
493 <Input value={this.state.client.issue_date} onChange={this.handleInputChange} name="issue_date"/>
494 </Form.Item>
495 </Col>
496 </Row>
497 <Button disabled={!this.state.currentDBidBack} type="primary" onClick={this.handleSubmitClientBack}>Save</Button>
498 </Form>
499 </Col>
500 </Row>
501 </Layout>
502 </Content>
503 <Footer style={{textAlign: 'center'}}>
504 EyeQ Tech - 2019
505 </Footer>
506 </Layout>
507 </div>
508 )
509 }
510}