@sanctum-key/react-native-sdk 1.0.48 → 1.0.50

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 (58) hide show
  1. package/build/package.json +1 -1
  2. package/build/src/components/KYCElements/CountrySelection.d.ts.map +1 -1
  3. package/build/src/components/KYCElements/CountrySelection.js +33 -108
  4. package/build/src/components/KYCElements/CountrySelection.js.map +1 -1
  5. package/build/src/components/KYCElements/CountrySelectionTemplate.d.ts.map +1 -1
  6. package/build/src/components/KYCElements/CountrySelectionTemplate.js +50 -164
  7. package/build/src/components/KYCElements/CountrySelectionTemplate.js.map +1 -1
  8. package/build/src/components/KYCElements/DocumentTypeSelection.d.ts.map +1 -1
  9. package/build/src/components/KYCElements/DocumentTypeSelection.js +32 -109
  10. package/build/src/components/KYCElements/DocumentTypeSelection.js.map +1 -1
  11. package/build/src/components/KYCElements/IDCardCapture.d.ts.map +1 -1
  12. package/build/src/components/KYCElements/IDCardCapture.js +58 -25
  13. package/build/src/components/KYCElements/IDCardCapture.js.map +1 -1
  14. package/build/src/components/KYCElements/InitializationStep.d.ts.map +1 -1
  15. package/build/src/components/KYCElements/InitializationStep.js +13 -1
  16. package/build/src/components/KYCElements/InitializationStep.js.map +1 -1
  17. package/build/src/components/KYCElements/LocationCaptureTemplate.d.ts.map +1 -1
  18. package/build/src/components/KYCElements/LocationCaptureTemplate.js +46 -157
  19. package/build/src/components/KYCElements/LocationCaptureTemplate.js.map +1 -1
  20. package/build/src/components/KYCElements/SelfieCapture.d.ts.map +1 -1
  21. package/build/src/components/KYCElements/SelfieCapture.js +28 -24
  22. package/build/src/components/KYCElements/SelfieCapture.js.map +1 -1
  23. package/build/src/components/KYCElements/VerificationProgressTemplate.d.ts.map +1 -1
  24. package/build/src/components/KYCElements/VerificationProgressTemplate.js +31 -40
  25. package/build/src/components/KYCElements/VerificationProgressTemplate.js.map +1 -1
  26. package/build/src/components/SelfieCapture.d.ts.map +1 -1
  27. package/build/src/components/SelfieCapture.js +33 -90
  28. package/build/src/components/SelfieCapture.js.map +1 -1
  29. package/build/src/components/TemplateKYCExample.d.ts.map +1 -1
  30. package/build/src/components/TemplateKYCExample.js +69 -120
  31. package/build/src/components/TemplateKYCExample.js.map +1 -1
  32. package/build/src/components/TemplateKYCFlowRefactored.d.ts +0 -2
  33. package/build/src/components/TemplateKYCFlowRefactored.d.ts.map +1 -1
  34. package/build/src/components/TemplateKYCFlowRefactored.js +95 -210
  35. package/build/src/components/TemplateKYCFlowRefactored.js.map +1 -1
  36. package/build/src/hooks/useTemplateKYCFlow.d.ts.map +1 -1
  37. package/build/src/hooks/useTemplateKYCFlow.js.map +1 -1
  38. package/build/src/types/KYC.types.d.ts.map +1 -1
  39. package/build/src/types/KYC.types.js.map +1 -1
  40. package/build/src/utils/logger.d.ts +12 -4
  41. package/build/src/utils/logger.d.ts.map +1 -1
  42. package/build/src/utils/logger.js +156 -28
  43. package/build/src/utils/logger.js.map +1 -1
  44. package/package.json +1 -1
  45. package/src/components/KYCElements/CountrySelection.tsx +36 -109
  46. package/src/components/KYCElements/CountrySelectionTemplate.tsx +67 -266
  47. package/src/components/KYCElements/DocumentTypeSelection.tsx +34 -110
  48. package/src/components/KYCElements/IDCardCapture.tsx +93 -39
  49. package/src/components/KYCElements/InitializationStep.tsx +17 -2
  50. package/src/components/KYCElements/LocationCaptureTemplate.tsx +53 -170
  51. package/src/components/KYCElements/SelfieCapture.tsx +50 -58
  52. package/src/components/KYCElements/VerificationProgressTemplate.tsx +38 -45
  53. package/src/components/SelfieCapture.tsx +44 -100
  54. package/src/components/TemplateKYCExample.tsx +94 -145
  55. package/src/components/TemplateKYCFlowRefactored.tsx +105 -239
  56. package/src/hooks/useTemplateKYCFlow.tsx +1 -0
  57. package/src/types/KYC.types.ts +0 -1
  58. package/src/utils/logger.ts +182 -29
@@ -6,6 +6,7 @@ import { useTemplateKYCFlowContext } from '../../hooks/useTemplateKYCFlow';
6
6
  import { Button } from '../ui/Button';
7
7
  import { countryData } from '../../config/countriesData';
8
8
  import REGION_MAPPING from '../../config/region_mapping.json';
9
+ import { sdkLogger } from '../../utils/logger'; // 🚨 IMPORT SDK LOGGER
9
10
 
10
11
  interface CountrySelectionTemplateProps {
11
12
  component: TemplateComponent;
@@ -25,51 +26,23 @@ type ExtendedIDCardConfig = IDCardConfig & {
25
26
  };
26
27
 
27
28
  const ISO_TO_COUNTRY_NAME: Record<string, string> = { 'KE': 'Kenya', 'CM': 'Cameroon', 'NG': 'Nigeria', 'CA': 'Canada', 'FR': 'France', 'GH': 'Ghana', 'ZA': 'South Africa', 'GB': 'Britain', 'CI': 'Ivory Coast', 'SN': 'Senegal', 'TG': 'Togo', 'ML': 'Mali' };
29
+ const jsonDocMap: Record<string, string> = { 'nationalId': 'identity_card', 'national_id': 'identity_card', 'passport': 'passport', 'driversLicense': 'drivers_licence', 'drivers_licence': 'drivers_licence', 'residencePermit': 'permanent_residence', 'healthInsuranceCard': 'health_insurance_card' };
30
+ const SUB_REGION_CODES: Record<string, string> = { "Alberta": "AB", "British Columbia": "BC", "Manitoba": "MB", "New Brunswick": "NB", "Newfoundland and Labrador": "NL", "Northwest Territories": "NT", "Nova Scotia": "NS", "Nunavut": "NU", "Ontario": "ON", "Prince Edward Island": "PE", "Quebec": "QC", "Saskatchewan": "SK", "Yukon": "YT" };
28
31
 
29
- const jsonDocMap: Record<string, string> = {
30
- 'nationalId': 'identity_card',
31
- 'national_id': 'identity_card',
32
- 'passport': 'passport',
33
- 'driversLicense': 'drivers_licence',
34
- 'drivers_licence': 'drivers_licence',
35
- 'residencePermit': 'permanent_residence',
36
- 'healthInsuranceCard': 'health_insurance_card'
37
- };
38
-
39
- const SUB_REGION_CODES: Record<string, string> = {
40
- "Alberta": "AB",
41
- "British Columbia": "BC",
42
- "Manitoba": "MB",
43
- "New Brunswick": "NB",
44
- "Newfoundland and Labrador": "NL",
45
- "Northwest Territories": "NT",
46
- "Nova Scotia": "NS",
47
- "Nunavut": "NU",
48
- "Ontario": "ON",
49
- "Prince Edward Island": "PE",
50
- "Quebec": "QC",
51
- "Saskatchewan": "SK",
52
- "Yukon": "YT"
53
- };
54
-
55
- export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> = ({
56
- component,
57
- value,
58
- onValueChange,
59
- error,
60
- language = 'en',
61
- }) => {
32
+ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> = ({ component, value, onValueChange, error, language = 'en', }) => {
62
33
  const config = component.config as CountrySelectionConfig;
63
34
  const { actions, state } = useTemplateKYCFlowContext();
64
35
 
65
- const idCardComponent = useMemo(() => {
66
- return state.template.components.find(c => c.type === 'id_card');
67
- }, [state.template.components]);
68
-
69
- const idCardConfig = useMemo(() => {
70
- return idCardComponent?.config as ExtendedIDCardConfig | undefined;
71
- }, [idCardComponent]);
36
+ // 🚨 LOG: Track when the user reaches this step
37
+ useEffect(() => {
38
+ if (state.session?.session_id) {
39
+ sdkLogger.info("User started country and document selection step");
40
+ }
41
+ }, [state.session?.session_id]);
72
42
 
43
+ const idCardComponent = useMemo(() => { return state.template.components.find(c => c.type === 'id_card'); }, [state.template.components]);
44
+ const idCardConfig = useMemo(() => { return idCardComponent?.config as ExtendedIDCardConfig | undefined; }, [idCardComponent]);
45
+
73
46
  const [currentStep, setCurrentStep] = useState<SelectionStep>(() => {
74
47
  if (value?.code && value?.documentType) {
75
48
  if (value.region) return 'region';
@@ -77,11 +50,10 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
77
50
  }
78
51
  return 'country';
79
52
  });
80
-
53
+
81
54
  const [selectedCountryCode, setSelectedCountryCode] = useState<string | null>(value?.code || null);
82
55
  const [selectedDocumentType, setSelectedDocumentType] = useState<string | null>(value?.documentType || null);
83
56
  const [selectedRegion, setSelectedRegion] = useState<string | null>(value?.region || null);
84
-
85
57
  const [searchQuery, setSearchQuery] = useState('');
86
58
 
87
59
  useEffect(() => {
@@ -89,28 +61,23 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
89
61
  setSelectedCountryCode(value.code);
90
62
  setSelectedDocumentType(value.documentType);
91
63
  setSelectedRegion(value.region || null);
92
-
93
64
  if (value.region) {
94
65
  setCurrentStep('region');
95
66
  } else {
96
67
  let regionsCheck = idCardConfig?.regionsByCountry?.[value.code]?.[value.documentType] || [];
97
-
98
68
  if (regionsCheck.length === 0) {
99
69
  const rawCountryName = ISO_TO_COUNTRY_NAME[value.code] || value.code;
100
70
  const searchDocType = jsonDocMap[value.documentType] || value.documentType;
101
71
  const baseMapping = (REGION_MAPPING as any).regionMapping || REGION_MAPPING;
102
-
103
72
  let countryMapping = baseMapping[rawCountryName];
104
73
  if (!countryMapping) {
105
74
  const foundKey = Object.keys(baseMapping).find(k => k.toLowerCase() === rawCountryName.toLowerCase());
106
75
  if (foundKey) countryMapping = baseMapping[foundKey];
107
76
  }
108
-
109
77
  if (countryMapping && countryMapping[searchDocType]) {
110
78
  regionsCheck = Object.keys(countryMapping[searchDocType]).filter(k => k !== 'root');
111
79
  }
112
80
  }
113
-
114
81
  if (Array.isArray(regionsCheck) && regionsCheck.length > 0) {
115
82
  setCurrentStep('region');
116
83
  } else {
@@ -126,16 +93,12 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
126
93
  }, [value?.code, value?.documentType, value?.region, idCardConfig]);
127
94
 
128
95
  useEffect(() => {
129
- if (error) {
130
- actions.updateComponentData(component.id, value);
131
- }
96
+ if (error) { actions.updateComponentData(component.id, value); }
132
97
  }, []);
133
98
 
134
99
  const availableCountries = useMemo(() => {
135
100
  const explicitlyAllowed = idCardConfig?.selectedCountries || config.allowed_countries || [];
136
-
137
101
  const configuredCodes = new Set(explicitlyAllowed);
138
-
139
102
  return Array.from(configuredCodes)
140
103
  .filter((code: string) => countryData[code])
141
104
  .map((code: string) => ({ code, ...countryData[code] }))
@@ -145,131 +108,86 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
145
108
  const filteredCountries = useMemo(() => {
146
109
  if (!searchQuery.trim()) return availableCountries;
147
110
  const cleanQuery = searchQuery.toLowerCase().trim();
148
-
149
- return availableCountries.filter(country =>
150
- country.name.toLowerCase().includes(cleanQuery) ||
151
- country.name_en.toLowerCase().includes(cleanQuery) ||
152
- country.code.toLowerCase().includes(cleanQuery)
111
+ return availableCountries.filter(country =>
112
+ country.name.toLowerCase().includes(cleanQuery) || country.name_en.toLowerCase().includes(cleanQuery) || country.code.toLowerCase().includes(cleanQuery)
153
113
  );
154
114
  }, [searchQuery, availableCountries]);
155
115
 
156
116
  const availableDocumentTypes = useMemo(() => {
157
117
  if (!selectedCountryCode) return [];
158
-
159
- // Check if custom layout configuration explicitly defined items for it
160
118
  if (idCardConfig?.documentTypesByCountry?.[selectedCountryCode]) {
161
119
  return idCardConfig.documentTypesByCountry[selectedCountryCode];
162
120
  }
163
-
164
- // Default Fallback: Query mapping matrix dynamically
165
121
  const rawCountryName = ISO_TO_COUNTRY_NAME[selectedCountryCode] || selectedCountryCode;
166
122
  const baseMapping = (REGION_MAPPING as any).regionMapping || REGION_MAPPING;
167
-
168
123
  let countryMapping = baseMapping[rawCountryName];
169
124
  if (!countryMapping) {
170
125
  const foundKey = Object.keys(baseMapping).find(k => k.toLowerCase() === rawCountryName.toLowerCase());
171
126
  if (foundKey) countryMapping = baseMapping[foundKey];
172
127
  }
173
-
174
128
  if (countryMapping) {
175
- const inverseDocMap: Record<string, string> = {
176
- 'identity_card': 'nationalId',
177
- 'passport': 'passport',
178
- 'drivers_licence': 'driversLicense',
179
- 'permanent_residence': 'residencePermit',
180
- 'health_insurance_card': 'healthInsuranceCard'
181
- };
129
+ const inverseDocMap: Record<string, string> = { 'identity_card': 'nationalId', 'passport': 'passport', 'drivers_licence': 'driversLicense', 'permanent_residence': 'residencePermit', 'health_insurance_card': 'healthInsuranceCard' };
182
130
  return Object.keys(countryMapping).map(key => inverseDocMap[key] || key);
183
131
  }
184
-
185
132
  return ['nationalId', 'passport', 'driversLicense'];
186
133
  }, [selectedCountryCode, idCardConfig?.documentTypesByCountry]);
187
134
 
188
135
  const availableRegions = useMemo(() => {
189
136
  if (!selectedCountryCode || !selectedDocumentType) return [];
190
-
191
137
  let rawRegions: string[] = [];
192
-
193
138
  if (idCardConfig?.regionsByCountry?.[selectedCountryCode]?.[selectedDocumentType]) {
194
139
  rawRegions = idCardConfig.regionsByCountry[selectedCountryCode][selectedDocumentType];
195
140
  }
196
-
197
141
  if (rawRegions.length === 0) {
198
142
  const rawCountryName = ISO_TO_COUNTRY_NAME[selectedCountryCode] || selectedCountryCode;
199
143
  const searchDocType = jsonDocMap[selectedDocumentType] || selectedDocumentType;
200
144
  const baseMapping = (REGION_MAPPING as any).regionMapping || REGION_MAPPING;
201
-
202
145
  let countryMapping = baseMapping[rawCountryName];
203
146
  if (!countryMapping) {
204
147
  const foundKey = Object.keys(baseMapping).find(k => k.toLowerCase() === rawCountryName.toLowerCase());
205
148
  if (foundKey) countryMapping = baseMapping[foundKey];
206
149
  }
207
-
208
150
  if (countryMapping && countryMapping[searchDocType]) {
209
151
  rawRegions = Object.keys(countryMapping[searchDocType]).filter(k => k !== 'root');
210
152
  }
211
153
  }
212
-
213
154
  if (!Array.isArray(rawRegions)) return [];
214
-
215
- return rawRegions.sort((a, b) => a.localeCompare(b)).map(region => ({
216
- label: region,
217
- value: SUB_REGION_CODES[region] || region
218
- }));
155
+ return rawRegions.sort((a, b) => a.localeCompare(b)).map(region => ({ label: region, value: SUB_REGION_CODES[region] || region }));
219
156
  }, [selectedCountryCode, selectedDocumentType, idCardConfig?.regionsByCountry]);
220
157
 
221
- const needsRegion = useMemo(() => {
222
- return availableRegions.length > 0;
223
- }, [availableRegions]);
158
+ const needsRegion = useMemo(() => { return availableRegions.length > 0; }, [availableRegions]);
159
+ const getLocalizedText = (text: LocalizedText): string => { return text[state.currentLanguage] || text.en || ''; };
224
160
 
225
- const getLocalizedText = (text: LocalizedText): string => {
226
- return text[state.currentLanguage] || text.en || '';
227
- };
228
-
229
- const handleCountrySelect = (countryCode: string) => {
230
- setSelectedCountryCode(countryCode);
231
- setSelectedDocumentType(null);
232
- setSelectedRegion(null);
233
- };
234
-
235
- const handleDocumentTypeSelect = (docType: string) => {
236
- setSelectedDocumentType(docType);
237
- setSelectedRegion(null);
238
- };
239
-
240
- const handleRegionSelect = (regionValue: string) => {
241
- setSelectedRegion(regionValue);
242
- };
161
+ const handleCountrySelect = (countryCode: string) => { setSelectedCountryCode(countryCode); setSelectedDocumentType(null); setSelectedRegion(null); };
162
+ const handleDocumentTypeSelect = (docType: string) => { setSelectedDocumentType(docType); setSelectedRegion(null); };
163
+ const handleRegionSelect = (regionValue: string) => { setSelectedRegion(regionValue); };
243
164
 
244
165
  const finalizeSelection = (countryCode: string, docType: string, region: string | null) => {
245
166
  const country = countryData[countryCode];
246
167
  if (!country) return;
168
+
169
+ // 🚨 LOG: Final payload successfully selected
170
+ sdkLogger.info("User finalized document configuration", {
171
+ countryCode,
172
+ documentType: docType,
173
+ region: region || 'none'
174
+ });
247
175
 
248
176
  const mapping = countryMapping[countryCode as keyof typeof countryMapping];
249
177
  const countryObj: Country & { documentType?: string; region?: string } = {
250
- code: countryCode,
251
- ...country,
252
- regionMapping: mapping,
253
- documentType: docType,
254
- region: region || undefined,
178
+ code: countryCode, ...country, regionMapping: mapping, documentType: docType, region: region || undefined,
255
179
  };
256
-
257
180
  onValueChange(countryObj);
258
-
259
- setTimeout(() => {
260
- actions.nextComponent(countryObj);
261
- }, 100);
181
+ setTimeout(() => { actions.nextComponent(countryObj); }, 100);
262
182
  };
263
183
 
264
184
  const handleBack = () => {
185
+ sdkLogger.info("User navigated back in document selection", { fromStep: currentStep }); // 🚨 LOG
186
+
265
187
  if (currentStep === 'region') {
266
- setCurrentStep('documentType');
267
- setSelectedRegion(null);
188
+ setCurrentStep('documentType'); setSelectedRegion(null);
268
189
  } else if (currentStep === 'documentType') {
269
- setCurrentStep('country');
270
- setSelectedDocumentType(null);
271
- setSelectedRegion(null);
272
- setSearchQuery('');
190
+ setCurrentStep('country'); setSelectedDocumentType(null); setSelectedRegion(null); setSearchQuery('');
273
191
  } else if (currentStep === 'country') {
274
192
  actions.previousComponent();
275
193
  }
@@ -279,68 +197,33 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
279
197
  if (currentStep === 'country' && selectedCountryCode) {
280
198
  setCurrentStep('documentType');
281
199
  } else if (currentStep === 'documentType' && selectedDocumentType) {
282
- if (needsRegion) {
283
- setCurrentStep('region');
284
- } else {
285
- if (selectedCountryCode) {
286
- finalizeSelection(selectedCountryCode, selectedDocumentType, null);
287
- }
200
+ if (needsRegion) { setCurrentStep('region'); } else {
201
+ if (selectedCountryCode) { finalizeSelection(selectedCountryCode, selectedDocumentType, null); }
288
202
  }
289
203
  } else if (currentStep === 'region' && selectedRegion) {
290
- if (selectedCountryCode && selectedDocumentType) {
291
- finalizeSelection(selectedCountryCode, selectedDocumentType, selectedRegion);
292
- }
204
+ if (selectedCountryCode && selectedDocumentType) { finalizeSelection(selectedCountryCode, selectedDocumentType, selectedRegion); }
293
205
  }
294
206
  };
295
207
 
296
208
  const renderCountrySelection = () => {
297
209
  return (
298
210
  <>
299
- <TextInput
300
- style={styles.searchBar}
301
- placeholder={state.currentLanguage === "en" ? "🔍 Search country..." : "🔍 Rechercher un pays..."}
302
- placeholderTextColor="#94A3B8"
303
- value={searchQuery}
304
- onChangeText={setSearchQuery}
305
- autoCorrect={false}
306
- />
211
+ <TextInput style={styles.searchBar} placeholder={state.currentLanguage === "en" ? "🔍 Search country..." : "🔍 Rechercher un pays..."} placeholderTextColor="#94A3B8" value={searchQuery} onChangeText={setSearchQuery} autoCorrect={false} />
307
212
  <ScrollView style={styles.listContainer} showsVerticalScrollIndicator={false}>
308
213
  {filteredCountries.map((country: Country & { code?: string }) => (
309
- <TouchableOpacity
310
- key={country.code}
311
- style={[
312
- styles.option,
313
- selectedCountryCode === country.code && styles.selectedOption
314
- ]}
315
- onPress={() => handleCountrySelect(country.code!)}
316
- >
214
+ <TouchableOpacity key={country.code} style={[styles.option, selectedCountryCode === country.code && styles.selectedOption]} onPress={() => handleCountrySelect(country.code!)}>
317
215
  <Text style={styles.flag}>{country.flag}</Text>
318
-
319
216
  <View style={styles.optionContent}>
320
- <Text style={[
321
- styles.optionName,
322
- selectedCountryCode === country.code && styles.selectedOptionName
323
- ]}>
324
- {state.currentLanguage === "en" ? country.name_en : country.name}
325
- </Text>
217
+ <Text style={[styles.optionName, selectedCountryCode === country.code && styles.selectedOptionName]}>{state.currentLanguage === "en" ? country.name_en : country.name}</Text>
326
218
  <Text style={styles.optionCode}>{country.code}</Text>
327
219
  </View>
328
-
329
220
  {selectedCountryCode === country.code && (
330
- <View style={[
331
- styles.checkmark,
332
- { backgroundColor: component.ui.themeColor as string || '#2DBD60' }
333
- ]}>
334
- <Text style={styles.checkmarkText}>✓</Text>
335
- </View>
221
+ <View style={[styles.checkmark, { backgroundColor: component.ui.themeColor as string || '#2DBD60' }]}><Text style={styles.checkmarkText}>✓</Text></View>
336
222
  )}
337
223
  </TouchableOpacity>
338
224
  ))}
339
-
340
225
  {filteredCountries.length === 0 && (
341
- <Text style={styles.emptyText}>
342
- {state.currentLanguage === "en" ? "No matching countries found." : "Aucun pays trouvé."}
343
- </Text>
226
+ <Text style={styles.emptyText}>{state.currentLanguage === "en" ? "No matching countries found." : "Aucun pays trouvé."}</Text>
344
227
  )}
345
228
  </ScrollView>
346
229
  </>
@@ -348,10 +231,7 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
348
231
  };
349
232
 
350
233
  const renderDocumentTypeSelection = () => {
351
- const instructions = selectedDocumentType && idCardConfig?.instructionsByDocumentType?.[selectedDocumentType]
352
- ? getLocalizedText(idCardConfig.instructionsByDocumentType[selectedDocumentType])
353
- : null;
354
-
234
+ const instructions = selectedDocumentType && idCardConfig?.instructionsByDocumentType?.[selectedDocumentType] ? getLocalizedText(idCardConfig.instructionsByDocumentType[selectedDocumentType]) : null;
355
235
  const documentTypeLabels: Record<string, { en: string; fr: string; icon?: string }> = {
356
236
  'nationalId': { en: 'National ID', fr: 'Carte nationale d\'identité', icon: '🏛️' },
357
237
  'passport': { en: 'Passport', fr: 'Passeport', icon: '📘' },
@@ -359,45 +239,22 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
359
239
  'residencePermit': { en: 'Residence Permit', fr: 'Permis de séjour', icon: '🏠' },
360
240
  'healthInsuranceCard': { en: 'Health Insurance Card', fr: 'Carte d\'assurance maladie', icon: '🗳️' },
361
241
  };
362
-
363
242
  return (
364
243
  <>
365
- {instructions && (
366
- <View style={styles.infoBox}>
367
- <Text style={styles.infoText}>{instructions}</Text>
368
- </View>
369
- )}
244
+ {instructions && (<View style={styles.infoBox}><Text style={styles.infoText}>{instructions}</Text></View>)}
370
245
  <ScrollView style={styles.listContainer} showsVerticalScrollIndicator={false}>
371
246
  {availableDocumentTypes.map((docType: string) => {
372
247
  const label = documentTypeLabels[docType];
373
248
  const displayName = label ? (state.currentLanguage === "en" ? label.en : label.fr) : docType;
374
249
  const icon = label?.icon || '📄';
375
-
376
250
  return (
377
- <TouchableOpacity
378
- key={docType}
379
- style={[
380
- styles.option,
381
- selectedDocumentType === docType && styles.selectedOption
382
- ]}
383
- onPress={() => handleDocumentTypeSelect(docType)}
384
- >
251
+ <TouchableOpacity key={docType} style={[styles.option, selectedDocumentType === docType && styles.selectedOption]} onPress={() => handleDocumentTypeSelect(docType)}>
385
252
  <Text style={styles.flag}>{icon}</Text>
386
253
  <View style={styles.optionContent}>
387
- <Text style={[
388
- styles.optionName,
389
- selectedDocumentType === docType && styles.selectedOptionName
390
- ]}>
391
- {displayName}
392
- </Text>
254
+ <Text style={[styles.optionName, selectedDocumentType === docType && styles.selectedOptionName]}>{displayName}</Text>
393
255
  </View>
394
256
  {selectedDocumentType === docType && (
395
- <View style={[
396
- styles.checkmark,
397
- { backgroundColor: component.ui.themeColor as string || '#2DBD60' }
398
- ]}>
399
- <Text style={styles.checkmarkText}>✓</Text>
400
- </View>
257
+ <View style={[styles.checkmark, { backgroundColor: component.ui.themeColor as string || '#2DBD60' }]}><Text style={styles.checkmarkText}>✓</Text></View>
401
258
  )}
402
259
  </TouchableOpacity>
403
260
  );
@@ -413,32 +270,13 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
413
270
  <ScrollView style={styles.listContainer} showsVerticalScrollIndicator={false}>
414
271
  {availableRegions.map((regionObj, index: number) => {
415
272
  return (
416
- <TouchableOpacity
417
- key={index}
418
- style={[
419
- styles.option,
420
- selectedRegion === regionObj.value && styles.selectedOption
421
- ]}
422
- onPress={() => handleRegionSelect(regionObj.value)}
423
- >
273
+ <TouchableOpacity key={index} style={[styles.option, selectedRegion === regionObj.value && styles.selectedOption]} onPress={() => handleRegionSelect(regionObj.value)}>
424
274
  <View style={styles.optionContent}>
425
- <Text style={[
426
- styles.optionName,
427
- selectedRegion === regionObj.value && styles.selectedOptionName
428
- ]}>
429
- {regionObj.label}
430
- </Text>
431
- {regionObj.value !== regionObj.label && (
432
- <Text style={styles.optionCode}>{regionObj.value}</Text>
433
- )}
275
+ <Text style={[styles.optionName, selectedRegion === regionObj.value && styles.selectedOptionName]}>{regionObj.label}</Text>
276
+ {regionObj.value !== regionObj.label && (<Text style={styles.optionCode}>{regionObj.value}</Text>)}
434
277
  </View>
435
278
  {selectedRegion === regionObj.value && (
436
- <View style={[
437
- styles.checkmark,
438
- { backgroundColor: component.ui.themeColor as string || '#2DBD60' }
439
- ]}>
440
- <Text style={styles.checkmarkText}>✓</Text>
441
- </View>
279
+ <View style={[styles.checkmark, { backgroundColor: component.ui.themeColor as string || '#2DBD60' }]}><Text style={styles.checkmarkText}>✓</Text></View>
442
280
  )}
443
281
  </TouchableOpacity>
444
282
  );
@@ -450,31 +288,19 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
450
288
 
451
289
  const getStepTitle = (): string => {
452
290
  switch (currentStep) {
453
- case 'country':
454
- return getLocalizedText(component.labels as LocalizedText);
455
- case 'documentType':
456
- return state.currentLanguage === "en" ? "Select Document Type" : "Sélectionnez le type de document";
457
- case 'region':
458
- return state.currentLanguage === "en" ? "Select Province/State" : "Sélectionnez la province/l'état";
459
- default:
460
- return '';
291
+ case 'country': return getLocalizedText(component.labels as LocalizedText);
292
+ case 'documentType': return state.currentLanguage === "en" ? "Select Document Type" : "Sélectionnez le type de document";
293
+ case 'region': return state.currentLanguage === "en" ? "Select Province/State" : "Sélectionnez la province/l'état";
294
+ default: return '';
461
295
  }
462
296
  };
463
297
 
464
298
  const getStepDescription = (): string => {
465
299
  switch (currentStep) {
466
- case 'country':
467
- return getLocalizedText(component.instructions as LocalizedText);
468
- case 'documentType':
469
- return state.currentLanguage === "en"
470
- ? "Choose the type of document you want to use"
471
- : "Choisissez le type de document que vous souhaitez utiliser";
472
- case 'region':
473
- return state.currentLanguage === "en"
474
- ? "Select the issuing province or territory"
475
- : "Sélectionnez la province ou le territoire de délivrance";
476
- default:
477
- return '';
300
+ case 'country': return getLocalizedText(component.instructions as LocalizedText);
301
+ case 'documentType': return state.currentLanguage === "en" ? "Choose the type of document you want to use" : "Choisissez le type de document que vous souhaitez utiliser";
302
+ case 'region': return state.currentLanguage === "en" ? "Select the issuing province or territory" : "Sélectionnez la province ou le territoire de délivrance";
303
+ default: return '';
478
304
  }
479
305
  };
480
306
 
@@ -484,9 +310,7 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
484
310
  return 3;
485
311
  };
486
312
 
487
- const getTotalSteps = (): number => {
488
- return needsRegion ? 3 : 2;
489
- };
313
+ const getTotalSteps = (): number => { return needsRegion ? 3 : 2; };
490
314
 
491
315
  const canGoNext = (): boolean => {
492
316
  if (currentStep === 'country') return selectedCountryCode !== null;
@@ -499,41 +323,18 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
499
323
  <View style={styles.root}>
500
324
  <View style={styles.container}>
501
325
  <View style={styles.progressContainer}>
502
- <Text style={styles.progressText}>
503
- {state.currentLanguage === "en"
504
- ? `Step ${getProgressStep()} of ${getTotalSteps()}`
505
- : `Étape ${getProgressStep()} sur ${getTotalSteps()}`}
506
- </Text>
326
+ <Text style={styles.progressText}>{state.currentLanguage === "en" ? `Step ${getProgressStep()} of ${getTotalSteps()}` : `Étape ${getProgressStep()} sur ${getTotalSteps()}`}</Text>
507
327
  </View>
508
-
509
328
  <Text style={styles.title}>{getStepTitle()}</Text>
510
329
  <Text style={styles.description}>{getStepDescription()}</Text>
511
-
512
330
  {currentStep === 'country' && renderCountrySelection()}
513
331
  {currentStep === 'documentType' && renderDocumentTypeSelection()}
514
332
  {currentStep === 'region' && renderRegionSelection()}
515
-
516
333
  <View style={styles.buttonContainer}>
517
- <Button
518
- title={state.currentLanguage === "en" ? "Back" : "Retour"}
519
- onPress={handleBack}
520
- variant={currentStep === 'country' ? "secondary" : "outline"}
521
- size="large"
522
- style={{ flex: 1, marginRight: 8 }}
523
- />
524
- <Button
525
- title={state.currentLanguage === "en" ? "Next" : "Suivant"}
526
- onPress={handleNext}
527
- variant="primary"
528
- size="large"
529
- style={{ flex: 1 }}
530
- disabled={!canGoNext()}
531
- />
334
+ <Button title={state.currentLanguage === "en" ? "Back" : "Retour"} onPress={handleBack} variant={currentStep === 'country' ? "secondary" : "outline"} size="large" style={{ flex: 1, marginRight: 8 }} />
335
+ <Button title={state.currentLanguage === "en" ? "Next" : "Suivant"} onPress={handleNext} variant="primary" size="large" style={{ flex: 1 }} disabled={!canGoNext()} />
532
336
  </View>
533
-
534
- {error && (
535
- <Text style={styles.errorText}>{error}</Text>
536
- )}
337
+ {error && (<Text style={styles.errorText}>{error}</Text>)}
537
338
  </View>
538
339
  </View>
539
340
  );