@transfergratis/react-native-sdk 0.1.4 → 0.1.6
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/build/api/axios.d.ts +30 -0
- package/build/api/axios.d.ts.map +1 -0
- package/build/api/axios.js +92 -0
- package/build/api/axios.js.map +1 -0
- package/build/components/EnhancedCameraView.d.ts +1 -41
- package/build/components/EnhancedCameraView.d.ts.map +1 -1
- package/build/components/EnhancedCameraView.js +75 -34
- package/build/components/EnhancedCameraView.js.map +1 -1
- package/build/components/EnhancedCameraView.web.d.ts +1 -41
- package/build/components/EnhancedCameraView.web.d.ts.map +1 -1
- package/build/components/EnhancedCameraView.web.js +28 -4
- package/build/components/EnhancedCameraView.web.js.map +1 -1
- package/build/components/KYCElements/CountrySelectionTemplate.d.ts +2 -2
- package/build/components/KYCElements/CountrySelectionTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/CountrySelectionTemplate.js +77 -114
- package/build/components/KYCElements/CountrySelectionTemplate.js.map +1 -1
- package/build/components/KYCElements/FileUploadTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/FileUploadTemplate.js +7 -3
- package/build/components/KYCElements/FileUploadTemplate.js.map +1 -1
- package/build/components/KYCElements/IDCardCapture.d.ts +7 -2
- package/build/components/KYCElements/IDCardCapture.d.ts.map +1 -1
- package/build/components/KYCElements/IDCardCapture.js +253 -104
- package/build/components/KYCElements/IDCardCapture.js.map +1 -1
- package/build/components/KYCElements/InitializationStep.d.ts +5 -0
- package/build/components/KYCElements/InitializationStep.d.ts.map +1 -0
- package/build/components/KYCElements/InitializationStep.js +41 -0
- package/build/components/KYCElements/InitializationStep.js.map +1 -0
- package/build/components/KYCElements/LocationCaptureTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/LocationCaptureTemplate.js +15 -13
- package/build/components/KYCElements/LocationCaptureTemplate.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCapture.d.ts +2 -2
- package/build/components/KYCElements/OrientationVideoCapture.d.ts.map +1 -1
- package/build/components/KYCElements/OrientationVideoCapture.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.d.ts +2 -2
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.d.ts.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureFinal.d.ts +2 -2
- package/build/components/KYCElements/OrientationVideoCaptureFinal.d.ts.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureFinal.js.map +1 -1
- package/build/components/KYCElements/ReviewSubmitTemplate.d.ts +12 -0
- package/build/components/KYCElements/ReviewSubmitTemplate.d.ts.map +1 -0
- package/build/components/KYCElements/ReviewSubmitTemplate.js +171 -0
- package/build/components/KYCElements/ReviewSubmitTemplate.js.map +1 -0
- package/build/components/KYCElements/SelfieCaptureTemplate.d.ts +6 -2
- package/build/components/KYCElements/SelfieCaptureTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/SelfieCaptureTemplate.js +137 -38
- package/build/components/KYCElements/SelfieCaptureTemplate.js.map +1 -1
- package/build/components/KYCElements/VerificationProgressTemplate.d.ts +12 -0
- package/build/components/KYCElements/VerificationProgressTemplate.d.ts.map +1 -0
- package/build/components/KYCElements/VerificationProgressTemplate.js +194 -0
- package/build/components/KYCElements/VerificationProgressTemplate.js.map +1 -0
- package/build/components/OverLay/IdCard.d.ts +1 -1
- package/build/components/OverLay/IdCard.d.ts.map +1 -1
- package/build/components/OverLay/IdCard.js +10 -6
- package/build/components/OverLay/IdCard.js.map +1 -1
- package/build/components/OverLay/SelfieOverlay.d.ts +1 -1
- package/build/components/OverLay/SelfieOverlay.d.ts.map +1 -1
- package/build/components/OverLay/SelfieOverlay.js +5 -4
- package/build/components/OverLay/SelfieOverlay.js.map +1 -1
- package/build/components/OverLay/type.d.ts +71 -1
- package/build/components/OverLay/type.d.ts.map +1 -1
- package/build/components/OverLay/type.js.map +1 -1
- package/build/components/TemplateKYCExample.d.ts +4 -1
- package/build/components/TemplateKYCExample.d.ts.map +1 -1
- package/build/components/TemplateKYCExample.js +74 -199
- package/build/components/TemplateKYCExample.js.map +1 -1
- package/build/components/TemplateKYCFlowRefactored.d.ts +3 -2
- package/build/components/TemplateKYCFlowRefactored.d.ts.map +1 -1
- package/build/components/TemplateKYCFlowRefactored.js +64 -40
- package/build/components/TemplateKYCFlowRefactored.js.map +1 -1
- package/build/components/example/OrientationVideoExample.d.ts.map +1 -1
- package/build/components/example/OrientationVideoExample.js +1 -5
- package/build/components/example/OrientationVideoExample.js.map +1 -1
- package/build/config/countriesData.d.ts +3 -0
- package/build/config/countriesData.d.ts.map +1 -0
- package/build/config/countriesData.js +79 -0
- package/build/config/countriesData.js.map +1 -0
- package/build/config/region_mapping.d.ts +3 -0
- package/build/config/region_mapping.d.ts.map +1 -0
- package/build/config/region_mapping.js +687 -0
- package/build/config/region_mapping.js.map +1 -0
- package/build/hooks/useI18n.d.ts +11 -0
- package/build/hooks/useI18n.d.ts.map +1 -0
- package/build/hooks/useI18n.js +37 -0
- package/build/hooks/useI18n.js.map +1 -0
- package/build/hooks/useOrientationVideo.d.ts +1 -2
- package/build/hooks/useOrientationVideo.d.ts.map +1 -1
- package/build/hooks/useOrientationVideo.js +2 -1
- package/build/hooks/useOrientationVideo.js.map +1 -1
- package/build/hooks/useRealtimeVerifier.d.ts +28 -0
- package/build/hooks/useRealtimeVerifier.d.ts.map +1 -0
- package/build/hooks/useRealtimeVerifier.js +91 -0
- package/build/hooks/useRealtimeVerifier.js.map +1 -0
- package/build/hooks/useTemplateKYCFlow.d.ts +6 -3
- package/build/hooks/useTemplateKYCFlow.d.ts.map +1 -1
- package/build/hooks/useTemplateKYCFlow.js +356 -42
- package/build/hooks/useTemplateKYCFlow.js.map +1 -1
- package/build/i18n/en/index.d.ts +168 -0
- package/build/i18n/en/index.d.ts.map +1 -0
- package/build/i18n/en/index.js +195 -0
- package/build/i18n/en/index.js.map +1 -0
- package/build/i18n/fr/index.d.ts +168 -0
- package/build/i18n/fr/index.d.ts.map +1 -0
- package/build/i18n/fr/index.js +194 -0
- package/build/i18n/fr/index.js.map +1 -0
- package/build/i18n/index.d.ts +10 -0
- package/build/i18n/index.d.ts.map +1 -0
- package/build/i18n/index.js +56 -0
- package/build/i18n/index.js.map +1 -0
- package/build/i18n/types.d.ts +153 -0
- package/build/i18n/types.d.ts.map +1 -0
- package/build/i18n/types.js +3 -0
- package/build/i18n/types.js.map +1 -0
- package/build/i18n/usage-example.d.ts +4 -0
- package/build/i18n/usage-example.d.ts.map +1 -0
- package/build/i18n/usage-example.js +189 -0
- package/build/i18n/usage-example.js.map +1 -0
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -0
- package/build/index.js.map +1 -1
- package/build/modules/api/CardAuthentification.d.ts +22 -0
- package/build/modules/api/CardAuthentification.d.ts.map +1 -0
- package/build/modules/api/CardAuthentification.js +107 -0
- package/build/modules/api/CardAuthentification.js.map +1 -0
- package/build/modules/api/KYCService.d.ts +58 -1
- package/build/modules/api/KYCService.d.ts.map +1 -1
- package/build/modules/api/KYCService.js +304 -27
- package/build/modules/api/KYCService.js.map +1 -1
- package/build/modules/api/SelfieVerification.d.ts +3 -0
- package/build/modules/api/SelfieVerification.d.ts.map +1 -0
- package/build/modules/api/SelfieVerification.js +9 -0
- package/build/modules/api/SelfieVerification.js.map +1 -0
- package/build/modules/api/backendApi.d.ts +2 -0
- package/build/modules/api/backendApi.d.ts.map +1 -0
- package/build/modules/api/backendApi.js +6 -0
- package/build/modules/api/backendApi.js.map +1 -0
- package/build/modules/api/types.d.ts +45 -0
- package/build/modules/api/types.d.ts.map +1 -0
- package/build/modules/api/types.js +2 -0
- package/build/modules/api/types.js.map +1 -0
- package/build/types/KYC.types.d.ts +56 -7
- package/build/types/KYC.types.d.ts.map +1 -1
- package/build/types/KYC.types.js +9 -1
- package/build/types/KYC.types.js.map +1 -1
- package/build/utils/cropByObb.d.ts +11 -0
- package/build/utils/cropByObb.d.ts.map +1 -0
- package/build/utils/cropByObb.js +78 -0
- package/build/utils/cropByObb.js.map +1 -0
- package/build/utils/get-document-type-info.d.ts +13 -0
- package/build/utils/get-document-type-info.d.ts.map +1 -0
- package/build/utils/get-document-type-info.js +59 -0
- package/build/utils/get-document-type-info.js.map +1 -0
- package/build/utils/pathToBase64.d.ts +3 -0
- package/build/utils/pathToBase64.d.ts.map +1 -0
- package/build/utils/pathToBase64.js +47 -0
- package/build/utils/pathToBase64.js.map +1 -0
- package/build/utils/remove-duplicate.d.ts +2 -0
- package/build/utils/remove-duplicate.d.ts.map +1 -0
- package/build/utils/remove-duplicate.js +4 -0
- package/build/utils/remove-duplicate.js.map +1 -0
- package/build/web/WebKYCEntry.d.ts +9 -0
- package/build/web/WebKYCEntry.d.ts.map +1 -0
- package/build/web/WebKYCEntry.js +156 -0
- package/build/web/WebKYCEntry.js.map +1 -0
- package/build/web/index.d.ts +2 -0
- package/build/web/index.d.ts.map +1 -0
- package/build/web/index.js +2 -0
- package/build/web/index.js.map +1 -0
- package/package.json +3 -1
- package/src/api/axios.ts +144 -0
- package/src/components/EnhancedCameraView.tsx +96 -78
- package/src/components/EnhancedCameraView.web.tsx +41 -40
- package/src/components/KYCElements/CountrySelectionTemplate.tsx +111 -136
- package/src/components/KYCElements/FileUploadTemplate.tsx +14 -8
- package/src/components/KYCElements/IDCardCapture.tsx +311 -115
- package/src/components/KYCElements/InitializationStep.tsx +53 -0
- package/src/components/KYCElements/LocationCaptureTemplate.tsx +17 -15
- 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/ReviewSubmitTemplate.tsx +201 -0
- package/src/components/KYCElements/SelfieCaptureTemplate.tsx +174 -57
- package/src/components/KYCElements/VerificationProgressTemplate.tsx +246 -0
- package/src/components/OverLay/IdCard.tsx +17 -9
- package/src/components/OverLay/SelfieOverlay.tsx +6 -5
- package/src/components/OverLay/type.ts +64 -2
- package/src/components/TemplateKYCExample.tsx +80 -200
- package/src/components/TemplateKYCFlowRefactored.tsx +80 -48
- package/src/components/example/OrientationVideoExample.tsx +3 -7
- package/src/config/countriesData.ts +84 -0
- package/src/config/region_mapping.ts +688 -0
- package/src/hooks/useI18n.ts +53 -0
- package/src/hooks/useOrientationVideo.ts +2 -2
- package/src/hooks/useRealtimeVerifier.ts +128 -0
- package/src/hooks/useTemplateKYCFlow.tsx +407 -57
- package/src/i18n/README.md +288 -0
- package/src/i18n/en/index.ts +206 -0
- package/src/i18n/fr/index.ts +205 -0
- package/src/i18n/index.ts +65 -0
- package/src/i18n/types.ts +172 -0
- package/src/i18n/usage-example.tsx +202 -0
- package/src/index.ts +3 -0
- package/src/modules/api/CardAuthentification.ts +114 -0
- package/src/modules/api/KYCService.ts +350 -30
- package/src/modules/api/SelfieVerification.ts +11 -0
- package/src/modules/api/backendApi.ts +8 -0
- package/src/modules/api/types.ts +51 -0
- package/src/types/KYC.types.ts +82 -14
- package/src/utils/cropByObb.ts +99 -0
- package/src/utils/get-document-type-info.ts +62 -0
- package/src/utils/pathToBase64.ts +47 -0
- package/src/utils/remove-duplicate.ts +3 -0
- package/src/web/WebKYCEntry.tsx +215 -0
- package/src/web/index.ts +1 -0
- package/src/types/nativewind.d.ts +0 -2
|
@@ -1,15 +1,23 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react';
|
|
1
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
|
2
2
|
import { View, Text, StyleSheet, Alert, ScrollView } from 'react-native';
|
|
3
|
-
import { TemplateComponent, SelfieConfig, LocalizedText } from '../../types/KYC.types';
|
|
3
|
+
import { TemplateComponent, SelfieConfig, LocalizedText, ISilentCaptureResult, OrientationType, GovernmentDocumentType } from '../../types/KYC.types';
|
|
4
4
|
import { EnhancedCameraView } from '../EnhancedCameraView';
|
|
5
5
|
import { Button } from '../ui/Button';
|
|
6
6
|
import { useTemplateKYCFlowContext } from '../../hooks/useTemplateKYCFlow';
|
|
7
|
+
import { useI18n } from '../../hooks/useI18n';
|
|
7
8
|
import SelfieOverlay from '../OverLay/SelfieOverlay';
|
|
9
|
+
import selfieVerification from '../../modules/api/SelfieVerification';
|
|
10
|
+
import pathToBase64 from '../../utils/pathToBase64';
|
|
11
|
+
import { truncateFields } from '../../modules/api/KYCService';
|
|
8
12
|
|
|
13
|
+
interface IImagePayload {
|
|
14
|
+
dir: string;
|
|
15
|
+
file: string;
|
|
16
|
+
}
|
|
9
17
|
interface SelfieCaptureTemplateProps {
|
|
10
18
|
component: TemplateComponent;
|
|
11
|
-
value: Record<string,
|
|
12
|
-
onValueChange: (value: Record<string, string>) => void;
|
|
19
|
+
value: Record<string, IImagePayload> | undefined;
|
|
20
|
+
onValueChange: (value: Record<string, IImagePayload | string>) => void;
|
|
13
21
|
error?: string;
|
|
14
22
|
language: string;
|
|
15
23
|
}
|
|
@@ -21,30 +29,41 @@ export const SelfieCaptureTemplate: React.FC<SelfieCaptureTemplateProps> = ({
|
|
|
21
29
|
error,
|
|
22
30
|
language,
|
|
23
31
|
}) => {
|
|
32
|
+
const { t } = useI18n();
|
|
24
33
|
const config = component.config as SelfieConfig;
|
|
25
|
-
const
|
|
26
|
-
const orientations = config.orientations || ['front'];
|
|
34
|
+
const orientations: OrientationType[] = (config.orientations || ['center']) as OrientationType[];
|
|
27
35
|
const { actions, state, } = useTemplateKYCFlowContext();
|
|
28
36
|
|
|
37
|
+
const [silentCaptureResult, setSilentCaptureResult] = useState<ISilentCaptureResult>({ success: false, isAnalyzing: false });
|
|
38
|
+
|
|
39
|
+
|
|
29
40
|
const [showCamera, setShowCamera] = useState(false);
|
|
30
|
-
const [currentOrientation, setCurrentOrientation] = useState<
|
|
31
|
-
const [capturedImages, setCapturedImages] = useState<Record<string,
|
|
32
|
-
const [attempts, setAttempts] = useState(0);
|
|
41
|
+
const [currentOrientation, setCurrentOrientation] = useState<OrientationType>(orientations[0]);
|
|
42
|
+
const [capturedImages, setCapturedImages] = useState<Record<string, IImagePayload>>(value || {});
|
|
33
43
|
|
|
34
|
-
const getLocalizedText = (text: LocalizedText): string => {
|
|
35
|
-
|
|
44
|
+
const getLocalizedText = (text: LocalizedText | Record<string, LocalizedText>): string => {
|
|
45
|
+
if (!text) return '';
|
|
46
|
+
// If text is a nested record (e.g., per theme/device), try to pick a default then localize
|
|
47
|
+
const maybeNested = text as Record<string, LocalizedText>;
|
|
48
|
+
if (maybeNested && typeof maybeNested === 'object' && 'en' in maybeNested === false && 'fr' in maybeNested === false) {
|
|
49
|
+
const firstKey = Object.keys(maybeNested)[0];
|
|
50
|
+
const nested = maybeNested[firstKey] as LocalizedText;
|
|
51
|
+
return nested?.[language] || nested?.en || '';
|
|
52
|
+
}
|
|
53
|
+
const loc = text as LocalizedText;
|
|
54
|
+
return loc[language] || loc.en || '';
|
|
36
55
|
};
|
|
37
56
|
|
|
38
|
-
const getOrientationInstructions = (orientation:
|
|
57
|
+
const getOrientationInstructions = (orientation: OrientationType): string => {
|
|
39
58
|
switch (orientation) {
|
|
40
|
-
case '
|
|
41
|
-
return
|
|
59
|
+
case 'center':
|
|
60
|
+
return state.currentLanguage === "en" ? "Take a selfie of face, look straight ahead you" : "Prenez un selfie de face, regardez droit devant vous";
|
|
42
61
|
case 'left':
|
|
43
|
-
return
|
|
62
|
+
return state.currentLanguage === "en" ? "Turn your head to the left, keep your shoulders straight" : "Tournez votre tête vers la gauche, gardez les épaules droites";
|
|
44
63
|
case 'right':
|
|
45
|
-
return
|
|
64
|
+
return state.currentLanguage === "en" ? "Turn your head to the right, keep your shoulders straight" : "Tournez votre tête vers la droite, gardez les épaules droites";
|
|
46
65
|
default:
|
|
47
|
-
return getLocalizedText(component.instructions);
|
|
66
|
+
return getLocalizedText(component.instructions as LocalizedText);
|
|
48
67
|
}
|
|
49
68
|
};
|
|
50
69
|
|
|
@@ -52,60 +71,136 @@ export const SelfieCaptureTemplate: React.FC<SelfieCaptureTemplateProps> = ({
|
|
|
52
71
|
actions.showCustomStepper(!showCamera);
|
|
53
72
|
}, [showCamera]);
|
|
54
73
|
|
|
55
|
-
const getOrientationLabel = (orientation:
|
|
74
|
+
const getOrientationLabel = (orientation: OrientationType): string => {
|
|
56
75
|
switch (orientation) {
|
|
57
|
-
case '
|
|
58
|
-
return
|
|
76
|
+
case 'center':
|
|
77
|
+
return state.currentLanguage === "en" ? "Selfie de face" : "Selfie de face";
|
|
59
78
|
case 'left':
|
|
60
|
-
return
|
|
79
|
+
return state.currentLanguage === "en" ? "Selfie profil gauche" : "Selfie profil gauche";
|
|
61
80
|
case 'right':
|
|
62
|
-
return
|
|
81
|
+
return state.currentLanguage === "en" ? "Selfie profil droit" : "Selfie profil droit";
|
|
63
82
|
default:
|
|
64
|
-
return getLocalizedText(component.labels);
|
|
83
|
+
return getLocalizedText(component.labels as LocalizedText);
|
|
65
84
|
}
|
|
66
85
|
};
|
|
86
|
+
const getOrientationOpposite = (orientation: OrientationType): OrientationType => {
|
|
87
|
+
switch (orientation) {
|
|
88
|
+
case 'center':
|
|
89
|
+
|
|
90
|
+
return 'center';
|
|
91
|
+
case 'left':
|
|
92
|
+
return 'left';
|
|
93
|
+
case 'right':
|
|
94
|
+
return 'right';
|
|
95
|
+
default:
|
|
96
|
+
return orientation;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// const countryData = useMemo(() => {
|
|
100
|
+
// const geCountryID = Object.keys(state.componentData).find((c: string) => c === "6");
|
|
67
101
|
|
|
68
|
-
|
|
102
|
+
// if (geCountryID) {
|
|
103
|
+
// const countryMapping = state.componentData[geCountryID];
|
|
104
|
+
// return countryMapping?.code;
|
|
105
|
+
// }
|
|
106
|
+
// return null;
|
|
107
|
+
// }, [state.componentData]);
|
|
108
|
+
|
|
109
|
+
const getInstructions = (orientation: OrientationType): { title: string, subtitle: string } => {
|
|
110
|
+
const lang = state.currentLanguage;
|
|
69
111
|
switch (orientation) {
|
|
70
|
-
case '
|
|
71
|
-
return {
|
|
112
|
+
case 'center':
|
|
113
|
+
return {
|
|
114
|
+
title:
|
|
115
|
+
|
|
116
|
+
lang === "en" ? 'Center your face' : 'Mettez votre face au centre',
|
|
117
|
+
subtitle: lang === "en"
|
|
118
|
+
? 'Align your face to the center of the selfie area and then take a photo'
|
|
119
|
+
: 'Alignez votre visage au centre de la zone selfie puis prenez une photo'
|
|
120
|
+
};
|
|
72
121
|
case 'left':
|
|
73
|
-
return {
|
|
122
|
+
return {
|
|
123
|
+
title:
|
|
124
|
+
lang === 'en'
|
|
125
|
+
? 'Turn your head left'
|
|
126
|
+
: 'Tournez la tête vers la gauche',
|
|
127
|
+
subtitle:
|
|
128
|
+
lang === 'en'
|
|
129
|
+
? 'Slowly turn your head to the left while keeping your face in the selfie area'
|
|
130
|
+
: 'Tournez lentement la tête vers la gauche en gardant votre visage dans la zone selfie'
|
|
131
|
+
};
|
|
74
132
|
case 'right':
|
|
75
|
-
return {
|
|
133
|
+
return {
|
|
134
|
+
title:
|
|
135
|
+
lang === 'en'
|
|
136
|
+
? 'Turn your head right'
|
|
137
|
+
: 'Tournez la tête vers la droite',
|
|
138
|
+
subtitle:
|
|
139
|
+
lang === 'en'
|
|
140
|
+
? 'Slowly turn your head to the right while keeping your face in the selfie area'
|
|
141
|
+
: 'Tournez lentement la tête vers la droite en gardant votre visage dans la zone selfie'
|
|
142
|
+
};
|
|
76
143
|
default:
|
|
77
|
-
return { title: getLocalizedText(component.labels), subtitle: getLocalizedText(component.instructions) };
|
|
144
|
+
return { title: getLocalizedText(component.labels as LocalizedText), subtitle: getLocalizedText(component.instructions as LocalizedText) };
|
|
78
145
|
}
|
|
79
146
|
};
|
|
80
147
|
|
|
81
|
-
const
|
|
148
|
+
const handleSilentCapture = (result: { success: boolean; path?: string; error?: string }) => {
|
|
149
|
+
if (silentCaptureResult.isAnalyzing) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
82
152
|
if (result.success && result.path) {
|
|
83
|
-
|
|
153
|
+
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: true, success: false, error: '' }));
|
|
154
|
+
selfieVerification(result.path).then((response) => {
|
|
155
|
+
if (response.length > 0) {
|
|
156
|
+
const res = response[0];
|
|
157
|
+
if (res?.orientation_direction === getOrientationOpposite(currentOrientation) && res?.capture) {
|
|
158
|
+
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: true, error: '', path: result.path }));
|
|
159
|
+
} else {
|
|
160
|
+
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: 'Le selfie n\'est pas correct' }));
|
|
161
|
+
}
|
|
162
|
+
} else {
|
|
163
|
+
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: 'Le selfie n\'est pas correct' }));
|
|
164
|
+
}
|
|
165
|
+
}).catch((e: any) => {
|
|
166
|
+
|
|
167
|
+
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: e?.message || 'Erreur de vérification du selfie' }));
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const handleCapture = async (result: { success: boolean; path?: string; error?: string }) => {
|
|
173
|
+
console.log("handleCapturessss", silentCaptureResult);
|
|
174
|
+
|
|
175
|
+
if (silentCaptureResult.success && silentCaptureResult.path) {
|
|
176
|
+
const base64 = await pathToBase64(silentCaptureResult.path);
|
|
177
|
+
// Keep backward-compatible structure for UI validation and add *_base64 fields for backend payload
|
|
178
|
+
const newImages: Record<string, any> = {
|
|
179
|
+
...capturedImages,
|
|
180
|
+
[currentOrientation]: { dir: silentCaptureResult.path, file: base64 } as IImagePayload,
|
|
181
|
+
};
|
|
84
182
|
setCapturedImages(newImages);
|
|
85
183
|
onValueChange(newImages);
|
|
86
184
|
setShowCamera(false);
|
|
87
|
-
|
|
185
|
+
|
|
88
186
|
|
|
89
187
|
// Passer à l'orientation suivante si disponible
|
|
90
|
-
const currentIndex = orientations.indexOf(currentOrientation as
|
|
188
|
+
const currentIndex = orientations.indexOf(currentOrientation as OrientationType);
|
|
91
189
|
if (currentIndex < orientations.length - 1) {
|
|
92
190
|
setCurrentOrientation(orientations[currentIndex + 1]);
|
|
93
191
|
}
|
|
94
|
-
} else {
|
|
95
|
-
const newAttempts = attempts + 1;
|
|
96
|
-
setAttempts(newAttempts);
|
|
97
|
-
|
|
98
|
-
if (newAttempts >= maxAttempts) {
|
|
99
|
-
Alert.alert(
|
|
100
|
-
'Limite atteinte',
|
|
101
|
-
`Vous avez atteint le nombre maximum de tentatives (${maxAttempts}).`
|
|
102
|
-
);
|
|
103
|
-
setShowCamera(false);
|
|
104
|
-
} else {
|
|
105
|
-
Alert.alert('Erreur', result.error || 'Impossible de prendre le selfie');
|
|
106
|
-
}
|
|
107
192
|
}
|
|
108
193
|
};
|
|
194
|
+
const idCardData = useMemo(() => {
|
|
195
|
+
const idCardID = Object.keys(state.componentData).find((c: string) => c === "1");
|
|
196
|
+
if (idCardID) {
|
|
197
|
+
const _idCardData = state.componentData[idCardID];
|
|
198
|
+
return _idCardData as unknown as { country: string; documentType: GovernmentDocumentType };
|
|
199
|
+
}
|
|
200
|
+
return null;
|
|
201
|
+
}, [state.componentData]);
|
|
202
|
+
console.log("idCardData", truncateFields(idCardData), JSON.stringify(truncateFields(state.componentData), null, 2));
|
|
203
|
+
|
|
109
204
|
|
|
110
205
|
const handleError = (event: { message: string }) => {
|
|
111
206
|
Alert.alert('Erreur', event.message);
|
|
@@ -113,13 +208,15 @@ export const SelfieCaptureTemplate: React.FC<SelfieCaptureTemplateProps> = ({
|
|
|
113
208
|
};
|
|
114
209
|
|
|
115
210
|
|
|
116
|
-
const isOrientationCompleted = (orientation:
|
|
211
|
+
const isOrientationCompleted = (orientation: OrientationType): boolean => {
|
|
117
212
|
return !!capturedImages[orientation];
|
|
118
213
|
};
|
|
119
214
|
|
|
120
215
|
const isAllOrientationsCompleted = (): boolean => {
|
|
121
216
|
return orientations.every(orientation => isOrientationCompleted(orientation));
|
|
122
217
|
};
|
|
218
|
+
console.log("Current Orientation", currentOrientation);
|
|
219
|
+
|
|
123
220
|
|
|
124
221
|
if (showCamera) {
|
|
125
222
|
return (
|
|
@@ -136,6 +233,8 @@ export const SelfieCaptureTemplate: React.FC<SelfieCaptureTemplateProps> = ({
|
|
|
136
233
|
showCaptureButton={true}
|
|
137
234
|
showSwitchCamera={false}
|
|
138
235
|
enableFlash={false}
|
|
236
|
+
silentCaptureResult={silentCaptureResult}
|
|
237
|
+
onSilentCapture={handleSilentCapture}
|
|
139
238
|
overlayComponent={<SelfieOverlay
|
|
140
239
|
xMin={20}
|
|
141
240
|
yMin={140}
|
|
@@ -143,7 +242,8 @@ export const SelfieCaptureTemplate: React.FC<SelfieCaptureTemplateProps> = ({
|
|
|
143
242
|
yMax={340}
|
|
144
243
|
cornerOpacity={1}
|
|
145
244
|
instructions={""}
|
|
146
|
-
|
|
245
|
+
language={state.currentLanguage}
|
|
246
|
+
orientation={currentOrientation as 'center' | 'left' | 'right'}
|
|
147
247
|
instructionsTile={getInstructions(currentOrientation).title}
|
|
148
248
|
instructionsSubtitle={getInstructions(currentOrientation).subtitle}
|
|
149
249
|
stepperProps={{
|
|
@@ -159,7 +259,6 @@ export const SelfieCaptureTemplate: React.FC<SelfieCaptureTemplateProps> = ({
|
|
|
159
259
|
);
|
|
160
260
|
}
|
|
161
261
|
|
|
162
|
-
|
|
163
262
|
return (
|
|
164
263
|
<View style={[{
|
|
165
264
|
maxWidth: 760,
|
|
@@ -167,8 +266,8 @@ export const SelfieCaptureTemplate: React.FC<SelfieCaptureTemplateProps> = ({
|
|
|
167
266
|
height: '100%',
|
|
168
267
|
}]}>
|
|
169
268
|
<View style={styles.container}>
|
|
170
|
-
<Text style={styles.title}>{getLocalizedText(component.labels)}</Text>
|
|
171
|
-
<Text style={styles.description}>{getLocalizedText(component.instructions)}</Text>
|
|
269
|
+
<Text style={styles.title}>{getLocalizedText(component.labels as LocalizedText)}</Text>
|
|
270
|
+
<Text style={styles.description}>{getLocalizedText(component.instructions as LocalizedText)}</Text>
|
|
172
271
|
|
|
173
272
|
<ScrollView style={styles.orientationsContainer} showsVerticalScrollIndicator={false}>
|
|
174
273
|
<View style={{ flexDirection: 'column', alignItems: 'center', gap: 10 }}>
|
|
@@ -207,25 +306,43 @@ export const SelfieCaptureTemplate: React.FC<SelfieCaptureTemplateProps> = ({
|
|
|
207
306
|
))}
|
|
208
307
|
<View style={{ backgroundColor: "#F6CB0D1A", width: "100%", padding: 10, borderRadius: 10 }} >
|
|
209
308
|
<Text style={{ color: '#997E06', fontSize: 16, fontWeight: 'bold' }}>
|
|
210
|
-
|
|
309
|
+
{state.currentLanguage === "en"
|
|
310
|
+
? "Tips for a good selfie:"
|
|
311
|
+
: "Conseils pour une bonne photo selfie :"}
|
|
211
312
|
</Text>
|
|
212
313
|
<View style={{ paddingLeft: 10, paddingTop: 4 }}>
|
|
213
314
|
<Text style={{ color: '#997E06', fontSize: 14, fontWeight: 'bold' }}>
|
|
214
|
-
{
|
|
315
|
+
{state.currentLanguage === "en"
|
|
316
|
+
? `• Remove glasses and hat \n• Look directly at the camera \n• Ensure good lighting \n`
|
|
317
|
+
: `• Retirez vos lunettes et votre chapeau \n• Regardez directement la caméra \n• Assurez-vous d'une bonne luminosité \n`
|
|
318
|
+
}
|
|
215
319
|
</Text>
|
|
216
320
|
</View>
|
|
217
321
|
</View>
|
|
218
322
|
<View style={{ height: 10 }} />
|
|
219
323
|
{isAllOrientationsCompleted() ? <>
|
|
220
|
-
<Button title=
|
|
221
|
-
|
|
324
|
+
<Button title={t('common.continue')} fullWidth style={{ paddingVertical: 20, paddingTop: 12 }} onPress={async () => {
|
|
325
|
+
if (idCardData?.country && idCardData?.documentType) {
|
|
326
|
+
const value = {
|
|
327
|
+
...capturedImages,
|
|
328
|
+
country: idCardData?.country || '',
|
|
329
|
+
documentType: idCardData?.documentType as GovernmentDocumentType,
|
|
330
|
+
}
|
|
331
|
+
console.log("value", JSON.stringify(truncateFields(value), null, 2));
|
|
332
|
+
onValueChange(value);
|
|
333
|
+
} else {
|
|
334
|
+
Alert.alert('Erreur', 'Veuillez sélectionner un pays et un type de document');
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
222
337
|
actions.nextComponent();
|
|
223
338
|
}} />
|
|
224
339
|
</> : (
|
|
225
|
-
<Button title=
|
|
340
|
+
<Button title={t('kyc.selfieCapture.captureButton')} fullWidth style={{ paddingVertical: 20, paddingTop: 12 }} onPress={() => {
|
|
226
341
|
if (isAllOrientationsCompleted()) {
|
|
227
|
-
|
|
342
|
+
|
|
343
|
+
actions.nextComponent();
|
|
228
344
|
} else {
|
|
345
|
+
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: '' }));
|
|
229
346
|
setShowCamera(true);
|
|
230
347
|
}
|
|
231
348
|
}} />
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
|
|
3
|
+
import { TemplateComponent } from '../../types/KYC.types';
|
|
4
|
+
import { useTemplateKYCFlowContext } from '../../hooks/useTemplateKYCFlow';
|
|
5
|
+
import { useI18n } from '../../hooks/useI18n';
|
|
6
|
+
import kycService from '../../modules/api/KYCService';
|
|
7
|
+
|
|
8
|
+
interface VerificationProgressTemplateProps {
|
|
9
|
+
component: TemplateComponent;
|
|
10
|
+
value: unknown;
|
|
11
|
+
onValueChange: (data: unknown) => void;
|
|
12
|
+
error?: string;
|
|
13
|
+
language?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const VerificationProgressTemplate: React.FC<VerificationProgressTemplateProps> = () => {
|
|
17
|
+
const { t } = useI18n();
|
|
18
|
+
const { state, actions } = useTemplateKYCFlowContext();
|
|
19
|
+
const [retryCount, setRetryCount] = useState(0);
|
|
20
|
+
const [isRetrying, setIsRetrying] = useState(false);
|
|
21
|
+
const [timeoutId, setTimeoutId] = useState<number | null>(null);
|
|
22
|
+
|
|
23
|
+
const verification = state.verification;
|
|
24
|
+
|
|
25
|
+
const isSuccess = verification.status === 'success';
|
|
26
|
+
const isFailed = verification.status === 'failed';
|
|
27
|
+
|
|
28
|
+
// Fonction pour récupérer le résultat de vérification avec retry
|
|
29
|
+
const getVerificationResult = async (currentRetryCount = 0, maxRetries = 40) => {
|
|
30
|
+
try {
|
|
31
|
+
console.log(`Starting verification check (attempt ${currentRetryCount + 1}/${maxRetries + 1})`);
|
|
32
|
+
|
|
33
|
+
const result = await kycService.getVerificationResult(state.session.session_id);
|
|
34
|
+
const verificationResult = result[state.session.session_id].data;
|
|
35
|
+
|
|
36
|
+
console.log('getVerificationResult result', JSON.stringify(result, null, 2));
|
|
37
|
+
|
|
38
|
+
// Vérifier le statut de vérification
|
|
39
|
+
if (verificationResult.verification_status === null || verificationResult.verification_status === "processing" || verificationResult.verification_status === "pending") {
|
|
40
|
+
if (currentRetryCount < maxRetries) {
|
|
41
|
+
const nextRetryCount = currentRetryCount + 1;
|
|
42
|
+
setRetryCount(nextRetryCount);
|
|
43
|
+
setIsRetrying(true);
|
|
44
|
+
|
|
45
|
+
console.log(`Verification still processing, retrying in 10s... (${nextRetryCount}/${maxRetries})`);
|
|
46
|
+
|
|
47
|
+
// Nettoyer le timeout précédent s'il existe
|
|
48
|
+
if (timeoutId) {
|
|
49
|
+
clearTimeout(timeoutId);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Attendre 10 secondes avant de relancer
|
|
53
|
+
const newTimeoutId = setTimeout(() => {
|
|
54
|
+
getVerificationResult(nextRetryCount, maxRetries);
|
|
55
|
+
}, 10000);
|
|
56
|
+
|
|
57
|
+
setTimeoutId(newTimeoutId);
|
|
58
|
+
return; // Sortir de la fonction pour éviter de traiter le résultat
|
|
59
|
+
} else {
|
|
60
|
+
console.error('Max retries reached, verification still processing');
|
|
61
|
+
setIsRetrying(false);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Traiter le résultat final (success, failed, etc.)
|
|
67
|
+
if (verificationResult.verification_status === "completed" ||
|
|
68
|
+
verificationResult.verification_status === "approved") {
|
|
69
|
+
// Mettre à jour l'état avec le succès
|
|
70
|
+
actions.setVerificationState({
|
|
71
|
+
status: 'success',
|
|
72
|
+
result: result
|
|
73
|
+
});
|
|
74
|
+
} else if (verificationResult.verification_status === "failed" ||
|
|
75
|
+
verificationResult.verification_status === "rejected") {
|
|
76
|
+
// Mettre à jour l'état avec l'échec
|
|
77
|
+
actions.setVerificationState({
|
|
78
|
+
status: 'failed',
|
|
79
|
+
result: {
|
|
80
|
+
referenceId: verificationResult.verification_id,
|
|
81
|
+
issues: ['Verification failed']
|
|
82
|
+
} as any
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
setIsRetrying(false);
|
|
87
|
+
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error('getVerificationResult error', error);
|
|
90
|
+
|
|
91
|
+
// En cas d'erreur, on peut aussi retry
|
|
92
|
+
if (currentRetryCount < maxRetries) {
|
|
93
|
+
const nextRetryCount = currentRetryCount + 1;
|
|
94
|
+
setRetryCount(nextRetryCount);
|
|
95
|
+
setIsRetrying(true);
|
|
96
|
+
|
|
97
|
+
console.log(`Error occurred, retrying in 10s... (${nextRetryCount}/${maxRetries})`);
|
|
98
|
+
|
|
99
|
+
// Nettoyer le timeout précédent s'il existe
|
|
100
|
+
if (timeoutId) {
|
|
101
|
+
clearTimeout(timeoutId);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const newTimeoutId = setTimeout(() => {
|
|
105
|
+
getVerificationResult(nextRetryCount, maxRetries);
|
|
106
|
+
}, 10000);
|
|
107
|
+
|
|
108
|
+
setTimeoutId(newTimeoutId);
|
|
109
|
+
} else {
|
|
110
|
+
setIsRetrying(false);
|
|
111
|
+
console.error('Max retries reached after errors');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
if (state.session.session_id) {
|
|
118
|
+
getVerificationResult();
|
|
119
|
+
}
|
|
120
|
+
}, [state.session.session_id]);
|
|
121
|
+
|
|
122
|
+
// Nettoyage des timeouts lors du démontage du composant
|
|
123
|
+
useEffect(() => {
|
|
124
|
+
return () => {
|
|
125
|
+
if (timeoutId) {
|
|
126
|
+
clearTimeout(timeoutId);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}, [timeoutId]);
|
|
130
|
+
|
|
131
|
+
if (isSuccess) {
|
|
132
|
+
return (
|
|
133
|
+
<View style={styles.container}>
|
|
134
|
+
<Text style={styles.title}>{t('kyc.verificationProgress.steps.complete')}</Text>
|
|
135
|
+
<Text style={styles.subtitle}>{t('kyc.verificationProgress.subtitle')}</Text>
|
|
136
|
+
<TouchableOpacity style={[styles.button, styles.primary]} onPress={() => actions.submitVerification()}>
|
|
137
|
+
<Text style={styles.buttonText}>{t('common.continue')}</Text>
|
|
138
|
+
</TouchableOpacity>
|
|
139
|
+
{verification.result?.referenceId ? (
|
|
140
|
+
<Text style={styles.refText}>{`Verification ID: ${verification.result.referenceId}`}</Text>
|
|
141
|
+
) : null}
|
|
142
|
+
</View>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (isFailed) {
|
|
147
|
+
return (
|
|
148
|
+
<View style={styles.container}>
|
|
149
|
+
<Text style={styles.title}>{t('kyc.verificationProgress.status.failed')}</Text>
|
|
150
|
+
<Text style={styles.subtitle}>{t('errors.validationError')}</Text>
|
|
151
|
+
<View style={styles.issuesBox}>
|
|
152
|
+
<Text style={styles.issuesTitle}>{t('common.error')}</Text>
|
|
153
|
+
{Array.isArray(verification.result?.issues) && verification.result.issues.map((issue: string, idx: number) => (
|
|
154
|
+
<Text key={idx} style={styles.issueItem}>• {issue}</Text>
|
|
155
|
+
))}
|
|
156
|
+
</View>
|
|
157
|
+
<TouchableOpacity style={[styles.button, styles.primary]} onPress={() => actions.goToComponent(state.template.components.find(c => c.type !== 'review_submit' && c.type !== 'verification_progress')?.id || 0)}>
|
|
158
|
+
<Text style={styles.buttonText}>{t('common.retry')}</Text>
|
|
159
|
+
</TouchableOpacity>
|
|
160
|
+
<TouchableOpacity style={[styles.button, styles.secondary]}>
|
|
161
|
+
<Text style={styles.secondaryText}>{t('common.info')}</Text>
|
|
162
|
+
</TouchableOpacity>
|
|
163
|
+
{verification.result?.referenceId ? (
|
|
164
|
+
<Text style={styles.refText}>{`Reference ID: ${verification.result.referenceId}`}</Text>
|
|
165
|
+
) : null}
|
|
166
|
+
</View>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
return (
|
|
177
|
+
<View style={styles.container}>
|
|
178
|
+
<Text style={styles.title}>{t('kyc.verificationProgress.title')}</Text>
|
|
179
|
+
<Text style={styles.subtitle}>
|
|
180
|
+
{isRetrying
|
|
181
|
+
? `${t('kyc.verificationProgress.retrying')} (${retryCount}/10)`
|
|
182
|
+
: t('kyc.verificationProgress.estimatedTime')
|
|
183
|
+
}
|
|
184
|
+
</Text>
|
|
185
|
+
|
|
186
|
+
<View style={styles.timeline}>
|
|
187
|
+
<View style={[styles.dot, styles.done]}><Text style={styles.stepCheckmark}>✓</Text></View>
|
|
188
|
+
<View style={styles.line} />
|
|
189
|
+
<View style={[styles.dot, styles.active]}><Text style={styles.stepCheckmark}>2</Text></View>
|
|
190
|
+
<View style={styles.line} />
|
|
191
|
+
<View style={[styles.dot, styles.pending]}><Text style={styles.stepCheckmark}>3</Text></View>
|
|
192
|
+
</View>
|
|
193
|
+
|
|
194
|
+
<View style={styles.row}>
|
|
195
|
+
<Text style={styles.stepLabel}>{t('kyc.verificationProgress.status.completed')}</Text>
|
|
196
|
+
<Text style={styles.stepLabel}>{t('kyc.verificationProgress.steps.analyzing')}</Text>
|
|
197
|
+
<Text style={styles.stepLabel}>{t('kyc.verificationProgress.steps.verifying')}</Text>
|
|
198
|
+
</View>
|
|
199
|
+
|
|
200
|
+
<View style={styles.card}>
|
|
201
|
+
<Text style={styles.cardTitle}>{t('kyc.idCardCapture.title')}</Text>
|
|
202
|
+
<Text style={styles.cardLine}>{t('kyc.verificationProgress.steps.extracting')}</Text>
|
|
203
|
+
<Text style={styles.cardTitle}>{t('kyc.selfieCapture.title')}</Text>
|
|
204
|
+
<Text style={styles.cardLine}>{t('kyc.verificationProgress.steps.analyzing')}</Text>
|
|
205
|
+
<Text style={styles.cardTitle}>{t('kyc.verificationProgress.title')}</Text>
|
|
206
|
+
<Text style={styles.cardLine}>
|
|
207
|
+
{isRetrying
|
|
208
|
+
? `${t('kyc.verificationProgress.status.processing')}...`
|
|
209
|
+
: t('kyc.verificationProgress.status.pending')
|
|
210
|
+
}
|
|
211
|
+
</Text>
|
|
212
|
+
</View>
|
|
213
|
+
</View>
|
|
214
|
+
);
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
const styles = StyleSheet.create({
|
|
218
|
+
container: { flex: 1, width: '100%', paddingHorizontal: 16, paddingVertical: 12 },
|
|
219
|
+
title: { fontSize: 24, fontWeight: 'bold', color: '#111827', textAlign: 'center', marginTop: 12 },
|
|
220
|
+
subtitle: { fontSize: 14, color: '#6B7280', textAlign: 'center', marginTop: 8 },
|
|
221
|
+
timeline: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginTop: 24 },
|
|
222
|
+
dot: { width: 38, height: 38, borderRadius: 34, justifyContent: 'center', alignItems: 'center' },
|
|
223
|
+
stepCheckmark: { color: 'white', fontSize: 16, fontWeight: 'bold' },
|
|
224
|
+
line: { flex: 1, height: 4, backgroundColor: '#E5E7EB' },
|
|
225
|
+
done: { backgroundColor: '#10B981' },
|
|
226
|
+
active: { backgroundColor: '#F59E0B' },
|
|
227
|
+
pending: { backgroundColor: '#E5E7EB' },
|
|
228
|
+
row: { flexDirection: 'row', justifyContent: 'space-between', marginTop: 8 },
|
|
229
|
+
stepLabel: { fontSize: 14, color: '#111827', fontWeight: '600' },
|
|
230
|
+
card: { backgroundColor: 'white', padding: 16, borderRadius: 16, marginTop: 24 },
|
|
231
|
+
cardTitle: { fontSize: 16, color: '#6B7280', marginTop: 8 },
|
|
232
|
+
cardLine: { fontSize: 18, color: '#111827', fontWeight: '600', marginTop: 2 },
|
|
233
|
+
// Success/Failure specific
|
|
234
|
+
button: { paddingVertical: 14, borderRadius: 10, alignItems: 'center', marginTop: 20 },
|
|
235
|
+
primary: { backgroundColor: '#2DBD60' },
|
|
236
|
+
buttonText: { color: 'white', fontSize: 16, fontWeight: '600' },
|
|
237
|
+
refText: { marginTop: 12, textAlign: 'center', color: '#6B7280' },
|
|
238
|
+
issuesBox: { backgroundColor: '#FEF2F2', borderRadius: 16, padding: 16, marginTop: 20 },
|
|
239
|
+
issuesTitle: { color: '#991B1B', fontWeight: '700', marginBottom: 8 },
|
|
240
|
+
issueItem: { color: '#991B1B', marginTop: 4 },
|
|
241
|
+
secondary: { backgroundColor: '#F3F4F6' },
|
|
242
|
+
secondaryText: { color: '#111827', fontSize: 16, fontWeight: '600' },
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
|
|
@@ -7,18 +7,18 @@ import StepOverlay from "./StepOverlay";
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
const IdCardOverlay = ({ xMin: xMinProps, yMin: yMinProps, xMax: xMaxProps, yMax: yMaxProps, cornerOpacity, instructions, cornerColor = "#4CAF50", stepperProps }: IdCardOverlayProps) => {
|
|
10
|
+
const IdCardOverlay = ({ xMin: xMinProps, yMin: yMinProps, xMax: xMaxProps, yMax: yMaxProps, cornerOpacity, instructions, cornerColor = "#4CAF50", stepperProps, isSuccess, language }: IdCardOverlayProps) => {
|
|
11
11
|
const screenWidth = Dimensions.get('window').width;
|
|
12
12
|
const screenHeight = Dimensions.get('window').height;
|
|
13
13
|
|
|
14
14
|
const boxWidth = xMaxProps - xMinProps;
|
|
15
15
|
const boxHeight = yMaxProps - yMinProps;
|
|
16
16
|
|
|
17
|
-
|
|
18
17
|
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
22
|
// Calculer les coordonnées pour centrer le cadre
|
|
23
23
|
const xMin = (screenWidth - boxWidth) / 2;
|
|
24
24
|
const yMin = (screenHeight - boxHeight) / 3;
|
|
@@ -30,7 +30,7 @@ const IdCardOverlay = ({ xMin: xMinProps, yMin: yMinProps, xMax: xMaxProps, yMax
|
|
|
30
30
|
{stepperProps ? (
|
|
31
31
|
<StepOverlay {...stepperProps} />
|
|
32
32
|
) : null}
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
<Animated.View style={[styles.topIntruction]}>
|
|
35
35
|
<Text style={styles.topIntructionText}>
|
|
36
36
|
💡 {instructions}
|
|
@@ -134,15 +134,23 @@ const IdCardOverlay = ({ xMin: xMinProps, yMin: yMinProps, xMax: xMaxProps, yMax
|
|
|
134
134
|
opacity={cornerOpacity}
|
|
135
135
|
/>
|
|
136
136
|
</Svg>
|
|
137
|
-
|
|
138
|
-
|
|
137
|
+
{isSuccess ? null : (
|
|
138
|
+
<ScanningLine yMin={yMin} screenWidth={screenWidth} height={screenHeight} yMax={yMax} />
|
|
139
|
+
)}
|
|
140
|
+
{/* <ScanningLine yMin={yMin} screenWidth={screenWidth} height={screenHeight} yMax={yMax} /> */}
|
|
139
141
|
|
|
140
142
|
<View style={styles.bottomIntruction}>
|
|
141
143
|
<Text style={styles.bottomTitle}>
|
|
142
|
-
Mesurez 100cm de hauteur.
|
|
144
|
+
{language === "en" ? "Measure 100cm in height.":"Mesurez 100cm de hauteur."}
|
|
145
|
+
|
|
143
146
|
</Text>
|
|
144
147
|
<Text style={styles.bottomSubtitle}>
|
|
145
|
-
|
|
148
|
+
{
|
|
149
|
+
language === "en"
|
|
150
|
+
? "Do not move the camera during capture. • Do not move the camera during capture."
|
|
151
|
+
: "Ne pas déplacer la caméra pendant la capture. • Ne pas déplacer la caméra pendant la capture."
|
|
152
|
+
}
|
|
153
|
+
|
|
146
154
|
</Text>
|
|
147
155
|
</View>
|
|
148
156
|
</View>)
|