@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.
Files changed (142) hide show
  1. package/android/src/main/AndroidManifest.xml +9 -4
  2. package/build/components/EnhancedCameraView.d.ts.map +1 -1
  3. package/build/components/EnhancedCameraView.js +26 -3
  4. package/build/components/EnhancedCameraView.js.map +1 -1
  5. package/build/components/EnhancedCameraView.web.d.ts.map +1 -1
  6. package/build/components/EnhancedCameraView.web.js +21 -0
  7. package/build/components/EnhancedCameraView.web.js.map +1 -1
  8. package/build/components/KYCElements/CameraCapture.d.ts.map +1 -1
  9. package/build/components/KYCElements/CameraCapture.js +4 -3
  10. package/build/components/KYCElements/CameraCapture.js.map +1 -1
  11. package/build/components/KYCElements/CountrySelectionTemplate.d.ts +5 -2
  12. package/build/components/KYCElements/CountrySelectionTemplate.d.ts.map +1 -1
  13. package/build/components/KYCElements/CountrySelectionTemplate.js +360 -101
  14. package/build/components/KYCElements/CountrySelectionTemplate.js.map +1 -1
  15. package/build/components/KYCElements/FileUpload.d.ts.map +1 -1
  16. package/build/components/KYCElements/FileUpload.js +5 -4
  17. package/build/components/KYCElements/FileUpload.js.map +1 -1
  18. package/build/components/KYCElements/FileUploadTemplate.d.ts.map +1 -1
  19. package/build/components/KYCElements/FileUploadTemplate.js +5 -4
  20. package/build/components/KYCElements/FileUploadTemplate.js.map +1 -1
  21. package/build/components/KYCElements/IDCardCapture.d.ts.map +1 -1
  22. package/build/components/KYCElements/IDCardCapture.js +193 -237
  23. package/build/components/KYCElements/IDCardCapture.js.map +1 -1
  24. package/build/components/KYCElements/LocationCaptureTemplate.d.ts.map +1 -1
  25. package/build/components/KYCElements/LocationCaptureTemplate.js +78 -37
  26. package/build/components/KYCElements/LocationCaptureTemplate.js.map +1 -1
  27. package/build/components/KYCElements/OrientationVideoCapture.js +3 -2
  28. package/build/components/KYCElements/OrientationVideoCapture.js.map +1 -1
  29. package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js +3 -2
  30. package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js.map +1 -1
  31. package/build/components/KYCElements/OrientationVideoCaptureFinal.js +3 -2
  32. package/build/components/KYCElements/OrientationVideoCaptureFinal.js.map +1 -1
  33. package/build/components/KYCElements/SelfieCapture.d.ts.map +1 -1
  34. package/build/components/KYCElements/SelfieCapture.js +4 -3
  35. package/build/components/KYCElements/SelfieCapture.js.map +1 -1
  36. package/build/components/KYCElements/SelfieCaptureTemplate.d.ts.map +1 -1
  37. package/build/components/KYCElements/SelfieCaptureTemplate.js +182 -39
  38. package/build/components/KYCElements/SelfieCaptureTemplate.js.map +1 -1
  39. package/build/components/KYCElements/WelcomeTemplate.d.ts +12 -0
  40. package/build/components/KYCElements/WelcomeTemplate.d.ts.map +1 -0
  41. package/build/components/KYCElements/WelcomeTemplate.js +243 -0
  42. package/build/components/KYCElements/WelcomeTemplate.js.map +1 -0
  43. package/build/components/TemplateKYCExample.d.ts +4 -2
  44. package/build/components/TemplateKYCExample.d.ts.map +1 -1
  45. package/build/components/TemplateKYCExample.js +5 -68
  46. package/build/components/TemplateKYCExample.js.map +1 -1
  47. package/build/components/TemplateKYCFlowRefactored.d.ts +2 -1
  48. package/build/components/TemplateKYCFlowRefactored.d.ts.map +1 -1
  49. package/build/components/TemplateKYCFlowRefactored.js +95 -9
  50. package/build/components/TemplateKYCFlowRefactored.js.map +1 -1
  51. package/build/components/example/DynamicTemplateExample.d.ts +10 -0
  52. package/build/components/example/DynamicTemplateExample.d.ts.map +1 -0
  53. package/build/components/example/DynamicTemplateExample.js +241 -0
  54. package/build/components/example/DynamicTemplateExample.js.map +1 -0
  55. package/build/config/allowedDomains.d.ts +30 -0
  56. package/build/config/allowedDomains.d.ts.map +1 -0
  57. package/build/config/allowedDomains.js +127 -0
  58. package/build/config/allowedDomains.js.map +1 -0
  59. package/build/hooks/useTemplateKYCFlow.d.ts.map +1 -1
  60. package/build/hooks/useTemplateKYCFlow.js +68 -43
  61. package/build/hooks/useTemplateKYCFlow.js.map +1 -1
  62. package/build/hooks/useTemplateLoader.d.ts +14 -0
  63. package/build/hooks/useTemplateLoader.d.ts.map +1 -0
  64. package/build/hooks/useTemplateLoader.js +85 -0
  65. package/build/hooks/useTemplateLoader.js.map +1 -0
  66. package/build/i18n/en/index.d.ts +9 -0
  67. package/build/i18n/en/index.d.ts.map +1 -1
  68. package/build/i18n/en/index.js +9 -0
  69. package/build/i18n/en/index.js.map +1 -1
  70. package/build/i18n/fr/index.d.ts +9 -0
  71. package/build/i18n/fr/index.d.ts.map +1 -1
  72. package/build/i18n/fr/index.js +9 -0
  73. package/build/i18n/fr/index.js.map +1 -1
  74. package/build/index.d.ts +5 -0
  75. package/build/index.d.ts.map +1 -1
  76. package/build/index.js +8 -0
  77. package/build/index.js.map +1 -1
  78. package/build/modules/api/CardAuthentification.js +1 -0
  79. package/build/modules/api/CardAuthentification.js.map +1 -1
  80. package/build/modules/api/KYCService.d.ts +4 -1
  81. package/build/modules/api/KYCService.d.ts.map +1 -1
  82. package/build/modules/api/KYCService.js +17 -5
  83. package/build/modules/api/KYCService.js.map +1 -1
  84. package/build/modules/api/TemplateService.d.ts +45 -0
  85. package/build/modules/api/TemplateService.d.ts.map +1 -0
  86. package/build/modules/api/TemplateService.js +145 -0
  87. package/build/modules/api/TemplateService.js.map +1 -0
  88. package/build/modules/api/types.d.ts +1 -0
  89. package/build/modules/api/types.d.ts.map +1 -1
  90. package/build/modules/api/types.js.map +1 -1
  91. package/build/types/KYC.types.d.ts +144 -4
  92. package/build/types/KYC.types.d.ts.map +1 -1
  93. package/build/types/KYC.types.js +15 -0
  94. package/build/types/KYC.types.js.map +1 -1
  95. package/build/utils/cropByObb.d.ts +1 -0
  96. package/build/utils/cropByObb.d.ts.map +1 -1
  97. package/build/utils/cropByObb.js +70 -0
  98. package/build/utils/cropByObb.js.map +1 -1
  99. package/build/utils/platformAlert.d.ts +20 -0
  100. package/build/utils/platformAlert.d.ts.map +1 -0
  101. package/build/utils/platformAlert.js +67 -0
  102. package/build/utils/platformAlert.js.map +1 -0
  103. package/build/utils/template-transformer.d.ts +10 -0
  104. package/build/utils/template-transformer.d.ts.map +1 -0
  105. package/build/utils/template-transformer.js +353 -0
  106. package/build/utils/template-transformer.js.map +1 -0
  107. package/build/web/WebKYCEntry.d.ts.map +1 -1
  108. package/build/web/WebKYCEntry.js +102 -20
  109. package/build/web/WebKYCEntry.js.map +1 -1
  110. package/package.json +1 -1
  111. package/src/components/EnhancedCameraView.tsx +31 -2
  112. package/src/components/EnhancedCameraView.web.tsx +24 -0
  113. package/src/components/KYCElements/CameraCapture.tsx +4 -3
  114. package/src/components/KYCElements/CountrySelectionTemplate.tsx +410 -113
  115. package/src/components/KYCElements/FileUpload.tsx +5 -4
  116. package/src/components/KYCElements/FileUploadTemplate.tsx +5 -4
  117. package/src/components/KYCElements/IDCardCapture.tsx +196 -254
  118. package/src/components/KYCElements/LocationCaptureTemplate.tsx +95 -44
  119. package/src/components/KYCElements/OrientationVideoCapture.tsx +2 -2
  120. package/src/components/KYCElements/OrientationVideoCaptureEnhanced.tsx +2 -2
  121. package/src/components/KYCElements/OrientationVideoCaptureFinal.tsx +2 -2
  122. package/src/components/KYCElements/SelfieCapture.tsx +4 -3
  123. package/src/components/KYCElements/SelfieCaptureTemplate.tsx +195 -41
  124. package/src/components/KYCElements/WelcomeTemplate.tsx +289 -0
  125. package/src/components/TemplateKYCExample.tsx +16 -71
  126. package/src/components/TemplateKYCFlowRefactored.tsx +121 -11
  127. package/src/components/example/DynamicTemplateExample.tsx +289 -0
  128. package/src/config/allowedDomains.ts +152 -0
  129. package/src/hooks/useTemplateKYCFlow.tsx +71 -46
  130. package/src/hooks/useTemplateLoader.ts +102 -0
  131. package/src/i18n/en/index.ts +10 -0
  132. package/src/i18n/fr/index.ts +9 -0
  133. package/src/index.ts +11 -0
  134. package/src/modules/api/CardAuthentification.ts +1 -1
  135. package/src/modules/api/KYCService.ts +18 -8
  136. package/src/modules/api/TemplateService.ts +167 -0
  137. package/src/modules/api/types.ts +1 -0
  138. package/src/types/KYC.types.ts +188 -3
  139. package/src/utils/cropByObb.ts +83 -3
  140. package/src/utils/platformAlert.ts +85 -0
  141. package/src/utils/template-transformer.ts +433 -0
  142. package/src/web/WebKYCEntry.tsx +122 -24
@@ -1,6 +1,8 @@
1
- import React, { useCallback, useEffect, useMemo, useState } from 'react';
2
- import { View, Text, TouchableOpacity, StyleSheet, Image, Alert, ScrollView, Dimensions } from 'react-native';
1
+ import React, { useEffect, useMemo, useState } from 'react';
2
+ import { View, Text, StyleSheet, Image, ScrollView } from 'react-native';
3
+ import { showAlert } from '../../utils/platformAlert';
3
4
  import { EnhancedCameraView } from '../EnhancedCameraView';
5
+ import { GovernmentDocumentTypeShorted, GovernmentDocumentTypeBackend } from '../../types/KYC.types';
4
6
  import IdCardOverlay from '../OverLay/IdCard';
5
7
  import { useTemplateKYCFlowContext } from '../../hooks/useTemplateKYCFlow';
6
8
  import { useI18n } from '../../hooks/useI18n';
@@ -10,7 +12,7 @@ import { backVerification, checkTemplateType, frontVerification } from '../../mo
10
12
  import { getDocumentTypeInfo } from '../../utils/get-document-type-info';
11
13
  import pathToBase64 from '../../utils/pathToBase64';
12
14
  import { truncateFields } from '../../modules/api/KYCService';
13
- import { cropByObb, cropImageWithBBox } from '../../utils/cropByObb';
15
+ import { cropByObb, cropImageWithBBox, cropImageWithBBoxWithTolerance } from '../../utils/cropByObb';
14
16
  import { logger } from '../../utils/logger';
15
17
  export const IDCardCapture = ({ component, value = {}, onValueChange, error, language = 'en', }) => {
16
18
  const { t, locale } = useI18n();
@@ -20,18 +22,17 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
20
22
  const [currentSide, setCurrentSide] = useState('front');
21
23
  // Stocker les bbox par côté pour pouvoir restaurer les images croppées
22
24
  const [bboxBySide, setBboxBySide] = useState({});
23
- const [selectedDocumentType, setSelectedDocumentType] = useState({
24
- type: 'identity_card',
25
- region: 'root'
26
- });
27
- const [showDocumentSelection, setShowDocumentSelection] = useState({
28
- documentSelection: true,
29
- regionSelection: false
30
- });
31
25
  const [silentCaptureResult, setSilentCaptureResult] = useState({ success: false, isAnalyzing: false });
26
+ // Mapping des types de documents backend vers SDK
27
+ const documentTypeMapping = {
28
+ 'nationalId': 'national_id',
29
+ 'passport': 'passport',
30
+ 'driversLicense': 'drivers_licence',
31
+ 'residencePermit': 'permanent_residence',
32
+ 'healthInsuranceCard': 'health_insurance_card',
33
+ };
32
34
  // const [imageNaturalSize, setImageNaturalSize] = useState<{ width: number; height: number } | null>(null);
33
- const { actions, state, } = useTemplateKYCFlowContext();
34
- const config = component.config;
35
+ const { actions, state } = useTemplateKYCFlowContext();
35
36
  const getLocalizedText = (text) => {
36
37
  // console.log("text", text, JSON.stringify(component, null, 2));
37
38
  if (text && typeof text[currentSide] === 'object' && text[currentSide][locale]) {
@@ -39,27 +40,27 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
39
40
  }
40
41
  return "";
41
42
  };
42
- const countryData = useMemo(() => {
43
- const geCountryID = Object.keys(state.componentData).find((c) => c === "6");
44
- if (geCountryID) {
45
- const countryMapping = state.componentData[geCountryID];
46
- return countryMapping;
43
+ // Récupérer les données depuis le composant country_selection
44
+ const countrySelectionData = useMemo(() => {
45
+ const countrySelectionComponent = state.template.components.find(c => c.type === 'country_selection');
46
+ if (countrySelectionComponent) {
47
+ return state.componentData[countrySelectionComponent.id];
47
48
  }
48
49
  return null;
49
- }, [state.componentData]);
50
- const availableDocumentTypes = useMemo(() => {
51
- const newconfig = [];
52
- if (countryData) {
53
- const countryMapping = Object.keys(countryData?.regionMapping);
54
- if (countryMapping && Array.isArray(countryMapping)) {
55
- countryMapping.forEach((c) => {
56
- newconfig.push(c);
57
- });
58
- }
59
- }
60
- logger.log("newconfig", truncateFields(newconfig));
61
- return newconfig;
62
- }, []);
50
+ }, [state.template.components, state.componentData]);
51
+ // Extraire selectedDocumentType depuis countrySelectionData
52
+ const selectedDocumentType = useMemo(() => {
53
+ if (!countrySelectionData?.documentType)
54
+ return null;
55
+ const backendDocType = countrySelectionData.documentType;
56
+ const mappedType = documentTypeMapping[backendDocType] || backendDocType;
57
+ const region = countrySelectionData.region || 'root';
58
+ return { type: mappedType, region };
59
+ }, [countrySelectionData, documentTypeMapping]);
60
+ // Récupérer countryData pour compatibilité avec le code existant
61
+ const countryData = useMemo(() => {
62
+ return countrySelectionData;
63
+ }, [countrySelectionData]);
63
64
  useEffect(() => {
64
65
  logger.log("cropImageUri", JSON.stringify(truncateFields({ box: silentCaptureResult }), null, 2));
65
66
  if (capturedImages[currentSide]?.dir && silentCaptureResult?.bbox) {
@@ -68,27 +69,32 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
68
69
  });
69
70
  }
70
71
  }, [capturedImages[currentSide]?.dir, silentCaptureResult?.bbox]);
71
- const cameraConfig = {
72
- aspectRatio: 4 / 3,
73
- quality: 0.8,
74
- flashMode: 'auto',
75
- cameraType: 'back',
76
- allowRetake: true,
77
- maxRetakes: 3,
78
- overlay: {
79
- showGuide: true,
80
- guideText: selectedDocumentType ? (locale === 'en' ? getDocumentTypeInfo(selectedDocumentType.type).instructions.en : getDocumentTypeInfo(selectedDocumentType.type).instructions.fr) : getLocalizedText(component.instructions),
81
- bbox: selectedDocumentType && config.bbox_configs[selectedDocumentType.type] ? config.bbox_configs[selectedDocumentType.type] : {
82
- xMin: 20,
83
- yMin: 140,
84
- xMax: 370,
85
- yMax: 340,
86
- borderColor: '#2DBD60',
87
- borderWidth: 3,
88
- cornerRadius: 8
72
+ const cameraConfig = useMemo(() => {
73
+ const instructions = selectedDocumentType
74
+ ? (locale === 'en' ? getDocumentTypeInfo(selectedDocumentType.type).instructions.en : getDocumentTypeInfo(selectedDocumentType.type).instructions.fr)
75
+ : getLocalizedText(component.instructions);
76
+ return {
77
+ aspectRatio: 4 / 3,
78
+ quality: 0.8,
79
+ flashMode: 'auto',
80
+ cameraType: 'back',
81
+ allowRetake: true,
82
+ maxRetakes: 3,
83
+ overlay: {
84
+ showGuide: true,
85
+ guideText: instructions,
86
+ bbox: {
87
+ xMin: 20,
88
+ yMin: 140,
89
+ xMax: 370,
90
+ yMax: 340,
91
+ borderColor: '#2DBD60',
92
+ borderWidth: 3,
93
+ cornerRadius: 8
94
+ }
89
95
  }
90
- }
91
- };
96
+ };
97
+ }, [selectedDocumentType, locale, component.instructions]);
92
98
  const retakePicture = (currentSide) => {
93
99
  setShowCamera(true);
94
100
  actions.showCustomStepper(false);
@@ -97,26 +103,14 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
97
103
  setCropImageUri('');
98
104
  onValueChange({ ...value, [currentSide]: { dir: '', file: '', mrz: '' } });
99
105
  };
100
- const hasRegions = useCallback((documentType) => {
101
- const regionMapping = countryData?.regionMapping[documentType];
102
- if (regionMapping && Object.keys(regionMapping).length > 1) {
103
- return {
104
- hasRegions: true,
105
- regionMapping: Object.keys(regionMapping)
106
- };
107
- }
108
- return {
109
- hasRegions: false,
110
- regionMapping: []
111
- };
112
- }, [countryData]);
113
106
  const getCurrentSideVerification = (currentSide) => {
114
- const regionMapping = countryData?.regionMapping[selectedDocumentType?.type];
107
+ if (!selectedDocumentType || !countryData?.regionMapping) {
108
+ return { authMethod: [], mrzTypes: [], regionMapping: null, key: 'root' };
109
+ }
110
+ const regionMapping = countryData.regionMapping[selectedDocumentType.type];
115
111
  const authMethod = [];
116
112
  const mrzTypes = [];
117
- const key = selectedDocumentType?.region?.trim()?.length > 0 ? selectedDocumentType?.region?.trim() : 'root';
118
- // console.log("regionMapping", JSON.stringify(regionMapping, null, 2), selectedDocumentType?.region);
119
- // const key = selectedDocumentType?.region as keyof typeof regionMapping;
113
+ const key = selectedDocumentType.region?.trim()?.length > 0 ? selectedDocumentType.region.trim() : 'root';
120
114
  if (regionMapping?.[key] && Array.isArray(regionMapping[key])) {
121
115
  regionMapping[key].forEach((item) => {
122
116
  if (item[currentSide]) {
@@ -127,11 +121,11 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
127
121
  }
128
122
  });
129
123
  }
130
- logger.log("regionMapping", JSON.stringify(truncateFields({ regionMapping, selectedDocumentType: selectedDocumentType?.region, key }), null, 2));
124
+ logger.log("regionMapping", JSON.stringify(truncateFields({ regionMapping, selectedDocumentType: selectedDocumentType.region, key }), null, 2));
131
125
  return { authMethod: removeDuplicates(authMethod), mrzTypes: removeDuplicates(mrzTypes), regionMapping: regionMapping, key: key };
132
126
  };
133
127
  const getCorrespondingMrzType = (templatePath, mapping, selectedDocumentType = "root") => {
134
- if (!mapping[selectedDocumentType])
128
+ if (!mapping || !mapping[selectedDocumentType])
135
129
  return null;
136
130
  // Extraire le nom du fichier depuis le template_path
137
131
  const fileName = templatePath.split("/").pop()?.replace(".jpg", "").replace(".png", "");
@@ -151,10 +145,19 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
151
145
  setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: true, success: false, error: '' }));
152
146
  let templatePath = silentCaptureResult.templatePath || '';
153
147
  let templateBbox;
148
+ if (!selectedDocumentType) {
149
+ setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: 'Document type not selected' }));
150
+ return;
151
+ }
154
152
  const regionMappings = getCurrentSideVerification(currentSide);
155
153
  // logger.log("regionMappings", JSON.stringify(truncateFields({regionMappings, templatePath}), null, 2));
156
154
  if (templatePath.length === 0) {
157
155
  try {
156
+ logger.log("checkTemplateType - BEFORE call", {
157
+ selectedDocumentTypeType: selectedDocumentType?.type,
158
+ countrySelectionDataDocumentType: countrySelectionData?.documentType,
159
+ docTypeToSend: selectedDocumentType?.type
160
+ });
158
161
  const templateType = await checkTemplateType({ path: result.path || '', docType: selectedDocumentType?.type, docRegion: countryData?.code || "", postfix: currentSide });
159
162
  if (templateType.template_path) {
160
163
  templatePath = templateType.template_path;
@@ -174,49 +177,79 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
174
177
  catch (e) {
175
178
  logger.log("error checking template type", truncateFields(e));
176
179
  setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: e?.message || 'Erreur de vérification du template' }));
180
+ return; // Return early if checkTemplateType fails
177
181
  }
178
182
  }
179
- logger.log("templatePath before front verification", templatePath);
183
+ logger.log("templatePath before verification", templatePath, "currentSide", currentSide);
180
184
  if (currentSide === 'front') {
181
- frontVerification({
182
- path: result.path,
183
- regionMapping: regionMappings,
184
- selectedDocumentType: selectedDocumentType?.type || '',
185
- code: countryData?.code || '',
186
- currentSide: currentSide,
187
- templatePath: templatePath,
188
- mrzType: getCorrespondingMrzType(templatePath, regionMappings.regionMapping, regionMappings.key || '') || '',
189
- }).then((mrz) => {
190
- logger.log("front verification result", truncateFields(mrz));
191
- const bbox = mrz?.bbox || templateBbox;
192
- setSilentCaptureResult((prev) => ({
193
- ...prev,
185
+ logger.log("frontVerification - BEFORE call", {
186
+ selectedDocumentTypeType: selectedDocumentType?.type,
187
+ countrySelectionDataDocumentType: countrySelectionData?.documentType,
188
+ docTypeToSend: selectedDocumentType?.type
189
+ });
190
+ logger.log("Calling frontVerification", { templatePath, selectedDocumentType: selectedDocumentType?.type, regionMappings });
191
+ console.log("About to call frontVerification", typeof frontVerification);
192
+ try {
193
+ const mrzType = getCorrespondingMrzType(templatePath, regionMappings.regionMapping, regionMappings.key || '') || '';
194
+ console.log("mrzType calculated", mrzType);
195
+ const verificationParams = {
194
196
  path: result.path,
197
+ regionMapping: {
198
+ authMethod: regionMappings.authMethod,
199
+ mrzTypes: regionMappings.mrzTypes,
200
+ },
201
+ selectedDocumentType: GovernmentDocumentTypeShorted[selectedDocumentType?.type] || '',
202
+ code: countryData?.code || '',
203
+ currentSide: currentSide,
195
204
  templatePath: templatePath,
196
- bbox: bbox, success: true,
197
- mrz: JSON.stringify(mrz), isAnalyzing: false,
198
- country: countryData?.code,
199
- documentType: selectedDocumentType?.type,
200
- }));
201
- // Stocker le bbox pour ce côté
202
- if (bbox && typeof bbox === 'object') {
203
- setBboxBySide((prev) => ({ ...prev, [currentSide]: bbox }));
204
- }
205
- }).catch((e) => {
206
- logger.log("error front verification", truncateFields(e));
207
- setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, templatePath: templatePath, success: false, error: e?.message || 'Erreur de détection du MRZ' }));
208
- // Alert.alert('Erreur', e?.message || 'Erreur de détection du MRZ');
209
- });
205
+ mrzType: mrzType,
206
+ };
207
+ console.log("frontVerification params", verificationParams);
208
+ console.log("About to call frontVerification function");
209
+ const promise = frontVerification(verificationParams);
210
+ console.log("frontVerification promise created", promise);
211
+ promise.then((mrz) => {
212
+ logger.log("front verification result", truncateFields(mrz));
213
+ const bbox = mrz?.bbox || templateBbox;
214
+ setSilentCaptureResult((prev) => ({
215
+ ...prev,
216
+ path: result.path,
217
+ templatePath: templatePath,
218
+ bbox: bbox, success: true,
219
+ mrz: JSON.stringify(mrz), isAnalyzing: false,
220
+ country: countryData?.code,
221
+ documentType: selectedDocumentType.type,
222
+ }));
223
+ // Stocker le bbox pour ce côté
224
+ if (bbox && typeof bbox === 'object') {
225
+ setBboxBySide((prev) => ({ ...prev, [currentSide]: bbox }));
226
+ }
227
+ }).catch((e) => {
228
+ console.log("error front verification", e);
229
+ logger.log("error front verification", truncateFields(e));
230
+ setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, templatePath: templatePath, success: false, error: e?.message || 'Erreur de détection du MRZ' }));
231
+ // showAlert('Erreur', e?.message || 'Erreur de détection du MRZ');
232
+ });
233
+ }
234
+ catch (error) {
235
+ console.log("Error setting up frontVerification call", error);
236
+ setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: error?.message || 'Erreur lors de la configuration de la vérification' }));
237
+ }
210
238
  }
211
239
  else {
240
+ const backRegionMappings = getCurrentSideVerification(currentSide);
241
+ logger.log("Calling backVerification", { templatePath, selectedDocumentType: selectedDocumentType.type, backRegionMappings });
212
242
  backVerification({
213
243
  path: result.path,
214
- regionMapping: getCurrentSideVerification(currentSide),
215
- selectedDocumentType: selectedDocumentType?.type || '',
244
+ regionMapping: {
245
+ authMethod: backRegionMappings.authMethod,
246
+ mrzTypes: backRegionMappings.mrzTypes,
247
+ },
248
+ selectedDocumentType: GovernmentDocumentTypeShorted[selectedDocumentType.type] || '',
216
249
  code: countryData?.code || '',
217
250
  currentSide: currentSide,
218
251
  templatePath: templatePath,
219
- mrzType: getCorrespondingMrzType(templatePath, regionMappings.regionMapping, regionMappings.key || '') || '',
252
+ mrzType: getCorrespondingMrzType(templatePath, backRegionMappings.regionMapping, backRegionMappings.key || '') || '',
220
253
  }).then((mrz) => {
221
254
  logger.log("back verification result", truncateFields(mrz));
222
255
  const bbox = mrz?.bbox || templateBbox;
@@ -224,7 +257,7 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
224
257
  ...prev, path: result.path, bbox: bbox,
225
258
  success: true, mrz: JSON.stringify(mrz), isAnalyzing: false,
226
259
  country: countryData?.code,
227
- documentType: selectedDocumentType?.type,
260
+ documentType: selectedDocumentType.type,
228
261
  }));
229
262
  // Stocker le bbox pour ce côté
230
263
  if (bbox && typeof bbox === 'object') {
@@ -233,109 +266,65 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
233
266
  }).catch((e) => {
234
267
  logger.log("error back verification", truncateFields(e));
235
268
  setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, templatePath: templatePath, success: false, error: e?.message || 'Erreur de détection du MRZ' }));
236
- // Alert.alert('Erreur', e?.message || 'Erreur de détection du MRZ');
269
+ // showAlert('Erreur', e?.message || 'Erreur de détection du MRZ');
237
270
  });
238
271
  }
239
272
  }
240
273
  };
241
274
  // Handle capture
242
275
  const handleCapture = async (result) => {
276
+ console.log("handleCapture", JSON.stringify(truncateFields({ result, silentCaptureResult }), null, 2));
243
277
  if (silentCaptureResult.path) {
244
- const base64 = await pathToBase64(silentCaptureResult.path);
278
+ // Créer une image rognée avec tolérance de 10% pour l'envoi
279
+ let imagePathForUpload = silentCaptureResult.path;
280
+ if (silentCaptureResult.bbox) {
281
+ try {
282
+ logger.log("Début du rognage avec tolérance, URI original:", silentCaptureResult.path);
283
+ imagePathForUpload = await cropImageWithBBoxWithTolerance(silentCaptureResult.path, silentCaptureResult.bbox, 0.05);
284
+ logger.log("Image rognée avec tolérance créée pour l'envoi, URI final:", imagePathForUpload);
285
+ }
286
+ catch (error) {
287
+ logger.log("Erreur lors du rognage avec tolérance, utilisation de l'image originale:", truncateFields(error));
288
+ // En cas d'erreur, on utilise l'image originale
289
+ imagePathForUpload = silentCaptureResult.path;
290
+ }
291
+ }
292
+ const base64 = await pathToBase64(imagePathForUpload);
245
293
  logger.log("silentCaptureResult captured", JSON.stringify(truncateFields(silentCaptureResult), null, 2));
294
+ // Utiliser l'image originale pour l'affichage (dir) mais l'image rognée avec tolérance pour l'envoi (file)
246
295
  const newImages = { ...capturedImages, [currentSide]: { dir: silentCaptureResult.path, file: base64, mrz: silentCaptureResult.mrz || "", templatePath: silentCaptureResult.templatePath } };
247
296
  setCapturedImages(newImages);
248
297
  if (silentCaptureResult.country && silentCaptureResult.documentType) {
249
298
  onValueChange({
250
299
  ...newImages,
251
300
  country: silentCaptureResult.country,
252
- documentType: silentCaptureResult.documentType,
301
+ documentType: GovernmentDocumentTypeBackend[silentCaptureResult.documentType] || '',
253
302
  });
254
303
  }
255
304
  setShowCamera(false);
256
305
  actions.showCustomStepper(true);
257
306
  }
258
307
  else {
259
- Alert.alert('Erreur', result.error || 'Impossible de prendre la photo');
308
+ showAlert('Erreur', result.error || 'Impossible de prendre la photo');
260
309
  }
261
310
  };
262
311
  const handleError = (event) => {
263
- Alert.alert('Erreur', event.message);
312
+ showAlert('Erreur', event.message);
264
313
  setShowCamera(false);
265
314
  };
266
315
  useEffect(() => {
267
316
  actions.showCustomStepper(!showCamera);
268
317
  }, [showCamera]);
269
- const handleDocumentTypeSelection = (docType) => {
270
- setSelectedDocumentType({ type: docType, region: hasRegions(docType) ? '' : 'root' });
271
- setSilentCaptureResult((prev) => ({ ...prev, templatePath: '', bbox: undefined, success: false, isAnalyzing: false, error: '', path: '', mrz: '', country: '', documentType: '' }));
272
- setCapturedImages((prev) => ({ front: { dir: '', file: '', mrz: '', templatePath: '' }, back: { dir: '', file: '', mrz: '', templatePath: '' } }));
273
- };
274
- const handleRegionSelection = (region) => {
275
- setSelectedDocumentType((prev) => ({ ...prev, region: region }));
276
- };
277
- // Interface de sélection du type de document
278
- if (showDocumentSelection.documentSelection || showDocumentSelection.regionSelection) {
318
+ // Vérifier si les données sont disponibles, sinon afficher un message d'erreur
319
+ if (!countrySelectionData || !selectedDocumentType) {
279
320
  return (<View style={styles.root}>
280
321
  <View style={styles.container}>
281
-
282
322
  <Text style={styles.title}>{getLocalizedText(component.labels)}</Text>
283
- <Text style={styles.description}>{getLocalizedText(component.instructions)}</Text>
284
-
285
- <ScrollView style={styles.documentTypesContainer} showsVerticalScrollIndicator={false}>
286
- {showDocumentSelection.documentSelection ? availableDocumentTypes.map((docType) => {
287
- const docInfo = getDocumentTypeInfo(docType);
288
- return (<TouchableOpacity key={docType} style={[styles.documentTypeButton, { backgroundColor: selectedDocumentType?.type === docType ? '#2DBD6030' : '#F8F9FA', borderColor: selectedDocumentType?.type === docType ? '#2DBD60' : '#E9ECEF', borderWidth: 2 }]} onPress={() => handleDocumentTypeSelection(docType)}>
289
- <View style={[styles.documentTypeIconContainer, { backgroundColor: 'gray', }]}>
290
- <Text style={styles.documentTypeIcon}>{docInfo.icon}</Text>
291
- </View>
292
- <Text style={styles.documentTypeName}>
293
- {docInfo.name[language] || docInfo.name.en}
294
- </Text>
295
- <Text style={styles.documentTypeArrow}>→</Text>
296
- </TouchableOpacity>);
297
- }) : null}
298
- {showDocumentSelection.regionSelection ?
299
- hasRegions(selectedDocumentType?.type || 'identity_card').regionMapping.map((region) => {
300
- return (<TouchableOpacity key={region} onPress={() => handleRegionSelection(region)} style={[styles.documentTypeButton, { backgroundColor: selectedDocumentType?.region === region ? '#2DBD6030' : '#F8F9FA', borderColor: selectedDocumentType?.region === region ? '#2DBD60' : '#E9ECEF', borderWidth: 2 }]}>
301
- <Text>{region}</Text>
302
- </TouchableOpacity>);
303
- }) : null}
304
- </ScrollView>
305
- <Button title={t('common.next')} onPress={() => {
306
- if (!selectedDocumentType) {
307
- Alert.alert(t('common.error'), t('validation.required'));
308
- return;
309
- }
310
- if (showDocumentSelection.regionSelection) {
311
- logger.log("showDocumentSelection", JSON.stringify(truncateFields(showDocumentSelection), null, 2));
312
- setShowDocumentSelection({
313
- documentSelection: false,
314
- regionSelection: false
315
- });
316
- setShowCamera(true);
317
- actions.showCustomStepper(false);
318
- return;
319
- }
320
- else {
321
- if (hasRegions(selectedDocumentType?.type)?.hasRegions) {
322
- setShowDocumentSelection({
323
- documentSelection: false,
324
- regionSelection: true
325
- });
326
- }
327
- else {
328
- setShowDocumentSelection({
329
- documentSelection: false,
330
- regionSelection: false
331
- });
332
- setShowCamera(true);
333
- actions.showCustomStepper(false);
334
- }
335
- }
336
- }} variant={selectedDocumentType ? 'primary' : "neutral"} size="large" fullWidth/>
337
-
338
-
323
+ <Text style={styles.description}>
324
+ {state.currentLanguage === "en"
325
+ ? "Please complete the country and document selection first."
326
+ : "Veuillez d'abord compléter la sélection du pays et du document."}
327
+ </Text>
339
328
  {error && (<Text style={styles.errorText}>{error}</Text>)}
340
329
  </View>
341
330
  </View>);
@@ -347,10 +336,6 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
347
336
  if (currentSide === 'back') {
348
337
  setCurrentSide('front');
349
338
  setShowCamera(false);
350
- setShowDocumentSelection({
351
- documentSelection: false,
352
- regionSelection: false
353
- });
354
339
  // Si une image front existe, on la restaure pour l'afficher
355
340
  if (capturedImages['front']?.dir) {
356
341
  // Restaurer l'état de capture du front pour afficher l'image
@@ -375,14 +360,11 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
375
360
  }
376
361
  }
377
362
  else {
378
- setShowDocumentSelection({
379
- documentSelection: true,
380
- regionSelection: false
381
- });
382
- actions.showCustomStepper(true);
363
+ // Retour au composant précédent (country_selection)
364
+ actions.previousComponent();
383
365
  }
384
366
  },
385
- selectedDocumentType: locale === 'en' ? getDocumentTypeInfo(selectedDocumentType?.type || "identity_card").name.en : getDocumentTypeInfo(selectedDocumentType?.type || "identity_card").name.fr || '',
367
+ selectedDocumentType: selectedDocumentType ? (locale === 'en' ? getDocumentTypeInfo(selectedDocumentType.type).name.en : getDocumentTypeInfo(selectedDocumentType.type).name.fr) : '',
386
368
  step: state.currentComponentIndex + 1,
387
369
  totalSteps: state.template.components.length,
388
370
  side: currentSide,
@@ -430,22 +412,33 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
430
412
  }}/>) : null}
431
413
 
432
414
  </View>
433
- {/* retake button */}
434
- <Button title={t('kyc.idCardCapture.retakeButton')} onPress={() => {
435
- retakePicture(currentSide);
436
- }} variant="outline" size="medium" fullWidth/>
437
- <Button title={t('common.next')} onPress={() => {
438
- if (currentSide === 'back' || selectedDocumentType?.type === 'passport') {
439
- actions.nextComponent();
440
- return;
441
- }
442
- else {
415
+ {/* Capture button si aucune image n'a été capturée */}
416
+ {!capturedImages[currentSide]?.dir && (<Button title={state.currentLanguage === "en" ? "Take Photo" : "Prendre une photo"} onPress={() => {
443
417
  setShowCamera(true);
444
- setCurrentSide('back');
445
- setSilentCaptureResult((prev) => ({ path: '', success: false, isAnalyzing: false, error: '', mrz: '', templatePath: '' }));
446
- setCropImageUri('');
447
- }
448
- }} variant="primary" size="large" fullWidth/>
418
+ actions.showCustomStepper(false);
419
+ }} variant="primary" size="large" fullWidth/>)}
420
+ {/* retake button si une image a été capturée */}
421
+ {capturedImages[currentSide]?.dir && (<>
422
+ <Button title={t('kyc.idCardCapture.retakeButton')} onPress={() => {
423
+ retakePicture(currentSide);
424
+ }} variant="outline" size="medium" fullWidth/>
425
+ <Button title={t('common.next')} onPress={() => {
426
+ if (!selectedDocumentType) {
427
+ showAlert('Error', 'Document type not selected');
428
+ return;
429
+ }
430
+ if (currentSide === 'back' || selectedDocumentType.type === 'passport') {
431
+ actions.nextComponent();
432
+ return;
433
+ }
434
+ else {
435
+ setShowCamera(true);
436
+ setCurrentSide('back');
437
+ setSilentCaptureResult((prev) => ({ path: '', success: false, isAnalyzing: false, error: '', mrz: '', templatePath: '' }));
438
+ setCropImageUri('');
439
+ }
440
+ }} variant="primary" size="large" fullWidth/>
441
+ </>)}
449
442
  </View>
450
443
  </View>
451
444
  </ScrollView>
@@ -606,42 +599,5 @@ const styles = StyleSheet.create({
606
599
  marginTop: 8,
607
600
  textAlign: 'center',
608
601
  },
609
- documentTypesContainer: {
610
- // flex: 1,
611
- // marginBottom: 16,
612
- // paddingHorizontal: 16,
613
- maxHeight: Dimensions.get('window').height - 400,
614
- },
615
- documentTypeButton: {
616
- flexDirection: 'row',
617
- alignItems: 'center',
618
- backgroundColor: '#F8F9FA',
619
- padding: 16,
620
- marginBottom: 12,
621
- borderRadius: 12,
622
- borderWidth: 1,
623
- borderColor: '#E9ECEF',
624
- },
625
- documentTypeIconContainer: {
626
- width: 40, height: 40,
627
- borderRadius: 10,
628
- alignItems: 'center',
629
- justifyContent: 'center',
630
- marginRight: 16,
631
- },
632
- documentTypeIcon: {
633
- fontSize: 24,
634
- },
635
- documentTypeName: {
636
- flex: 1,
637
- fontSize: 16,
638
- fontWeight: '600',
639
- color: '#333',
640
- },
641
- documentTypeArrow: {
642
- fontSize: 18,
643
- color: '#666',
644
- fontWeight: 'bold',
645
- },
646
602
  });
647
603
  //# sourceMappingURL=IDCardCapture.js.map