react-native-timacare 3.3.56-alert → 3.3.58-cccd

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 (211) hide show
  1. package/lib/commonjs/assets/icons/index.js +1 -1
  2. package/lib/commonjs/assets/icons/index.js.flow +2 -0
  3. package/lib/commonjs/assets/icons/index.js.map +1 -1
  4. package/lib/commonjs/assets/icons/modal_confirm.svg +5 -5
  5. package/lib/commonjs/assets/icons/modal_notice.svg +32 -32
  6. package/lib/commonjs/assets/icons/modal_success.svg +26 -26
  7. package/lib/commonjs/assets/icons/modal_warning.svg +21 -21
  8. package/lib/commonjs/assets/icons/user_security.svg +10 -0
  9. package/lib/commonjs/assets/tts/Frame1000011947.png +0 -0
  10. package/lib/commonjs/components/AlertLoan.js +1 -1
  11. package/lib/commonjs/components/AlertLoan.js.flow +1 -1
  12. package/lib/commonjs/components/AlertLoan.js.map +1 -1
  13. package/lib/commonjs/components/AppModal.js +1 -1
  14. package/lib/commonjs/components/AppModal.js.flow +40 -2
  15. package/lib/commonjs/components/AppModal.js.map +1 -1
  16. package/lib/commonjs/components/ItemTimaOne.js +1 -1
  17. package/lib/commonjs/components/ItemTimaOne.js.flow +1 -1
  18. package/lib/commonjs/components/ItemTimaOne.js.map +1 -1
  19. package/lib/commonjs/components/ModalNotification/AlertGlobal.js +1 -1
  20. package/lib/commonjs/components/ModalNotification/AlertGlobal.js.flow +92 -33
  21. package/lib/commonjs/components/ModalNotification/AlertGlobal.js.map +1 -1
  22. package/lib/commonjs/components/ModalNotification/index.js +1 -1
  23. package/lib/commonjs/components/ModalNotification/index.js.flow +7 -0
  24. package/lib/commonjs/components/ModalNotification/index.js.map +1 -1
  25. package/lib/commonjs/components/ModalOptionLoan.js +1 -1
  26. package/lib/commonjs/components/ModalOptionLoan.js.flow +1 -1
  27. package/lib/commonjs/components/ModalOptionLoan.js.map +1 -1
  28. package/lib/commonjs/components/ModalOptionLoanDigital.js +1 -1
  29. package/lib/commonjs/components/ModalOptionLoanDigital.js.flow +1 -1
  30. package/lib/commonjs/components/ModalOptionLoanDigital.js.map +1 -1
  31. package/lib/commonjs/components/modalStack.js +2 -0
  32. package/lib/commonjs/components/modalStack.js.flow +47 -0
  33. package/lib/commonjs/components/modalStack.js.map +1 -0
  34. package/lib/commonjs/navigation/primary-navigator.js +1 -1
  35. package/lib/commonjs/navigation/primary-navigator.js.flow +7 -0
  36. package/lib/commonjs/navigation/primary-navigator.js.map +1 -1
  37. package/lib/commonjs/screens/NFC/OcrStart.js +2 -0
  38. package/lib/commonjs/screens/NFC/OcrStart.js.flow +171 -0
  39. package/lib/commonjs/screens/NFC/OcrStart.js.map +1 -0
  40. package/lib/commonjs/screens/NFC/ScanMRZ.js +2 -0
  41. package/lib/commonjs/screens/NFC/ScanMRZ.js.flow +563 -0
  42. package/lib/commonjs/screens/NFC/ScanMRZ.js.map +1 -0
  43. package/lib/commonjs/screens/camera/CCCDCameraScreen.js +1 -1
  44. package/lib/commonjs/screens/camera/CCCDCameraScreen.js.flow +203 -133
  45. package/lib/commonjs/screens/camera/CCCDCameraScreen.js.map +1 -1
  46. package/lib/commonjs/screens/camera/index.js +1 -1
  47. package/lib/commonjs/screens/camera/index.js.flow +1 -1
  48. package/lib/commonjs/screens/camera/index.js.map +1 -1
  49. package/lib/commonjs/screens/detail-loan/PaymentInfo.js +1 -1
  50. package/lib/commonjs/screens/detail-loan/PaymentInfo.js.flow +1 -1
  51. package/lib/commonjs/screens/detail-loan/PaymentInfo.js.map +1 -1
  52. package/lib/commonjs/screens/detail-loan/ShowQrCode.js +1 -1
  53. package/lib/commonjs/screens/detail-loan/ShowQrCode.js.flow +1 -1
  54. package/lib/commonjs/screens/detail-loan/ShowQrCode.js.map +1 -1
  55. package/lib/commonjs/screens/digital-lending/Step6.js +1 -1
  56. package/lib/commonjs/screens/digital-lending/Step6.js.flow +1 -1
  57. package/lib/commonjs/screens/digital-lending/Step6.js.map +1 -1
  58. package/lib/commonjs/screens/eSign/index.js +1 -1
  59. package/lib/commonjs/screens/eSign/index.js.flow +1 -1
  60. package/lib/commonjs/screens/eSign/index.js.map +1 -1
  61. package/lib/commonjs/screens/home/DigitalTopupItem.js +1 -1
  62. package/lib/commonjs/screens/home/DigitalTopupItem.js.flow +1 -1
  63. package/lib/commonjs/screens/home/DigitalTopupItem.js.map +1 -1
  64. package/lib/commonjs/screens/home/ItemMotoBikeLoan.js +1 -1
  65. package/lib/commonjs/screens/home/ItemMotoBikeLoan.js.flow +1 -1
  66. package/lib/commonjs/screens/home/ItemMotoBikeLoan.js.map +1 -1
  67. package/lib/commonjs/screens/home/index.js +1 -1
  68. package/lib/commonjs/screens/home/index.js.flow +8 -113
  69. package/lib/commonjs/screens/home/index.js.map +1 -1
  70. package/lib/commonjs/screens/nationalID/index.js +1 -1
  71. package/lib/commonjs/screens/nationalID/index.js.flow +123 -218
  72. package/lib/commonjs/screens/nationalID/index.js.map +1 -1
  73. package/lib/commonjs/screens/nationalIDBack/index.js +1 -1
  74. package/lib/commonjs/screens/nationalIDBack/index.js.flow +129 -209
  75. package/lib/commonjs/screens/nationalIDBack/index.js.map +1 -1
  76. package/lib/commonjs/screens/payment-evidence/ModalGuideline.js +1 -1
  77. package/lib/commonjs/screens/payment-evidence/ModalGuideline.js.flow +1 -1
  78. package/lib/commonjs/screens/payment-evidence/ModalGuideline.js.map +1 -1
  79. package/lib/commonjs/screens/toan-trinh-so/OCR.js +1 -1
  80. package/lib/commonjs/screens/toan-trinh-so/OCR.js.flow +270 -556
  81. package/lib/commonjs/screens/toan-trinh-so/OCR.js.map +1 -1
  82. package/lib/commonjs/screens/toan-trinh-so/RegisterCamera.js +1 -1
  83. package/lib/commonjs/screens/toan-trinh-so/RegisterCamera.js.flow +1 -1
  84. package/lib/commonjs/screens/toan-trinh-so/RegisterCamera.js.map +1 -1
  85. package/lib/commonjs/screens/toan-trinh-so/VehicleCamera.js +1 -1
  86. package/lib/commonjs/screens/toan-trinh-so/VehicleCamera.js.flow +226 -288
  87. package/lib/commonjs/screens/toan-trinh-so/VehicleCamera.js.map +1 -1
  88. package/lib/commonjs/utils/cameraCrop.js +2 -0
  89. package/lib/commonjs/utils/cameraCrop.js.flow +96 -0
  90. package/lib/commonjs/utils/cameraCrop.js.map +1 -0
  91. package/lib/module/assets/icons/index.js +1 -1
  92. package/lib/module/assets/icons/index.js.map +1 -1
  93. package/lib/module/assets/icons/modal_confirm.svg +5 -5
  94. package/lib/module/assets/icons/modal_notice.svg +32 -32
  95. package/lib/module/assets/icons/modal_success.svg +26 -26
  96. package/lib/module/assets/icons/modal_warning.svg +21 -21
  97. package/lib/module/assets/icons/user_security.svg +10 -0
  98. package/lib/module/assets/tts/Frame1000011947.png +0 -0
  99. package/lib/module/components/AlertLoan.js +1 -1
  100. package/lib/module/components/AlertLoan.js.map +1 -1
  101. package/lib/module/components/AppModal.js +1 -1
  102. package/lib/module/components/AppModal.js.map +1 -1
  103. package/lib/module/components/ItemTimaOne.js +1 -1
  104. package/lib/module/components/ItemTimaOne.js.map +1 -1
  105. package/lib/module/components/ModalNotification/AlertGlobal.js +1 -1
  106. package/lib/module/components/ModalNotification/AlertGlobal.js.map +1 -1
  107. package/lib/module/components/ModalNotification/index.js +1 -1
  108. package/lib/module/components/ModalNotification/index.js.map +1 -1
  109. package/lib/module/components/ModalOptionLoan.js +1 -1
  110. package/lib/module/components/ModalOptionLoan.js.map +1 -1
  111. package/lib/module/components/ModalOptionLoanDigital.js +1 -1
  112. package/lib/module/components/ModalOptionLoanDigital.js.map +1 -1
  113. package/lib/module/components/modalStack.js +2 -0
  114. package/lib/module/components/modalStack.js.map +1 -0
  115. package/lib/module/navigation/primary-navigator.js +1 -1
  116. package/lib/module/navigation/primary-navigator.js.map +1 -1
  117. package/lib/module/screens/NFC/OcrStart.js +2 -0
  118. package/lib/module/screens/NFC/OcrStart.js.map +1 -0
  119. package/lib/module/screens/NFC/ScanMRZ.js +2 -0
  120. package/lib/module/screens/NFC/ScanMRZ.js.map +1 -0
  121. package/lib/module/screens/camera/CCCDCameraScreen.js +1 -1
  122. package/lib/module/screens/camera/CCCDCameraScreen.js.map +1 -1
  123. package/lib/module/screens/camera/index.js +1 -1
  124. package/lib/module/screens/camera/index.js.map +1 -1
  125. package/lib/module/screens/detail-loan/PaymentInfo.js +1 -1
  126. package/lib/module/screens/detail-loan/PaymentInfo.js.map +1 -1
  127. package/lib/module/screens/detail-loan/ShowQrCode.js +1 -1
  128. package/lib/module/screens/detail-loan/ShowQrCode.js.map +1 -1
  129. package/lib/module/screens/digital-lending/Step6.js +1 -1
  130. package/lib/module/screens/digital-lending/Step6.js.map +1 -1
  131. package/lib/module/screens/eSign/index.js +1 -1
  132. package/lib/module/screens/eSign/index.js.map +1 -1
  133. package/lib/module/screens/home/DigitalTopupItem.js +1 -1
  134. package/lib/module/screens/home/DigitalTopupItem.js.map +1 -1
  135. package/lib/module/screens/home/ItemMotoBikeLoan.js +1 -1
  136. package/lib/module/screens/home/ItemMotoBikeLoan.js.map +1 -1
  137. package/lib/module/screens/home/index.js +1 -1
  138. package/lib/module/screens/home/index.js.map +1 -1
  139. package/lib/module/screens/nationalID/index.js +1 -1
  140. package/lib/module/screens/nationalID/index.js.map +1 -1
  141. package/lib/module/screens/nationalIDBack/index.js +1 -1
  142. package/lib/module/screens/nationalIDBack/index.js.map +1 -1
  143. package/lib/module/screens/payment-evidence/ModalGuideline.js +1 -1
  144. package/lib/module/screens/payment-evidence/ModalGuideline.js.map +1 -1
  145. package/lib/module/screens/toan-trinh-so/OCR.js +1 -1
  146. package/lib/module/screens/toan-trinh-so/OCR.js.map +1 -1
  147. package/lib/module/screens/toan-trinh-so/RegisterCamera.js +1 -1
  148. package/lib/module/screens/toan-trinh-so/RegisterCamera.js.map +1 -1
  149. package/lib/module/screens/toan-trinh-so/VehicleCamera.js +1 -1
  150. package/lib/module/screens/toan-trinh-so/VehicleCamera.js.map +1 -1
  151. package/lib/module/utils/cameraCrop.js +2 -0
  152. package/lib/module/utils/cameraCrop.js.map +1 -0
  153. package/lib/typescript/assets/icons/index.d.ts +2 -1
  154. package/lib/typescript/assets/icons/index.d.ts.map +1 -1
  155. package/lib/typescript/components/AppModal.d.ts +6 -1
  156. package/lib/typescript/components/AppModal.d.ts.map +1 -1
  157. package/lib/typescript/components/ModalNotification/AlertGlobal.d.ts +20 -4
  158. package/lib/typescript/components/ModalNotification/AlertGlobal.d.ts.map +1 -1
  159. package/lib/typescript/components/ModalNotification/index.d.ts +6 -1
  160. package/lib/typescript/components/ModalNotification/index.d.ts.map +1 -1
  161. package/lib/typescript/components/modalStack.d.ts +11 -0
  162. package/lib/typescript/components/modalStack.d.ts.map +1 -0
  163. package/lib/typescript/navigation/primary-navigator.d.ts +3 -0
  164. package/lib/typescript/navigation/primary-navigator.d.ts.map +1 -1
  165. package/lib/typescript/screens/NFC/OcrStart.d.ts +2 -0
  166. package/lib/typescript/screens/NFC/OcrStart.d.ts.map +1 -0
  167. package/lib/typescript/screens/NFC/ScanMRZ.d.ts +15 -0
  168. package/lib/typescript/screens/NFC/ScanMRZ.d.ts.map +1 -0
  169. package/lib/typescript/screens/camera/CCCDCameraScreen.d.ts.map +1 -1
  170. package/lib/typescript/screens/home/index.d.ts.map +1 -1
  171. package/lib/typescript/screens/nationalID/index.d.ts.map +1 -1
  172. package/lib/typescript/screens/nationalIDBack/index.d.ts.map +1 -1
  173. package/lib/typescript/screens/toan-trinh-so/OCR.d.ts.map +1 -1
  174. package/lib/typescript/screens/toan-trinh-so/VehicleCamera.d.ts.map +1 -1
  175. package/lib/typescript/utils/cameraCrop.d.ts +43 -0
  176. package/lib/typescript/utils/cameraCrop.d.ts.map +1 -0
  177. package/package.json +2 -1
  178. package/src/assets/icons/index.tsx +2 -0
  179. package/src/assets/icons/modal_confirm.svg +5 -5
  180. package/src/assets/icons/modal_notice.svg +32 -32
  181. package/src/assets/icons/modal_success.svg +26 -26
  182. package/src/assets/icons/modal_warning.svg +21 -21
  183. package/src/assets/icons/user_security.svg +10 -0
  184. package/src/assets/tts/Frame1000011947.png +0 -0
  185. package/src/components/AlertLoan.tsx +1 -1
  186. package/src/components/AppModal.tsx +40 -2
  187. package/src/components/ItemTimaOne.tsx +1 -1
  188. package/src/components/ModalNotification/AlertGlobal.tsx +92 -33
  189. package/src/components/ModalNotification/index.tsx +7 -0
  190. package/src/components/ModalOptionLoan.tsx +1 -1
  191. package/src/components/ModalOptionLoanDigital.tsx +1 -1
  192. package/src/components/modalStack.ts +47 -0
  193. package/src/navigation/primary-navigator.tsx +7 -0
  194. package/src/screens/NFC/OcrStart.tsx +171 -0
  195. package/src/screens/NFC/ScanMRZ.tsx +563 -0
  196. package/src/screens/camera/CCCDCameraScreen.tsx +203 -133
  197. package/src/screens/camera/index.tsx +1 -1
  198. package/src/screens/detail-loan/PaymentInfo.tsx +1 -1
  199. package/src/screens/detail-loan/ShowQrCode.tsx +1 -1
  200. package/src/screens/digital-lending/Step6.tsx +1 -1
  201. package/src/screens/eSign/index.tsx +1 -1
  202. package/src/screens/home/DigitalTopupItem.tsx +1 -1
  203. package/src/screens/home/ItemMotoBikeLoan.tsx +1 -1
  204. package/src/screens/home/index.tsx +8 -113
  205. package/src/screens/nationalID/index.tsx +123 -218
  206. package/src/screens/nationalIDBack/index.tsx +129 -209
  207. package/src/screens/payment-evidence/ModalGuideline.tsx +1 -1
  208. package/src/screens/toan-trinh-so/OCR.tsx +270 -556
  209. package/src/screens/toan-trinh-so/RegisterCamera.tsx +1 -1
  210. package/src/screens/toan-trinh-so/VehicleCamera.tsx +226 -288
  211. package/src/utils/cameraCrop.ts +96 -0
@@ -1,8 +1,13 @@
1
1
  // @ts-nocheck
2
- import React, { useEffect, useRef, useState } from 'react';
2
+ import React, {
3
+ useCallback,
4
+ useEffect,
5
+ useMemo,
6
+ useRef,
7
+ useState,
8
+ } from 'react';
3
9
  import {
4
10
  ActivityIndicator,
5
- Dimensions,
6
11
  Platform,
7
12
  StyleSheet,
8
13
  TouchableOpacity,
@@ -10,10 +15,9 @@ import {
10
15
  } from 'react-native';
11
16
  import {
12
17
  Camera as VisionCamera,
13
- useCameraDevice,
14
- useCameraFormat,
18
+ useCameraDevices,
15
19
  } from 'react-native-vision-camera';
16
- import { IconBackWhite, TakePhotoSvg } from '../../assets/icons';
20
+ import { IconBack, TakePhotoSvg } from '../../assets/icons';
17
21
  import { MText } from '../../components/MText';
18
22
  import { AlertGlobal } from '../../components/ModalNotification/AlertGlobal';
19
23
  import { useNavigation, useIsFocused } from '@react-navigation/native';
@@ -25,31 +29,77 @@ import {
25
29
  RESULTS,
26
30
  openSettings,
27
31
  } from 'react-native-permissions';
32
+ import {
33
+ cropPhotoToAspect,
34
+ pickClosestFocusDevice,
35
+ } from '../../utils/cameraCrop';
36
+
37
+ const ORANGE = '#F05123';
38
+ // Thẻ CMND/CCCD theo chuẩn ID-1: 85.6mm x 54mm
39
+ const CARD_ASPECT_RATIO = 85.6 / 54;
40
+ // Cắt ảnh vừa đúng khung (khung dùng aspectRatio = CARD_ASPECT_RATIO)
41
+ const FRAME_ASPECT = CARD_ASPECT_RATIO;
28
42
 
29
43
  export default function CCCDCameraScreen(props) {
30
44
  const insets = useSafeAreaInsets();
31
45
  const navigation = useNavigation();
32
46
  const isFocused = useIsFocused();
33
47
  const myCamera = useRef(null);
48
+ const frameSize = useRef({ width: 0, height: 0 });
49
+ const focusTimer = useRef(null);
50
+ const takingRef = useRef(false);
34
51
  const [passPermission, setPassPermission] = useState(false);
35
52
  const [shouldRenderCamera, setShouldRenderCamera] = useState(false);
36
- const device = useCameraDevice('back');
37
- const format = useCameraFormat(device, [
38
- { photoResolution: { width: 1280, height: 720 } },
53
+ const [focusPoint, setFocusPoint] = useState(null);
54
+
55
+ // Chọn ống kính sau lấy nét gần nhất (macro) để chụp cận thẻ mà không mờ
56
+ const devices = useCameraDevices();
57
+ const device = useMemo(() => pickClosestFocusDevice(devices, 'back'), [
58
+ devices,
39
59
  ]);
40
60
 
61
+ // Lấy nét vào một điểm (toạ độ theo hệ của khung preview = camera view).
62
+ // Dùng cho chạm-để-lấy-nét và lấy nét giữa khung trước khi chụp -> tránh mờ
63
+ // khi đưa giấy tờ lại gần (camera không tự bám nét kịp).
64
+ const focusAt = useCallback(
65
+ async (x, y) => {
66
+ const cam = myCamera.current;
67
+ if (cam == null || !device?.supportsFocus) return;
68
+ setFocusPoint({ x, y });
69
+ if (focusTimer.current) clearTimeout(focusTimer.current);
70
+ focusTimer.current = setTimeout(() => setFocusPoint(null), 800);
71
+ try {
72
+ await cam.focus({ x, y });
73
+ } catch (e) {
74
+ // focus có thể lỗi nếu đang lấy nét dở hoặc điểm ngoài vùng -> bỏ qua
75
+ }
76
+ },
77
+ [device]
78
+ );
79
+
41
80
  const takePicture = async () => {
42
- if (myCamera.current == null) return;
81
+ if (myCamera.current == null || takingRef.current) return;
82
+ takingRef.current = true;
43
83
  try {
84
+ // Lấy nét giữa khung trước khi chụp để tài liệu ở gần vẫn nét
85
+ const { width: fw, height: fh } = frameSize.current;
86
+ if (device?.supportsFocus && fw && fh) {
87
+ try {
88
+ await myCamera.current.focus({ x: fw / 2, y: fh / 2 });
89
+ } catch (e) {}
90
+ }
44
91
  const data = await myCamera.current.takePhoto({
45
92
  qualityPrioritization: 'quality',
46
93
  });
94
+ // Cắt ảnh vừa đúng khung preview (giữ nguyên logic điều hướng bên dưới)
95
+ const uri = await cropPhotoToAspect(data, FRAME_ASPECT);
47
96
  navigation.goBack();
48
97
  if (props.route?.params?.callback) {
49
- props.route.params.callback('file://' + data.path);
98
+ props.route.params.callback(uri);
50
99
  }
51
100
  } catch (err) {
52
101
  console.error(err);
102
+ takingRef.current = false;
53
103
  }
54
104
  };
55
105
 
@@ -135,6 +185,9 @@ export default function CCCDCameraScreen(props) {
135
185
 
136
186
  useEffect(() => {
137
187
  requestPermissions();
188
+ return () => {
189
+ if (focusTimer.current) clearTimeout(focusTimer.current);
190
+ };
138
191
  }, []);
139
192
 
140
193
  useEffect(() => {
@@ -160,138 +213,155 @@ export default function CCCDCameraScreen(props) {
160
213
  }
161
214
 
162
215
  return (
163
- <View
164
- style={{ flex: 1, backgroundColor: 'black' }}
165
- pointerEvents={'box-none'}
166
- >
167
- <View
168
- style={[
169
- commonStyles.alignCenter,
170
- commonStyles.fill,
171
- commonStyles.justifyCenter,
172
- {
173
- position: 'absolute',
174
- width: Dimensions.get('window').width,
175
- height: Dimensions.get('window').height,
176
- },
177
- ]}
178
- >
179
- {device ? (
180
- <View style={$cameraFrame}>
181
- <VisionCamera
182
- ref={myCamera}
183
- style={StyleSheet.absoluteFill}
184
- device={device}
185
- isActive={true}
186
- photo={true}
187
- format={format}
188
- />
189
- </View>
190
- ) : (
191
- <ActivityIndicator />
192
- )}
193
- </View>
194
-
195
- <View style={[$back, { top: insets.top + 16 }]}>
216
+ <View style={styles.container}>
217
+ <View style={[styles.header, { paddingTop: insets.top + 16 }]}>
196
218
  <TouchableOpacity
197
- onPress={() => {
198
- navigation.goBack();
199
- }}
200
- style={{
201
- position: 'absolute',
202
- left: 0,
203
- width: 48,
204
- height: 48,
205
- zIndex: 1000,
206
- alignItems: 'center',
207
- }}
219
+ onPress={() => navigation.goBack()}
220
+ hitSlop={{ top: 12, bottom: 12, left: 12, right: 12 }}
208
221
  >
209
- <IconBackWhite />
222
+ <IconBack />
210
223
  </TouchableOpacity>
211
- <MText
212
- style={{
213
- textAlign: 'center',
214
- zIndex: 10,
215
- color: '#FFFFFF',
216
- fontSize: 16,
217
- }}
218
- >
219
- {props?.route?.params?.front
220
- ? 'Chụp CMND/ CCCD mặt trước'
221
- : 'Chụp CMND/ CCCD mặt sau'}
222
- </MText>
224
+ <View style={styles.titleWrap}>
225
+ <MText style={styles.headerTitle}>CMND / CCCD</MText>
226
+ </View>
223
227
  </View>
228
+
229
+ <MText style={styles.instruction}>
230
+ {props?.route?.params?.front
231
+ ? 'Chụp CMND/ CCCD mặt trước'
232
+ : 'Chụp CMND/ CCCD mặt sau'}
233
+ </MText>
234
+
235
+ {/* Khung tỉ lệ thẻ: vùng nhìn thấy của preview = vùng sẽ crop.
236
+ Chạm vào khung để lấy nét thủ công. */}
224
237
  <View
225
- style={{
226
- position: 'absolute',
227
- bottom: insets.bottom,
228
- alignSelf: 'center',
229
- flexDirection: 'column',
230
- alignItems: 'center',
238
+ style={styles.photoFrame}
239
+ onLayout={(e) => {
240
+ frameSize.current = e.nativeEvent.layout;
231
241
  }}
242
+ onStartShouldSetResponder={() => true}
243
+ onResponderRelease={(e) =>
244
+ focusAt(e.nativeEvent.locationX, e.nativeEvent.locationY)
245
+ }
232
246
  >
233
- <MText
234
- style={{
235
- color: '#fff',
236
- marginBottom: 16,
237
- textAlign: 'center',
238
- paddingHorizontal: 24,
239
- }}
240
- >
241
- Vui lòng đặt giấy tờ nằm vừa khung hình chữ nhật, chụp đủ ánh sáng và
242
- nét.
243
- </MText>
244
- <TouchableOpacity onPress={takePicture}>
245
- <TakePhotoSvg />
246
- </TouchableOpacity>
247
+ {device ? (
248
+ <VisionCamera
249
+ ref={myCamera}
250
+ style={StyleSheet.absoluteFill}
251
+ device={device}
252
+ isActive={isFocused}
253
+ photo={true}
254
+ />
255
+ ) : null}
256
+ <View style={[styles.corner, styles.cornerTL]} />
257
+ <View style={[styles.corner, styles.cornerTR]} />
258
+ <View style={[styles.corner, styles.cornerBL]} />
259
+ <View style={[styles.corner, styles.cornerBR]} />
260
+ {focusPoint && (
261
+ <View
262
+ pointerEvents="none"
263
+ style={[
264
+ styles.focusRing,
265
+ { left: focusPoint.x - 32, top: focusPoint.y - 32 },
266
+ ]}
267
+ />
268
+ )}
247
269
  </View>
270
+
271
+ <View style={styles.spacer} />
272
+ <MText style={[styles.hint, { marginTop: 0, marginBottom: 20 }]}>
273
+ Đưa giấy tờ lại gần cho vừa khung, chạm vào màn hình{'\n'}để lấy nét nếu
274
+ ảnh bị mờ.
275
+ </MText>
276
+ <TouchableOpacity
277
+ style={[styles.captureButton, { marginBottom: insets.bottom + 24 }]}
278
+ onPress={takePicture}
279
+ >
280
+ <TakePhotoSvg />
281
+ </TouchableOpacity>
248
282
  </View>
249
283
  );
250
284
  }
251
285
 
252
- const overlayColor = 'rgba(22, 22, 22, 0.7)';
253
- const $back: ViewStyle = {
254
- position: 'absolute',
255
- left: 0,
256
- right: 0,
257
- };
258
-
259
- const $cameraFrame: ViewStyle = {
260
- width: Dimensions.get('window').width,
261
- height: 260,
262
- overflow: 'hidden',
263
- backgroundColor: 'black',
264
- };
265
-
266
- const $overlay: ViewStyle = {
267
- ...StyleSheet.absoluteFillObject,
268
- justifyContent: 'center',
269
- alignItems: 'center',
270
- };
271
-
272
- const $container: ViewStyle = {
273
- flex: 1,
274
- backgroundColor: '#000',
275
- };
276
-
277
- const $row: ViewStyle = {
278
- flexDirection: 'row',
279
- alignItems: 'center',
280
- };
281
-
282
- const $darkOverlayTop: ViewStyle = {
283
- width: '100%',
284
- backgroundColor: overlayColor,
285
- };
286
-
287
- const $darkOverlayBottom: ViewStyle = {
288
- width: '100%',
289
- backgroundColor: overlayColor,
290
- };
291
- const $darkOverlaySide: ViewStyle = {
292
- backgroundColor: overlayColor,
293
- };
294
- const $frameBorder: ViewStyle = {
295
- // borderColor: '#FDFDFD',
296
- // borderWidth: 2,
297
- };
286
+ const styles = StyleSheet.create({
287
+ container: { flex: 1, backgroundColor: '#FFFFFF' },
288
+ header: {
289
+ flexDirection: 'row',
290
+ alignItems: 'center',
291
+ paddingHorizontal: 16,
292
+ paddingTop: 8,
293
+ },
294
+ titleWrap: {
295
+ flex: 1,
296
+ alignItems: 'center',
297
+ justifyContent: 'center',
298
+ marginRight: 24,
299
+ },
300
+ headerTitle: { color: '#333333', fontSize: 16, fontWeight: '600' },
301
+ instruction: {
302
+ textAlign: 'center',
303
+ color: '#333333',
304
+ fontSize: 14,
305
+ lineHeight: 20,
306
+ marginTop: 20,
307
+ marginBottom: 28,
308
+ },
309
+ photoFrame: {
310
+ marginHorizontal: 24,
311
+ aspectRatio: CARD_ASPECT_RATIO,
312
+ borderRadius: 8,
313
+ overflow: 'hidden',
314
+ backgroundColor: '#000000',
315
+ },
316
+ corner: {
317
+ position: 'absolute',
318
+ width: 26,
319
+ height: 26,
320
+ borderColor: ORANGE,
321
+ },
322
+ focusRing: {
323
+ position: 'absolute',
324
+ width: 64,
325
+ height: 64,
326
+ borderRadius: 8,
327
+ borderWidth: 1.5,
328
+ borderColor: '#FFD54A',
329
+ },
330
+ cornerTL: {
331
+ top: 0,
332
+ left: 0,
333
+ borderTopWidth: 4,
334
+ borderLeftWidth: 4,
335
+ borderTopLeftRadius: 8,
336
+ },
337
+ cornerTR: {
338
+ top: 0,
339
+ right: 0,
340
+ borderTopWidth: 4,
341
+ borderRightWidth: 4,
342
+ borderTopRightRadius: 8,
343
+ },
344
+ cornerBL: {
345
+ bottom: 0,
346
+ left: 0,
347
+ borderBottomWidth: 4,
348
+ borderLeftWidth: 4,
349
+ borderBottomLeftRadius: 8,
350
+ },
351
+ cornerBR: {
352
+ bottom: 0,
353
+ right: 0,
354
+ borderBottomWidth: 4,
355
+ borderRightWidth: 4,
356
+ borderBottomRightRadius: 8,
357
+ },
358
+ hint: {
359
+ textAlign: 'center',
360
+ color: '#555555',
361
+ fontSize: 13,
362
+ lineHeight: 19,
363
+ marginTop: 48,
364
+ },
365
+ spacer: { flex: 1 },
366
+ captureButton: { alignSelf: 'center' },
367
+ });
@@ -50,7 +50,7 @@ import { Svg, Circle, Defs, ClipPath, Rect } from 'react-native-svg';
50
50
  import Store from './Store';
51
51
  import { MText } from '../../components/MText';
52
52
  import { AlertGlobal } from '../../components/ModalNotification/AlertGlobal';
53
- import Modal from 'react-native-modal';
53
+ import Modal from '../../components/AppModal';
54
54
  import LinearGradient from 'react-native-linear-gradient';
55
55
  import RNFS from 'react-native-fs';
56
56
 
@@ -35,7 +35,7 @@ import MHeader from '../../components/MHeader';
35
35
  import ReactNativeBlobUtil from 'react-native-blob-util';
36
36
  import { CameraRoll } from '@react-native-camera-roll/camera-roll';
37
37
  import moment from 'moment';
38
- import ReactNativeModal from 'react-native-modal';
38
+ import ReactNativeModal from '../../components/AppModal';
39
39
  import LinearGradient from 'react-native-linear-gradient';
40
40
  import {
41
41
  TourGuideProvider, // Main provider
@@ -28,7 +28,7 @@ import { CameraRoll } from '@react-native-camera-roll/camera-roll';
28
28
  import ReactNativeBlobUtil from 'react-native-blob-util';
29
29
  import { formatMoney } from '../../utils';
30
30
  import MHeader from '../../components/MHeader';
31
- import ReactNativeModal from 'react-native-modal';
31
+ import ReactNativeModal from '../../components/AppModal';
32
32
  import LinearGradient from 'react-native-linear-gradient';
33
33
  import moment from 'moment';
34
34
  import {
@@ -24,7 +24,7 @@ import {
24
24
  import { MText } from '../../components/MText';
25
25
  import digitalLendingStore from './store';
26
26
  import { ScreenNames } from '../../navigation';
27
- import Modal from 'react-native-modal';
27
+ import Modal from '../../components/AppModal';
28
28
  import { AlertGlobal } from '../../components/ModalNotification/AlertGlobal';
29
29
 
30
30
  export const Step6 = observer(function Step6() {
@@ -31,7 +31,7 @@ import Slack from 'react-native-slack-webhook';
31
31
  import homeStore from '../home/Store';
32
32
  import appStore from '../../AppStore';
33
33
  import Pdf from 'react-native-pdf';
34
- import Modal from 'react-native-modal';
34
+ import Modal from '../../components/AppModal';
35
35
  import KeyboardSpacer from '../../components/keyboardspace';
36
36
  import Loading from '../../components/Loading';
37
37
  import MHeader from '../../components/MHeader';
@@ -12,7 +12,7 @@ import LinearGradient from 'react-native-linear-gradient';
12
12
  import { IconMoney2, IconQuestion, IconTick } from '../../assets/svgs';
13
13
  import { formatMoney } from '../../utils';
14
14
  import { MText } from '../../components/MText';
15
- import Modal from 'react-native-modal';
15
+ import Modal from '../../components/AppModal';
16
16
  import {
17
17
  IconStep1,
18
18
  IconStep1Disable,
@@ -22,7 +22,7 @@ import {
22
22
  } from '../../assets/v3';
23
23
  import { ScreenNames } from '../../navigation';
24
24
  import { CheckBox, CheckBoxActive, Close2Icon, Info } from '../../assets/icons';
25
- import Modal from 'react-native-modal';
25
+ import Modal from '../../components/AppModal';
26
26
  import { Api } from '../../services/api';
27
27
  import { AlertGlobal } from '../../components/ModalNotification/AlertGlobal';
28
28
 
@@ -11,22 +11,16 @@ import {
11
11
  RefreshControl,
12
12
  SafeAreaView,
13
13
  ScrollView,
14
- StatusBar,
15
14
  StyleSheet,
16
15
  TouchableOpacity,
17
16
  View,
18
- ViewStyle,
19
17
  } from 'react-native';
20
- import {
21
- useNavigation,
22
- StackActions,
23
- CommonActions,
24
- } from '@react-navigation/native';
18
+ import { useNavigation, StackActions } from '@react-navigation/native';
25
19
  import { observer, Observer } from 'mobx-react-lite';
26
20
  import { commonStyles } from '../CommonStyles';
27
21
  import { MText } from '../../components/MText';
28
22
  import { color } from '../../theme';
29
- import { diffDays, formatDDMMYYY, formatMoney } from '../../utils';
23
+ import { formatDDMMYYY, formatMoney } from '../../utils';
30
24
  import homeStore from './Store';
31
25
  import { ScreenNames } from '../../navigation';
32
26
  import {
@@ -37,40 +31,25 @@ import {
37
31
  CheckBoxActive,
38
32
  CIMBSmall,
39
33
  Close2Icon,
40
- CloseIcon,
41
34
  Contract,
42
35
  ContractActive,
43
36
  ContractTimeIcon,
44
- IconBackWhite,
45
37
  IconEviden,
46
- IconNavClose,
47
- IconNotify,
48
38
  IconSchedule,
49
- IconSign,
50
39
  IconSign2,
51
40
  IconVideo,
52
41
  Info,
53
42
  LogoSmall,
54
43
  NotFoundSvg,
55
- OcrSvg,
56
- SignDisable,
57
- TimaNormal,
58
- TopupSuccessSvg,
59
44
  TopupSvg,
60
45
  UpdateIcon,
61
46
  } from '../../assets/icons';
62
47
  import Geolocation from 'react-native-geolocation-service';
63
- import axios from 'axios';
64
- import {
65
- getUniqueId,
66
- getManufacturer,
67
- getDeviceId,
68
- } from 'react-native-device-info';
48
+
69
49
  import FullSubmitStore from '../full-submit/store';
70
50
  import QuickSubmitStore from '../quick-submit/store';
71
51
  import LinearGradient from 'react-native-linear-gradient';
72
- import { SliderBox } from 'react-native-image-slider-box';
73
- import notificationStore from '../notification/store';
52
+
74
53
  import {
75
54
  openSettings,
76
55
  PERMISSIONS,
@@ -78,7 +57,7 @@ import {
78
57
  RESULTS,
79
58
  } from 'react-native-permissions';
80
59
  import appStore from '../../AppStore';
81
- import Modal from 'react-native-modal';
60
+ import Modal from '../../components/AppModal';
82
61
  import Pdf from 'react-native-pdf';
83
62
  import { Api } from '../../services/api';
84
63
  import { load, save } from '../../utils/storage';
@@ -87,24 +66,7 @@ import SkeletonLoanList, {
87
66
  } from '../../components/SkeletonLoanCard';
88
67
  import MButton from '../../components/MButton';
89
68
  import ttsStore from '../toan-trinh-so/store';
90
- import {
91
- IconOCRSuccess,
92
- IconEdit,
93
- IconEditSuccess,
94
- IconEkyc,
95
- IconEkycSuccess,
96
- IconEkycDisable,
97
- IconSignDisable,
98
- IconTima16,
99
- IconExpand,
100
- IconExpandUp,
101
- IconSignSuccess,
102
- IconMoney2,
103
- IconEditDisable,
104
- IconTick,
105
- IconOcr,
106
- } from '../../assets/svgs';
107
- import { o } from 'ramda';
69
+ import { IconMoney2 } from '../../assets/svgs';
108
70
  import ItemTimaOne from '../../components/ItemTimaOne';
109
71
  import ModalOptionLoan from '../../components/ModalOptionLoan';
110
72
  import AlertLoan from '../../components/AlertLoan';
@@ -114,21 +76,11 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
114
76
  import ItemMotoBikeLoan from './ItemMotoBikeLoan';
115
77
  import BoxGuidline from './BoxGuidline';
116
78
  import { AlertGlobal } from '../../components/ModalNotification/AlertGlobal';
117
-
118
- const listBanners = [
119
- require('../../assets/img/banner1.png'),
120
- require('../../assets/img/banner2.png'),
121
- ];
122
-
123
- const $action: ViewStyle = {
124
- flexDirection: 'column',
125
- alignItems: 'center',
126
- };
79
+ import MHeader from '../../components/MHeader';
127
80
 
128
81
  // Gradient cam thương hiệu, dùng lặp lại ở nhiều nút trong màn hình
129
82
  const GRADIENT_ORANGE = ['#FF8E4F', '#EF592E'];
130
83
 
131
- let _unsubscribe;
132
84
  // Dữ liệu tham chiếu tĩnh (ngân hàng, nghề nghiệp, tỉnh...) chỉ cần prefetch 1 lần/phiên
133
85
  let _didPrefetchRefData = false;
134
86
 
@@ -161,7 +113,6 @@ export const Home = observer(function Home() {
161
113
  // Hành động điều hướng chờ chạy SAU khi modal đóng hẳn (onModalHide)
162
114
  const pendingNavRef = React.useRef<(() => void) | null>(null);
163
115
  const [listLoan, setListLoan] = useState<any[]>([]);
164
- const [checkEKYC, setCheckEKYC] = useState<any>({});
165
116
  const [isLoading, setIsLoading] = useState(false);
166
117
  const [loanCimb, setLoanCimb] = useState(null);
167
118
  const [loan, setLoan] = useState(null);
@@ -594,63 +545,7 @@ export const Home = observer(function Home() {
594
545
  <View
595
546
  style={[commonStyles.fill, { zIndex: 1, backgroundColor: '#FFFFFF' }]}
596
547
  >
597
- <LinearGradient colors={GRADIENT_ORANGE}>
598
- <View style={{ marginTop: insets.top + 16 }}>
599
- <View
600
- style={{
601
- flexDirection: 'row',
602
- paddingHorizontal: 16,
603
- alignItems: 'center',
604
- justifyContent: 'space-between',
605
- paddingBottom: 8,
606
- }}
607
- >
608
- <MText
609
- style={{
610
- fontWeight: 'bold',
611
- color: 'white',
612
- fontSize: 14,
613
- }}
614
- >
615
- Vay Online 24/7
616
- </MText>
617
- <View
618
- style={{
619
- borderWidth: 1,
620
- borderColor: 'white',
621
- flexDirection: 'row',
622
- borderRadius: 16,
623
- height: 30,
624
- alignItems: 'center',
625
- }}
626
- >
627
- <TouchableOpacity
628
- style={{
629
- paddingHorizontal: 10,
630
- }}
631
- onPress={() => {
632
- Linking.openURL(`tel:1900633688`);
633
- }}
634
- >
635
- <Call />
636
- </TouchableOpacity>
637
- <View
638
- style={{ width: 1, height: 30, backgroundColor: 'white' }}
639
- />
640
- <TouchableOpacity
641
- style={{
642
- paddingHorizontal: 10,
643
- }}
644
- onPress={() => {
645
- navigation.navigate('MyBank.Main');
646
- }}
647
- >
648
- <CloseIcon />
649
- </TouchableOpacity>
650
- </View>
651
- </View>
652
- </View>
653
- </LinearGradient>
548
+ <MHeader title="Vay Online 24/7" />
654
549
  <ScrollView
655
550
  refreshControl={
656
551
  <RefreshControl