@transfergratis/react-native-sdk 0.1.22 → 0.1.24
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/android/src/main/AndroidManifest.xml +9 -4
- package/build/components/EnhancedCameraView.d.ts.map +1 -1
- package/build/components/EnhancedCameraView.js +26 -3
- package/build/components/EnhancedCameraView.js.map +1 -1
- package/build/components/EnhancedCameraView.web.d.ts.map +1 -1
- package/build/components/EnhancedCameraView.web.js +21 -0
- package/build/components/EnhancedCameraView.web.js.map +1 -1
- package/build/components/KYCElements/CameraCapture.d.ts.map +1 -1
- package/build/components/KYCElements/CameraCapture.js +4 -3
- package/build/components/KYCElements/CameraCapture.js.map +1 -1
- package/build/components/KYCElements/CountrySelectionTemplate.d.ts +5 -2
- package/build/components/KYCElements/CountrySelectionTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/CountrySelectionTemplate.js +360 -101
- package/build/components/KYCElements/CountrySelectionTemplate.js.map +1 -1
- package/build/components/KYCElements/FileUpload.d.ts.map +1 -1
- package/build/components/KYCElements/FileUpload.js +5 -4
- package/build/components/KYCElements/FileUpload.js.map +1 -1
- package/build/components/KYCElements/FileUploadTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/FileUploadTemplate.js +5 -4
- package/build/components/KYCElements/FileUploadTemplate.js.map +1 -1
- package/build/components/KYCElements/IDCardCapture.d.ts.map +1 -1
- package/build/components/KYCElements/IDCardCapture.js +193 -237
- package/build/components/KYCElements/IDCardCapture.js.map +1 -1
- package/build/components/KYCElements/LocationCaptureTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/LocationCaptureTemplate.js +78 -37
- package/build/components/KYCElements/LocationCaptureTemplate.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCapture.js +3 -2
- package/build/components/KYCElements/OrientationVideoCapture.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js +3 -2
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureFinal.js +3 -2
- package/build/components/KYCElements/OrientationVideoCaptureFinal.js.map +1 -1
- package/build/components/KYCElements/SelfieCapture.d.ts.map +1 -1
- package/build/components/KYCElements/SelfieCapture.js +4 -3
- package/build/components/KYCElements/SelfieCapture.js.map +1 -1
- package/build/components/KYCElements/SelfieCaptureTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/SelfieCaptureTemplate.js +182 -39
- package/build/components/KYCElements/SelfieCaptureTemplate.js.map +1 -1
- package/build/components/KYCElements/WelcomeTemplate.d.ts +12 -0
- package/build/components/KYCElements/WelcomeTemplate.d.ts.map +1 -0
- package/build/components/KYCElements/WelcomeTemplate.js +243 -0
- package/build/components/KYCElements/WelcomeTemplate.js.map +1 -0
- package/build/components/TemplateKYCExample.d.ts +4 -2
- package/build/components/TemplateKYCExample.d.ts.map +1 -1
- package/build/components/TemplateKYCExample.js +5 -68
- package/build/components/TemplateKYCExample.js.map +1 -1
- package/build/components/TemplateKYCFlowRefactored.d.ts +2 -1
- package/build/components/TemplateKYCFlowRefactored.d.ts.map +1 -1
- package/build/components/TemplateKYCFlowRefactored.js +95 -9
- package/build/components/TemplateKYCFlowRefactored.js.map +1 -1
- package/build/components/example/DynamicTemplateExample.d.ts +10 -0
- package/build/components/example/DynamicTemplateExample.d.ts.map +1 -0
- package/build/components/example/DynamicTemplateExample.js +241 -0
- package/build/components/example/DynamicTemplateExample.js.map +1 -0
- package/build/config/allowedDomains.d.ts +30 -0
- package/build/config/allowedDomains.d.ts.map +1 -0
- package/build/config/allowedDomains.js +127 -0
- package/build/config/allowedDomains.js.map +1 -0
- package/build/hooks/useTemplateKYCFlow.d.ts.map +1 -1
- package/build/hooks/useTemplateKYCFlow.js +68 -43
- package/build/hooks/useTemplateKYCFlow.js.map +1 -1
- package/build/hooks/useTemplateLoader.d.ts +14 -0
- package/build/hooks/useTemplateLoader.d.ts.map +1 -0
- package/build/hooks/useTemplateLoader.js +85 -0
- package/build/hooks/useTemplateLoader.js.map +1 -0
- package/build/i18n/en/index.d.ts +9 -0
- package/build/i18n/en/index.d.ts.map +1 -1
- package/build/i18n/en/index.js +9 -0
- package/build/i18n/en/index.js.map +1 -1
- package/build/i18n/fr/index.d.ts +9 -0
- package/build/i18n/fr/index.d.ts.map +1 -1
- package/build/i18n/fr/index.js +9 -0
- package/build/i18n/fr/index.js.map +1 -1
- package/build/index.d.ts +5 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +8 -0
- package/build/index.js.map +1 -1
- package/build/modules/api/CardAuthentification.js +1 -0
- package/build/modules/api/CardAuthentification.js.map +1 -1
- package/build/modules/api/KYCService.d.ts +4 -1
- package/build/modules/api/KYCService.d.ts.map +1 -1
- package/build/modules/api/KYCService.js +17 -5
- package/build/modules/api/KYCService.js.map +1 -1
- package/build/modules/api/TemplateService.d.ts +45 -0
- package/build/modules/api/TemplateService.d.ts.map +1 -0
- package/build/modules/api/TemplateService.js +145 -0
- package/build/modules/api/TemplateService.js.map +1 -0
- package/build/modules/api/types.d.ts +1 -0
- package/build/modules/api/types.d.ts.map +1 -1
- package/build/modules/api/types.js.map +1 -1
- package/build/types/KYC.types.d.ts +144 -4
- package/build/types/KYC.types.d.ts.map +1 -1
- package/build/types/KYC.types.js +15 -0
- package/build/types/KYC.types.js.map +1 -1
- package/build/utils/cropByObb.d.ts +1 -0
- package/build/utils/cropByObb.d.ts.map +1 -1
- package/build/utils/cropByObb.js +70 -0
- package/build/utils/cropByObb.js.map +1 -1
- package/build/utils/platformAlert.d.ts +20 -0
- package/build/utils/platformAlert.d.ts.map +1 -0
- package/build/utils/platformAlert.js +67 -0
- package/build/utils/platformAlert.js.map +1 -0
- package/build/utils/template-transformer.d.ts +10 -0
- package/build/utils/template-transformer.d.ts.map +1 -0
- package/build/utils/template-transformer.js +353 -0
- package/build/utils/template-transformer.js.map +1 -0
- package/build/web/WebKYCEntry.d.ts.map +1 -1
- package/build/web/WebKYCEntry.js +102 -20
- package/build/web/WebKYCEntry.js.map +1 -1
- package/package.json +1 -1
- package/src/components/EnhancedCameraView.tsx +31 -2
- package/src/components/EnhancedCameraView.web.tsx +24 -0
- package/src/components/KYCElements/CameraCapture.tsx +4 -3
- package/src/components/KYCElements/CountrySelectionTemplate.tsx +410 -113
- package/src/components/KYCElements/FileUpload.tsx +5 -4
- package/src/components/KYCElements/FileUploadTemplate.tsx +5 -4
- package/src/components/KYCElements/IDCardCapture.tsx +196 -254
- package/src/components/KYCElements/LocationCaptureTemplate.tsx +95 -44
- package/src/components/KYCElements/OrientationVideoCapture.tsx +2 -2
- package/src/components/KYCElements/OrientationVideoCaptureEnhanced.tsx +2 -2
- package/src/components/KYCElements/OrientationVideoCaptureFinal.tsx +2 -2
- package/src/components/KYCElements/SelfieCapture.tsx +4 -3
- package/src/components/KYCElements/SelfieCaptureTemplate.tsx +195 -41
- package/src/components/KYCElements/WelcomeTemplate.tsx +289 -0
- package/src/components/TemplateKYCExample.tsx +16 -71
- package/src/components/TemplateKYCFlowRefactored.tsx +121 -11
- package/src/components/example/DynamicTemplateExample.tsx +289 -0
- package/src/config/allowedDomains.ts +152 -0
- package/src/hooks/useTemplateKYCFlow.tsx +71 -46
- package/src/hooks/useTemplateLoader.ts +102 -0
- package/src/i18n/en/index.ts +10 -0
- package/src/i18n/fr/index.ts +9 -0
- package/src/index.ts +11 -0
- package/src/modules/api/CardAuthentification.ts +1 -1
- package/src/modules/api/KYCService.ts +18 -8
- package/src/modules/api/TemplateService.ts +167 -0
- package/src/modules/api/types.ts +1 -0
- package/src/types/KYC.types.ts +188 -3
- package/src/utils/cropByObb.ts +83 -3
- package/src/utils/platformAlert.ts +85 -0
- package/src/utils/template-transformer.ts +433 -0
- package/src/web/WebKYCEntry.tsx +122 -24
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { View, Text, StyleSheet } from 'react-native';
|
|
3
|
+
import { TemplateComponent, WelcomeConfig, LocalizedText } from '../../types/KYC.types';
|
|
4
|
+
import { useTemplateKYCFlowContext } from '../../hooks/useTemplateKYCFlow';
|
|
5
|
+
import { useI18n } from '../../hooks/useI18n';
|
|
6
|
+
import { Button } from '../ui/Button';
|
|
7
|
+
import ShieldIcon from '../Svgs/Schield';
|
|
8
|
+
|
|
9
|
+
interface WelcomeTemplateProps {
|
|
10
|
+
component: TemplateComponent;
|
|
11
|
+
value?: any;
|
|
12
|
+
onValueChange: (data: any) => void;
|
|
13
|
+
error?: string;
|
|
14
|
+
language?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const WelcomeTemplate: React.FC<WelcomeTemplateProps> = ({
|
|
18
|
+
component,
|
|
19
|
+
value,
|
|
20
|
+
onValueChange,
|
|
21
|
+
error,
|
|
22
|
+
}) => {
|
|
23
|
+
const { t } = useI18n();
|
|
24
|
+
const { getLocalizedText, actions } = useTemplateKYCFlowContext();
|
|
25
|
+
const config = component.config as WelcomeConfig;
|
|
26
|
+
|
|
27
|
+
// Consentements cochés par défaut
|
|
28
|
+
const privacyConsent = true;
|
|
29
|
+
const termsConsent = true;
|
|
30
|
+
const [shouldProceed, setShouldProceed] = useState(false);
|
|
31
|
+
|
|
32
|
+
// Get localized text
|
|
33
|
+
const title = getLocalizedText(component.labels as LocalizedText);
|
|
34
|
+
const description = getLocalizedText(component.instructions as LocalizedText);
|
|
35
|
+
const welcomeMessage = config.welcomeMessage || description;
|
|
36
|
+
const buttonText = config.buttonText || getLocalizedText((component.ui as any).buttonText || { en: 'Get Started', fr: 'Commencer' });
|
|
37
|
+
|
|
38
|
+
// Passer à l'étape suivante après que les données sont mises à jour
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (shouldProceed && value && value.consentGiven) {
|
|
41
|
+
// Petit délai pour s'assurer que le state est bien mis à jour
|
|
42
|
+
const timer = setTimeout(() => {
|
|
43
|
+
actions.nextComponent();
|
|
44
|
+
setShouldProceed(false);
|
|
45
|
+
}, 100);
|
|
46
|
+
|
|
47
|
+
return () => clearTimeout(timer);
|
|
48
|
+
}
|
|
49
|
+
return undefined;
|
|
50
|
+
}, [value, shouldProceed, actions]);
|
|
51
|
+
|
|
52
|
+
const handleGetStarted = () => {
|
|
53
|
+
// Mark component as complete
|
|
54
|
+
const consentData = { consentGiven: true, privacyConsent, termsConsent };
|
|
55
|
+
onValueChange(consentData);
|
|
56
|
+
setShouldProceed(true);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<View style={styles.container}>
|
|
61
|
+
<View style={{ flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
|
|
62
|
+
{/* Icon Section */}
|
|
63
|
+
<View style={{ position: 'relative', width: 70 }}>
|
|
64
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'center', width: 60, height: 60, backgroundColor: '#2DBE60', borderRadius: 100 }}>
|
|
65
|
+
<ShieldIcon />
|
|
66
|
+
</View>
|
|
67
|
+
<View style={{ position: 'absolute', top: '60%', right: 0, flexDirection: 'row', alignItems: 'center', justifyContent: 'center', width: 40, height: 40, backgroundColor: 'white', borderRadius: 100, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.15, shadowRadius: 1.84, elevation: 5 }}>
|
|
68
|
+
<Text style={{ fontSize: 20, color: '#2DBE60' }}>✓</Text>
|
|
69
|
+
</View>
|
|
70
|
+
</View>
|
|
71
|
+
|
|
72
|
+
{/* Title and Description */}
|
|
73
|
+
<View style={{ flexDirection: 'column', alignItems: 'center', justifyContent: 'center', marginTop: 36 }}>
|
|
74
|
+
<Text style={styles.title}>{title}</Text>
|
|
75
|
+
{welcomeMessage && (
|
|
76
|
+
<Text style={styles.description}>
|
|
77
|
+
{welcomeMessage}
|
|
78
|
+
</Text>
|
|
79
|
+
)}
|
|
80
|
+
</View>
|
|
81
|
+
|
|
82
|
+
{/* Requirements List */}
|
|
83
|
+
{config.requirements && config.requirements.length > 0 && (
|
|
84
|
+
<View style={styles.requirementsSection}>
|
|
85
|
+
<Text style={styles.sectionTitle}>
|
|
86
|
+
{t('kyc.welcome.requirements') || `What you'll need:`}
|
|
87
|
+
</Text>
|
|
88
|
+
{config.requirements.map((requirement, index) => (
|
|
89
|
+
<View key={index} style={styles.requirementItem}>
|
|
90
|
+
<Text style={styles.checkmark}>✓</Text>
|
|
91
|
+
<Text style={styles.requirementText}>{requirement}</Text>
|
|
92
|
+
</View>
|
|
93
|
+
))}
|
|
94
|
+
</View>
|
|
95
|
+
)}
|
|
96
|
+
|
|
97
|
+
{/* Estimated Time */}
|
|
98
|
+
{config.showEstimatedTime !== false && config.estimatedTime && (
|
|
99
|
+
<View style={styles.timeSection}>
|
|
100
|
+
<Text style={styles.timeLabel}>
|
|
101
|
+
{t('kyc.welcome.estimatedTime') || 'Estimated time:'}
|
|
102
|
+
</Text>
|
|
103
|
+
<Text style={styles.timeValue}>{config.estimatedTime}</Text>
|
|
104
|
+
</View>
|
|
105
|
+
)}
|
|
106
|
+
|
|
107
|
+
{/* Consent Options - Hidden by default as they're pre-checked */}
|
|
108
|
+
{(config.consentOptions?.showPrivacyPolicy || config.consentOptions?.showTermsOfService || config.consentOptions?.showMarketingConsent) && (
|
|
109
|
+
<View style={styles.consentSection}>
|
|
110
|
+
{config.consentOptions.showPrivacyPolicy && (
|
|
111
|
+
<View style={styles.consentItem}>
|
|
112
|
+
<View style={[styles.checkbox, styles.checkboxChecked]}>
|
|
113
|
+
<Text style={styles.checkmarkSmall}>✓</Text>
|
|
114
|
+
</View>
|
|
115
|
+
<Text style={styles.consentText}>
|
|
116
|
+
{t('kyc.welcome.privacyPolicy') || 'I agree to the Privacy Policy'}
|
|
117
|
+
</Text>
|
|
118
|
+
</View>
|
|
119
|
+
)}
|
|
120
|
+
|
|
121
|
+
{config.consentOptions.showTermsOfService && (
|
|
122
|
+
<View style={styles.consentItem}>
|
|
123
|
+
<View style={[styles.checkbox, styles.checkboxChecked]}>
|
|
124
|
+
<Text style={styles.checkmarkSmall}>✓</Text>
|
|
125
|
+
</View>
|
|
126
|
+
<Text style={styles.consentText}>
|
|
127
|
+
{t('kyc.welcome.termsOfService') || 'I agree to the Terms of Service'}
|
|
128
|
+
</Text>
|
|
129
|
+
</View>
|
|
130
|
+
)}
|
|
131
|
+
|
|
132
|
+
{config.consentOptions.showMarketingConsent && (
|
|
133
|
+
<View style={styles.consentItem}>
|
|
134
|
+
<View style={[styles.checkbox, styles.checkboxChecked]}>
|
|
135
|
+
<Text style={styles.checkmarkSmall}>✓</Text>
|
|
136
|
+
</View>
|
|
137
|
+
<Text style={styles.consentText}>
|
|
138
|
+
{t('kyc.welcome.marketingConsent') || 'I agree to receive marketing communications'}
|
|
139
|
+
</Text>
|
|
140
|
+
</View>
|
|
141
|
+
)}
|
|
142
|
+
</View>
|
|
143
|
+
)}
|
|
144
|
+
|
|
145
|
+
{error && (
|
|
146
|
+
<View style={styles.errorContainer}>
|
|
147
|
+
<Text style={styles.errorText}>{error}</Text>
|
|
148
|
+
</View>
|
|
149
|
+
)}
|
|
150
|
+
|
|
151
|
+
{/* Get Started Button */}
|
|
152
|
+
<Button
|
|
153
|
+
title={buttonText}
|
|
154
|
+
fullWidth
|
|
155
|
+
onPress={handleGetStarted}
|
|
156
|
+
style={{ paddingVertical: 20, marginTop: 36 }}
|
|
157
|
+
/>
|
|
158
|
+
|
|
159
|
+
<View style={{ height: 12 }} />
|
|
160
|
+
</View>
|
|
161
|
+
</View>
|
|
162
|
+
);
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const styles = StyleSheet.create({
|
|
166
|
+
container: {
|
|
167
|
+
padding: 16,
|
|
168
|
+
backgroundColor: 'white',
|
|
169
|
+
marginHorizontal: 12,
|
|
170
|
+
marginTop: 12,
|
|
171
|
+
borderRadius: 12,
|
|
172
|
+
shadowColor: '#000',
|
|
173
|
+
shadowOffset: { width: 0, height: 2 },
|
|
174
|
+
shadowOpacity: 0.15,
|
|
175
|
+
shadowRadius: 1.84,
|
|
176
|
+
elevation: 3,
|
|
177
|
+
maxWidth: 760,
|
|
178
|
+
},
|
|
179
|
+
title: {
|
|
180
|
+
fontSize: 24,
|
|
181
|
+
fontWeight: 'bold',
|
|
182
|
+
color: '#333',
|
|
183
|
+
marginBottom: 8,
|
|
184
|
+
textAlign: 'center',
|
|
185
|
+
},
|
|
186
|
+
description: {
|
|
187
|
+
fontSize: 16,
|
|
188
|
+
color: '#666',
|
|
189
|
+
textAlign: 'center',
|
|
190
|
+
marginBottom: 24,
|
|
191
|
+
lineHeight: 22,
|
|
192
|
+
},
|
|
193
|
+
requirementsSection: {
|
|
194
|
+
backgroundColor: '#F9FAFB',
|
|
195
|
+
padding: 12,
|
|
196
|
+
borderRadius: 12,
|
|
197
|
+
width: '100%',
|
|
198
|
+
marginTop: 24,
|
|
199
|
+
},
|
|
200
|
+
sectionTitle: {
|
|
201
|
+
fontSize: 16,
|
|
202
|
+
fontWeight: 'bold',
|
|
203
|
+
color: 'black',
|
|
204
|
+
marginBottom: 12,
|
|
205
|
+
textAlign: 'left',
|
|
206
|
+
},
|
|
207
|
+
requirementItem: {
|
|
208
|
+
flexDirection: 'row',
|
|
209
|
+
alignItems: 'center',
|
|
210
|
+
marginBottom: 8,
|
|
211
|
+
},
|
|
212
|
+
checkmark: {
|
|
213
|
+
fontSize: 18,
|
|
214
|
+
color: '#2DBD60',
|
|
215
|
+
marginRight: 12,
|
|
216
|
+
fontWeight: 'bold',
|
|
217
|
+
},
|
|
218
|
+
requirementText: {
|
|
219
|
+
flex: 1,
|
|
220
|
+
fontSize: 16,
|
|
221
|
+
color: '#666',
|
|
222
|
+
textAlign: 'left',
|
|
223
|
+
lineHeight: 22,
|
|
224
|
+
},
|
|
225
|
+
timeSection: {
|
|
226
|
+
backgroundColor: '#F9FAFB',
|
|
227
|
+
padding: 12,
|
|
228
|
+
borderRadius: 12,
|
|
229
|
+
marginTop: 16,
|
|
230
|
+
alignItems: 'center',
|
|
231
|
+
width: '100%',
|
|
232
|
+
},
|
|
233
|
+
timeLabel: {
|
|
234
|
+
fontSize: 14,
|
|
235
|
+
color: '#666',
|
|
236
|
+
marginBottom: 4,
|
|
237
|
+
},
|
|
238
|
+
timeValue: {
|
|
239
|
+
fontSize: 20,
|
|
240
|
+
fontWeight: 'bold',
|
|
241
|
+
color: '#2DBD60',
|
|
242
|
+
},
|
|
243
|
+
consentSection: {
|
|
244
|
+
width: '100%',
|
|
245
|
+
marginTop: 24,
|
|
246
|
+
},
|
|
247
|
+
consentItem: {
|
|
248
|
+
flexDirection: 'row',
|
|
249
|
+
alignItems: 'center',
|
|
250
|
+
marginBottom: 12,
|
|
251
|
+
},
|
|
252
|
+
checkbox: {
|
|
253
|
+
width: 20,
|
|
254
|
+
height: 20,
|
|
255
|
+
borderWidth: 2,
|
|
256
|
+
borderColor: '#ddd',
|
|
257
|
+
borderRadius: 4,
|
|
258
|
+
marginRight: 12,
|
|
259
|
+
alignItems: 'center',
|
|
260
|
+
justifyContent: 'center',
|
|
261
|
+
},
|
|
262
|
+
checkboxChecked: {
|
|
263
|
+
backgroundColor: '#2DBD60',
|
|
264
|
+
borderColor: '#2DBD60',
|
|
265
|
+
},
|
|
266
|
+
checkmarkSmall: {
|
|
267
|
+
fontSize: 14,
|
|
268
|
+
color: 'white',
|
|
269
|
+
fontWeight: 'bold',
|
|
270
|
+
},
|
|
271
|
+
consentText: {
|
|
272
|
+
flex: 1,
|
|
273
|
+
fontSize: 15,
|
|
274
|
+
color: '#333',
|
|
275
|
+
lineHeight: 22,
|
|
276
|
+
},
|
|
277
|
+
errorContainer: {
|
|
278
|
+
backgroundColor: '#fee',
|
|
279
|
+
padding: 12,
|
|
280
|
+
borderRadius: 8,
|
|
281
|
+
marginTop: 16,
|
|
282
|
+
width: '100%',
|
|
283
|
+
},
|
|
284
|
+
errorText: {
|
|
285
|
+
color: '#dc2626',
|
|
286
|
+
fontSize: 14,
|
|
287
|
+
textAlign: 'center',
|
|
288
|
+
},
|
|
289
|
+
});
|
|
@@ -103,74 +103,7 @@ const advancedVerificationTemplate: KYCTemplate = {
|
|
|
103
103
|
allowed_formats: ["jpg", "png"],
|
|
104
104
|
max_size_mb: 5,
|
|
105
105
|
document_types: ["drivers_licence", "passport", "drivers_licence", "national_id"],
|
|
106
|
-
|
|
107
|
-
drivers_licence: {
|
|
108
|
-
xMin: 20,
|
|
109
|
-
yMin: 140,
|
|
110
|
-
xMax: 370,
|
|
111
|
-
yMax: 340,
|
|
112
|
-
borderColor: "#2DBD60",
|
|
113
|
-
borderWidth: 4,
|
|
114
|
-
cornerRadius: 12
|
|
115
|
-
},
|
|
116
|
-
passport: {
|
|
117
|
-
xMin: 15,
|
|
118
|
-
yMin: 130,
|
|
119
|
-
xMax: 375,
|
|
120
|
-
yMax: 350,
|
|
121
|
-
borderColor: "#007AFF",
|
|
122
|
-
borderWidth: 4,
|
|
123
|
-
cornerRadius: 8
|
|
124
|
-
},
|
|
125
|
-
identity_card: {
|
|
126
|
-
xMin: 20,
|
|
127
|
-
yMin: 140,
|
|
128
|
-
xMax: 370,
|
|
129
|
-
yMax: 340,
|
|
130
|
-
borderColor: "#2DBD60",
|
|
131
|
-
borderWidth: 4,
|
|
132
|
-
cornerRadius: 12
|
|
133
|
-
},
|
|
134
|
-
health_insurance_card: {
|
|
135
|
-
xMin: 20,
|
|
136
|
-
yMin: 140,
|
|
137
|
-
xMax: 370,
|
|
138
|
-
yMax: 340,
|
|
139
|
-
borderColor: "#2DBD60",
|
|
140
|
-
borderWidth: 4,
|
|
141
|
-
cornerRadius: 12
|
|
142
|
-
},
|
|
143
|
-
national_id: {
|
|
144
|
-
xMin: 20,
|
|
145
|
-
yMin: 140,
|
|
146
|
-
xMax: 370,
|
|
147
|
-
yMax: 340,
|
|
148
|
-
borderColor: "#5856D6",
|
|
149
|
-
borderWidth: 4,
|
|
150
|
-
cornerRadius: 12
|
|
151
|
-
},
|
|
152
|
-
permanent_residence: {
|
|
153
|
-
xMin: 20,
|
|
154
|
-
yMin: 140,
|
|
155
|
-
xMax: 370,
|
|
156
|
-
yMax: 340,
|
|
157
|
-
borderColor: "#2DBD60",
|
|
158
|
-
borderWidth: 4,
|
|
159
|
-
cornerRadius: 12
|
|
160
|
-
},
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
work_permit: {
|
|
164
|
-
xMin: 20,
|
|
165
|
-
yMin: 140,
|
|
166
|
-
xMax: 370,
|
|
167
|
-
yMax: 340,
|
|
168
|
-
borderColor: "#2DBD60",
|
|
169
|
-
borderWidth: 4,
|
|
170
|
-
cornerRadius: 12
|
|
171
|
-
},
|
|
172
|
-
|
|
173
|
-
}
|
|
106
|
+
|
|
174
107
|
} as const
|
|
175
108
|
},
|
|
176
109
|
{
|
|
@@ -224,7 +157,15 @@ const advancedVerificationTemplate: KYCTemplate = {
|
|
|
224
157
|
]
|
|
225
158
|
};
|
|
226
159
|
|
|
227
|
-
export const TemplateKYCExample: React.FC<{
|
|
160
|
+
export const TemplateKYCExample: React.FC<{
|
|
161
|
+
onComplete: (data: VerificationState) => void;
|
|
162
|
+
onCancel: () => void;
|
|
163
|
+
onError: (error: string) => void;
|
|
164
|
+
language: string;
|
|
165
|
+
API_KEY?: string;
|
|
166
|
+
templateId?: string;
|
|
167
|
+
template?: KYCTemplate;
|
|
168
|
+
}> = ({ onComplete, onCancel, onError, language, API_KEY, templateId, template }) => {
|
|
228
169
|
const handleComplete = (data: VerificationState) => {
|
|
229
170
|
console.log('KYC Template completed with data:', data);
|
|
230
171
|
onComplete(data);
|
|
@@ -238,14 +179,18 @@ export const TemplateKYCExample: React.FC<{ onComplete: (data: VerificationState
|
|
|
238
179
|
|
|
239
180
|
const handleError = (error: string) => {
|
|
240
181
|
console.error('KYC Template error:', error);
|
|
241
|
-
|
|
182
|
+
onError(error);
|
|
242
183
|
};
|
|
243
184
|
|
|
185
|
+
// Determine which template to use: prefer templateId for dynamic loading, then template prop, then fallback to hardcoded
|
|
186
|
+
const templateToUse = templateId ? undefined : (template || advancedVerificationTemplate);
|
|
187
|
+
|
|
244
188
|
return (
|
|
245
189
|
<SafeAreaView style={{ flex: 1 , paddingVertical:25}}>
|
|
246
190
|
<View style={{ flex: 1 }}>
|
|
247
191
|
<TemplateKYCFlow
|
|
248
|
-
template={
|
|
192
|
+
template={templateToUse}
|
|
193
|
+
templateId={templateId}
|
|
249
194
|
onComplete={handleComplete}
|
|
250
195
|
onError={handleError}
|
|
251
196
|
onCancel={handleCancel}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { View, Text, StyleSheet, SafeAreaView, TouchableOpacity, ActivityIndicator, Dimensions,
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { View, Text, StyleSheet, SafeAreaView, TouchableOpacity, ActivityIndicator, Dimensions, ScrollView, Platform } from 'react-native';
|
|
3
3
|
import { KYCTemplate, VerificationState } from '../types/KYC.types';
|
|
4
4
|
import { TemplateKYCFlowProvider, useTemplateKYCFlowContext } from '../hooks/useTemplateKYCFlow';
|
|
5
5
|
import { useI18n } from '../hooks/useI18n';
|
|
6
|
+
import { showAlert } from '../utils/platformAlert';
|
|
6
7
|
import { IDCardCapture } from './KYCElements/IDCardCapture';
|
|
7
8
|
import { SelfieCaptureTemplate } from './KYCElements/SelfieCaptureTemplate';
|
|
8
9
|
import { FileUploadTemplate } from './KYCElements/FileUploadTemplate';
|
|
@@ -11,18 +12,22 @@ import { CountrySelectionTemplate } from './KYCElements/CountrySelectionTemplate
|
|
|
11
12
|
import { InitializationStep } from './KYCElements/InitializationStep';
|
|
12
13
|
import { ReviewSubmitTemplate } from './KYCElements/ReviewSubmitTemplate';
|
|
13
14
|
import { VerificationProgressTemplate } from './KYCElements/VerificationProgressTemplate';
|
|
15
|
+
import { useTemplateLoader } from '../hooks/useTemplateLoader';
|
|
16
|
+
import { WelcomeTemplate } from './KYCElements/WelcomeTemplate';
|
|
14
17
|
|
|
15
18
|
interface TemplateKYCFlowProps {
|
|
16
|
-
template
|
|
19
|
+
template?: KYCTemplate; // Format SDK direct (existing, now optional)
|
|
20
|
+
templateId?: string; // New: ID to load from API
|
|
17
21
|
onComplete?: (data: VerificationState) => void;
|
|
18
22
|
onError?: (error: string) => void;
|
|
19
23
|
language?: string;
|
|
20
24
|
onCancel?: () => void;
|
|
21
|
-
API_KEY?: string;
|
|
25
|
+
API_KEY?: string; // Required if templateId is used
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
export const TemplateKYCFlow: React.FC<TemplateKYCFlowProps> = ({
|
|
25
|
-
template,
|
|
29
|
+
template: providedTemplate,
|
|
30
|
+
templateId,
|
|
26
31
|
onComplete,
|
|
27
32
|
onError,
|
|
28
33
|
language = 'fr',
|
|
@@ -30,9 +35,33 @@ export const TemplateKYCFlow: React.FC<TemplateKYCFlowProps> = ({
|
|
|
30
35
|
API_KEY,
|
|
31
36
|
}) => {
|
|
32
37
|
const { t } = useI18n();
|
|
38
|
+
const { template: loadedTemplate, isLoading, error, loadTemplate } = useTemplateLoader();
|
|
39
|
+
|
|
40
|
+
// Validate props
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (!providedTemplate && !templateId) {
|
|
43
|
+
const errorMsg = 'Either template or templateId must be provided';
|
|
44
|
+
onError?.(errorMsg);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (templateId && !API_KEY) {
|
|
49
|
+
// Try to load without API key (will use token authentication)
|
|
50
|
+
loadTemplate(templateId);
|
|
51
|
+
} else if (templateId && API_KEY) {
|
|
52
|
+
loadTemplate(templateId, API_KEY);
|
|
53
|
+
}
|
|
54
|
+
}, [templateId, API_KEY, providedTemplate, loadTemplate, onError]);
|
|
55
|
+
|
|
56
|
+
// Handle loading errors
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
if (error) {
|
|
59
|
+
onError?.(error);
|
|
60
|
+
}
|
|
61
|
+
}, [error, onError]);
|
|
33
62
|
|
|
34
63
|
const OnCancel = () => {
|
|
35
|
-
|
|
64
|
+
showAlert(
|
|
36
65
|
t('kyc.cancelConfirmation.title'),
|
|
37
66
|
t('kyc.cancelConfirmation.message'),
|
|
38
67
|
[
|
|
@@ -46,6 +75,46 @@ export const TemplateKYCFlow: React.FC<TemplateKYCFlowProps> = ({
|
|
|
46
75
|
]
|
|
47
76
|
);
|
|
48
77
|
};
|
|
78
|
+
|
|
79
|
+
// Determine which template to use
|
|
80
|
+
const template = providedTemplate || loadedTemplate;
|
|
81
|
+
|
|
82
|
+
// Show loading state while fetching template
|
|
83
|
+
if (templateId && isLoading && !template) {
|
|
84
|
+
return (
|
|
85
|
+
<View style={styles.loadingContainer}>
|
|
86
|
+
<ActivityIndicator size="large" color="#2DBD60" />
|
|
87
|
+
<Text style={styles.loadingText}>{t('common.loading') || 'Loading template...'}</Text>
|
|
88
|
+
</View>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Show error state if template failed to load
|
|
93
|
+
if (templateId && error && !template) {
|
|
94
|
+
return (
|
|
95
|
+
<View style={styles.errorContainer}>
|
|
96
|
+
<Text style={styles.errorText}>{error}</Text>
|
|
97
|
+
<TouchableOpacity
|
|
98
|
+
style={styles.retryButton}
|
|
99
|
+
onPress={() => loadTemplate(templateId, API_KEY)}
|
|
100
|
+
>
|
|
101
|
+
<Text style={styles.retryButtonText}>{t('common.retry') || 'Retry'}</Text>
|
|
102
|
+
</TouchableOpacity>
|
|
103
|
+
</View>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Show error if no template available
|
|
108
|
+
if (!template) {
|
|
109
|
+
return (
|
|
110
|
+
<View style={styles.errorContainer}>
|
|
111
|
+
<Text style={styles.errorText}>
|
|
112
|
+
{t('errors.unknownError') || 'Template not available'}
|
|
113
|
+
</Text>
|
|
114
|
+
</View>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
49
118
|
return (
|
|
50
119
|
<TemplateKYCFlowProvider
|
|
51
120
|
template={template}
|
|
@@ -97,6 +166,9 @@ const TemplateKYCFlowContent: React.FC<{ onCancel?: () => void }> = ({ onCancel
|
|
|
97
166
|
}
|
|
98
167
|
|
|
99
168
|
switch (currentComponent.type) {
|
|
169
|
+
case 'welcome':
|
|
170
|
+
return <WelcomeTemplate {...commonProps} />;
|
|
171
|
+
|
|
100
172
|
case 'id_card':
|
|
101
173
|
return <IDCardCapture {...commonProps} />;
|
|
102
174
|
|
|
@@ -166,9 +238,14 @@ const TemplateKYCFlowContent: React.FC<{ onCancel?: () => void }> = ({ onCancel
|
|
|
166
238
|
) : null}
|
|
167
239
|
|
|
168
240
|
{/* Contenu principal */}
|
|
169
|
-
<
|
|
241
|
+
<ScrollView
|
|
242
|
+
style={styles.scrollView}
|
|
243
|
+
contentContainerStyle={styles.content}
|
|
244
|
+
showsVerticalScrollIndicator={Platform.OS === 'web'}
|
|
245
|
+
bounces={false}
|
|
246
|
+
>
|
|
170
247
|
{renderCurrentComponent()}
|
|
171
|
-
</
|
|
248
|
+
</ScrollView>
|
|
172
249
|
|
|
173
250
|
{state.isProcessing && (
|
|
174
251
|
<View style={styles.processingContainer}>
|
|
@@ -253,11 +330,13 @@ const styles = StyleSheet.create({
|
|
|
253
330
|
color: '#666',
|
|
254
331
|
lineHeight: 20,
|
|
255
332
|
},
|
|
256
|
-
|
|
333
|
+
scrollView: {
|
|
257
334
|
flex: 1,
|
|
258
|
-
|
|
335
|
+
},
|
|
336
|
+
content: {
|
|
337
|
+
flexGrow: 1,
|
|
259
338
|
alignItems: 'center',
|
|
260
|
-
|
|
339
|
+
paddingBottom: 20, // Add padding for better mobile scrolling
|
|
261
340
|
},
|
|
262
341
|
navigation: {
|
|
263
342
|
flexDirection: 'row',
|
|
@@ -316,4 +395,35 @@ const styles = StyleSheet.create({
|
|
|
316
395
|
fontWeight: 'bold',
|
|
317
396
|
marginBottom: 10,
|
|
318
397
|
},
|
|
398
|
+
loadingContainer: {
|
|
399
|
+
flex: 1,
|
|
400
|
+
justifyContent: 'center',
|
|
401
|
+
alignItems: 'center',
|
|
402
|
+
backgroundColor: '#f5f5f5',
|
|
403
|
+
},
|
|
404
|
+
loadingText: {
|
|
405
|
+
marginTop: 16,
|
|
406
|
+
fontSize: 16,
|
|
407
|
+
color: '#666',
|
|
408
|
+
textAlign: 'center',
|
|
409
|
+
},
|
|
410
|
+
errorContainer: {
|
|
411
|
+
flex: 1,
|
|
412
|
+
justifyContent: 'center',
|
|
413
|
+
alignItems: 'center',
|
|
414
|
+
backgroundColor: '#f5f5f5',
|
|
415
|
+
padding: 20,
|
|
416
|
+
},
|
|
417
|
+
retryButton: {
|
|
418
|
+
marginTop: 20,
|
|
419
|
+
paddingHorizontal: 24,
|
|
420
|
+
paddingVertical: 12,
|
|
421
|
+
backgroundColor: '#2DBD60',
|
|
422
|
+
borderRadius: 8,
|
|
423
|
+
},
|
|
424
|
+
retryButtonText: {
|
|
425
|
+
color: '#fff',
|
|
426
|
+
fontSize: 16,
|
|
427
|
+
fontWeight: '600',
|
|
428
|
+
},
|
|
319
429
|
});
|