react-native-timacare 1.0.23 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/lib/commonjs/navigation/primary-navigator.js +1 -1
  2. package/lib/commonjs/navigation/primary-navigator.js.flow +9 -0
  3. package/lib/commonjs/navigation/primary-navigator.js.map +1 -1
  4. package/lib/commonjs/screens/detail-loan/DetailLoanTima.js +2 -0
  5. package/lib/commonjs/screens/detail-loan/DetailLoanTima.js.flow +342 -0
  6. package/lib/commonjs/screens/detail-loan/DetailLoanTima.js.map +1 -0
  7. package/lib/commonjs/screens/detail-loan/Info.js +1 -1
  8. package/lib/commonjs/screens/detail-loan/Info.js.flow +4 -2
  9. package/lib/commonjs/screens/detail-loan/Info.js.map +1 -1
  10. package/lib/commonjs/screens/detail-loan/index.js +1 -1
  11. package/lib/commonjs/screens/detail-loan/index.js.flow +2 -1
  12. package/lib/commonjs/screens/detail-loan/index.js.map +1 -1
  13. package/lib/commonjs/screens/home/index.js +1 -1
  14. package/lib/commonjs/screens/home/index.js.flow +281 -226
  15. package/lib/commonjs/screens/home/index.js.map +1 -1
  16. package/lib/commonjs/screens/liveness/LivenessStore.js +1 -1
  17. package/lib/commonjs/screens/liveness/LivenessStore.js.flow +30 -1
  18. package/lib/commonjs/screens/liveness/LivenessStore.js.map +1 -1
  19. package/lib/commonjs/screens/mrz-scanner/index.js +2 -0
  20. package/lib/commonjs/screens/mrz-scanner/index.js.flow +394 -0
  21. package/lib/commonjs/screens/mrz-scanner/index.js.map +1 -0
  22. package/lib/commonjs/screens/mrz-scanner/store.js +2 -0
  23. package/lib/commonjs/screens/mrz-scanner/store.js.flow +35 -0
  24. package/lib/commonjs/screens/mrz-scanner/store.js.map +1 -0
  25. package/lib/commonjs/screens/register/Store.js +1 -1
  26. package/lib/commonjs/screens/register/Store.js.flow +1 -1
  27. package/lib/commonjs/screens/terms/TermScreen.js +1 -1
  28. package/lib/commonjs/screens/terms/TermScreen.js.flow +114 -1
  29. package/lib/commonjs/screens/terms/TermScreen.js.map +1 -1
  30. package/lib/commonjs/services/api/api-config.js +1 -1
  31. package/lib/commonjs/services/api/api-config.js.flow +2 -2
  32. package/lib/commonjs/services/api/api-config.js.map +1 -1
  33. package/lib/commonjs/services/api/api.js +1 -1
  34. package/lib/commonjs/services/api/api.js.flow +56 -0
  35. package/lib/commonjs/services/api/api.js.map +1 -1
  36. package/lib/module/navigation/primary-navigator.js +1 -1
  37. package/lib/module/navigation/primary-navigator.js.map +1 -1
  38. package/lib/module/screens/detail-loan/DetailLoanTima.js +2 -0
  39. package/lib/module/screens/detail-loan/DetailLoanTima.js.map +1 -0
  40. package/lib/module/screens/detail-loan/Info.js +1 -1
  41. package/lib/module/screens/detail-loan/Info.js.map +1 -1
  42. package/lib/module/screens/detail-loan/index.js +1 -1
  43. package/lib/module/screens/detail-loan/index.js.map +1 -1
  44. package/lib/module/screens/home/index.js +1 -1
  45. package/lib/module/screens/home/index.js.map +1 -1
  46. package/lib/module/screens/liveness/LivenessStore.js +1 -1
  47. package/lib/module/screens/liveness/LivenessStore.js.map +1 -1
  48. package/lib/module/screens/mrz-scanner/index.js +2 -0
  49. package/lib/module/screens/mrz-scanner/index.js.map +1 -0
  50. package/lib/module/screens/mrz-scanner/store.js +2 -0
  51. package/lib/module/screens/mrz-scanner/store.js.map +1 -0
  52. package/lib/module/screens/register/Store.js +1 -1
  53. package/lib/module/screens/terms/TermScreen.js +1 -1
  54. package/lib/module/screens/terms/TermScreen.js.map +1 -1
  55. package/lib/module/services/api/api-config.js +1 -1
  56. package/lib/module/services/api/api-config.js.map +1 -1
  57. package/lib/module/services/api/api.js +1 -1
  58. package/lib/module/services/api/api.js.map +1 -1
  59. package/lib/typescript/navigation/primary-navigator.d.ts +2 -0
  60. package/lib/typescript/navigation/primary-navigator.d.ts.map +1 -1
  61. package/lib/typescript/screens/detail-loan/DetailLoanTima.d.ts +2 -0
  62. package/lib/typescript/screens/detail-loan/DetailLoanTima.d.ts.map +1 -0
  63. package/lib/typescript/screens/detail-loan/Info.d.ts.map +1 -1
  64. package/lib/typescript/screens/detail-loan/index.d.ts.map +1 -1
  65. package/lib/typescript/screens/home/index.d.ts.map +1 -1
  66. package/lib/typescript/screens/liveness/LivenessStore.d.ts +2 -0
  67. package/lib/typescript/screens/liveness/LivenessStore.d.ts.map +1 -1
  68. package/lib/typescript/screens/mrz-scanner/index.d.ts +3 -0
  69. package/lib/typescript/screens/mrz-scanner/index.d.ts.map +1 -0
  70. package/lib/typescript/screens/mrz-scanner/store.d.ts +8 -0
  71. package/lib/typescript/screens/mrz-scanner/store.d.ts.map +1 -0
  72. package/lib/typescript/screens/terms/TermScreen.d.ts.map +1 -1
  73. package/lib/typescript/services/api/api.d.ts +48 -0
  74. package/lib/typescript/services/api/api.d.ts.map +1 -1
  75. package/package.json +2 -1
  76. package/src/navigation/primary-navigator.tsx +9 -0
  77. package/src/screens/detail-loan/DetailLoanTima.tsx +342 -0
  78. package/src/screens/detail-loan/Info.tsx +4 -2
  79. package/src/screens/detail-loan/index.tsx +2 -1
  80. package/src/screens/home/index.tsx +281 -226
  81. package/src/screens/liveness/LivenessStore.tsx +30 -1
  82. package/src/screens/mrz-scanner/index.tsx +394 -0
  83. package/src/screens/mrz-scanner/store.ts +35 -0
  84. package/src/screens/register/Store.tsx +1 -1
  85. package/src/screens/terms/TermScreen.tsx +114 -1
  86. package/src/services/api/api-config.ts +2 -2
  87. package/src/services/api/api.ts +56 -0
@@ -1,5 +1,5 @@
1
1
  //@ts-nocheck
2
- import { observable, action } from 'mobx';
2
+ import { observable, action, makeAutoObservable } from 'mobx';
3
3
  import { useState } from 'react';
4
4
  import { Api } from '../../services/api';
5
5
  import { myLog } from '../../utils/log';
@@ -24,6 +24,10 @@ class Store {
24
24
 
25
25
  @observable ekycSuccess = false;
26
26
 
27
+ constructor() {
28
+ makeAutoObservable(this);
29
+ }
30
+
27
31
  @action
28
32
  async uploadLiveness(body, onSuccess?, onFailure?) {
29
33
  this.isLoading = true;
@@ -59,6 +63,31 @@ class Store {
59
63
  }
60
64
  }
61
65
  }
66
+
67
+ @action
68
+ async confirmLicense(loanId, onSuccess) {
69
+ try {
70
+ const response = await Api.getInstance().confirmRule(loanId);
71
+ if (response.kind === 'ok') {
72
+ if (response.data.meta.errorCode === 200) {
73
+ if (onSuccess) onSuccess();
74
+ } else {
75
+ Alert.alert('Thông báo', response.data.meta.errorMessage, [
76
+ {
77
+ text: 'Xác nhận',
78
+ onPress: () => {
79
+ if (onSuccess) onSuccess();
80
+ },
81
+ },
82
+ ]);
83
+ }
84
+ } else {
85
+ Alert.alert('Thông báo', 'Có lỗi không mong muốn xảy ra');
86
+ }
87
+ } catch (error) {
88
+ console.log();
89
+ }
90
+ }
62
91
  }
63
92
  const livenessStore = new Store();
64
93
  export default livenessStore;
@@ -0,0 +1,394 @@
1
+ //@ts-nocheck
2
+ import React, { useState, useEffect, useRef } from 'react';
3
+ import {
4
+ View,
5
+ Text,
6
+ Button,
7
+ StyleSheet,
8
+ PermissionsAndroid,
9
+ Platform,
10
+ Alert,
11
+ SafeAreaView,
12
+ TouchableOpacity,
13
+ NativeModules,
14
+ } from 'react-native';
15
+ import { StackActions, useNavigation } from '@react-navigation/native';
16
+ import { RNCamera } from 'react-native-camera';
17
+ import TextRecognition from 'react-native-text-recognition';
18
+ import {
19
+ openSettings,
20
+ PERMISSIONS,
21
+ request,
22
+ RESULTS,
23
+ } from 'react-native-permissions';
24
+ import { MText } from '../../components/MText';
25
+ import MButton from '../../components/MButton';
26
+ import { IconBackWhite } from '../../assets/icons';
27
+ import { commonStyles } from '../CommonStyles';
28
+ import nfcStore from './store';
29
+
30
+ const { NFCReader } = NativeModules;
31
+
32
+ const MRZScanner = (props: any) => {
33
+ const navigation = useNavigation();
34
+ const loan = props?.route?.params?.loan;
35
+
36
+ const [hasCameraPermission, setHasCameraPermission] = useState(null);
37
+ const [mrzData, setMrzData] = useState('');
38
+ const [passPermission, setPassPermission] = useState(false);
39
+ const cameraRef = useRef(null);
40
+
41
+ const requestPermissions = () => {
42
+ request(
43
+ Platform.OS === 'ios'
44
+ ? PERMISSIONS.IOS.CAMERA
45
+ : PERMISSIONS.ANDROID.CAMERA
46
+ ).then((result) => {
47
+ switch (result) {
48
+ case RESULTS.UNAVAILABLE:
49
+ console.log(
50
+ 'This feature is not available (on this device / in this context)'
51
+ );
52
+ Alert.alert(
53
+ 'Thông báo',
54
+ 'Máy ảnh trên thiết bị không tương thích.\nVui lòng kiểm tra lại thiết bị!',
55
+ [{ text: 'Đồng ý' }]
56
+ );
57
+ break;
58
+ case RESULTS.DENIED:
59
+ console.log(
60
+ 'The permission has not been requested / is denied but requestable'
61
+ );
62
+ Alert.alert(
63
+ 'Thông báo',
64
+ 'Bạn đã từ chối quyền máy ảnh. Vui lòng cấp quyền máy ảnh để tiếp tục!',
65
+ [
66
+ {
67
+ text: 'Đồng ý',
68
+ onPress: () => {
69
+ if (Platform.OS === 'ios') {
70
+ openSettings();
71
+ } else {
72
+ requestPermissions();
73
+ }
74
+ },
75
+ },
76
+ ]
77
+ );
78
+ break;
79
+ case RESULTS.LIMITED:
80
+ console.log('The permission is limited: some actions are possible');
81
+ Alert.alert(
82
+ 'Thông báo',
83
+ 'Quyền máy ảnh bị hạn chế. Vui lòng kiểm tra lại để tiếp tục!',
84
+ [
85
+ {
86
+ text: 'Đồng ý',
87
+ onPress: () => {
88
+ if (Platform.OS === 'ios') {
89
+ openSettings();
90
+ } else {
91
+ requestPermissions();
92
+ }
93
+ },
94
+ },
95
+ ]
96
+ );
97
+ break;
98
+ case RESULTS.GRANTED:
99
+ console.log('The permission is granted');
100
+ setPassPermission(true);
101
+ break;
102
+ case RESULTS.BLOCKED:
103
+ console.log('The permission is denied and not requestable anymore');
104
+ Alert.alert(
105
+ 'Thông báo',
106
+ 'Bạn đã từ chối quyền máy ảnh. Vui lòng cấp quyền máy ảnh để tiếp tục!',
107
+ [
108
+ {
109
+ text: 'Đồng ý',
110
+ onPress: () => {
111
+ if (Platform.OS === 'ios') {
112
+ openSettings();
113
+ } else {
114
+ openSettings();
115
+ }
116
+ },
117
+ },
118
+ ]
119
+ );
120
+ break;
121
+ }
122
+ });
123
+ };
124
+
125
+ useEffect(() => {
126
+ requestPermissions();
127
+ }, []);
128
+
129
+ const convertToDate = (input, end) => {
130
+ let yearPrefix = input.substring(0, 2);
131
+ let year = end
132
+ ? '20' + yearPrefix
133
+ : parseInt(yearPrefix) > 20
134
+ ? '19' + yearPrefix
135
+ : '20' + yearPrefix;
136
+ let month = input.substring(2, 4);
137
+ let day = input.substring(4, 6);
138
+
139
+ return year + '-' + month + '-' + day;
140
+ };
141
+
142
+ const extractMRZInfo = (text) => {
143
+ let documentNumber = '';
144
+ let birthDate = '';
145
+ let expirationDate = '';
146
+ const regex1 = /VNM(\d{9})/;
147
+ const match1 = text.match(regex1);
148
+
149
+ // If a match is found, return the 9 digits, otherwise return null
150
+ if (match1) {
151
+ documentNumber = match1[1];
152
+ }
153
+
154
+ console.log('documentNumber', documentNumber);
155
+
156
+ // Regular expression to match 'VNM' followed by 9 digits, then two 6-digit numbers
157
+ const regex = /(\d{6}).[MF](\d{6})/;
158
+
159
+ // Search for the pattern in the text
160
+ const match = text.replace(/ /g, '').match(regex);
161
+
162
+ // If a match is found, return the captured groups, otherwise return null
163
+ if (match) {
164
+ console.log({
165
+ documentNumber: documentNumber,
166
+ birthDate: match[1],
167
+ expirationDate: match[2],
168
+ });
169
+ (birthDate = match[1]), (expirationDate = match[2]);
170
+ } else {
171
+ return null;
172
+ }
173
+ if (documentNumber && birthDate && expirationDate) {
174
+ console.log(convertToDate(birthDate, false));
175
+ console.log(convertToDate(expirationDate, true));
176
+ try {
177
+ NFCReader.startNFCReader(
178
+ documentNumber,
179
+ convertToDate(birthDate, false),
180
+ convertToDate(expirationDate, true),
181
+ (error, response) => {
182
+ try {
183
+ const convertData = JSON.parse(response);
184
+ const body = {
185
+ LoanBriefId: loan?.id,
186
+ RawSod: convertData?.sod,
187
+ RawDg1: convertData?.dg1,
188
+ RawDg2: convertData?.dg2,
189
+ RawDg13: convertData?.dg13,
190
+ RawDg14: convertData?.dg14,
191
+ RawDg15: convertData?.dg15,
192
+ };
193
+ nfcStore.addNfcData(body, () => {
194
+ navigation.dispatch(
195
+ StackActions.push(ScreenNames.FullSubmit, {
196
+ loan: loan,
197
+ })
198
+ );
199
+ });
200
+ } catch (e) {
201
+ console.log(e);
202
+ Alert.alert('Lỗi', e);
203
+ }
204
+ }
205
+ );
206
+ } catch (e) {
207
+ console.log(e);
208
+ }
209
+ }
210
+ };
211
+
212
+ const handleTextRecognition = async (imagePath) => {
213
+ const result = await TextRecognition.recognize(imagePath);
214
+ const mrzText = result.join('');
215
+ setMrzData(mrzText);
216
+ console.log(extractMRZInfo(mrzText));
217
+ };
218
+
219
+ const takePicture = async () => {
220
+ if (cameraRef.current) {
221
+ const options = { quality: 0.8, base64: true };
222
+ const data = await cameraRef.current.takePictureAsync(options);
223
+ await handleTextRecognition(data.uri);
224
+ }
225
+ };
226
+
227
+ return (
228
+ <View style={styles.container}>
229
+ <RNCamera
230
+ ref={cameraRef}
231
+ style={styles.camera}
232
+ type={RNCamera.Constants.Type.back}
233
+ captureAudio={false}
234
+ ></RNCamera>
235
+ <View style={styles.overlay}>
236
+ <View style={styles.overlayTop} />
237
+ <View style={styles.overlayCenter}>
238
+ <View style={styles.overlayLeft} />
239
+ <View style={styles.overlayRect}></View>
240
+ <View style={styles.overlayRight} />
241
+ </View>
242
+ <View style={styles.overlayBottom} />
243
+ </View>
244
+
245
+ <View style={{ position: 'absolute', top: 0, left: 0 }}>
246
+ <SafeAreaView style={{ flex: 1 }}>
247
+ <View
248
+ style={[
249
+ commonStyles.row,
250
+ commonStyles.alignCenter,
251
+ { height: 56, paddingHorizontal: 16 },
252
+ ]}
253
+ >
254
+ <MButton
255
+ onPress={() => {
256
+ navigation.goBack();
257
+ }}
258
+ style={[{ width: 48, height: 48, justifyContent: 'center' }]}
259
+ >
260
+ <IconBackWhite />
261
+ </MButton>
262
+ <View style={{ flex: 1, paddingRight: 48 }}>
263
+ <MText
264
+ style={{
265
+ color: 'white',
266
+ fontSize: 16,
267
+ textAlign: 'center',
268
+ padding: 16,
269
+ fontWeight: '600',
270
+ }}
271
+ >
272
+ EKYC
273
+ </MText>
274
+ </View>
275
+ </View>
276
+ <MText
277
+ style={{
278
+ color: 'white',
279
+ fontSize: 16,
280
+ textAlign: 'center',
281
+ padding: 16,
282
+ }}
283
+ >
284
+ Dùng camera để quét chuỗi ký tự mặt sau thẻ CCCD gắn chip ở phía
285
+ dưới
286
+ </MText>
287
+ </SafeAreaView>
288
+ </View>
289
+ <View style={styles.buttonContainer}>
290
+ <MText
291
+ style={{
292
+ color: 'white',
293
+ fontSize: 14,
294
+ textAlign: 'center',
295
+ padding: 16,
296
+ }}
297
+ >
298
+ Vui lòng đặt giấy tờ nằm vừa khung hình chữ nhật, chụp đủ ánh sáng và
299
+ rõ nét.
300
+ </MText>
301
+ <TouchableOpacity
302
+ onPress={() => takePicture()}
303
+ style={styles.captureButton}
304
+ ></TouchableOpacity>
305
+ </View>
306
+ </View>
307
+ );
308
+ };
309
+ const styles = StyleSheet.create({
310
+ container: {
311
+ flex: 1,
312
+ },
313
+ camera: {
314
+ flex: 1,
315
+ },
316
+ buttonContainer: {
317
+ flex: 0,
318
+ flexDirection: 'column',
319
+ justifyContent: 'center',
320
+ alignItems: 'center',
321
+ position: 'absolute',
322
+ bottom: 40,
323
+ left: 0,
324
+ right: 0,
325
+ },
326
+ captureButton: {
327
+ width: 56,
328
+ height: 56,
329
+ borderRadius: 35,
330
+ backgroundColor: 'white',
331
+ justifyContent: 'center',
332
+ alignItems: 'center',
333
+ },
334
+ innerCaptureButton: {
335
+ width: 60,
336
+ height: 60,
337
+ borderRadius: 30,
338
+ backgroundColor: 'red',
339
+ },
340
+ overlay: {
341
+ position: 'absolute',
342
+ top: 0,
343
+ left: 0,
344
+ right: 0,
345
+ bottom: 0,
346
+ justifyContent: 'center',
347
+ alignItems: 'center',
348
+ },
349
+ overlayTop: {
350
+ flex: 1,
351
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
352
+ width: '100%',
353
+ },
354
+ overlayCenter: {
355
+ flexDirection: 'row',
356
+ },
357
+ overlayLeft: {
358
+ flex: 1,
359
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
360
+ },
361
+ overlayRect: {
362
+ width: '90%',
363
+ height: 100,
364
+ borderColor: 'white',
365
+ borderWidth: 2,
366
+ justifyContent: 'center',
367
+ alignItems: 'center',
368
+ },
369
+ instructionText: {
370
+ color: 'white',
371
+ textAlign: 'center',
372
+ paddingHorizontal: 10,
373
+ fontSize: 14,
374
+ position: 'absolute',
375
+ top: -50,
376
+ },
377
+ overlayRight: {
378
+ flex: 1,
379
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
380
+ },
381
+ overlayBottom: {
382
+ flex: 1,
383
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
384
+ width: '100%',
385
+ },
386
+ mrzContainer: {
387
+ padding: 10,
388
+ },
389
+ mrzText: {
390
+ fontSize: 16,
391
+ },
392
+ });
393
+
394
+ export default MRZScanner;
@@ -0,0 +1,35 @@
1
+ //@ts-nocheck
2
+ import { makeAutoObservable } from "mobx"
3
+ import { Api } from '../../services/api';
4
+ class Store {
5
+ isLoading = false
6
+
7
+ constructor() {
8
+ makeAutoObservable(this)
9
+ }
10
+
11
+ async addNfcData(body: any, onSuccess?: Function, onError?: Function) {
12
+ this.isLoading = true
13
+ try {
14
+ const response = await Api.getInstance().addNfcData(body)
15
+ this.isLoading = false
16
+ if (response.kind === "ok") {
17
+ if (response.data.meta.errorCode === 200) {
18
+ if (onSuccess) onSuccess()
19
+ } else {
20
+ Alert.alert("Thông báo", response.data.meta?.errorMessage)
21
+ if (onError) onError()
22
+ }
23
+ } else {
24
+ Alert.alert("Thông báo", "Có lỗi xảy ra. Vui lòng thử lại sau")
25
+ if (onError) onError()
26
+ }
27
+ } catch (error) {
28
+ console.log(error)
29
+ this.isLoading = false
30
+ }
31
+ }
32
+ }
33
+
34
+ const nfcStore = new Store()
35
+ export default nfcStore
@@ -8,7 +8,7 @@ import { save, USER } from '../../utils/storage';
8
8
  class Store {
9
9
  @observable isLoading = false;
10
10
  @observable isError = false;
11
- @observable type = 2;
11
+ @observable type = 3;
12
12
 
13
13
  @action
14
14
  async getOTP(params, onSuccess?) {
@@ -9,9 +9,14 @@ import MButton from '../../components/MButton';
9
9
  import { MText } from '../../components/MText';
10
10
  import { color } from '../../theme';
11
11
  import { IconBack } from '../../assets/icons';
12
+ import Pdf from 'react-native-pdf';
13
+ import LinearGradient from 'react-native-linear-gradient';
14
+ import livenessStore from '../liveness/LivenessStore';
12
15
 
13
16
  export const TermScreen = observer(function TermScreen(props) {
14
17
  const navigation = useNavigation();
18
+ const [isAccept, setIsAccept] = useState(true);
19
+ const loan = props?.route?.params;
15
20
 
16
21
  useEffect(() => {}, []);
17
22
 
@@ -59,10 +64,118 @@ export const TermScreen = observer(function TermScreen(props) {
59
64
  </MText>
60
65
  </View>
61
66
  <View style={{ backgroundColor: color.border }} />
62
- <WebView
67
+ {/* <WebView
63
68
  source={{ uri: 'https://tima.vn/dieu-khoan.html' }}
64
69
  style={{ flex: 1 }}
70
+ /> */}
71
+ <Pdf
72
+ source={{
73
+ uri: 'https://cdn.tima.vn/file-pdf/20240509_DIEU_KHOAN_VA_DIEU_KIEN_TIMA.pdf',
74
+ }}
75
+ style={[commonStyles.fill]}
65
76
  />
77
+ <View
78
+ style={{
79
+ backgroundColor: 'white',
80
+ paddingHorizontal: 24,
81
+ position: 'absolute',
82
+ bottom: 0,
83
+ left: 0,
84
+ right: 0,
85
+ paddingVertical: 16,
86
+ }}
87
+ >
88
+ <View
89
+ style={{
90
+ width: '100%',
91
+ alignItems: 'center',
92
+ flexDirection: 'row',
93
+ }}
94
+ >
95
+ <MButton
96
+ onPress={() => {
97
+ setIsAccept(!isAccept);
98
+ }}
99
+ >
100
+ {!isAccept ? <CheckBox /> : <CheckBoxActive />}
101
+ </MButton>
102
+ <MButton
103
+ style={{ flexDirection: 'row' }}
104
+ onPress={() => {
105
+ setIsAccept(!isAccept);
106
+ }}
107
+ >
108
+ <MText
109
+ style={{
110
+ marginLeft: 10,
111
+ color: '#1D1B1B',
112
+ fontSize: 14,
113
+ fontWeight: '400',
114
+ }}
115
+ >
116
+ Tôi đồng ý với các
117
+ </MText>
118
+
119
+ <MText
120
+ style={{
121
+ color: color.primary,
122
+ fontSize: 14,
123
+ fontWeight: '400',
124
+ }}
125
+ >
126
+ {' '}
127
+ điều khoản
128
+ </MText>
129
+ <MText
130
+ style={{
131
+ marginLeft: 4,
132
+ color: '#1D1B1B',
133
+ fontSize: 14,
134
+ fontWeight: '400',
135
+ }}
136
+ >
137
+ của Tima
138
+ </MText>
139
+ </MButton>
140
+ </View>
141
+ <TouchableOpacity
142
+ style={{
143
+ flex: 1,
144
+ width: '100%',
145
+ }}
146
+ disabled={!isAccept}
147
+ onPress={() => {
148
+ livenessStore.confirmLicense(loan?.id, () => {
149
+ navigation.goBack();
150
+ });
151
+ }}
152
+ >
153
+ <LinearGradient
154
+ style={{
155
+ height: 40,
156
+ marginVertical: 16,
157
+ borderRadius: 30,
158
+ alignItems: 'center',
159
+ justifyContent: 'center',
160
+ }}
161
+ colors={
162
+ isAccept ? ['#FF7A00', '#EF4123'] : ['#BDBDBD', '#BDBDBD']
163
+ }
164
+ >
165
+ <MText
166
+ style={[
167
+ commonStyles.textNormalBold,
168
+ {
169
+ color: true ? 'white' : '#333333',
170
+ textAlign: 'center',
171
+ },
172
+ ]}
173
+ >
174
+ {'xác nhận'.toUpperCase()}
175
+ </MText>
176
+ </LinearGradient>
177
+ </TouchableOpacity>
178
+ </View>
66
179
  </View>
67
180
  </SafeAreaView>
68
181
  </View>
@@ -1,5 +1,5 @@
1
- const API_URL = 'https://apiapplos.tima.vn/'
2
- // const API_URL = 'https://apidevlos.tima.vn/'
1
+ // const API_URL = 'https://apiapplos.tima.vn/'
2
+ const API_URL = 'https://apidevlos.tima.vn/'
3
3
  export interface ApiConfig {
4
4
  url: string
5
5
  timeout: number
@@ -2319,4 +2319,60 @@ export class Api {
2319
2319
  return { kind: "bad-data" }
2320
2320
  }
2321
2321
  }
2322
+
2323
+ async getPaymentScheduleTima(id) {
2324
+ // make the api call
2325
+ const response: ApiResponse<any> = await this.apisauce.get(`api/v2.0/loanbrief/payment_schedule_tima?loanBriefId=${id}`)
2326
+ myLog(response)
2327
+ // the typical ways to die when calling an api
2328
+ if (!response.ok) {
2329
+ const problem = getGeneralApiProblem(response)
2330
+ if (problem) return problem
2331
+ }
2332
+
2333
+ // transform the data into the format we are expecting
2334
+ try {
2335
+ return { kind: "ok", data: response.data }
2336
+ } catch {
2337
+ return { kind: "bad-data" }
2338
+ }
2339
+ }
2340
+
2341
+ async confirmRule(loandID) {
2342
+ // make the api call
2343
+ const response: ApiResponse<any> = await this.apisauce.post(`api/v2.0/loanbrief/log_confirm_tima_rules`, {
2344
+ LoanBriefId: loandID
2345
+ })
2346
+ myLog(response)
2347
+ // the typical ways to die when calling an api
2348
+ if (!response.ok) {
2349
+ const problem = getGeneralApiProblem(response)
2350
+ if (problem) return problem
2351
+ }
2352
+
2353
+ // transform the data into the format we are expecting
2354
+ try {
2355
+ return { kind: "ok", data: response.data }
2356
+ } catch {
2357
+ return { kind: "bad-data" }
2358
+ }
2359
+ }
2360
+
2361
+ async addNfcData(body: any) {
2362
+ // make the api call
2363
+ const response: ApiResponse<any> = await this.apisauce.post(`api/v1.0/timacare/add_nfc_raw`, body)
2364
+ myLog(response)
2365
+ // the typical ways to die when calling an api
2366
+ if (!response.ok) {
2367
+ const problem = getGeneralApiProblem(response)
2368
+ if (problem) return problem
2369
+ }
2370
+ // transform the data into the format we are expecting
2371
+ try {
2372
+ return { kind: "ok", data: response.data }
2373
+ } catch {
2374
+ return { kind: "bad-data" }
2375
+ }
2376
+ }
2377
+
2322
2378
  }