react-native-timacare 3.3.64 → 3.3.66
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.
- package/lib/commonjs/components/AlertLoan.js +1 -1
- package/lib/commonjs/components/AlertLoan.js.flow +12 -2
- package/lib/commonjs/components/AlertLoan.js.map +1 -1
- package/lib/commonjs/components/ItemTimaOne.js +1 -1
- package/lib/commonjs/components/ItemTimaOne.js.flow +2 -0
- package/lib/commonjs/components/ItemTimaOne.js.map +1 -1
- package/lib/commonjs/navigation/primary-navigator.js +1 -1
- package/lib/commonjs/navigation/primary-navigator.js.flow +9 -0
- package/lib/commonjs/navigation/primary-navigator.js.map +1 -1
- package/lib/commonjs/screens/full-submit/selfie.js +1 -1
- package/lib/commonjs/screens/full-submit/selfie.js.flow +257 -114
- package/lib/commonjs/screens/full-submit/selfie.js.map +1 -1
- package/lib/commonjs/screens/motobike/InfoLoanMotobike.js +1 -1
- package/lib/commonjs/screens/motobike/InfoLoanMotobike.js.flow +3 -2
- package/lib/commonjs/screens/motobike/InfoLoanMotobike.js.map +1 -1
- package/lib/commonjs/screens/motobike/ReviewLoanMotobike.js +1 -1
- package/lib/commonjs/screens/motobike/ReviewLoanMotobike.js.flow +1 -0
- package/lib/commonjs/screens/motobike/ReviewLoanMotobike.js.map +1 -1
- package/lib/commonjs/screens/selfie/SelfieCamera.js +2 -0
- package/lib/commonjs/screens/selfie/SelfieCamera.js.flow +302 -0
- package/lib/commonjs/screens/selfie/SelfieCamera.js.map +1 -0
- package/lib/commonjs/screens/selfie/index.js +1 -1
- package/lib/commonjs/screens/selfie/index.js.flow +295 -165
- package/lib/commonjs/screens/selfie/index.js.map +1 -1
- package/lib/commonjs/screens/toan-trinh-so/ReviewInformation.js +1 -1
- package/lib/commonjs/screens/toan-trinh-so/ReviewInformation.js.flow +1 -0
- package/lib/commonjs/screens/toan-trinh-so/ReviewInformation.js.map +1 -1
- package/lib/commonjs/screens/toan-trinh-so/ReviewInformationOther.js +1 -1
- package/lib/commonjs/screens/toan-trinh-so/ReviewInformationOther.js.flow +1 -0
- package/lib/commonjs/screens/toan-trinh-so/ReviewInformationOther.js.map +1 -1
- package/lib/commonjs/screens/toan-trinh-so/ReviewLoan.js +1 -1
- package/lib/commonjs/screens/toan-trinh-so/ReviewLoan.js.flow +1 -0
- package/lib/commonjs/screens/toan-trinh-so/ReviewLoan.js.map +1 -1
- package/lib/commonjs/screens/toan-trinh-so/TopupLoanInfo.js +1 -1
- package/lib/commonjs/screens/toan-trinh-so/TopupLoanInfo.js.flow +8 -5
- package/lib/commonjs/screens/toan-trinh-so/TopupLoanInfo.js.map +1 -1
- package/lib/commonjs/screens/v3/AssetInformation.js +1 -1
- package/lib/commonjs/screens/v3/AssetInformation.js.flow +1 -0
- package/lib/commonjs/screens/v3/AssetInformation.js.map +1 -1
- package/lib/commonjs/screens/v3/ReviewInfoLoanBuyCar.js +2 -0
- package/lib/commonjs/screens/v3/ReviewInfoLoanBuyCar.js.flow +522 -0
- package/lib/commonjs/screens/v3/ReviewInfoLoanBuyCar.js.map +1 -0
- package/lib/commonjs/services/api/api.js +1 -1
- package/lib/commonjs/services/api/api.js.flow +41 -7
- package/lib/commonjs/services/api/api.js.map +1 -1
- package/lib/module/components/AlertLoan.js +1 -1
- package/lib/module/components/AlertLoan.js.map +1 -1
- package/lib/module/components/ItemTimaOne.js +1 -1
- package/lib/module/components/ItemTimaOne.js.map +1 -1
- package/lib/module/navigation/primary-navigator.js +1 -1
- package/lib/module/navigation/primary-navigator.js.map +1 -1
- package/lib/module/screens/full-submit/selfie.js +1 -1
- package/lib/module/screens/full-submit/selfie.js.map +1 -1
- package/lib/module/screens/motobike/InfoLoanMotobike.js +1 -1
- package/lib/module/screens/motobike/InfoLoanMotobike.js.map +1 -1
- package/lib/module/screens/motobike/ReviewLoanMotobike.js +1 -1
- package/lib/module/screens/motobike/ReviewLoanMotobike.js.map +1 -1
- package/lib/module/screens/selfie/SelfieCamera.js +2 -0
- package/lib/module/screens/selfie/SelfieCamera.js.map +1 -0
- package/lib/module/screens/selfie/index.js +1 -1
- package/lib/module/screens/selfie/index.js.map +1 -1
- package/lib/module/screens/toan-trinh-so/ReviewInformation.js +1 -1
- package/lib/module/screens/toan-trinh-so/ReviewInformation.js.map +1 -1
- package/lib/module/screens/toan-trinh-so/ReviewInformationOther.js +1 -1
- package/lib/module/screens/toan-trinh-so/ReviewInformationOther.js.map +1 -1
- package/lib/module/screens/toan-trinh-so/ReviewLoan.js +1 -1
- package/lib/module/screens/toan-trinh-so/ReviewLoan.js.map +1 -1
- package/lib/module/screens/toan-trinh-so/TopupLoanInfo.js +1 -1
- package/lib/module/screens/toan-trinh-so/TopupLoanInfo.js.map +1 -1
- package/lib/module/screens/v3/AssetInformation.js +1 -1
- package/lib/module/screens/v3/AssetInformation.js.map +1 -1
- package/lib/module/screens/v3/ReviewInfoLoanBuyCar.js +2 -0
- package/lib/module/screens/v3/ReviewInfoLoanBuyCar.js.map +1 -0
- package/lib/module/services/api/api.js +1 -1
- package/lib/module/services/api/api.js.map +1 -1
- package/lib/typescript/components/AlertLoan.d.ts.map +1 -1
- package/lib/typescript/components/ItemTimaOne.d.ts.map +1 -1
- package/lib/typescript/navigation/primary-navigator.d.ts +2 -0
- package/lib/typescript/navigation/primary-navigator.d.ts.map +1 -1
- package/lib/typescript/screens/full-submit/selfie.d.ts.map +1 -1
- package/lib/typescript/screens/selfie/SelfieCamera.d.ts +2 -0
- package/lib/typescript/screens/selfie/SelfieCamera.d.ts.map +1 -0
- package/lib/typescript/screens/selfie/index.d.ts.map +1 -1
- package/lib/typescript/screens/toan-trinh-so/TopupLoanInfo.d.ts.map +1 -1
- package/lib/typescript/screens/v3/ReviewInfoLoanBuyCar.d.ts +2 -0
- package/lib/typescript/screens/v3/ReviewInfoLoanBuyCar.d.ts.map +1 -0
- package/lib/typescript/services/api/api.d.ts +32 -0
- package/lib/typescript/services/api/api.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/AlertLoan.tsx +12 -2
- package/src/components/ItemTimaOne.tsx +2 -0
- package/src/navigation/primary-navigator.tsx +9 -0
- package/src/screens/full-submit/selfie.tsx +257 -114
- package/src/screens/motobike/InfoLoanMotobike.tsx +3 -2
- package/src/screens/motobike/ReviewLoanMotobike.tsx +1 -0
- package/src/screens/selfie/SelfieCamera.tsx +302 -0
- package/src/screens/selfie/index.tsx +295 -165
- package/src/screens/toan-trinh-so/ReviewInformation.tsx +1 -0
- package/src/screens/toan-trinh-so/ReviewInformationOther.tsx +1 -0
- package/src/screens/toan-trinh-so/ReviewLoan.tsx +1 -0
- package/src/screens/toan-trinh-so/TopupLoanInfo.tsx +8 -5
- package/src/screens/v3/AssetInformation.tsx +1 -0
- package/src/screens/v3/ReviewInfoLoanBuyCar.tsx +522 -0
- package/src/services/api/api.ts +41 -7
|
@@ -1,33 +1,26 @@
|
|
|
1
1
|
//@ts-nocheck
|
|
2
|
-
import React, {
|
|
2
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
3
3
|
import {
|
|
4
4
|
ActivityIndicator,
|
|
5
|
-
|
|
5
|
+
Animated,
|
|
6
|
+
Easing,
|
|
6
7
|
Image,
|
|
7
|
-
ImageStyle,
|
|
8
|
-
Platform,
|
|
9
8
|
SafeAreaView,
|
|
10
9
|
ScrollView,
|
|
11
|
-
|
|
10
|
+
StyleSheet,
|
|
12
11
|
View,
|
|
13
|
-
ViewStyle,
|
|
14
12
|
} from 'react-native';
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
StackActions,
|
|
19
|
-
} from '@react-navigation/native';
|
|
20
|
-
import { observer, Observer } from 'mobx-react-lite';
|
|
13
|
+
import { useNavigation, StackActions } from '@react-navigation/native';
|
|
14
|
+
import { observer } from 'mobx-react-lite';
|
|
15
|
+
import LinearGradient from 'react-native-linear-gradient';
|
|
21
16
|
import { commonStyles } from '../CommonStyles';
|
|
22
|
-
import KeyboardSpacer from '../../components/keyboardspace';
|
|
23
17
|
import MButton from '../../components/MButton';
|
|
24
|
-
import { color } from '../../theme';
|
|
25
18
|
import { MText } from '../../components/MText';
|
|
26
19
|
import {
|
|
27
20
|
CIMBBank,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
IConCamera,
|
|
22
|
+
Tick2,
|
|
23
|
+
TimaSmall,
|
|
31
24
|
TimaSmallWhite,
|
|
32
25
|
} from '../../assets/icons';
|
|
33
26
|
import { ScreenNames } from '../../navigation';
|
|
@@ -35,36 +28,55 @@ import appStore from '../../AppStore';
|
|
|
35
28
|
import selfieStore from './SelfieStore';
|
|
36
29
|
import nationalIDStore from '../nationalID/Store';
|
|
37
30
|
import Loading from '../../components/Loading';
|
|
38
|
-
import LinearGradient from 'react-native-linear-gradient';
|
|
39
|
-
import livenessStore from '../liveness/LivenessStore';
|
|
40
31
|
import MHeader from '../../components/MHeader';
|
|
41
32
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
33
|
+
// require() ở module scope: không phải resolve lại asset mỗi lần render
|
|
34
|
+
const BACKGROUND = require('../../assets/img/EKYC.png');
|
|
35
|
+
const PLACEHOLDER = require('../../assets/img/selfie.png');
|
|
36
|
+
|
|
37
|
+
// Khung dọc 3:4 - đúng tỉ lệ ảnh máy ảnh trước trả về nên ảnh khách chụp
|
|
38
|
+
// không bị cắt, và khớp với khung ở màn CimbSelfie
|
|
39
|
+
const PREVIEW_ASPECT = 3 / 4;
|
|
40
|
+
|
|
41
|
+
const NOTES = [
|
|
42
|
+
'Nhìn thẳng vào máy ảnh, khuôn mặt nằm gọn trong khung hình',
|
|
43
|
+
'Chụp nơi đủ sáng, tránh ngược sáng hoặc bóng đổ lên mặt',
|
|
44
|
+
'Không đeo kính, khẩu trang, mũ và để lộ rõ đường nét khuôn mặt',
|
|
45
|
+
];
|
|
48
46
|
|
|
49
47
|
export const Selfie = observer(function Selfie(props: any) {
|
|
50
48
|
const navigation = useNavigation();
|
|
51
|
-
const step = 3;
|
|
52
49
|
const [isLoading, setIsLoading] = useState(false);
|
|
53
50
|
const [photo, setPhoto] = useState(null);
|
|
54
|
-
|
|
51
|
+
// Chặn double-submit: setIsLoading là bất đồng bộ nên hai lần bấm liên tiếp
|
|
52
|
+
// vẫn lọt qua được nếu chỉ dựa vào state.
|
|
53
|
+
const submitting = useRef(false);
|
|
55
54
|
const loan = props.route.params?.loan;
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
// Ảnh vừa chụp hiện lên bằng fade + scale nhẹ để người dùng thấy rõ là khung
|
|
57
|
+
// ảnh đã đổi nội dung (trước đây ảnh thay thầm lặng, dễ tưởng chưa chụp được)
|
|
58
|
+
const reveal = useRef(new Animated.Value(1)).current;
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
if (!photo) return;
|
|
61
|
+
reveal.setValue(0);
|
|
62
|
+
Animated.timing(reveal, {
|
|
63
|
+
toValue: 1,
|
|
64
|
+
duration: 260,
|
|
65
|
+
easing: Easing.out(Easing.cubic),
|
|
66
|
+
useNativeDriver: true,
|
|
67
|
+
}).start();
|
|
68
|
+
}, [photo, reveal]);
|
|
69
|
+
|
|
70
|
+
const nextStep = useCallback(() => {
|
|
71
|
+
if (!photo || submitting.current) return;
|
|
72
|
+
submitting.current = true;
|
|
59
73
|
setIsLoading(true);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
form.append('TypeDocumentId', 125);
|
|
67
|
-
form.append('UploadFrom', 3);
|
|
74
|
+
|
|
75
|
+
const stopLoading = () => {
|
|
76
|
+
submitting.current = false;
|
|
77
|
+
setIsLoading(false);
|
|
78
|
+
};
|
|
79
|
+
|
|
68
80
|
const formSelfie = new FormData();
|
|
69
81
|
formSelfie.append('NationalCard', {
|
|
70
82
|
uri: nationalIDStore.photo,
|
|
@@ -81,171 +93,289 @@ export const Selfie = observer(function Selfie(props: any) {
|
|
|
81
93
|
formSelfie,
|
|
82
94
|
loan.id,
|
|
83
95
|
() => {
|
|
96
|
+
// Chỉ dựng form upload khi ảnh đã qua bước đối chiếu
|
|
97
|
+
const form = new FormData();
|
|
98
|
+
form.append('images', {
|
|
99
|
+
uri: photo,
|
|
100
|
+
type: 'image/jpg',
|
|
101
|
+
name: 'image.jpg',
|
|
102
|
+
});
|
|
103
|
+
form.append('loanbriefId', loan.id);
|
|
104
|
+
form.append('TypeDocumentId', 125);
|
|
105
|
+
form.append('UploadFrom', 3);
|
|
106
|
+
|
|
84
107
|
selfieStore.uploadImage(
|
|
85
108
|
form,
|
|
86
109
|
() => {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
StackActions.push(ScreenNames.LiveNess, { loan })
|
|
92
|
-
);
|
|
93
|
-
} else {
|
|
94
|
-
navigation.dispatch(
|
|
95
|
-
StackActions.push(ScreenNames.LivenessV2, { loan })
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
});
|
|
110
|
+
stopLoading();
|
|
111
|
+
navigation.dispatch(
|
|
112
|
+
StackActions.push(ScreenNames.LivenessV2, { loan })
|
|
113
|
+
);
|
|
99
114
|
},
|
|
100
|
-
|
|
101
|
-
setIsLoading(false);
|
|
102
|
-
}
|
|
115
|
+
stopLoading
|
|
103
116
|
);
|
|
104
117
|
},
|
|
105
|
-
|
|
106
|
-
setIsLoading(false);
|
|
107
|
-
}
|
|
118
|
+
stopLoading
|
|
108
119
|
);
|
|
109
|
-
};
|
|
120
|
+
}, [photo, loan, navigation]);
|
|
110
121
|
|
|
111
|
-
const takePhoto = () => {
|
|
112
|
-
|
|
113
|
-
navigation.push(ScreenNames.Camera, {
|
|
122
|
+
const takePhoto = useCallback(() => {
|
|
123
|
+
navigation.push(ScreenNames.SelfieCamera, {
|
|
114
124
|
front: true,
|
|
115
125
|
selfie: true,
|
|
116
|
-
callback: (
|
|
117
|
-
selfieStore.photo =
|
|
118
|
-
setPhoto(
|
|
126
|
+
callback: (uri) => {
|
|
127
|
+
selfieStore.photo = uri;
|
|
128
|
+
setPhoto(uri);
|
|
119
129
|
},
|
|
120
130
|
base64: (data) => {
|
|
121
|
-
setBase64(data);
|
|
122
131
|
selfieStore.photoBase64 = data;
|
|
123
132
|
},
|
|
124
133
|
});
|
|
125
|
-
};
|
|
134
|
+
}, [navigation]);
|
|
135
|
+
|
|
136
|
+
const goBack = useCallback(() => navigation.goBack(), [navigation]);
|
|
137
|
+
|
|
138
|
+
const capturing = appStore.isLoading || selfieStore.isLoading;
|
|
139
|
+
const canSubmit = !!photo && !isLoading;
|
|
126
140
|
|
|
127
141
|
return (
|
|
128
|
-
<View style={
|
|
129
|
-
<Image source={
|
|
130
|
-
<MHeader title="Xác thực khách hàng" onBack={
|
|
142
|
+
<View style={commonStyles.fill}>
|
|
143
|
+
<Image source={BACKGROUND} style={styles.background} />
|
|
144
|
+
<MHeader title="Xác thực khách hàng" onBack={goBack} />
|
|
131
145
|
<SafeAreaView style={commonStyles.fill}>
|
|
132
|
-
<ScrollView
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
146
|
+
<ScrollView
|
|
147
|
+
style={commonStyles.fill}
|
|
148
|
+
contentContainerStyle={styles.scrollContent}
|
|
149
|
+
showsVerticalScrollIndicator={false}
|
|
150
|
+
>
|
|
151
|
+
<View style={styles.titleRow}>
|
|
152
|
+
<TimaSmallWhite />
|
|
153
|
+
<MText style={styles.title}>Ảnh chụp khuôn mặt</MText>
|
|
154
|
+
</View>
|
|
155
|
+
|
|
156
|
+
<View style={styles.card}>
|
|
157
|
+
{/* Bọc một lớp cắt riêng: để Image tự bo góc thì mép ảnh vẫn thò ra
|
|
158
|
+
ngoài đường cong của card trên Android */}
|
|
159
|
+
<View style={styles.previewFrame}>
|
|
160
|
+
<Animated.Image
|
|
161
|
+
source={photo ? { uri: photo } : PLACEHOLDER}
|
|
162
|
+
resizeMode="cover"
|
|
143
163
|
style={[
|
|
144
|
-
|
|
145
|
-
{
|
|
164
|
+
styles.preview,
|
|
165
|
+
{
|
|
166
|
+
opacity: reveal,
|
|
167
|
+
transform: [
|
|
168
|
+
{
|
|
169
|
+
scale: reveal.interpolate({
|
|
170
|
+
inputRange: [0, 1],
|
|
171
|
+
outputRange: [0.97, 1],
|
|
172
|
+
}),
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
},
|
|
146
176
|
]}
|
|
147
|
-
|
|
148
|
-
|
|
177
|
+
/>
|
|
178
|
+
</View>
|
|
179
|
+
{/* Nhãn trạng thái: phân biệt rõ ảnh mẫu minh hoạ và ảnh đã chụp */}
|
|
180
|
+
<View style={[styles.badge, photo && styles.badgeDone]}>
|
|
181
|
+
{photo ? <Tick2 /> : null}
|
|
182
|
+
<MText style={[styles.badgeText, photo && styles.badgeTextDone]}>
|
|
183
|
+
{photo ? 'Ảnh của bạn' : 'Ảnh mẫu'}
|
|
149
184
|
</MText>
|
|
150
185
|
</View>
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
marginTop: 16,
|
|
162
|
-
}}
|
|
163
|
-
/>
|
|
186
|
+
</View>
|
|
187
|
+
|
|
188
|
+
<View style={styles.noteCard}>
|
|
189
|
+
<MText style={styles.noteTitle}>Lưu ý khi chụp ảnh khuôn mặt</MText>
|
|
190
|
+
{NOTES.map((note) => (
|
|
191
|
+
<View key={note} style={styles.noteRow}>
|
|
192
|
+
<TimaSmall style={styles.noteBullet} />
|
|
193
|
+
<MText style={styles.noteText}>{note}</MText>
|
|
194
|
+
</View>
|
|
195
|
+
))}
|
|
164
196
|
</View>
|
|
165
197
|
</ScrollView>
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
flexDirection: 'row',
|
|
169
|
-
paddingHorizontal: 16,
|
|
170
|
-
marginBottom: 30,
|
|
171
|
-
}}
|
|
172
|
-
>
|
|
198
|
+
|
|
199
|
+
<View style={styles.footer}>
|
|
173
200
|
<MButton
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}}
|
|
178
|
-
disabled={appStore.isLoading || selfieStore.isLoading}
|
|
179
|
-
style={[
|
|
180
|
-
commonStyles.row,
|
|
181
|
-
commonStyles.alignCenter,
|
|
182
|
-
commonStyles.justifyCenter,
|
|
183
|
-
{
|
|
184
|
-
backgroundColor: '#FFFFFF',
|
|
185
|
-
height: 40,
|
|
186
|
-
borderRadius: 30,
|
|
187
|
-
flex: 1,
|
|
188
|
-
marginRight: 8,
|
|
189
|
-
borderWidth: 1,
|
|
190
|
-
borderColor: '#EF4123',
|
|
191
|
-
},
|
|
192
|
-
]}
|
|
201
|
+
onPress={takePhoto}
|
|
202
|
+
disabled={capturing}
|
|
203
|
+
style={[styles.captureButton, capturing && styles.buttonMuted]}
|
|
193
204
|
>
|
|
194
|
-
<
|
|
195
|
-
|
|
205
|
+
<IConCamera width={16} height={16} />
|
|
206
|
+
<MText style={styles.captureText}>
|
|
207
|
+
{photo ? 'Chụp lại' : 'Chụp ảnh'}
|
|
196
208
|
</MText>
|
|
197
209
|
</MButton>
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
210
|
+
|
|
211
|
+
<MButton
|
|
212
|
+
disabled={!canSubmit}
|
|
213
|
+
onPress={nextStep}
|
|
214
|
+
style={commonStyles.fill}
|
|
215
|
+
>
|
|
216
|
+
{canSubmit ? (
|
|
217
|
+
<LinearGradient
|
|
218
|
+
colors={['#FF7A00', '#EF4123']}
|
|
219
|
+
start={{ x: 0, y: 0 }}
|
|
220
|
+
end={{ x: 1, y: 1 }}
|
|
221
|
+
style={[styles.submitButton, styles.submitShadow]}
|
|
204
222
|
>
|
|
205
|
-
<
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
>
|
|
217
|
-
{isLoading ? (
|
|
218
|
-
<ActivityIndicator color={'white'} size="small" />
|
|
219
|
-
) : (
|
|
220
|
-
<MText
|
|
221
|
-
style={[commonStyles.textNormal, { color: 'white' }]}
|
|
222
|
-
>
|
|
223
|
-
Tiếp tục
|
|
224
|
-
</MText>
|
|
225
|
-
)}
|
|
226
|
-
</LinearGradient>
|
|
227
|
-
</MButton>
|
|
223
|
+
<MText style={styles.submitText}>Tiếp tục</MText>
|
|
224
|
+
</LinearGradient>
|
|
225
|
+
) : (
|
|
226
|
+
// Trạng thái chưa chụp/đang xử lý phải nhìn là biết chưa bấm được
|
|
227
|
+
<View style={[styles.submitButton, styles.submitDisabled]}>
|
|
228
|
+
{isLoading ? (
|
|
229
|
+
<ActivityIndicator color={'#FFFFFF'} size="small" />
|
|
230
|
+
) : (
|
|
231
|
+
<MText style={styles.submitTextDisabled}>Tiếp tục</MText>
|
|
232
|
+
)}
|
|
233
|
+
</View>
|
|
228
234
|
)}
|
|
229
|
-
</
|
|
235
|
+
</MButton>
|
|
230
236
|
</View>
|
|
237
|
+
|
|
231
238
|
{loan?.isPipelineCIMB && (
|
|
232
|
-
<View
|
|
233
|
-
style={
|
|
234
|
-
marginBottom: 24,
|
|
235
|
-
marginTop: 8,
|
|
236
|
-
flexDirection: 'row',
|
|
237
|
-
justifyContent: 'center',
|
|
238
|
-
}}
|
|
239
|
-
>
|
|
240
|
-
<MText style={{ fontSize: 12, color: '#333333' }}>
|
|
241
|
-
Cung cấp bởi{' '}
|
|
242
|
-
</MText>
|
|
239
|
+
<View style={styles.cimbRow}>
|
|
240
|
+
<MText style={styles.cimbText}>Cung cấp bởi </MText>
|
|
243
241
|
<CIMBBank />
|
|
244
242
|
</View>
|
|
245
243
|
)}
|
|
246
|
-
<KeyboardSpacer />
|
|
247
244
|
</SafeAreaView>
|
|
248
245
|
<Loading isLoading={isLoading} />
|
|
249
246
|
</View>
|
|
250
247
|
);
|
|
251
248
|
});
|
|
249
|
+
|
|
250
|
+
const styles = StyleSheet.create({
|
|
251
|
+
background: {
|
|
252
|
+
position: 'absolute',
|
|
253
|
+
width: '100%',
|
|
254
|
+
height: '100%',
|
|
255
|
+
resizeMode: 'cover',
|
|
256
|
+
},
|
|
257
|
+
scrollContent: { paddingHorizontal: 24, paddingBottom: 24 },
|
|
258
|
+
|
|
259
|
+
titleRow: { flexDirection: 'row', alignItems: 'center', marginTop: 20 },
|
|
260
|
+
title: {
|
|
261
|
+
...commonStyles.textNormalBold,
|
|
262
|
+
fontSize: 16,
|
|
263
|
+
color: '#FFFFFF',
|
|
264
|
+
marginLeft: 8,
|
|
265
|
+
letterSpacing: 0.2,
|
|
266
|
+
},
|
|
267
|
+
|
|
268
|
+
card: {
|
|
269
|
+
marginTop: 16,
|
|
270
|
+
padding: 8,
|
|
271
|
+
borderRadius: 20,
|
|
272
|
+
backgroundColor: '#FFFFFF',
|
|
273
|
+
shadowColor: '#7A2E12',
|
|
274
|
+
shadowOffset: { width: 0, height: 10 },
|
|
275
|
+
shadowOpacity: 0.18,
|
|
276
|
+
shadowRadius: 20,
|
|
277
|
+
elevation: 8,
|
|
278
|
+
},
|
|
279
|
+
// Bán kính trong = bán kính card (20) - padding (8) để hai đường cong khớp nhau
|
|
280
|
+
previewFrame: {
|
|
281
|
+
width: '100%',
|
|
282
|
+
aspectRatio: PREVIEW_ASPECT,
|
|
283
|
+
borderRadius: 12,
|
|
284
|
+
overflow: 'hidden',
|
|
285
|
+
backgroundColor: '#F5EDE9',
|
|
286
|
+
},
|
|
287
|
+
preview: { width: '100%', height: '100%' },
|
|
288
|
+
badge: {
|
|
289
|
+
position: 'absolute',
|
|
290
|
+
left: 20,
|
|
291
|
+
bottom: 20,
|
|
292
|
+
flexDirection: 'row',
|
|
293
|
+
alignItems: 'center',
|
|
294
|
+
paddingHorizontal: 10,
|
|
295
|
+
paddingVertical: 5,
|
|
296
|
+
borderRadius: 14,
|
|
297
|
+
backgroundColor: 'rgba(0, 0, 0, 0.45)',
|
|
298
|
+
},
|
|
299
|
+
badgeDone: { backgroundColor: 'rgba(255, 255, 255, 0.94)' },
|
|
300
|
+
badgeText: { color: '#FFFFFF', fontSize: 11, fontWeight: '600' },
|
|
301
|
+
badgeTextDone: { color: '#28A745', marginLeft: 6 },
|
|
302
|
+
|
|
303
|
+
noteCard: {
|
|
304
|
+
marginTop: 20,
|
|
305
|
+
padding: 16,
|
|
306
|
+
borderRadius: 16,
|
|
307
|
+
backgroundColor: 'rgba(255, 255, 255, 0.75)',
|
|
308
|
+
borderWidth: 1,
|
|
309
|
+
borderColor: '#FFE1D3',
|
|
310
|
+
},
|
|
311
|
+
noteTitle: {
|
|
312
|
+
...commonStyles.textNormalBold,
|
|
313
|
+
fontSize: 15,
|
|
314
|
+
color: '#333333',
|
|
315
|
+
},
|
|
316
|
+
noteRow: { flexDirection: 'row', marginTop: 12 },
|
|
317
|
+
noteBullet: { marginTop: 5 },
|
|
318
|
+
noteText: {
|
|
319
|
+
color: '#5A5A5A',
|
|
320
|
+
marginLeft: 10,
|
|
321
|
+
fontSize: 13,
|
|
322
|
+
lineHeight: 20,
|
|
323
|
+
flex: 1,
|
|
324
|
+
},
|
|
325
|
+
|
|
326
|
+
// SafeAreaView đã cộng inset dưới trên iOS nên chỉ cần khoảng thở cố định
|
|
327
|
+
footer: {
|
|
328
|
+
flexDirection: 'row',
|
|
329
|
+
paddingHorizontal: 24,
|
|
330
|
+
paddingTop: 4,
|
|
331
|
+
marginBottom: 24,
|
|
332
|
+
},
|
|
333
|
+
captureButton: {
|
|
334
|
+
flexDirection: 'row',
|
|
335
|
+
alignItems: 'center',
|
|
336
|
+
justifyContent: 'center',
|
|
337
|
+
backgroundColor: '#FFFFFF',
|
|
338
|
+
height: 48,
|
|
339
|
+
borderRadius: 24,
|
|
340
|
+
flex: 1,
|
|
341
|
+
marginRight: 10,
|
|
342
|
+
borderWidth: 1.5,
|
|
343
|
+
borderColor: '#EF4123',
|
|
344
|
+
},
|
|
345
|
+
buttonMuted: { opacity: 0.5 },
|
|
346
|
+
captureText: {
|
|
347
|
+
...commonStyles.textNormal,
|
|
348
|
+
color: '#F05123',
|
|
349
|
+
fontWeight: '600',
|
|
350
|
+
marginLeft: 8,
|
|
351
|
+
},
|
|
352
|
+
submitButton: {
|
|
353
|
+
alignItems: 'center',
|
|
354
|
+
justifyContent: 'center',
|
|
355
|
+
height: 48,
|
|
356
|
+
borderRadius: 24,
|
|
357
|
+
},
|
|
358
|
+
submitShadow: {
|
|
359
|
+
shadowColor: '#EF4123',
|
|
360
|
+
shadowOffset: { width: 0, height: 6 },
|
|
361
|
+
shadowOpacity: 0.35,
|
|
362
|
+
shadowRadius: 12,
|
|
363
|
+
elevation: 6,
|
|
364
|
+
},
|
|
365
|
+
submitDisabled: { backgroundColor: '#D8D2CF' },
|
|
366
|
+
submitText: {
|
|
367
|
+
...commonStyles.textNormal,
|
|
368
|
+
color: '#FFFFFF',
|
|
369
|
+
fontWeight: '600',
|
|
370
|
+
},
|
|
371
|
+
submitTextDisabled: { ...commonStyles.textNormal, color: '#FFFFFF' },
|
|
372
|
+
|
|
373
|
+
cimbRow: {
|
|
374
|
+
marginTop: -8,
|
|
375
|
+
marginBottom: 24,
|
|
376
|
+
flexDirection: 'row',
|
|
377
|
+
justifyContent: 'center',
|
|
378
|
+
alignItems: 'center',
|
|
379
|
+
},
|
|
380
|
+
cimbText: { fontSize: 12, color: '#333333' },
|
|
381
|
+
});
|
|
@@ -220,7 +220,9 @@ export default function TopupLoanInfo(props) {
|
|
|
220
220
|
validateOnBlur={false}
|
|
221
221
|
validateOnChange={false}
|
|
222
222
|
validationSchema={yup.object().shape({
|
|
223
|
-
dateNationalId: yup
|
|
223
|
+
dateNationalId: yup
|
|
224
|
+
.string()
|
|
225
|
+
.required('Vui lòng chọn ngày cấp CCCD'),
|
|
224
226
|
bankName: yup.string().required('Vui lòng chọn ngân hàng'),
|
|
225
227
|
bankAccountName: yup.string().required('Vui lòng nhập chủ thẻ'),
|
|
226
228
|
bankAccountNumber: yup
|
|
@@ -293,8 +295,8 @@ export default function TopupLoanInfo(props) {
|
|
|
293
295
|
{values.gender === 0
|
|
294
296
|
? 'Nam'
|
|
295
297
|
: values.gender === 1
|
|
296
|
-
|
|
297
|
-
|
|
298
|
+
? 'Nữ'
|
|
299
|
+
: ''}
|
|
298
300
|
</MText>
|
|
299
301
|
<DropDown2 />
|
|
300
302
|
</TouchableOpacity>
|
|
@@ -346,8 +348,8 @@ export default function TopupLoanInfo(props) {
|
|
|
346
348
|
</MText>
|
|
347
349
|
</TouchableOpacity>
|
|
348
350
|
{errors && errors.dateNationalId && (
|
|
349
|
-
|
|
350
|
-
|
|
351
|
+
<MText style={$error}>{errors.dateNationalId}</MText>
|
|
352
|
+
)}
|
|
351
353
|
</View>
|
|
352
354
|
|
|
353
355
|
<DatePicker
|
|
@@ -500,6 +502,7 @@ const $textInput: ViewStyle = {
|
|
|
500
502
|
height: 40,
|
|
501
503
|
paddingHorizontal: 8,
|
|
502
504
|
fontFamily: 'BeVietnamPro-Medium',
|
|
505
|
+
fontSize: 14,
|
|
503
506
|
};
|
|
504
507
|
|
|
505
508
|
const $label: TextStyle = {
|