@sanctum-key/react-native-sdk 1.0.6 → 1.0.8
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/README.md +3 -3
- package/android/build/.transforms/{f62cb96b2d1f78ca96ab35932dd530dc → c9d62bb333688ab562f51958998d5a48}/transformed/classes/classes_dex/classes.dex +0 -0
- package/android/build/generated/source/buildConfig/debug/kyc/{transfergratis → SanctumKey}/com/BuildConfig.java +2 -2
- package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +1 -1
- package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +1 -1
- package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
- package/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +2 -2
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/kyc/SanctumKey/com/BuildConfig.class +0 -0
- package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +1 -1
- package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +1 -1
- package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
- package/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +1 -1
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
- package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
- package/android/build/outputs/logs/manifest-merger-debug-report.txt +1 -1
- package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/SanctumKey/com/SanctumKeySdkModule$definition$1$5$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/SanctumKey/com/SanctumKeySdkModule$definition$1$5$2.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunction$1.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$1.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunction$2.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$2.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunction$3.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$3.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunction$4.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$4.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunction$5.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$5.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunction$6.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$6.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$1.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$1.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$2.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$2.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$3.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$3.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$4.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$4.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$View$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$lambda$4$$inlined$Prop$1.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$lambda$4$$inlined$Prop$1.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$lambda$4$$inlined$Prop$2.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$lambda$4$$inlined$Prop$2.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule.class → SanctumKey/com/SanctumKeySdkModule.class} +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkView.class → SanctumKey/com/SanctumKeySdkView.class} +0 -0
- package/android/build.gradle +2 -2
- package/android/src/main/AndroidManifest.xml +1 -1
- package/android/src/main/java/kyc/transfergratis/com/TransfergratisSdkModule.kt +6 -6
- package/android/src/main/java/kyc/transfergratis/com/TransfergratisSdkView.kt +2 -2
- package/build/package.json +9 -7
- package/build/src/App.d.ts +2 -2
- package/build/src/App.d.ts.map +1 -1
- package/build/src/App.js +2 -2
- package/build/src/App.js.map +1 -1
- package/build/src/{TransfergratisSdk.types.d.ts → SanctumKeySdk.types.d.ts} +3 -3
- package/build/src/SanctumKeySdk.types.d.ts.map +1 -0
- package/build/src/SanctumKeySdk.types.js +2 -0
- package/build/src/SanctumKeySdk.types.js.map +1 -0
- package/build/src/{TransfergratisSdkModule.d.ts → SanctumKeySdkModule.d.ts} +4 -4
- package/build/src/SanctumKeySdkModule.d.ts.map +1 -0
- package/build/src/{TransfergratisSdkModule.js → SanctumKeySdkModule.js} +2 -2
- package/build/src/SanctumKeySdkModule.js.map +1 -0
- package/build/src/{TransfergratisSdkModule.web.d.ts → SanctumKeySdkModule.web.d.ts} +4 -4
- package/build/src/SanctumKeySdkModule.web.d.ts.map +1 -0
- package/build/src/{TransfergratisSdkModule.web.js → SanctumKeySdkModule.web.js} +3 -3
- package/build/src/SanctumKeySdkModule.web.js.map +1 -0
- package/build/src/SanctumKeySdkView.d.ts +4 -0
- package/build/src/SanctumKeySdkView.d.ts.map +1 -0
- package/build/src/SanctumKeySdkView.js +7 -0
- package/build/src/SanctumKeySdkView.js.map +1 -0
- package/build/src/SanctumKeySdkView.web.d.ts +4 -0
- package/build/src/SanctumKeySdkView.web.d.ts.map +1 -0
- package/build/src/{TransfergratisSdkView.web.js → SanctumKeySdkView.web.js} +2 -2
- package/build/src/SanctumKeySdkView.web.js.map +1 -0
- package/build/src/api/axios.js +2 -2
- package/build/src/api/axios.js.map +1 -1
- package/build/src/components/EnhancedCameraView.d.ts.map +1 -1
- package/build/src/components/EnhancedCameraView.js +107 -330
- package/build/src/components/EnhancedCameraView.js.map +1 -1
- package/build/src/components/KYCElements/EmailVerificationTemplate.d.ts.map +1 -1
- package/build/src/components/KYCElements/EmailVerificationTemplate.js +114 -15
- package/build/src/components/KYCElements/EmailVerificationTemplate.js.map +1 -1
- package/build/src/components/KYCElements/IDCardCapture.d.ts.map +1 -1
- package/build/src/components/KYCElements/IDCardCapture.js +166 -695
- package/build/src/components/KYCElements/IDCardCapture.js.map +1 -1
- package/build/src/components/KYCElements/PhoneVerificationTemplate.d.ts.map +1 -1
- package/build/src/components/KYCElements/PhoneVerificationTemplate.js +282 -40
- package/build/src/components/KYCElements/PhoneVerificationTemplate.js.map +1 -1
- package/build/src/components/KYCElements/SelfieCapture.d.ts +1 -1
- package/build/src/components/KYCElements/SelfieCapture.d.ts.map +1 -1
- package/build/src/components/KYCElements/SelfieCapture.js +130 -192
- package/build/src/components/KYCElements/SelfieCapture.js.map +1 -1
- package/build/src/components/KYCElements/SelfieCaptureTemplate.d.ts.map +1 -1
- package/build/src/components/KYCElements/SelfieCaptureTemplate.js +131 -433
- package/build/src/components/KYCElements/SelfieCaptureTemplate.js.map +1 -1
- package/build/src/components/NativeCameraView.js +1 -1
- package/build/src/components/NativeCameraView.js.map +1 -1
- package/build/src/components/OverLay/IdCard.d.ts +3 -2
- package/build/src/components/OverLay/IdCard.d.ts.map +1 -1
- package/build/src/components/OverLay/IdCard.js +149 -141
- package/build/src/components/OverLay/IdCard.js.map +1 -1
- package/build/src/components/OverLay/SelfieOverlay.d.ts +2 -1
- package/build/src/components/OverLay/SelfieOverlay.d.ts.map +1 -1
- package/build/src/components/OverLay/SelfieOverlay.js +37 -95
- package/build/src/components/OverLay/SelfieOverlay.js.map +1 -1
- package/build/src/components/OverLay/type.d.ts +1 -0
- package/build/src/components/OverLay/type.d.ts.map +1 -1
- package/build/src/components/OverLay/type.js.map +1 -1
- package/build/src/components/Svgs/scanningLine.d.ts +2 -1
- package/build/src/components/Svgs/scanningLine.d.ts.map +1 -1
- package/build/src/components/Svgs/scanningLine.js +55 -51
- package/build/src/components/Svgs/scanningLine.js.map +1 -1
- package/build/src/config/KYCConfig.js +1 -1
- package/build/src/config/KYCConfig.js.map +1 -1
- package/build/src/config/allowedDomains.js +6 -6
- package/build/src/config/allowedDomains.js.map +1 -1
- package/build/src/hooks/useTemplateKYCFlow.d.ts.map +1 -1
- package/build/src/hooks/useTemplateKYCFlow.js +37 -38
- package/build/src/hooks/useTemplateKYCFlow.js.map +1 -1
- package/build/src/index.d.ts +3 -3
- package/build/src/index.d.ts.map +1 -1
- package/build/src/index.js +3 -3
- package/build/src/index.js.map +1 -1
- package/build/src/modules/api/CardAuthentification.d.ts +0 -5
- package/build/src/modules/api/CardAuthentification.d.ts.map +1 -1
- package/build/src/modules/api/CardAuthentification.js +114 -116
- package/build/src/modules/api/CardAuthentification.js.map +1 -1
- package/build/src/modules/api/KYCService.d.ts +12 -1
- package/build/src/modules/api/KYCService.d.ts.map +1 -1
- package/build/src/modules/api/KYCService.js +102 -38
- package/build/src/modules/api/KYCService.js.map +1 -1
- package/build/src/modules/camera/NativeCameraModule.js +17 -17
- package/build/src/modules/camera/NativeCameraModule.js.map +1 -1
- package/expo-module.config.json +2 -2
- package/ios/TransfergratisSdk.podspec +2 -2
- package/ios/TransfergratisSdkModule.swift +12 -12
- package/package.json +9 -7
- package/src/App.tsx +2 -2
- package/src/{TransfergratisSdk.types.ts → SanctumKeySdk.types.ts} +2 -2
- package/src/{TransfergratisSdkModule.ts → SanctumKeySdkModule.ts} +3 -3
- package/src/{TransfergratisSdkModule.web.ts → SanctumKeySdkModule.web.ts} +3 -3
- package/src/SanctumKeySdkView.tsx +11 -0
- package/src/{TransfergratisSdkView.web.tsx → SanctumKeySdkView.web.tsx} +2 -2
- package/src/api/axios.ts +2 -2
- package/src/components/EnhancedCameraView.tsx +131 -385
- package/src/components/KYCElements/EmailVerificationTemplate.tsx +141 -26
- package/src/components/KYCElements/IDCardCapture.tsx +228 -868
- package/src/components/KYCElements/PhoneVerificationTemplate.tsx +342 -60
- package/src/components/KYCElements/SelfieCapture.tsx +184 -213
- package/src/components/KYCElements/SelfieCaptureTemplate.tsx +330 -662
- package/src/components/NativeCameraView.tsx +1 -1
- package/src/components/OverLay/IdCard.tsx +218 -217
- package/src/components/OverLay/SelfieOverlay.tsx +56 -134
- package/src/components/OverLay/type.ts +1 -0
- package/src/components/Svgs/scanningLine.tsx +71 -72
- package/src/config/KYCConfig.ts +1 -1
- package/src/config/allowedDomains.ts +6 -6
- package/src/hooks/useTemplateKYCFlow.tsx +45 -39
- package/src/i18n/README.md +1 -1
- package/src/index.ts +3 -3
- package/src/modules/api/CardAuthentification.ts +202 -200
- package/src/modules/api/KYCService.ts +169 -53
- package/src/modules/camera/NativeCameraModule.ts +17 -17
- package/android/build/tmp/kotlin-classes/debug/kyc/transfergratis/com/TransfergratisSdkModule$definition$1$5$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/transfergratis/com/TransfergratisSdkModule$definition$1$5$2.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/kyc/transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$View$1.class +0 -0
- package/build/src/TransfergratisSdk.types.d.ts.map +0 -1
- package/build/src/TransfergratisSdk.types.js +0 -2
- package/build/src/TransfergratisSdk.types.js.map +0 -1
- package/build/src/TransfergratisSdkModule.d.ts.map +0 -1
- package/build/src/TransfergratisSdkModule.js.map +0 -1
- package/build/src/TransfergratisSdkModule.web.d.ts.map +0 -1
- package/build/src/TransfergratisSdkModule.web.js.map +0 -1
- package/build/src/TransfergratisSdkView.d.ts +0 -4
- package/build/src/TransfergratisSdkView.d.ts.map +0 -1
- package/build/src/TransfergratisSdkView.js +0 -7
- package/build/src/TransfergratisSdkView.js.map +0 -1
- package/build/src/TransfergratisSdkView.web.d.ts +0 -4
- package/build/src/TransfergratisSdkView.web.d.ts.map +0 -1
- package/build/src/TransfergratisSdkView.web.js.map +0 -1
- package/src/TransfergratisSdkView.tsx +0 -11
- /package/android/build/.transforms/{532c0e65d82f446633d0a7dab2772198 → ab90740579f5bd05b27b4343ada2d1c9}/results.bin +0 -0
- /package/android/build/.transforms/{532c0e65d82f446633d0a7dab2772198 → ab90740579f5bd05b27b4343ada2d1c9}/transformed/classes/classes_dex/classes.dex +0 -0
- /package/android/build/.transforms/{f62cb96b2d1f78ca96ab35932dd530dc → c9d62bb333688ab562f51958998d5a48}/results.bin +0 -0
- /package/android/build/{intermediates/javac/debug/compileDebugJavaWithJavac/classes/kyc/transfergratis/com/BuildConfig.class → tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/BuildConfig.class.uniqueId0} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
2
|
-
import { View, Text, StyleSheet, Image, ScrollView, Platform,
|
|
2
|
+
import { View, Text, StyleSheet, Image, ScrollView, Platform, ActivityIndicator } from 'react-native';
|
|
3
3
|
import { showAlert } from '../../utils/platformAlert';
|
|
4
4
|
import { EnhancedCameraView } from '../EnhancedCameraView';
|
|
5
5
|
import { GovernmentDocumentTypeShorted, GovernmentDocumentTypeBackend } from '../../types/KYC.types';
|
|
@@ -11,140 +11,71 @@ import { removeDuplicates } from '../../utils/remove-duplicate';
|
|
|
11
11
|
import { backVerification, checkTemplateType, frontVerification } from '../../modules/api/CardAuthentification';
|
|
12
12
|
import { getDocumentTypeInfo } from '../../utils/get-document-type-info';
|
|
13
13
|
import pathToBase64 from '../../utils/pathToBase64';
|
|
14
|
-
import
|
|
15
|
-
|
|
16
|
-
import { isMobileWeb } from '../../utils/deviceDetection';
|
|
17
|
-
import { logger } from '../../utils/logger';
|
|
18
|
-
export const IDCardCapture = ({ component, value = {}, onValueChange, error, language = 'en', }) => {
|
|
14
|
+
import { cropByObb, cropImageWithBBoxWithTolerance, getObbConfidence, OBB_CONFIDENCE_THRESHOLD } from '../../utils/cropByObb';
|
|
15
|
+
export const IDCardCapture = ({ component, value = {}, onValueChange, error, language = 'en' }) => {
|
|
19
16
|
const { t, locale } = useI18n();
|
|
20
17
|
const [showCamera, setShowCamera] = useState(false);
|
|
21
18
|
const [capturedImages, setCapturedImages] = useState(value || {});
|
|
22
|
-
// const [cropImageUri, setCropImageUri] = useState<string>('');
|
|
23
19
|
const [currentSide, setCurrentSide] = useState('front');
|
|
24
20
|
const [bboxBySide, setBboxBySide] = useState({});
|
|
25
21
|
const [silentCaptureResult, setSilentCaptureResult] = useState({ success: false, isAnalyzing: false });
|
|
26
|
-
const [
|
|
27
|
-
|
|
22
|
+
const [isProcessingCapture, setIsProcessingCapture] = useState(false);
|
|
23
|
+
const [processingImagePath, setProcessingImagePath] = useState(null);
|
|
28
24
|
const documentTypeMapping = {
|
|
29
|
-
'nationalId': 'national_id',
|
|
30
|
-
'
|
|
31
|
-
'driversLicense': 'drivers_licence',
|
|
32
|
-
'residencePermit': 'permanent_residence',
|
|
33
|
-
'healthInsuranceCard': 'health_insurance_card',
|
|
25
|
+
'nationalId': 'national_id', 'passport': 'passport', 'driversLicense': 'drivers_licence',
|
|
26
|
+
'residencePermit': 'permanent_residence', 'healthInsuranceCard': 'health_insurance_card',
|
|
34
27
|
};
|
|
35
|
-
// const [imageNaturalSize, setImageNaturalSize] = useState<{ width: number; height: number } | null>(null);
|
|
36
28
|
const { actions, state, env } = useTemplateKYCFlowContext();
|
|
37
29
|
const getLocalizedText = (text) => {
|
|
38
|
-
|
|
39
|
-
if (text && typeof text[currentSide] === 'object' && text[currentSide][locale]) {
|
|
30
|
+
if (text && typeof text[currentSide] === 'object' && text[currentSide][locale])
|
|
40
31
|
return text[currentSide][locale] || '';
|
|
41
|
-
}
|
|
42
32
|
return "";
|
|
43
33
|
};
|
|
44
|
-
// Récupérer les données depuis le composant country_selection
|
|
45
34
|
const countrySelectionData = useMemo(() => {
|
|
46
35
|
const countrySelectionComponent = state.template.components.find(c => c.type === 'country_selection');
|
|
47
|
-
|
|
48
|
-
return state.componentData[countrySelectionComponent.id];
|
|
49
|
-
}
|
|
50
|
-
return null;
|
|
36
|
+
return countrySelectionComponent ? state.componentData[countrySelectionComponent.id] : null;
|
|
51
37
|
}, [state.template.components, state.componentData]);
|
|
52
|
-
// Extraire selectedDocumentType depuis countrySelectionData
|
|
53
38
|
const selectedDocumentType = useMemo(() => {
|
|
54
39
|
if (!countrySelectionData?.documentType)
|
|
55
40
|
return null;
|
|
56
41
|
const backendDocType = countrySelectionData.documentType;
|
|
57
42
|
const mappedType = documentTypeMapping[backendDocType] || backendDocType;
|
|
58
|
-
|
|
59
|
-
return { type: mappedType, region };
|
|
43
|
+
return { type: mappedType, region: countrySelectionData.region || 'root' };
|
|
60
44
|
}, [countrySelectionData, documentTypeMapping]);
|
|
61
|
-
|
|
62
|
-
const countryData = useMemo(() => {
|
|
63
|
-
return countrySelectionData;
|
|
64
|
-
}, [countrySelectionData]);
|
|
65
|
-
// console.log();
|
|
66
|
-
// Synchroniser capturedImages avec value quand les données sont chargées (ex: reprise de session)
|
|
45
|
+
const countryData = useMemo(() => countrySelectionData, [countrySelectionData]);
|
|
67
46
|
useEffect(() => {
|
|
68
47
|
if (value && Object.keys(value).length > 0) {
|
|
69
|
-
|
|
70
|
-
const valueChanged = JSON.stringify(value) !== JSON.stringify(capturedImages);
|
|
71
|
-
if (valueChanged) {
|
|
72
|
-
logger.log("Updating capturedImages from value:", Object.keys(value));
|
|
73
|
-
logger.log("Value data sample:", truncateFields(value));
|
|
48
|
+
if (JSON.stringify(value) !== JSON.stringify(capturedImages)) {
|
|
74
49
|
const updatedImages = value;
|
|
75
50
|
setCapturedImages(updatedImages);
|
|
76
|
-
// Si on a des images chargées, mettre à jour silentCaptureResult pour l'affichage
|
|
77
51
|
Object.keys(updatedImages).forEach((side) => {
|
|
78
52
|
const imageData = updatedImages[side];
|
|
79
53
|
if (imageData?.dir) {
|
|
80
54
|
setSilentCaptureResult(prev => ({
|
|
81
|
-
...prev,
|
|
82
|
-
path: imageData.dir,
|
|
83
|
-
success: true,
|
|
84
|
-
isAnalyzing: false,
|
|
85
|
-
mrz: imageData.mrz || '',
|
|
86
|
-
templatePath: imageData.templatePath || '',
|
|
55
|
+
...prev, path: imageData.dir, success: true, isAnalyzing: false, mrz: imageData.mrz || '', templatePath: imageData.templatePath || '',
|
|
87
56
|
}));
|
|
88
57
|
}
|
|
89
58
|
});
|
|
90
59
|
}
|
|
91
60
|
}
|
|
92
61
|
}, [value]);
|
|
93
|
-
useEffect(() => {
|
|
94
|
-
logger.log("cropImageUri", JSON.stringify(truncateFields({ box: silentCaptureResult }), null, 2));
|
|
95
|
-
if (capturedImages[currentSide]?.dir && silentCaptureResult?.bbox) {
|
|
96
|
-
cropImageWithBBox(capturedImages[currentSide].dir, silentCaptureResult.bbox)?.then((uri) => {
|
|
97
|
-
// setCropImageUri(uri);
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
}, [capturedImages[currentSide]?.dir, silentCaptureResult?.bbox]);
|
|
101
62
|
const cameraConfig = useMemo(() => {
|
|
102
63
|
const instructions = selectedDocumentType
|
|
103
64
|
? (locale === 'en' ? getDocumentTypeInfo(selectedDocumentType.type).instructions.en : getDocumentTypeInfo(selectedDocumentType.type).instructions.fr)
|
|
104
65
|
: getLocalizedText(component.instructions);
|
|
105
66
|
return {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
flashMode: 'auto',
|
|
109
|
-
cameraType: 'back',
|
|
110
|
-
autoFocus: 'on',
|
|
111
|
-
whiteBalance: 'auto',
|
|
112
|
-
allowRetake: true,
|
|
113
|
-
maxRetakes: 3,
|
|
114
|
-
overlay: {
|
|
115
|
-
showGuide: true,
|
|
116
|
-
guideText: instructions,
|
|
117
|
-
bbox: {
|
|
118
|
-
xMin: 20,
|
|
119
|
-
yMin: 140,
|
|
120
|
-
xMax: 370,
|
|
121
|
-
yMax: 340,
|
|
122
|
-
borderColor: '#2DBD60',
|
|
123
|
-
borderWidth: 3,
|
|
124
|
-
cornerRadius: 8
|
|
125
|
-
}
|
|
126
|
-
}
|
|
67
|
+
cameraType: 'back', flashMode: 'auto',
|
|
68
|
+
overlay: { guideText: instructions, bbox: { xMin: 15, yMin: 20, xMax: 85, yMax: 70, borderColor: '#2DBD60', borderWidth: 3, cornerRadius: 8 } }
|
|
127
69
|
};
|
|
128
70
|
}, [selectedDocumentType, locale, component.instructions]);
|
|
129
71
|
const retakePicture = (sideToRetake) => {
|
|
130
|
-
//
|
|
72
|
+
// Completely wipe all processing states to prevent leakage
|
|
73
|
+
setIsProcessingCapture(false);
|
|
74
|
+
setProcessingImagePath(null);
|
|
75
|
+
setSilentCaptureResult({ path: '', success: false, isAnalyzing: false, error: '', templatePath: '', mrz: '', bbox: undefined });
|
|
131
76
|
setShowCamera(true);
|
|
132
77
|
actions.showCustomStepper(false);
|
|
133
|
-
|
|
134
|
-
setCapturedImages((prev) => {
|
|
135
|
-
const newState = { ...prev };
|
|
136
|
-
delete newState[sideToRetake];
|
|
137
|
-
return newState;
|
|
138
|
-
});
|
|
139
|
-
setSilentCaptureResult({
|
|
140
|
-
path: '',
|
|
141
|
-
success: false,
|
|
142
|
-
isAnalyzing: false,
|
|
143
|
-
error: '',
|
|
144
|
-
templatePath: '',
|
|
145
|
-
mrz: '',
|
|
146
|
-
bbox: undefined,
|
|
147
|
-
});
|
|
78
|
+
setCapturedImages((prev) => { const newState = { ...prev }; delete newState[sideToRetake]; return newState; });
|
|
148
79
|
if (value) {
|
|
149
80
|
const newValue = { ...value };
|
|
150
81
|
delete newValue[sideToRetake];
|
|
@@ -152,9 +83,8 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
152
83
|
}
|
|
153
84
|
};
|
|
154
85
|
const getCurrentSideVerification = (currentSide) => {
|
|
155
|
-
if (!selectedDocumentType || !countryData?.regionMapping)
|
|
86
|
+
if (!selectedDocumentType || !countryData?.regionMapping)
|
|
156
87
|
return { authMethod: [], mrzTypes: [], regionMapping: null, key: 'root' };
|
|
157
|
-
}
|
|
158
88
|
const regionMapping = countryData.regionMapping[selectedDocumentType.type];
|
|
159
89
|
const authMethod = [];
|
|
160
90
|
const mrzTypes = [];
|
|
@@ -163,25 +93,20 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
163
93
|
regionMapping[key].forEach((item) => {
|
|
164
94
|
if (item[currentSide]) {
|
|
165
95
|
authMethod.push(item[currentSide]);
|
|
166
|
-
if (item?.mrz_type)
|
|
96
|
+
if (item?.mrz_type)
|
|
167
97
|
mrzTypes.push(item?.mrz_type);
|
|
168
|
-
}
|
|
169
98
|
}
|
|
170
99
|
});
|
|
171
100
|
}
|
|
172
|
-
|
|
173
|
-
return { authMethod: removeDuplicates(authMethod), mrzTypes: removeDuplicates(mrzTypes), regionMapping: regionMapping, key: key };
|
|
101
|
+
return { authMethod: removeDuplicates(authMethod), mrzTypes: removeDuplicates(mrzTypes), regionMapping, key };
|
|
174
102
|
};
|
|
175
103
|
const getCorrespondingMrzType = (templatePath, mapping, selectedDocumentType = "root") => {
|
|
176
104
|
if (!mapping || !mapping[selectedDocumentType])
|
|
177
105
|
return null;
|
|
178
|
-
// Extraire le nom du fichier depuis le template_path
|
|
179
106
|
const fileName = templatePath.split("/").pop()?.replace(".jpg", "").replace(".png", "");
|
|
180
107
|
if (!fileName)
|
|
181
108
|
return null;
|
|
182
|
-
|
|
183
|
-
const pyName = `${fileName}.py`; // ex: cameroon_id_back_3_1.py
|
|
184
|
-
// Chercher dans la liste
|
|
109
|
+
const pyName = `${fileName}.py`;
|
|
185
110
|
const found = mapping[selectedDocumentType].find((item) => item.py_file === pyName);
|
|
186
111
|
return found?.mrz_type || null;
|
|
187
112
|
};
|
|
@@ -195,10 +120,52 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
195
120
|
const found = mapping[selectedDocumentType].find((item) => item.py_file === pyName);
|
|
196
121
|
return found?.[side] || null;
|
|
197
122
|
};
|
|
198
|
-
const
|
|
199
|
-
if (
|
|
123
|
+
const autoCapture = async (capturePath, verified) => {
|
|
124
|
+
if (isProcessingCapture)
|
|
200
125
|
return;
|
|
126
|
+
setIsProcessingCapture(true);
|
|
127
|
+
setProcessingImagePath(capturePath);
|
|
128
|
+
try {
|
|
129
|
+
let imagePathForUpload = capturePath;
|
|
130
|
+
if (verified.bbox) {
|
|
131
|
+
try {
|
|
132
|
+
imagePathForUpload = await cropImageWithBBoxWithTolerance(capturePath, verified.bbox, 0.15);
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
imagePathForUpload = capturePath;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const base64 = await pathToBase64(imagePathForUpload);
|
|
139
|
+
const newImages = {
|
|
140
|
+
...capturedImages,
|
|
141
|
+
[currentSide]: { dir: imagePathForUpload, file: base64, mrz: verified.mrz || "", templatePath: verified.templatePath },
|
|
142
|
+
};
|
|
143
|
+
setCapturedImages(newImages);
|
|
144
|
+
if (verified.country && verified.documentType) {
|
|
145
|
+
onValueChange({
|
|
146
|
+
...newImages,
|
|
147
|
+
country: verified.country,
|
|
148
|
+
documentType: GovernmentDocumentTypeBackend[verified.documentType] || '',
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
setTimeout(() => {
|
|
152
|
+
setShowCamera(false);
|
|
153
|
+
actions.showCustomStepper(true);
|
|
154
|
+
setSilentCaptureResult(prev => ({ ...prev, isAnalyzing: false }));
|
|
155
|
+
setIsProcessingCapture(false);
|
|
156
|
+
setProcessingImagePath(null);
|
|
157
|
+
}, 600);
|
|
201
158
|
}
|
|
159
|
+
catch (e) {
|
|
160
|
+
showAlert('Error', e?.message || 'Impossible de capturer la photo');
|
|
161
|
+
setSilentCaptureResult(prev => ({ ...prev, isAnalyzing: false, success: false }));
|
|
162
|
+
setIsProcessingCapture(false);
|
|
163
|
+
setProcessingImagePath(null);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
const handleSilentCapture = async (result) => {
|
|
167
|
+
if (silentCaptureResult.isAnalyzing || isProcessingCapture)
|
|
168
|
+
return;
|
|
202
169
|
if (result.success && result.path) {
|
|
203
170
|
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: true, success: false, error: '' }));
|
|
204
171
|
let templatePath = silentCaptureResult.templatePath || '';
|
|
@@ -209,336 +176,119 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
209
176
|
return;
|
|
210
177
|
}
|
|
211
178
|
const regionMappings = getCurrentSideVerification(currentSide);
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
try {
|
|
215
|
-
logger.log("checkTemplateType - BEFORE call", {
|
|
216
|
-
selectedDocumentTypeType: selectedDocumentType?.type,
|
|
217
|
-
countrySelectionDataDocumentType: countrySelectionData?.documentType,
|
|
218
|
-
docTypeToSend: selectedDocumentType?.type
|
|
219
|
-
});
|
|
179
|
+
try {
|
|
180
|
+
if (templatePath.length === 0) {
|
|
220
181
|
const templateType = await checkTemplateType({ path: result.path || '', docType: selectedDocumentType?.type, docRegion: countryData?.code || "", postfix: currentSide }, env);
|
|
221
182
|
templateResponse = templateType;
|
|
222
|
-
if (templateType.template_path)
|
|
183
|
+
if (templateType.template_path)
|
|
223
184
|
templatePath = templateType.template_path;
|
|
224
|
-
logger.log("templatePath", templatePath);
|
|
225
|
-
setSilentCaptureResult((prev) => ({ ...prev, templatePath: templatePath }));
|
|
226
|
-
}
|
|
227
185
|
if (templateType.card_obb) {
|
|
228
186
|
const obbConfidence = getObbConfidence(templateType.card_obb);
|
|
229
187
|
if (obbConfidence !== null && obbConfidence < OBB_CONFIDENCE_THRESHOLD) {
|
|
230
|
-
setSilentCaptureResult((prev) => ({
|
|
231
|
-
...prev,
|
|
232
|
-
isAnalyzing: false,
|
|
233
|
-
success: false,
|
|
234
|
-
error: t('kyc.idCardCapture.cardNotFullyInFrame'),
|
|
235
|
-
}));
|
|
188
|
+
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: t('kyc.idCardCapture.cardNotFullyInFrame') }));
|
|
236
189
|
return;
|
|
237
190
|
}
|
|
238
|
-
let bbox;
|
|
239
191
|
try {
|
|
240
|
-
const crop = await cropByObb(result
|
|
241
|
-
|
|
242
|
-
templateBbox = bbox;
|
|
192
|
+
const crop = await cropByObb(result.path, templateType.card_obb);
|
|
193
|
+
templateBbox = crop.bbox;
|
|
243
194
|
}
|
|
244
195
|
catch { }
|
|
245
196
|
}
|
|
246
197
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: e?.message || 'Erreur de vérification du template' }));
|
|
250
|
-
return; // Return early if checkTemplateType fails
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
logger.log("templatePath before verification", templatePath, "currentSide", currentSide);
|
|
254
|
-
if (currentSide === 'front') {
|
|
255
|
-
logger.log("frontVerification - BEFORE call", {
|
|
256
|
-
selectedDocumentTypeType: selectedDocumentType?.type,
|
|
257
|
-
countrySelectionDataDocumentType: countrySelectionData?.documentType,
|
|
258
|
-
docTypeToSend: selectedDocumentType?.type
|
|
259
|
-
});
|
|
260
|
-
logger.log("Calling frontVerification", { templatePath, selectedDocumentType: selectedDocumentType?.type, regionMappings });
|
|
261
|
-
console.log("About to call frontVerification", typeof frontVerification);
|
|
262
|
-
try {
|
|
198
|
+
let verificationRes;
|
|
199
|
+
if (currentSide === 'front') {
|
|
263
200
|
const matchedAuthMethod = getCorrespondingAuthMethod(templatePath, regionMappings.regionMapping, regionMappings.key || '', 'front');
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
const authMethod = matchedAuthMethod
|
|
267
|
-
? regionMappings.authMethod.filter((method) => method === matchedAuthMethod)
|
|
268
|
-
: regionMappings.authMethod.filter((method) => method !== 'MRZ' && method !== '2D_barcode');
|
|
269
|
-
console.log("mrzType calculated", mrzType);
|
|
270
|
-
const verificationParams = {
|
|
271
|
-
path: result.path,
|
|
272
|
-
regionMapping: {
|
|
273
|
-
authMethod,
|
|
274
|
-
mrzTypes: regionMappings.mrzTypes,
|
|
275
|
-
},
|
|
276
|
-
selectedDocumentType: GovernmentDocumentTypeShorted[selectedDocumentType?.type] || '',
|
|
277
|
-
code: countryData?.code || '',
|
|
278
|
-
currentSide: currentSide,
|
|
279
|
-
templatePath: templatePath,
|
|
280
|
-
mrzType: mrzType,
|
|
281
|
-
};
|
|
282
|
-
console.log("frontVerification params", verificationParams);
|
|
283
|
-
console.log("About to call frontVerification function");
|
|
284
|
-
const promise = frontVerification(verificationParams, env);
|
|
285
|
-
console.log("frontVerification promise created", promise);
|
|
286
|
-
promise.then((res) => {
|
|
287
|
-
logger.log("front verification result", truncateFields(res));
|
|
288
|
-
const bbox = res?.bbox || templateBbox;
|
|
289
|
-
setSilentCaptureResult((prev) => ({
|
|
290
|
-
...prev,
|
|
291
|
-
path: result.path,
|
|
292
|
-
templatePath: templatePath,
|
|
293
|
-
bbox: bbox,
|
|
294
|
-
success: true,
|
|
295
|
-
mrz: res?.mrz ? JSON.stringify(res.mrz) : "",
|
|
296
|
-
isAnalyzing: false,
|
|
297
|
-
country: countryData?.code,
|
|
298
|
-
documentType: selectedDocumentType.type,
|
|
299
|
-
}));
|
|
300
|
-
// Stocker le bbox pour ce côté
|
|
301
|
-
if (bbox && typeof bbox === 'object') {
|
|
302
|
-
setBboxBySide((prev) => ({ ...prev, [currentSide]: bbox }));
|
|
303
|
-
}
|
|
304
|
-
}).catch((e) => {
|
|
305
|
-
}).catch((e) => {
|
|
306
|
-
console.log("error front verification", e);
|
|
307
|
-
logger.log("error front verification", truncateFields(e));
|
|
308
|
-
const isCardNotFullyInFrame = e?.message === 'CARD_NOT_FULLY_IN_FRAME' ||
|
|
309
|
-
e?.message?.includes('entirement') ||
|
|
310
|
-
e?.message?.includes('fully in frame');
|
|
311
|
-
const errorMessage = isCardNotFullyInFrame
|
|
312
|
-
? t('kyc.idCardCapture.cardNotFullyInFrame')
|
|
313
|
-
: (e?.message || 'Erreur de détection du MRZ');
|
|
314
|
-
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, templatePath: templatePath, success: false, error: errorMessage }));
|
|
315
|
-
});
|
|
316
|
-
}
|
|
317
|
-
catch (error) {
|
|
318
|
-
console.log("Error setting up frontVerification call", error);
|
|
319
|
-
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: error?.message || 'Erreur lors de la configuration de la vérification' }));
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
else {
|
|
323
|
-
const backRegionMappings = getCurrentSideVerification(currentSide);
|
|
324
|
-
logger.log("Calling backVerification", { templatePath, selectedDocumentType: selectedDocumentType.type, backRegionMappings });
|
|
325
|
-
const matchedBackAuthMethod = getCorrespondingAuthMethod(templatePath, backRegionMappings.regionMapping, backRegionMappings.key || '', 'back');
|
|
326
|
-
const backMrzType = getCorrespondingMrzType(templatePath, backRegionMappings.regionMapping, backRegionMappings.key || '') || '';
|
|
327
|
-
backVerification({
|
|
328
|
-
path: result.path,
|
|
329
|
-
regionMapping: {
|
|
330
|
-
authMethod: matchedBackAuthMethod
|
|
331
|
-
? backRegionMappings.authMethod.filter((method) => method === matchedBackAuthMethod)
|
|
332
|
-
: backRegionMappings.authMethod.filter((method) => method !== 'MRZ' && method !== '2D_barcode'),
|
|
333
|
-
mrzTypes: backRegionMappings.mrzTypes,
|
|
334
|
-
},
|
|
335
|
-
selectedDocumentType: GovernmentDocumentTypeShorted[selectedDocumentType.type] || '',
|
|
336
|
-
code: countryData?.code || '',
|
|
337
|
-
currentSide: currentSide,
|
|
338
|
-
templatePath: templatePath,
|
|
339
|
-
mrzType: backMrzType,
|
|
340
|
-
templateResponse,
|
|
341
|
-
}, env).then((res) => {
|
|
342
|
-
logger.log("back verification result", truncateFields(res));
|
|
343
|
-
const bbox = res?.bbox || templateBbox;
|
|
344
|
-
setSilentCaptureResult((prev) => ({
|
|
345
|
-
...prev,
|
|
346
|
-
path: result.path,
|
|
347
|
-
bbox: bbox,
|
|
348
|
-
success: true,
|
|
349
|
-
mrz: res?.mrz ? JSON.stringify(res.mrz) : "",
|
|
350
|
-
isAnalyzing: false,
|
|
351
|
-
country: countryData?.code,
|
|
352
|
-
documentType: selectedDocumentType.type,
|
|
353
|
-
}));
|
|
354
|
-
// Stocker le bbox pour ce côté
|
|
355
|
-
if (bbox && typeof bbox === 'object') {
|
|
356
|
-
setBboxBySide((prev) => ({ ...prev, [currentSide]: bbox }));
|
|
357
|
-
}
|
|
358
|
-
}).catch((e) => {
|
|
359
|
-
logger.log("error back verification", truncateFields(e));
|
|
360
|
-
const isCardNotFullyInFrame = e?.message === 'CARD_NOT_FULLY_IN_FRAME' ||
|
|
361
|
-
e?.message?.includes('entirement') ||
|
|
362
|
-
e?.message?.includes('fully in frame');
|
|
363
|
-
const errorMessage = isCardNotFullyInFrame
|
|
364
|
-
? t('kyc.idCardCapture.cardNotFullyInFrame')
|
|
365
|
-
: (e?.message || 'Erreur de détection du MRZ');
|
|
366
|
-
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, templatePath: templatePath, success: false, error: errorMessage }));
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
};
|
|
371
|
-
const handleCapture = async (result) => {
|
|
372
|
-
if (silentCaptureResult.path) {
|
|
373
|
-
let imagePathForUpload = silentCaptureResult.path;
|
|
374
|
-
if (silentCaptureResult.bbox) {
|
|
375
|
-
try {
|
|
376
|
-
imagePathForUpload = await cropImageWithBBoxWithTolerance(silentCaptureResult.path, silentCaptureResult.bbox, 0.05);
|
|
201
|
+
const mrzType = getCorrespondingMrzType(templatePath, regionMappings.regionMapping, regionMappings.key || '') || '';
|
|
202
|
+
verificationRes = await frontVerification({ path: result.path, regionMapping: { authMethod: matchedAuthMethod ? [matchedAuthMethod] : regionMappings.authMethod, mrzTypes: regionMappings.mrzTypes }, selectedDocumentType: GovernmentDocumentTypeShorted[selectedDocumentType?.type] || '', code: countryData?.code || '', currentSide, templatePath, mrzType }, env);
|
|
377
203
|
}
|
|
378
|
-
|
|
379
|
-
|
|
204
|
+
else {
|
|
205
|
+
const matchedBackAuthMethod = getCorrespondingAuthMethod(templatePath, regionMappings.regionMapping, regionMappings.key || '', 'back');
|
|
206
|
+
const backMrzType = getCorrespondingMrzType(templatePath, regionMappings.regionMapping, regionMappings.key || '') || '';
|
|
207
|
+
verificationRes = await backVerification({ path: result.path, regionMapping: { authMethod: matchedBackAuthMethod ? [matchedBackAuthMethod] : regionMappings.authMethod, mrzTypes: regionMappings.mrzTypes }, selectedDocumentType: GovernmentDocumentTypeShorted[selectedDocumentType.type] || '', code: countryData?.code || '', currentSide, templatePath, mrzType: backMrzType, templateResponse }, env);
|
|
380
208
|
}
|
|
209
|
+
const bbox = verificationRes?.bbox || templateBbox;
|
|
210
|
+
const mrz = verificationRes?.mrz ? JSON.stringify(verificationRes.mrz) : "";
|
|
211
|
+
const verifiedResult = { path: result.path, templatePath, bbox, success: true, mrz, isAnalyzing: false, country: countryData?.code, documentType: selectedDocumentType.type };
|
|
212
|
+
setSilentCaptureResult(verifiedResult);
|
|
213
|
+
if (bbox)
|
|
214
|
+
setBboxBySide(prev => ({ ...prev, [currentSide]: bbox }));
|
|
215
|
+
await autoCapture(result.path, verifiedResult);
|
|
381
216
|
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
...
|
|
386
|
-
[currentSide]: {
|
|
387
|
-
dir: imagePathForUpload, // <--- CHANGED THIS LINE
|
|
388
|
-
file: base64,
|
|
389
|
-
mrz: silentCaptureResult.mrz || "",
|
|
390
|
-
templatePath: silentCaptureResult.templatePath
|
|
391
|
-
}
|
|
392
|
-
};
|
|
393
|
-
setCapturedImages(newImages);
|
|
394
|
-
if (silentCaptureResult.country && silentCaptureResult.documentType) {
|
|
395
|
-
onValueChange({
|
|
396
|
-
...newImages,
|
|
397
|
-
country: silentCaptureResult.country,
|
|
398
|
-
documentType: GovernmentDocumentTypeBackend[silentCaptureResult.documentType] || '',
|
|
399
|
-
});
|
|
217
|
+
catch (error) {
|
|
218
|
+
const isCardNotFullyInFrame = error?.message === 'CARD_NOT_FULLY_IN_FRAME' || error?.message?.includes('entirement');
|
|
219
|
+
const errorMessage = isCardNotFullyInFrame ? t('kyc.idCardCapture.cardNotFullyInFrame') : (error?.message || 'Erreur de détection');
|
|
220
|
+
setSilentCaptureResult(prev => ({ ...prev, isAnalyzing: false, success: false, error: errorMessage }));
|
|
400
221
|
}
|
|
401
|
-
setShowCamera(false);
|
|
402
|
-
actions.showCustomStepper(true);
|
|
403
|
-
}
|
|
404
|
-
else {
|
|
405
|
-
showAlert('Erreur', result.error || 'Impossible de prendre la photo');
|
|
406
222
|
}
|
|
407
223
|
};
|
|
408
224
|
const handleError = (event) => {
|
|
409
225
|
showAlert('Erreur', event.message);
|
|
410
226
|
setShowCamera(false);
|
|
227
|
+
setIsProcessingCapture(false);
|
|
411
228
|
};
|
|
412
|
-
useEffect(() => {
|
|
413
|
-
actions.showCustomStepper(!showCamera);
|
|
414
|
-
}, [showCamera]);
|
|
415
|
-
// Cross-device polling logic
|
|
416
|
-
useEffect(() => {
|
|
417
|
-
if (!showQRModal || !state.session.session_id)
|
|
418
|
-
return;
|
|
419
|
-
const pollInterval = setInterval(async () => {
|
|
420
|
-
try {
|
|
421
|
-
const result = await kycService.getVerificationResult(state.session.session_id);
|
|
422
|
-
const sessionData = result[state.session.session_id]?.data;
|
|
423
|
-
if (sessionData) {
|
|
424
|
-
// Check if verification is completed or if we have ID card data
|
|
425
|
-
// Since the requirement is "verification restarts", we might look for overall completion
|
|
426
|
-
// or we could check if user_data is populated.
|
|
427
|
-
// For now, let's assume if status is not PENDING/INITIALIZED it might be done.
|
|
428
|
-
// Or simplier: if the mobile flow completes, the session status updates.
|
|
429
|
-
logger.log('Polling result:', truncateFields(sessionData));
|
|
430
|
-
if (sessionData.verification_status === 'completed' || sessionData.verification_status === 'approved' || sessionData.verification_status === 'review') {
|
|
431
|
-
clearInterval(pollInterval);
|
|
432
|
-
setShowQRModal(false);
|
|
433
|
-
actions.submitVerification(); // Or handleComplete
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
catch (error) {
|
|
438
|
-
console.error('Polling error:', error);
|
|
439
|
-
}
|
|
440
|
-
}, 5000);
|
|
441
|
-
return () => clearInterval(pollInterval);
|
|
442
|
-
}, [showQRModal, state.session.session_id, actions]);
|
|
443
|
-
const getQrCodeUrl = () => {
|
|
444
|
-
// Only available on web platform
|
|
445
|
-
if (Platform.OS !== 'web')
|
|
446
|
-
return '';
|
|
447
|
-
if (typeof window === 'undefined' || !window.location || !window.location.href)
|
|
448
|
-
return '';
|
|
449
|
-
try {
|
|
450
|
-
const currentUrl = new URL(window.location.href);
|
|
451
|
-
if (!currentUrl.searchParams.has('kyc_id') && state.session.session_id) {
|
|
452
|
-
currentUrl.searchParams.set('kyc_id', state.session.session_id);
|
|
453
|
-
}
|
|
454
|
-
currentUrl.searchParams.set('component_index', String(state.currentComponentIndex));
|
|
455
|
-
if (countrySelectionData?.code) {
|
|
456
|
-
currentUrl.searchParams.set('country', countrySelectionData.code);
|
|
457
|
-
if (countrySelectionData.documentType)
|
|
458
|
-
currentUrl.searchParams.set('document_type', countrySelectionData.documentType);
|
|
459
|
-
if (countrySelectionData.region)
|
|
460
|
-
currentUrl.searchParams.set('region', countrySelectionData.region);
|
|
461
|
-
}
|
|
462
|
-
return `https://api.qrserver.com/v1/create-qr-code/?size=250x250&data=${encodeURIComponent(currentUrl.toString())}`;
|
|
463
|
-
}
|
|
464
|
-
catch (error) {
|
|
465
|
-
console.warn('Error generating QR code URL:', error);
|
|
466
|
-
return '';
|
|
467
|
-
}
|
|
468
|
-
};
|
|
469
|
-
// En reprise sur un autre appareil: afficher un chargement tant que les données de session ne sont pas restaurées
|
|
470
|
-
const isResumingSession = Boolean(state.session.session_id && state.currentComponentIndex > 0);
|
|
471
|
-
const sessionDataRestored = state.session.sessionDataRestored !== false;
|
|
472
|
-
if (isResumingSession && !sessionDataRestored && (!countrySelectionData || !selectedDocumentType)) {
|
|
473
|
-
return (<View style={styles.root}>
|
|
474
|
-
<View style={[styles.container, { justifyContent: 'center', alignItems: 'center' }]}>
|
|
475
|
-
<ActivityIndicator size="large" color="#2DBD60"/>
|
|
476
|
-
<Text style={[styles.description, { marginTop: 16 }]}>
|
|
477
|
-
{state.currentLanguage === 'en' ? 'Loading your session...' : 'Chargement de votre session...'}
|
|
478
|
-
</Text>
|
|
479
|
-
</View>
|
|
480
|
-
</View>);
|
|
481
|
-
}
|
|
482
|
-
// Vérifier si les données sont disponibles, sinon afficher un message d'erreur
|
|
229
|
+
useEffect(() => { actions.showCustomStepper(!showCamera); }, [showCamera]);
|
|
483
230
|
if (!countrySelectionData || !selectedDocumentType) {
|
|
484
231
|
return (<View style={styles.root}>
|
|
485
232
|
<View style={styles.container}>
|
|
486
233
|
<Text style={styles.title}>{getLocalizedText(component.labels)}</Text>
|
|
487
234
|
<Text style={styles.description}>
|
|
488
|
-
{state.currentLanguage === "en"
|
|
489
|
-
? "Please complete the country and document selection first."
|
|
490
|
-
: "Veuillez d'abord compléter la sélection du pays et du document."}
|
|
235
|
+
{state.currentLanguage === "en" ? "Please complete the country and document selection first." : "Veuillez d'abord compléter la sélection du pays et du document."}
|
|
491
236
|
</Text>
|
|
492
|
-
{error && (<Text style={styles.errorText}>{error}</Text>)}
|
|
493
237
|
</View>
|
|
494
238
|
</View>);
|
|
495
239
|
}
|
|
240
|
+
// --- CAMERA RENDER ---
|
|
496
241
|
if (showCamera) {
|
|
242
|
+
const isBusy = isProcessingCapture;
|
|
497
243
|
return (<View style={styles.cameraContainer}>
|
|
498
|
-
<EnhancedCameraView showCamera={true} cameraType={cameraConfig.cameraType} style={styles.camera}
|
|
244
|
+
<EnhancedCameraView key={currentSide} showCamera={true} isProcessing={isBusy} cameraType={cameraConfig.cameraType} style={styles.camera} onError={handleError} onSilentCapture={handleSilentCapture} silentCaptureResult={silentCaptureResult} overlayComponent={<>
|
|
245
|
+
{!isBusy && silentCaptureResult.isAnalyzing && (<View style={styles.topAnalyzingPillContainer}>
|
|
246
|
+
<View style={styles.topAnalyzingPill}>
|
|
247
|
+
<ActivityIndicator size="small" color="white"/>
|
|
248
|
+
<Text style={styles.analyzingPillText}>
|
|
249
|
+
{state.currentLanguage === 'en' ? 'Scanning...' : 'Analyse...'}
|
|
250
|
+
</Text>
|
|
251
|
+
</View>
|
|
252
|
+
</View>)}
|
|
253
|
+
|
|
254
|
+
{isBusy && (<View style={StyleSheet.absoluteFillObject}>
|
|
255
|
+
{processingImagePath && (<Image source={{ uri: processingImagePath.startsWith('file://') ? processingImagePath : `file://${processingImagePath}` }} style={StyleSheet.absoluteFillObject} resizeMode="cover"/>)}
|
|
256
|
+
<View style={styles.processingOverlay}>
|
|
257
|
+
<ActivityIndicator size="large" color="#2DBD60"/>
|
|
258
|
+
<Text style={styles.processingText}>
|
|
259
|
+
{state.currentLanguage === 'en' ? 'Perfect!\nProcessing Document...' : 'Parfait!\nTraitement du document...'}
|
|
260
|
+
</Text>
|
|
261
|
+
</View>
|
|
262
|
+
</View>)}
|
|
263
|
+
|
|
264
|
+
<IdCardOverlay xMin={cameraConfig.overlay.bbox.xMin} yMin={cameraConfig.overlay.bbox.yMin} xMax={cameraConfig.overlay.bbox.xMax} yMax={cameraConfig.overlay.bbox.yMax} instructions={cameraConfig.overlay.guideText} cornerOpacity={cameraConfig.overlay.bbox.cornerRadius || 0} isSuccess={silentCaptureResult.success} language={state.currentLanguage} stepperProps={{
|
|
499
265
|
back: () => {
|
|
500
266
|
if (currentSide === 'back') {
|
|
501
267
|
setCurrentSide('front');
|
|
502
268
|
setShowCamera(false);
|
|
503
|
-
//
|
|
269
|
+
// 🚨 Clean up any residual state when going backwards
|
|
270
|
+
setIsProcessingCapture(false);
|
|
271
|
+
setProcessingImagePath(null);
|
|
504
272
|
if (capturedImages['front']?.dir) {
|
|
505
|
-
// Restaurer l'état de capture du front pour afficher l'image
|
|
506
273
|
const frontImage = capturedImages['front'];
|
|
507
|
-
|
|
508
|
-
setSilentCaptureResult((prev) => ({
|
|
509
|
-
path: frontImage.dir,
|
|
510
|
-
success: true,
|
|
511
|
-
isAnalyzing: false,
|
|
512
|
-
error: '',
|
|
513
|
-
mrz: frontImage.mrz || '',
|
|
514
|
-
templatePath: frontImage.templatePath || '',
|
|
515
|
-
country: silentCaptureResult.country,
|
|
516
|
-
documentType: silentCaptureResult.documentType,
|
|
517
|
-
bbox: frontBbox // Restaurer le bbox pour recalculer le cropImageUri
|
|
518
|
-
}));
|
|
274
|
+
setSilentCaptureResult((prev) => ({ ...prev, path: frontImage.dir, success: true, isAnalyzing: false, error: '', mrz: frontImage.mrz || '', templatePath: frontImage.templatePath || '', bbox: bboxBySide['front'] }));
|
|
519
275
|
}
|
|
520
276
|
else {
|
|
521
|
-
|
|
522
|
-
setSilentCaptureResult((prev) => ({ path: '', success: false, isAnalyzing: false, error: '', templatePath: '' }));
|
|
277
|
+
setSilentCaptureResult((prev) => ({ ...prev, path: '', success: false, isAnalyzing: false, error: '', templatePath: '' }));
|
|
523
278
|
}
|
|
524
279
|
}
|
|
525
280
|
else {
|
|
526
|
-
// Retour au composant précédent (country_selection)
|
|
527
281
|
actions.previousComponent();
|
|
528
282
|
}
|
|
529
283
|
},
|
|
530
284
|
selectedDocumentType: selectedDocumentType ? (locale === 'en' ? getDocumentTypeInfo(selectedDocumentType.type).name.en : getDocumentTypeInfo(selectedDocumentType.type).name.fr) : '',
|
|
531
|
-
step: state.currentComponentIndex + 1,
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
}}/>}/>
|
|
285
|
+
step: state.currentComponentIndex + 1, totalSteps: state.template.components.length, side: currentSide,
|
|
286
|
+
}}/>
|
|
287
|
+
</>}/>
|
|
535
288
|
|
|
536
|
-
{silentCaptureResult.error ? (<View style={styles.floatingErrorBanner}>
|
|
537
|
-
<Text style={styles.floatingErrorText}>
|
|
538
|
-
{silentCaptureResult.error}
|
|
539
|
-
</Text>
|
|
289
|
+
{silentCaptureResult.error && !isBusy ? (<View style={styles.floatingErrorBanner}>
|
|
290
|
+
<Text style={styles.floatingErrorText}>{silentCaptureResult.error}</Text>
|
|
540
291
|
</View>) : null}
|
|
541
|
-
|
|
542
292
|
</View>);
|
|
543
293
|
}
|
|
544
294
|
return (<View style={styles.root}>
|
|
@@ -551,349 +301,70 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
551
301
|
<Text style={{ fontSize: 14, color: '#666', textAlign: 'center', marginBottom: 16, lineHeight: 22 }}>
|
|
552
302
|
{getLocalizedText(component.instructions)}
|
|
553
303
|
</Text>
|
|
554
|
-
|
|
555
304
|
<View style={{ alignItems: 'center', justifyContent: 'center', flexDirection: "column", gap: 16 }}>
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
shadowOffset: { width: 0, height: 2 },
|
|
563
|
-
shadowOpacity: 0.2,
|
|
564
|
-
shadowRadius: 4,
|
|
565
|
-
elevation: 4
|
|
566
|
-
}}>
|
|
567
|
-
<Text style={{ color: 'white', fontWeight: 'bold', textAlign: 'center', fontSize: 16 }}>
|
|
568
|
-
{state.currentLanguage === "en"
|
|
569
|
-
? "Move the document closer to the camera."
|
|
570
|
-
: "Veuillez rapprocher le document de la caméra."}
|
|
571
|
-
</Text>
|
|
572
|
-
</View>)}
|
|
305
|
+
|
|
306
|
+
{silentCaptureResult?.error === 'TOO_FAR_AWAY' && (<View style={styles.warningBanner}>
|
|
307
|
+
<Text style={styles.warningText}>
|
|
308
|
+
{state.currentLanguage === "en" ? "Move the document closer to the camera and place it on a flat surface." : "Veuillez rapprocher le document de la caméra et le poser à plat."}
|
|
309
|
+
</Text>
|
|
310
|
+
</View>)}
|
|
573
311
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
height: 200,
|
|
577
|
-
borderRadius: 12,
|
|
578
|
-
padding: 1,
|
|
579
|
-
overflow: 'hidden',
|
|
580
|
-
shadowColor: '#000',
|
|
581
|
-
shadowOffset: { width: 0, height: 4 },
|
|
582
|
-
shadowOpacity: 0.18,
|
|
583
|
-
shadowRadius: 8,
|
|
584
|
-
elevation: 8,
|
|
585
|
-
backgroundColor: '#000',
|
|
586
|
-
}}>
|
|
587
|
-
{capturedImages[currentSide]?.dir ? (<Image source={{ uri: capturedImages[currentSide].dir }} style={{
|
|
588
|
-
width: '100%',
|
|
589
|
-
height: '100%',
|
|
590
|
-
borderRadius: 12,
|
|
591
|
-
resizeMode: 'contain',
|
|
592
|
-
}}/>) : silentCaptureResult.path ? (<Image source={{ uri: silentCaptureResult.path }} style={{
|
|
593
|
-
width: '100%',
|
|
594
|
-
height: '100%',
|
|
595
|
-
borderRadius: 12,
|
|
596
|
-
resizeMode: 'contain',
|
|
597
|
-
}}/>) : null}
|
|
312
|
+
<View style={styles.imagePreviewWrapper}>
|
|
313
|
+
{capturedImages[currentSide]?.dir ? (<Image source={{ uri: capturedImages[currentSide].dir }} style={styles.previewImage}/>) : silentCaptureResult.path ? (<Image source={{ uri: silentCaptureResult.path }} style={styles.previewImage}/>) : null}
|
|
598
314
|
</View>
|
|
599
|
-
|
|
600
|
-
{!capturedImages[currentSide]?.dir && (<Button title={state.currentLanguage === "en" ? "
|
|
601
|
-
|
|
602
|
-
actions.showCustomStepper(false);
|
|
603
|
-
}} variant="primary" size="large" fullWidth/>)}
|
|
604
|
-
{/* retake button si une image a été capturée */}
|
|
315
|
+
|
|
316
|
+
{!capturedImages[currentSide]?.dir && (<Button title={state.currentLanguage === "en" ? "Start Scanning" : "Commencer la numérisation"} onPress={() => { setShowCamera(true); actions.showCustomStepper(false); }} variant="primary" size="large" fullWidth/>)}
|
|
317
|
+
|
|
605
318
|
{capturedImages[currentSide]?.dir && (<>
|
|
606
|
-
<Button title={t('kyc.idCardCapture.retakeButton')} onPress={() =>
|
|
607
|
-
retakePicture(currentSide);
|
|
608
|
-
}} variant="outline" size="medium" fullWidth/>
|
|
319
|
+
<Button title={t('kyc.idCardCapture.retakeButton')} onPress={() => retakePicture(currentSide)} variant="outline" size="medium" fullWidth/>
|
|
609
320
|
<Button title={t('common.next')} onPress={() => {
|
|
610
321
|
if (!selectedDocumentType) {
|
|
611
322
|
showAlert('Error', 'Document type not selected');
|
|
612
323
|
return;
|
|
613
324
|
}
|
|
325
|
+
// 🚨 BUG FIX: Clear all state before moving forward
|
|
614
326
|
if (currentSide === 'back' || selectedDocumentType.type === 'passport') {
|
|
615
327
|
actions.nextComponent();
|
|
616
|
-
return;
|
|
617
328
|
}
|
|
618
329
|
else {
|
|
619
330
|
setShowCamera(true);
|
|
620
331
|
setCurrentSide('back');
|
|
621
|
-
setSilentCaptureResult(
|
|
622
|
-
|
|
332
|
+
setSilentCaptureResult({ success: false, isAnalyzing: false, path: '', error: '' });
|
|
333
|
+
setIsProcessingCapture(false);
|
|
334
|
+
setProcessingImagePath(null);
|
|
623
335
|
}
|
|
624
336
|
}} variant="primary" size="large" fullWidth/>
|
|
625
337
|
</>)}
|
|
626
338
|
</View>
|
|
627
339
|
</View>
|
|
628
340
|
</ScrollView>
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
{error && (<Text style={styles.errorText}>{error}</Text>)}
|
|
633
|
-
|
|
634
|
-
{/* Cross-Device / Continue on Phone Button (Web Only) */}
|
|
635
|
-
{Platform.OS === 'web' && !isMobileWeb() && !capturedImages[currentSide]?.dir && (<Button title={t('kyc.idCardCapture.continueOnPhone')} onPress={() => { setShowQRModal(true); }}/>)}
|
|
636
|
-
|
|
637
|
-
{/* QR Code Modal - Web Only */}
|
|
638
|
-
{Platform.OS === 'web' && (<Modal visible={showQRModal} transparent={true} animationType="fade" onRequestClose={() => setShowQRModal(false)}>
|
|
639
|
-
<View style={styles.modalOverlay}>
|
|
640
|
-
<View style={styles.modalContent}>
|
|
641
|
-
<Text style={styles.modalTitle}>
|
|
642
|
-
{t('kyc.idCardCapture.continueOnMobile')}
|
|
643
|
-
</Text>
|
|
644
|
-
<Text style={styles.modalDescription}>
|
|
645
|
-
{t('kyc.idCardCapture.scanQrCode')}
|
|
646
|
-
</Text>
|
|
647
|
-
|
|
648
|
-
{showQRModal && getQrCodeUrl() ? (<Image source={{ uri: getQrCodeUrl() }} style={styles.qrCodeImage}/>) : null}
|
|
649
|
-
|
|
650
|
-
<TouchableOpacity style={styles.closeButton} onPress={() => setShowQRModal(false)}>
|
|
651
|
-
<Text style={styles.closeButtonText}>
|
|
652
|
-
{t('common.close')}
|
|
653
|
-
</Text>
|
|
654
|
-
</TouchableOpacity>
|
|
655
|
-
</View>
|
|
656
|
-
</View>
|
|
657
|
-
</Modal>)}
|
|
658
|
-
|
|
659
341
|
</View>
|
|
660
342
|
</View>);
|
|
661
343
|
};
|
|
662
344
|
const styles = StyleSheet.create({
|
|
663
|
-
root: {
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
},
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
},
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
width: '100%',
|
|
685
|
-
height: '100%',
|
|
686
|
-
},
|
|
687
|
-
previewContainer: {
|
|
688
|
-
width: '95%',
|
|
689
|
-
backgroundColor: 'white',
|
|
690
|
-
margin: 10,
|
|
691
|
-
borderRadius: 10,
|
|
692
|
-
paddingVertical: 16,
|
|
693
|
-
paddingHorizontal: 16,
|
|
694
|
-
},
|
|
695
|
-
previewItemContainer: {
|
|
696
|
-
// marginBottom: 24,
|
|
697
|
-
},
|
|
698
|
-
title: {
|
|
699
|
-
fontSize: 24,
|
|
700
|
-
fontWeight: 'bold',
|
|
701
|
-
color: '#333',
|
|
702
|
-
marginBottom: 8,
|
|
703
|
-
textAlign: 'center',
|
|
704
|
-
},
|
|
705
|
-
subtitle: {
|
|
706
|
-
fontSize: 18,
|
|
707
|
-
color: '#666',
|
|
708
|
-
textAlign: 'center',
|
|
709
|
-
marginBottom: 16,
|
|
710
|
-
},
|
|
711
|
-
sideInfo: {
|
|
712
|
-
fontSize: 14,
|
|
713
|
-
color: '#888',
|
|
714
|
-
textAlign: 'center',
|
|
715
|
-
marginBottom: 16,
|
|
716
|
-
fontStyle: 'italic',
|
|
717
|
-
},
|
|
718
|
-
description: {
|
|
719
|
-
fontSize: 16,
|
|
720
|
-
color: '#666',
|
|
721
|
-
textAlign: 'center',
|
|
722
|
-
marginBottom: 24,
|
|
723
|
-
lineHeight: 22,
|
|
724
|
-
},
|
|
725
|
-
sidesContainer: {
|
|
726
|
-
flex: 1,
|
|
727
|
-
},
|
|
728
|
-
sideContainer: {
|
|
729
|
-
marginBottom: 24,
|
|
730
|
-
},
|
|
731
|
-
sideTitle: {
|
|
732
|
-
fontSize: 25,
|
|
733
|
-
fontWeight: 'bold',
|
|
734
|
-
color: '#000',
|
|
735
|
-
marginBottom: 12,
|
|
736
|
-
textAlign: 'center',
|
|
737
|
-
},
|
|
738
|
-
captureButton: {
|
|
739
|
-
borderWidth: 2,
|
|
740
|
-
borderColor: '#2DBD60',
|
|
741
|
-
borderStyle: 'dashed',
|
|
742
|
-
borderRadius: 12,
|
|
743
|
-
padding: 32,
|
|
744
|
-
alignItems: 'center',
|
|
745
|
-
backgroundColor: '#f0f9f0',
|
|
746
|
-
},
|
|
747
|
-
captureIcon: {
|
|
748
|
-
fontSize: 48,
|
|
749
|
-
marginBottom: 16,
|
|
750
|
-
},
|
|
751
|
-
captureText: {
|
|
752
|
-
fontSize: 16,
|
|
753
|
-
color: '#2DBD60',
|
|
754
|
-
fontWeight: '600',
|
|
755
|
-
},
|
|
756
|
-
capturedImageContainer: {
|
|
757
|
-
position: 'relative',
|
|
758
|
-
},
|
|
759
|
-
capturedImage: {
|
|
760
|
-
width: '100%',
|
|
761
|
-
height: 200,
|
|
762
|
-
borderRadius: 12,
|
|
763
|
-
resizeMode: 'contain',
|
|
764
|
-
backgroundColor: '#f0f0f0',
|
|
765
|
-
},
|
|
766
|
-
retakeButton: {
|
|
767
|
-
position: 'absolute',
|
|
768
|
-
top: 8,
|
|
769
|
-
right: 8,
|
|
770
|
-
backgroundColor: 'rgba(0, 0, 0, 0.7)',
|
|
771
|
-
paddingHorizontal: 12,
|
|
772
|
-
paddingVertical: 6,
|
|
773
|
-
borderRadius: 6,
|
|
774
|
-
},
|
|
775
|
-
retakeButtonText: {
|
|
776
|
-
color: 'white',
|
|
777
|
-
fontSize: 12,
|
|
778
|
-
fontWeight: '600',
|
|
779
|
-
},
|
|
345
|
+
root: { flex: 1, maxWidth: 760, width: '100%' },
|
|
346
|
+
container: { backgroundColor: 'white', margin: 10, borderRadius: 10, paddingVertical: 16, paddingHorizontal: 16, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.35, shadowRadius: 4.84, elevation: 10 },
|
|
347
|
+
cameraContainer: { flex: 1, width: '100%', height: '100%' },
|
|
348
|
+
previewContainer: { width: '95%', backgroundColor: 'white', margin: 10, borderRadius: 10, paddingVertical: 16, paddingHorizontal: 16 },
|
|
349
|
+
previewItemContainer: {},
|
|
350
|
+
title: { fontSize: 24, fontWeight: 'bold', color: '#333', marginBottom: 8, textAlign: 'center' },
|
|
351
|
+
description: { fontSize: 16, color: '#666', textAlign: 'center', marginBottom: 24, lineHeight: 22 },
|
|
352
|
+
sideContainer: { marginBottom: 24 },
|
|
353
|
+
sideTitle: { fontSize: 25, fontWeight: 'bold', color: '#000', marginBottom: 12, textAlign: 'center' },
|
|
354
|
+
imagePreviewWrapper: { width: '100%', height: 200, borderRadius: 12, padding: 1, overflow: 'hidden', shadowColor: '#000', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.18, shadowRadius: 8, elevation: 8, backgroundColor: '#000' },
|
|
355
|
+
previewImage: { width: '100%', height: '100%', borderRadius: 12, resizeMode: 'contain' },
|
|
356
|
+
floatingErrorBanner: { position: 'absolute', top: 60, left: '10%', right: '10%', backgroundColor: 'rgba(220, 38, 38, 0.95)', paddingVertical: 12, paddingHorizontal: 16, borderRadius: 8, alignItems: 'center', justifyContent: 'center', shadowColor: '#000', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.3, shadowRadius: 5, elevation: 8, zIndex: 100 },
|
|
357
|
+
floatingErrorText: { color: 'white', fontSize: 14, fontWeight: '700', textAlign: 'center' },
|
|
358
|
+
processingOverlay: { flex: 1, backgroundColor: 'rgba(0, 0, 0, 0.6)', justifyContent: 'center', alignItems: 'center', zIndex: 9999 },
|
|
359
|
+
processingText: { color: '#FFF', fontSize: 18, fontWeight: 'bold', marginTop: 16, textAlign: 'center' },
|
|
360
|
+
warningBanner: { backgroundColor: '#FF9500', padding: 12, borderRadius: 8, width: '100%', shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.2, shadowRadius: 4, elevation: 4 },
|
|
361
|
+
warningText: { color: 'white', fontWeight: 'bold', textAlign: 'center', fontSize: 16 },
|
|
362
|
+
errorText: { color: '#dc2626', fontSize: 14, marginTop: 8, textAlign: 'center' },
|
|
363
|
+
topAnalyzingPillContainer: { position: 'absolute', top: Platform.OS === 'android' ? 60 : 50, left: 0, right: 0, alignItems: 'center', zIndex: 100 },
|
|
364
|
+
topAnalyzingPill: { flexDirection: 'row', alignItems: 'center', backgroundColor: 'rgba(0,0,0,0.6)', paddingVertical: 8, paddingHorizontal: 16, borderRadius: 20, gap: 8 },
|
|
365
|
+
analyzingPillText: { color: 'white', fontSize: 14, fontWeight: 'bold' },
|
|
780
366
|
camera: {
|
|
781
367
|
flex: 1,
|
|
782
368
|
},
|
|
783
|
-
completionContainer: {
|
|
784
|
-
marginTop: 24,
|
|
785
|
-
alignItems: 'center',
|
|
786
|
-
},
|
|
787
|
-
completionText: {
|
|
788
|
-
fontSize: 16,
|
|
789
|
-
color: '#2DBD60',
|
|
790
|
-
fontWeight: '600',
|
|
791
|
-
marginBottom: 16,
|
|
792
|
-
},
|
|
793
|
-
primaryButton: {
|
|
794
|
-
paddingHorizontal: 32,
|
|
795
|
-
paddingVertical: 16,
|
|
796
|
-
borderRadius: 8,
|
|
797
|
-
// minWidth: 120,
|
|
798
|
-
alignItems: 'center',
|
|
799
|
-
backgroundColor: '#2DBD60',
|
|
800
|
-
},
|
|
801
|
-
primaryButtonText: {
|
|
802
|
-
color: 'white',
|
|
803
|
-
fontWeight: '600',
|
|
804
|
-
fontSize: 16,
|
|
805
|
-
},
|
|
806
|
-
errorText: {
|
|
807
|
-
color: '#dc2626',
|
|
808
|
-
fontSize: 14,
|
|
809
|
-
marginTop: 8,
|
|
810
|
-
textAlign: 'center',
|
|
811
|
-
},
|
|
812
|
-
crossDeviceButton: {
|
|
813
|
-
marginTop: 16,
|
|
814
|
-
padding: 12,
|
|
815
|
-
alignItems: 'center',
|
|
816
|
-
borderWidth: 1,
|
|
817
|
-
borderColor: '#2DBD60',
|
|
818
|
-
borderRadius: 8,
|
|
819
|
-
backgroundColor: '#f0f9f0',
|
|
820
|
-
},
|
|
821
|
-
crossDeviceText: {
|
|
822
|
-
color: '#2DBD60',
|
|
823
|
-
fontSize: 16,
|
|
824
|
-
fontWeight: '600',
|
|
825
|
-
},
|
|
826
|
-
modalOverlay: {
|
|
827
|
-
flex: 1,
|
|
828
|
-
backgroundColor: 'rgba(0,0,0,0.5)',
|
|
829
|
-
justifyContent: 'center',
|
|
830
|
-
alignItems: 'center',
|
|
831
|
-
},
|
|
832
|
-
modalContent: {
|
|
833
|
-
backgroundColor: 'white',
|
|
834
|
-
borderRadius: 16,
|
|
835
|
-
padding: 24,
|
|
836
|
-
alignItems: 'center',
|
|
837
|
-
width: '90%',
|
|
838
|
-
maxWidth: 340,
|
|
839
|
-
shadowColor: '#000',
|
|
840
|
-
shadowOffset: { width: 0, height: 2 },
|
|
841
|
-
shadowOpacity: 0.25,
|
|
842
|
-
shadowRadius: 4,
|
|
843
|
-
elevation: 5,
|
|
844
|
-
},
|
|
845
|
-
modalTitle: {
|
|
846
|
-
fontSize: 20,
|
|
847
|
-
fontWeight: 'bold',
|
|
848
|
-
marginBottom: 12,
|
|
849
|
-
color: '#333',
|
|
850
|
-
},
|
|
851
|
-
modalDescription: {
|
|
852
|
-
fontSize: 16,
|
|
853
|
-
color: '#666',
|
|
854
|
-
textAlign: 'center',
|
|
855
|
-
marginBottom: 20,
|
|
856
|
-
lineHeight: 22,
|
|
857
|
-
},
|
|
858
|
-
qrCodeImage: {
|
|
859
|
-
width: 200,
|
|
860
|
-
height: 200,
|
|
861
|
-
marginBottom: 20,
|
|
862
|
-
},
|
|
863
|
-
closeButton: {
|
|
864
|
-
paddingVertical: 10,
|
|
865
|
-
paddingHorizontal: 20,
|
|
866
|
-
backgroundColor: '#f5f5f5',
|
|
867
|
-
borderRadius: 8,
|
|
868
|
-
},
|
|
869
|
-
closeButtonText: {
|
|
870
|
-
fontSize: 16,
|
|
871
|
-
color: '#666',
|
|
872
|
-
fontWeight: '600',
|
|
873
|
-
},
|
|
874
|
-
floatingErrorBanner: {
|
|
875
|
-
position: 'absolute',
|
|
876
|
-
top: 60, // Pushes it down slightly from the very top of the screen
|
|
877
|
-
left: '10%',
|
|
878
|
-
right: '10%',
|
|
879
|
-
backgroundColor: 'rgba(220, 38, 38, 0.95)', // Bright red
|
|
880
|
-
paddingVertical: 12,
|
|
881
|
-
paddingHorizontal: 16,
|
|
882
|
-
borderRadius: 8,
|
|
883
|
-
alignItems: 'center',
|
|
884
|
-
justifyContent: 'center',
|
|
885
|
-
shadowColor: '#000',
|
|
886
|
-
shadowOffset: { width: 0, height: 4 },
|
|
887
|
-
shadowOpacity: 0.3,
|
|
888
|
-
shadowRadius: 5,
|
|
889
|
-
elevation: 8,
|
|
890
|
-
zIndex: 100,
|
|
891
|
-
},
|
|
892
|
-
floatingErrorText: {
|
|
893
|
-
color: 'white',
|
|
894
|
-
fontSize: 14,
|
|
895
|
-
fontWeight: '700',
|
|
896
|
-
textAlign: 'center',
|
|
897
|
-
},
|
|
898
369
|
});
|
|
899
370
|
//# sourceMappingURL=IDCardCapture.js.map
|