@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
|
@@ -1,82 +1,348 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useState, useMemo, useEffect } from 'react';
|
|
2
2
|
import { View, Text, TouchableOpacity, StyleSheet, ScrollView } from 'react-native';
|
|
3
3
|
import { countryMapping } from '../../config/region_mapping';
|
|
4
4
|
import { useTemplateKYCFlowContext } from '../../hooks/useTemplateKYCFlow';
|
|
5
|
-
import { useI18n } from '../../hooks/useI18n';
|
|
6
5
|
import { Button } from '../ui/Button';
|
|
7
6
|
import { countryData } from '../../config/countriesData';
|
|
8
7
|
export const CountrySelectionTemplate = ({ component, value, onValueChange, error, language = 'en', }) => {
|
|
9
|
-
const { t } = useI18n();
|
|
10
8
|
const config = component.config;
|
|
11
|
-
const allowedCountries = (config.allowed_countries || Object.keys(countryData));
|
|
12
|
-
const defaultCountry = config.default_country || 'CM';
|
|
13
9
|
const { actions, state } = useTemplateKYCFlowContext();
|
|
14
|
-
|
|
15
|
-
const
|
|
10
|
+
// Récupérer les données depuis le composant id_card
|
|
11
|
+
const idCardComponent = useMemo(() => {
|
|
12
|
+
return state.template.components.find(c => c.type === 'id_card');
|
|
13
|
+
}, [state.template.components]);
|
|
14
|
+
const idCardConfig = useMemo(() => {
|
|
15
|
+
return idCardComponent?.config;
|
|
16
|
+
}, [idCardComponent]);
|
|
17
|
+
// États de navigation - initialiser depuis value si disponible
|
|
18
|
+
const [currentStep, setCurrentStep] = useState(() => {
|
|
19
|
+
// Si value existe, on a déjà sélectionné -> aller à la dernière étape nécessaire
|
|
20
|
+
if (value?.code && value?.documentType) {
|
|
21
|
+
if (value.region)
|
|
22
|
+
return 'region';
|
|
23
|
+
return 'documentType';
|
|
24
|
+
}
|
|
25
|
+
return 'country';
|
|
26
|
+
});
|
|
27
|
+
const [selectedCountryCode, setSelectedCountryCode] = useState(value?.code || null);
|
|
28
|
+
const [selectedDocumentType, setSelectedDocumentType] = useState(value?.documentType || null);
|
|
29
|
+
const [selectedRegion, setSelectedRegion] = useState(value?.region || null);
|
|
30
|
+
// Restaurer l'état depuis value si le composant est remonté avec des données
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (value?.code && value?.documentType) {
|
|
33
|
+
setSelectedCountryCode(value.code);
|
|
34
|
+
setSelectedDocumentType(value.documentType);
|
|
35
|
+
setSelectedRegion(value.region || null);
|
|
36
|
+
// Déterminer l'étape actuelle
|
|
37
|
+
if (value.region) {
|
|
38
|
+
setCurrentStep('region');
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
// Vérifier si une région est nécessaire
|
|
42
|
+
const needsRegionCheck = value.code && value.documentType && idCardConfig?.regionsByCountry?.[value.code]?.[value.documentType];
|
|
43
|
+
if (needsRegionCheck && Array.isArray(needsRegionCheck) && needsRegionCheck.length > 0) {
|
|
44
|
+
setCurrentStep('region');
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
setCurrentStep('documentType');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// Réinitialiser si value est vide
|
|
53
|
+
setSelectedCountryCode(null);
|
|
54
|
+
setSelectedDocumentType(null);
|
|
55
|
+
setSelectedRegion(null);
|
|
56
|
+
setCurrentStep('country');
|
|
57
|
+
}
|
|
58
|
+
}, [value?.code, value?.documentType, value?.region, idCardConfig]);
|
|
59
|
+
// Récupérer les pays disponibles
|
|
60
|
+
const availableCountries = useMemo(() => {
|
|
61
|
+
const countries = idCardConfig?.selectedCountries || config.allowed_countries || Object.keys(countryData);
|
|
62
|
+
return countries
|
|
63
|
+
.filter((code) => countryData[code])
|
|
64
|
+
.map((code) => ({ code, ...countryData[code] }))
|
|
65
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
66
|
+
}, [idCardConfig?.selectedCountries, config.allowed_countries]);
|
|
67
|
+
// Récupérer les types de documents disponibles pour le pays sélectionné
|
|
68
|
+
const availableDocumentTypes = useMemo(() => {
|
|
69
|
+
if (!selectedCountryCode || !idCardConfig?.documentTypesByCountry)
|
|
70
|
+
return [];
|
|
71
|
+
return idCardConfig.documentTypesByCountry[selectedCountryCode] || [];
|
|
72
|
+
}, [selectedCountryCode, idCardConfig?.documentTypesByCountry]);
|
|
73
|
+
// Récupérer les régions disponibles pour le pays et type de document sélectionnés
|
|
74
|
+
const availableRegions = useMemo(() => {
|
|
75
|
+
if (!selectedCountryCode || !selectedDocumentType || !idCardConfig?.regionsByCountry)
|
|
76
|
+
return [];
|
|
77
|
+
const regions = idCardConfig.regionsByCountry[selectedCountryCode];
|
|
78
|
+
if (!regions)
|
|
79
|
+
return [];
|
|
80
|
+
return Array.isArray(regions[selectedDocumentType]) ? regions[selectedDocumentType] : [];
|
|
81
|
+
}, [selectedCountryCode, selectedDocumentType, idCardConfig?.regionsByCountry]);
|
|
82
|
+
// Vérifier si une région est nécessaire
|
|
83
|
+
const needsRegion = useMemo(() => {
|
|
84
|
+
return availableRegions.length > 0;
|
|
85
|
+
}, [availableRegions]);
|
|
16
86
|
const getLocalizedText = (text) => {
|
|
17
|
-
return text[
|
|
87
|
+
return text[state.currentLanguage] || text.en || '';
|
|
18
88
|
};
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
89
|
+
// Navigation entre les étapes
|
|
90
|
+
const handleCountrySelect = (countryCode) => {
|
|
91
|
+
setSelectedCountryCode(countryCode);
|
|
92
|
+
setSelectedDocumentType(null);
|
|
93
|
+
setSelectedRegion(null);
|
|
94
|
+
setCurrentStep('documentType');
|
|
95
|
+
};
|
|
96
|
+
const handleDocumentTypeSelect = (docType) => {
|
|
97
|
+
setSelectedDocumentType(docType);
|
|
98
|
+
setSelectedRegion(null);
|
|
99
|
+
// Vérifier si une région est nécessaire (doit être recalculé après setSelectedDocumentType)
|
|
100
|
+
const regions = selectedCountryCode && idCardConfig?.regionsByCountry?.[selectedCountryCode]?.[docType];
|
|
101
|
+
if (regions && Array.isArray(regions) && regions.length > 0) {
|
|
102
|
+
setCurrentStep('region');
|
|
31
103
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
104
|
+
else {
|
|
105
|
+
// Pas de région nécessaire, on peut finaliser
|
|
106
|
+
if (selectedCountryCode) {
|
|
107
|
+
finalizeSelection(selectedCountryCode, docType, null);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
const handleRegionSelect = (region) => {
|
|
112
|
+
setSelectedRegion(region);
|
|
113
|
+
if (selectedCountryCode && selectedDocumentType) {
|
|
114
|
+
finalizeSelection(selectedCountryCode, selectedDocumentType, region);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
const finalizeSelection = (countryCode, docType, region) => {
|
|
118
|
+
const country = countryData[countryCode];
|
|
119
|
+
if (!country)
|
|
120
|
+
return;
|
|
121
|
+
const mapping = countryMapping[countryCode];
|
|
122
|
+
const countryObj = {
|
|
123
|
+
code: countryCode,
|
|
124
|
+
...country,
|
|
125
|
+
regionMapping: mapping,
|
|
126
|
+
documentType: docType,
|
|
127
|
+
region: region || undefined,
|
|
128
|
+
};
|
|
129
|
+
onValueChange(countryObj);
|
|
130
|
+
// Passer à l'étape suivante après un court délai
|
|
131
|
+
setTimeout(() => {
|
|
132
|
+
actions.nextComponent();
|
|
133
|
+
}, 300);
|
|
134
|
+
};
|
|
135
|
+
const handleBack = () => {
|
|
136
|
+
if (currentStep === 'region') {
|
|
137
|
+
setCurrentStep('documentType');
|
|
138
|
+
setSelectedRegion(null);
|
|
139
|
+
}
|
|
140
|
+
else if (currentStep === 'documentType') {
|
|
141
|
+
setCurrentStep('country');
|
|
142
|
+
setSelectedDocumentType(null);
|
|
143
|
+
setSelectedRegion(null);
|
|
144
|
+
}
|
|
145
|
+
else if (currentStep === 'country') {
|
|
146
|
+
// Retour au composant précédent
|
|
147
|
+
actions.previousComponent();
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
const handleNext = () => {
|
|
151
|
+
if (currentStep === 'country' && selectedCountryCode) {
|
|
152
|
+
setCurrentStep('documentType');
|
|
153
|
+
}
|
|
154
|
+
else if (currentStep === 'documentType' && selectedDocumentType) {
|
|
155
|
+
if (needsRegion) {
|
|
156
|
+
setCurrentStep('region');
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
if (selectedCountryCode) {
|
|
160
|
+
finalizeSelection(selectedCountryCode, selectedDocumentType, null);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else if (currentStep === 'region' && selectedRegion) {
|
|
165
|
+
if (selectedCountryCode && selectedDocumentType) {
|
|
166
|
+
finalizeSelection(selectedCountryCode, selectedDocumentType, selectedRegion);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
// Rendu de l'étape de sélection du pays
|
|
171
|
+
const renderCountrySelection = () => {
|
|
172
|
+
return (<>
|
|
173
|
+
<ScrollView style={styles.listContainer} showsVerticalScrollIndicator={false}>
|
|
174
|
+
{availableCountries.map((country) => (<TouchableOpacity key={country.code} style={[
|
|
175
|
+
styles.option,
|
|
176
|
+
selectedCountryCode === country.code && styles.selectedOption
|
|
177
|
+
]} onPress={() => handleCountrySelect(country.code)}>
|
|
178
|
+
<Text style={styles.flag}>{country.flag}</Text>
|
|
179
|
+
<View style={styles.optionContent}>
|
|
50
180
|
<Text style={[
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
181
|
+
styles.optionName,
|
|
182
|
+
selectedCountryCode === country.code && styles.selectedOptionName
|
|
183
|
+
]}>
|
|
54
184
|
{state.currentLanguage === "en" ? country.name_en : country.name}
|
|
55
185
|
</Text>
|
|
56
|
-
<Text style={styles.
|
|
186
|
+
<Text style={styles.optionCode}>{country.code}</Text>
|
|
57
187
|
</View>
|
|
58
|
-
{
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
188
|
+
{selectedCountryCode === country.code && (<View style={[
|
|
189
|
+
styles.checkmark,
|
|
190
|
+
{ backgroundColor: component.ui.themeColor || '#2DBD60' }
|
|
191
|
+
]}>
|
|
62
192
|
<Text style={styles.checkmarkText}>✓</Text>
|
|
63
193
|
</View>)}
|
|
64
194
|
</TouchableOpacity>))}
|
|
65
195
|
</ScrollView>
|
|
196
|
+
</>);
|
|
197
|
+
};
|
|
198
|
+
// Rendu de l'étape de sélection du type de document
|
|
199
|
+
const renderDocumentTypeSelection = () => {
|
|
200
|
+
const instructions = selectedDocumentType && idCardConfig?.instructionsByDocumentType?.[selectedDocumentType]
|
|
201
|
+
? getLocalizedText(idCardConfig.instructionsByDocumentType[selectedDocumentType])
|
|
202
|
+
: null;
|
|
203
|
+
// Mapping des labels pour l'affichage
|
|
204
|
+
const documentTypeLabels = {
|
|
205
|
+
'nationalId': { en: 'National ID', fr: 'Carte nationale d\'identité', icon: '🏛️' },
|
|
206
|
+
'passport': { en: 'Passport', fr: 'Passeport', icon: '📘' },
|
|
207
|
+
'driversLicense': { en: 'Driver\'s License', fr: 'Permis de conduire', icon: '🚗' },
|
|
208
|
+
'residencePermit': { en: 'Residence Permit', fr: 'Permis de séjour', icon: '🏠' },
|
|
209
|
+
'healthInsuranceCard': { en: 'Health Insurance Card', fr: 'Carte d\'assurance maladie', icon: '🗳️' },
|
|
210
|
+
};
|
|
211
|
+
return (<>
|
|
212
|
+
{instructions && (<View style={styles.infoBox}>
|
|
213
|
+
<Text style={styles.infoText}>{instructions}</Text>
|
|
214
|
+
</View>)}
|
|
215
|
+
<ScrollView style={styles.listContainer} showsVerticalScrollIndicator={false}>
|
|
216
|
+
{availableDocumentTypes.map((docType) => {
|
|
217
|
+
const label = documentTypeLabels[docType];
|
|
218
|
+
const displayName = label ? (state.currentLanguage === "en" ? label.en : label.fr) : docType;
|
|
219
|
+
const icon = label?.icon || '📄';
|
|
220
|
+
return (<TouchableOpacity key={docType} style={[
|
|
221
|
+
styles.option,
|
|
222
|
+
selectedDocumentType === docType && styles.selectedOption
|
|
223
|
+
]} onPress={() => handleDocumentTypeSelect(docType)}>
|
|
224
|
+
<Text style={styles.flag}>{icon}</Text>
|
|
225
|
+
<View style={styles.optionContent}>
|
|
226
|
+
<Text style={[
|
|
227
|
+
styles.optionName,
|
|
228
|
+
selectedDocumentType === docType && styles.selectedOptionName
|
|
229
|
+
]}>
|
|
230
|
+
{displayName}
|
|
231
|
+
</Text>
|
|
232
|
+
</View>
|
|
233
|
+
{selectedDocumentType === docType && (<View style={[
|
|
234
|
+
styles.checkmark,
|
|
235
|
+
{ backgroundColor: component.ui.themeColor || '#2DBD60' }
|
|
236
|
+
]}>
|
|
237
|
+
<Text style={styles.checkmarkText}>✓</Text>
|
|
238
|
+
</View>)}
|
|
239
|
+
</TouchableOpacity>);
|
|
240
|
+
})}
|
|
241
|
+
</ScrollView>
|
|
242
|
+
</>);
|
|
243
|
+
};
|
|
244
|
+
// Rendu de l'étape de sélection de la région
|
|
245
|
+
const renderRegionSelection = () => {
|
|
246
|
+
return (<>
|
|
247
|
+
<ScrollView style={styles.listContainer} showsVerticalScrollIndicator={false}>
|
|
248
|
+
{availableRegions.map((region, index) => {
|
|
249
|
+
const regionLabel = typeof region === 'string' ? region : String(region);
|
|
250
|
+
return (<TouchableOpacity key={index} style={[
|
|
251
|
+
styles.option,
|
|
252
|
+
selectedRegion === regionLabel && styles.selectedOption
|
|
253
|
+
]} onPress={() => handleRegionSelect(regionLabel)}>
|
|
254
|
+
<View style={styles.optionContent}>
|
|
255
|
+
<Text style={[
|
|
256
|
+
styles.optionName,
|
|
257
|
+
selectedRegion === regionLabel && styles.selectedOptionName
|
|
258
|
+
]}>
|
|
259
|
+
{regionLabel}
|
|
260
|
+
</Text>
|
|
261
|
+
</View>
|
|
262
|
+
{selectedRegion === regionLabel && (<View style={[
|
|
263
|
+
styles.checkmark,
|
|
264
|
+
{ backgroundColor: component.ui.themeColor || '#2DBD60' }
|
|
265
|
+
]}>
|
|
266
|
+
<Text style={styles.checkmarkText}>✓</Text>
|
|
267
|
+
</View>)}
|
|
268
|
+
</TouchableOpacity>);
|
|
269
|
+
})}
|
|
270
|
+
</ScrollView>
|
|
271
|
+
</>);
|
|
272
|
+
};
|
|
273
|
+
// Titres des étapes
|
|
274
|
+
const getStepTitle = () => {
|
|
275
|
+
switch (currentStep) {
|
|
276
|
+
case 'country':
|
|
277
|
+
return getLocalizedText(component.labels);
|
|
278
|
+
case 'documentType':
|
|
279
|
+
return state.currentLanguage === "en" ? "Select Document Type" : "Sélectionnez le type de document";
|
|
280
|
+
case 'region':
|
|
281
|
+
return state.currentLanguage === "en" ? "Select Region" : "Sélectionnez la région";
|
|
282
|
+
default:
|
|
283
|
+
return '';
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
const getStepDescription = () => {
|
|
287
|
+
switch (currentStep) {
|
|
288
|
+
case 'country':
|
|
289
|
+
return getLocalizedText(component.instructions);
|
|
290
|
+
case 'documentType':
|
|
291
|
+
return state.currentLanguage === "en"
|
|
292
|
+
? "Choose the type of document you want to use"
|
|
293
|
+
: "Choisissez le type de document que vous souhaitez utiliser";
|
|
294
|
+
case 'region':
|
|
295
|
+
return state.currentLanguage === "en"
|
|
296
|
+
? "Select your region"
|
|
297
|
+
: "Sélectionnez votre région";
|
|
298
|
+
default:
|
|
299
|
+
return '';
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
// Indicateur de progression
|
|
303
|
+
const getProgressStep = () => {
|
|
304
|
+
if (currentStep === 'country')
|
|
305
|
+
return 1;
|
|
306
|
+
if (currentStep === 'documentType')
|
|
307
|
+
return 2;
|
|
308
|
+
return 3;
|
|
309
|
+
};
|
|
310
|
+
const getTotalSteps = () => {
|
|
311
|
+
return needsRegion ? 3 : 2;
|
|
312
|
+
};
|
|
313
|
+
const canGoNext = () => {
|
|
314
|
+
if (currentStep === 'country')
|
|
315
|
+
return selectedCountryCode !== null;
|
|
316
|
+
if (currentStep === 'documentType')
|
|
317
|
+
return selectedDocumentType !== null;
|
|
318
|
+
if (currentStep === 'region')
|
|
319
|
+
return selectedRegion !== null;
|
|
320
|
+
return false;
|
|
321
|
+
};
|
|
322
|
+
return (<View style={styles.root}>
|
|
323
|
+
<View style={styles.container}>
|
|
324
|
+
{/* Indicateur de progression */}
|
|
325
|
+
<View style={styles.progressContainer}>
|
|
326
|
+
<Text style={styles.progressText}>
|
|
327
|
+
{state.currentLanguage === "en"
|
|
328
|
+
? `Step ${getProgressStep()} of ${getTotalSteps()}`
|
|
329
|
+
: `Étape ${getProgressStep()} sur ${getTotalSteps()}`}
|
|
330
|
+
</Text>
|
|
331
|
+
</View>
|
|
66
332
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
onValueChange({ ...selectedCountry, regionMapping: mapping });
|
|
70
|
-
setTimeout(() => {
|
|
71
|
-
actions.nextComponent();
|
|
72
|
-
}, 500);
|
|
73
|
-
}} variant="primary" size="large" fullWidth/>)}
|
|
74
|
-
|
|
75
|
-
{config.required && !selectedValue && (<View style={styles.requiredContainer}>
|
|
333
|
+
<Text style={styles.title}>{getStepTitle()}</Text>
|
|
334
|
+
<Text style={styles.description}>{getStepDescription()}</Text>
|
|
76
335
|
|
|
336
|
+
{/* Contenu de l'étape actuelle */}
|
|
337
|
+
{currentStep === 'country' && renderCountrySelection()}
|
|
338
|
+
{currentStep === 'documentType' && renderDocumentTypeSelection()}
|
|
339
|
+
{currentStep === 'region' && renderRegionSelection()}
|
|
77
340
|
|
|
78
|
-
|
|
79
|
-
|
|
341
|
+
{/* Boutons de navigation */}
|
|
342
|
+
<View style={styles.buttonContainer}>
|
|
343
|
+
<Button title={state.currentLanguage === "en" ? "Back" : "Retour"} onPress={handleBack} variant={currentStep === 'country' ? "secondary" : "outline"} size="large" style={currentStep === 'country' ? { flex: 1 } : { flex: 1, marginRight: 8 }}/>
|
|
344
|
+
{currentStep !== 'country' && (<Button title={state.currentLanguage === "en" ? "Next" : "Suivant"} onPress={handleNext} variant="primary" size="large" style={{ flex: 1 }} disabled={!canGoNext()}/>)}
|
|
345
|
+
</View>
|
|
80
346
|
|
|
81
347
|
{error && (<Text style={styles.errorText}>{error}</Text>)}
|
|
82
348
|
</View>
|
|
@@ -94,13 +360,21 @@ const styles = StyleSheet.create({
|
|
|
94
360
|
borderRadius: 10,
|
|
95
361
|
paddingVertical: 16,
|
|
96
362
|
paddingHorizontal: 16,
|
|
97
|
-
// shadow
|
|
98
363
|
shadowColor: '#000',
|
|
99
364
|
shadowOffset: { width: 0, height: 2 },
|
|
100
365
|
shadowOpacity: 0.35,
|
|
101
366
|
shadowRadius: 4.84,
|
|
102
367
|
elevation: 10,
|
|
103
368
|
},
|
|
369
|
+
progressContainer: {
|
|
370
|
+
marginBottom: 16,
|
|
371
|
+
alignItems: 'center',
|
|
372
|
+
},
|
|
373
|
+
progressText: {
|
|
374
|
+
fontSize: 14,
|
|
375
|
+
color: '#666',
|
|
376
|
+
fontWeight: '500',
|
|
377
|
+
},
|
|
104
378
|
title: {
|
|
105
379
|
fontSize: 24,
|
|
106
380
|
fontWeight: 'bold',
|
|
@@ -115,48 +389,41 @@ const styles = StyleSheet.create({
|
|
|
115
389
|
marginBottom: 24,
|
|
116
390
|
lineHeight: 22,
|
|
117
391
|
},
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
392
|
+
listContainer: {
|
|
393
|
+
maxHeight: 400,
|
|
394
|
+
marginBottom: 24,
|
|
121
395
|
},
|
|
122
|
-
|
|
396
|
+
option: {
|
|
123
397
|
flexDirection: 'row',
|
|
124
398
|
alignItems: 'center',
|
|
125
399
|
padding: 16,
|
|
126
|
-
backgroundColor: '
|
|
400
|
+
backgroundColor: '#F8F9FA',
|
|
127
401
|
borderRadius: 12,
|
|
128
402
|
marginBottom: 12,
|
|
129
403
|
borderWidth: 2,
|
|
130
|
-
borderColor: '#
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
height: 2,
|
|
135
|
-
},
|
|
136
|
-
shadowOpacity: 0.1,
|
|
137
|
-
shadowRadius: 3.84,
|
|
138
|
-
elevation: 5,
|
|
139
|
-
},
|
|
140
|
-
selectedCountryOption: {
|
|
404
|
+
borderColor: '#E9ECEF',
|
|
405
|
+
minHeight: 64,
|
|
406
|
+
},
|
|
407
|
+
selectedOption: {
|
|
141
408
|
borderColor: '#2DBD60',
|
|
142
|
-
backgroundColor: '#
|
|
409
|
+
backgroundColor: '#F0F9F0',
|
|
143
410
|
},
|
|
144
|
-
|
|
411
|
+
flag: {
|
|
145
412
|
fontSize: 32,
|
|
146
413
|
marginRight: 16,
|
|
147
414
|
},
|
|
148
|
-
|
|
415
|
+
optionContent: {
|
|
149
416
|
flex: 1,
|
|
150
417
|
},
|
|
151
|
-
|
|
418
|
+
optionName: {
|
|
152
419
|
fontSize: 18,
|
|
153
420
|
fontWeight: '600',
|
|
154
421
|
color: '#333',
|
|
155
422
|
},
|
|
156
|
-
|
|
423
|
+
selectedOptionName: {
|
|
157
424
|
color: '#2DBD60',
|
|
158
425
|
},
|
|
159
|
-
|
|
426
|
+
optionCode: {
|
|
160
427
|
fontSize: 14,
|
|
161
428
|
color: '#666',
|
|
162
429
|
marginTop: 4,
|
|
@@ -174,29 +441,21 @@ const styles = StyleSheet.create({
|
|
|
174
441
|
fontSize: 16,
|
|
175
442
|
fontWeight: 'bold',
|
|
176
443
|
},
|
|
177
|
-
|
|
178
|
-
backgroundColor: '#
|
|
179
|
-
padding:
|
|
180
|
-
borderRadius:
|
|
181
|
-
|
|
182
|
-
alignItems: 'center',
|
|
183
|
-
},
|
|
184
|
-
selectionText: {
|
|
185
|
-
fontSize: 16,
|
|
186
|
-
fontWeight: '600',
|
|
187
|
-
color: '#2DBD60',
|
|
444
|
+
infoBox: {
|
|
445
|
+
backgroundColor: '#F9FAFB',
|
|
446
|
+
padding: 12,
|
|
447
|
+
borderRadius: 12,
|
|
448
|
+
marginBottom: 16,
|
|
188
449
|
},
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
marginTop: 16,
|
|
194
|
-
alignItems: 'center',
|
|
450
|
+
infoText: {
|
|
451
|
+
fontSize: 14,
|
|
452
|
+
color: '#666',
|
|
453
|
+
lineHeight: 20,
|
|
195
454
|
},
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
455
|
+
buttonContainer: {
|
|
456
|
+
flexDirection: 'row',
|
|
457
|
+
marginTop: 24,
|
|
458
|
+
gap: 12,
|
|
200
459
|
},
|
|
201
460
|
errorText: {
|
|
202
461
|
color: '#dc2626',
|