@transfergratis/react-native-sdk 0.1.28 → 0.1.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/build/components/EnhancedCameraView.js +1 -1
  2. package/build/components/EnhancedCameraView.js.map +1 -1
  3. package/build/components/KYCElements/CountrySelectionTemplate.d.ts.map +1 -1
  4. package/build/components/KYCElements/CountrySelectionTemplate.js +13 -42
  5. package/build/components/KYCElements/CountrySelectionTemplate.js.map +1 -1
  6. package/build/components/KYCElements/IDCardCapture.d.ts.map +1 -1
  7. package/build/components/KYCElements/IDCardCapture.js +113 -49
  8. package/build/components/KYCElements/IDCardCapture.js.map +1 -1
  9. package/build/components/KYCElements/SelfieCaptureTemplate.js +2 -2
  10. package/build/components/KYCElements/SelfieCaptureTemplate.js.map +1 -1
  11. package/build/hooks/useTemplateKYCFlow.js +1 -1
  12. package/build/hooks/useTemplateKYCFlow.js.map +1 -1
  13. package/build/modules/api/CardAuthentification.d.ts +15 -7
  14. package/build/modules/api/CardAuthentification.d.ts.map +1 -1
  15. package/build/modules/api/CardAuthentification.js +360 -104
  16. package/build/modules/api/CardAuthentification.js.map +1 -1
  17. package/build/modules/api/KYCService.d.ts +3 -1
  18. package/build/modules/api/KYCService.d.ts.map +1 -1
  19. package/build/modules/api/KYCService.js +25 -24
  20. package/build/modules/api/KYCService.js.map +1 -1
  21. package/build/modules/camera/VisionCameraModule.js +2 -2
  22. package/build/modules/camera/VisionCameraModule.js.map +1 -1
  23. package/build/utils/cropByObb.d.ts +8 -0
  24. package/build/utils/cropByObb.d.ts.map +1 -1
  25. package/build/utils/cropByObb.js +20 -3
  26. package/build/utils/cropByObb.js.map +1 -1
  27. package/build/utils/pathToBase64.js +1 -1
  28. package/build/utils/pathToBase64.js.map +1 -1
  29. package/package.json +1 -1
  30. package/src/components/EnhancedCameraView.tsx +1 -1
  31. package/src/components/KYCElements/CountrySelectionTemplate.tsx +24 -52
  32. package/src/components/KYCElements/IDCardCapture.tsx +179 -109
  33. package/src/components/KYCElements/SelfieCaptureTemplate.tsx +2 -2
  34. package/src/hooks/useTemplateKYCFlow.tsx +1 -1
  35. package/src/modules/api/CardAuthentification.ts +450 -113
  36. package/src/modules/api/KYCService.ts +52 -39
  37. package/src/modules/camera/VisionCameraModule.ts +2 -2
  38. package/src/utils/cropByObb.ts +22 -3
  39. package/src/utils/pathToBase64.ts +1 -1
@@ -43,9 +43,8 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
43
43
  const { t, locale } = useI18n();
44
44
  const [showCamera, setShowCamera] = useState(false);
45
45
  const [capturedImages, setCapturedImages] = useState<Record<string, IIDCardPayload>>(value || {});
46
- const [cropImageUri, setCropImageUri] = useState<string>('');
47
- const [currentSide, setCurrentSide] = useState<string>('front');
48
- // Stocker les bbox par côté pour pouvoir restaurer les images croppées
46
+ // const [cropImageUri, setCropImageUri] = useState<string>('');
47
+ const [currentSide, setCurrentSide] = useState<'front' | 'back'>('front');
49
48
  const [bboxBySide, setBboxBySide] = useState<Record<string, IBbox>>({});
50
49
  const [silentCaptureResult, setSilentCaptureResult] = useState<ISilentCaptureResult>({ success: false, isAnalyzing: false });
51
50
  const [showQRModal, setShowQRModal] = useState(false);
@@ -97,6 +96,7 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
97
96
  return countrySelectionData;
98
97
  }, [countrySelectionData]);
99
98
 
99
+ // console.log();
100
100
 
101
101
  // Synchroniser capturedImages avec value quand les données sont chargées (ex: reprise de session)
102
102
  useEffect(() => {
@@ -131,7 +131,7 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
131
131
  logger.log("cropImageUri", JSON.stringify(truncateFields({ box: silentCaptureResult }), null, 2));
132
132
  if (capturedImages[currentSide]?.dir && silentCaptureResult?.bbox) {
133
133
  cropImageWithBBox(capturedImages[currentSide].dir, silentCaptureResult.bbox)?.then((uri) => {
134
- setCropImageUri(uri);
134
+ // setCropImageUri(uri);
135
135
  });
136
136
  }
137
137
  }, [capturedImages[currentSide]?.dir, silentCaptureResult?.bbox])
@@ -145,9 +145,11 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
145
145
 
146
146
  return {
147
147
  aspectRatio: 4 / 3,
148
- quality: 0.8,
148
+ quality: 0.7,
149
149
  flashMode: 'auto' as const,
150
150
  cameraType: 'back' as const,
151
+ autoFocus: 'on',
152
+ whiteBalance: 'auto',
151
153
  allowRetake: true,
152
154
  maxRetakes: 3,
153
155
  overlay: {
@@ -166,13 +168,34 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
166
168
  };
167
169
  }, [selectedDocumentType, locale, component.instructions]);
168
170
 
169
- const retakePicture = (currentSide: string) => {
171
+ const retakePicture = (sideToRetake: 'front' | 'back') => {
172
+ // 1. Turn the camera back on and hide the stepper
170
173
  setShowCamera(true);
171
174
  actions.showCustomStepper(false);
172
- setCapturedImages({ ...capturedImages, [currentSide]: { dir: '', file: '', mrz: '' } });
173
- setSilentCaptureResult((prev) => ({ ...prev, path: '', success: false, isAnalyzing: false, error: '' }));
174
- setCropImageUri('');
175
- onValueChange({ ...value, [currentSide]: { dir: '', file: '', mrz: '' } });
175
+
176
+ // 2. WIPE LOCAL STATE: Use functional update to prevent stale closures
177
+ setCapturedImages((prev) => {
178
+ const newState = { ...prev };
179
+ delete newState[sideToRetake];
180
+ return newState;
181
+ });
182
+
183
+ setSilentCaptureResult({
184
+ path: '',
185
+ success: false,
186
+ isAnalyzing: false,
187
+ error: '',
188
+ templatePath: '',
189
+ mrz: '',
190
+ bbox: undefined,
191
+ });
192
+
193
+
194
+ if (value) {
195
+ const newValue = { ...value };
196
+ delete newValue[sideToRetake];
197
+ onValueChange(newValue);
198
+ }
176
199
  };
177
200
 
178
201
 
@@ -301,26 +324,33 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
301
324
  };
302
325
  console.log("frontVerification params", verificationParams);
303
326
  console.log("About to call frontVerification function");
327
+
304
328
  const promise = frontVerification(verificationParams, env);
305
329
  console.log("frontVerification promise created", promise);
306
- promise.then((mrz) => {
307
- logger.log("front verification result", truncateFields(mrz));
308
- const bbox = (mrz as any)?.bbox || templateBbox;
330
+
331
+ promise.then((res: any) => {
332
+ logger.log("front verification result", truncateFields(res));
333
+ const bbox = res?.bbox || templateBbox;
334
+
309
335
  setSilentCaptureResult((prev) => ({
310
336
  ...prev,
311
337
  path: result.path,
312
338
  templatePath: templatePath,
313
- bbox: bbox, success: true,
314
- mrz: JSON.stringify(mrz), isAnalyzing: false,
339
+ bbox: bbox,
340
+ success: true,
341
+ mrz: res?.mrz ? JSON.stringify(res.mrz) : "",
342
+ isAnalyzing: false,
315
343
  country: countryData?.code,
316
344
  documentType: selectedDocumentType.type,
317
- }),
318
- );
345
+ }));
346
+
319
347
  // Stocker le bbox pour ce côté
320
348
  if (bbox && typeof bbox === 'object') {
321
349
  setBboxBySide((prev) => ({ ...prev, [currentSide]: bbox }));
322
350
  }
323
351
 
352
+ }).catch((e: any) => {
353
+
324
354
  }).catch((e: any) => {
325
355
  console.log("error front verification", e);
326
356
  logger.log("error front verification", truncateFields(e));
@@ -340,6 +370,7 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
340
370
  } else {
341
371
  const backRegionMappings = getCurrentSideVerification(currentSide);
342
372
  logger.log("Calling backVerification", { templatePath, selectedDocumentType: selectedDocumentType.type, backRegionMappings });
373
+
343
374
  backVerification({
344
375
  path: result.path,
345
376
  regionMapping: {
@@ -351,16 +382,21 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
351
382
  currentSide: currentSide,
352
383
  templatePath: templatePath,
353
384
  mrzType: getCorrespondingMrzType(templatePath, backRegionMappings.regionMapping, backRegionMappings.key || '') || '',
354
- }, env).then((mrz) => {
355
- logger.log("back verification result", truncateFields(mrz));
356
- const bbox = (mrz as any)?.bbox || templateBbox;
385
+ }, env).then((res: any) => {
386
+ logger.log("back verification result", truncateFields(res));
387
+ const bbox = res?.bbox || templateBbox;
388
+
357
389
  setSilentCaptureResult((prev) => ({
358
- ...prev, path: result.path, bbox: bbox,
359
- success: true, mrz: JSON.stringify(mrz), isAnalyzing: false,
390
+ ...prev,
391
+ path: result.path,
392
+ bbox: bbox,
393
+ success: true,
394
+ mrz: res?.mrz ? JSON.stringify(res.mrz) : "",
395
+ isAnalyzing: false,
360
396
  country: countryData?.code,
361
397
  documentType: selectedDocumentType.type,
362
-
363
398
  }));
399
+
364
400
  // Stocker le bbox pour ce côté
365
401
  if (bbox && typeof bbox === 'object') {
366
402
  setBboxBySide((prev) => ({ ...prev, [currentSide]: bbox }));
@@ -375,37 +411,38 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
375
411
  ? t('kyc.idCardCapture.cardNotFullyInFrame')
376
412
  : (e?.message || 'Erreur de détection du MRZ');
377
413
  setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, templatePath: templatePath, success: false, error: errorMessage }));
378
- })
414
+ });
379
415
  }
380
416
 
381
417
  }
382
418
  }
383
419
 
384
- // Handle capture
385
420
  const handleCapture = async (result: { success: boolean; path?: string; error?: string }) => {
386
- console.log("handleCapture", JSON.stringify(truncateFields({ result, silentCaptureResult }), null, 2));
387
-
388
421
  if (silentCaptureResult.path) {
389
- // Créer une image rognée avec tolérance de 10% pour l'envoi
390
422
  let imagePathForUpload = silentCaptureResult.path;
391
423
  if (silentCaptureResult.bbox) {
392
424
  try {
393
- logger.log("Début du rognage avec tolérance, URI original:", silentCaptureResult.path);
394
425
  imagePathForUpload = await cropImageWithBBoxWithTolerance(silentCaptureResult.path, silentCaptureResult.bbox, 0.05);
395
- logger.log("Image rognée avec tolérance créée pour l'envoi, URI final:", imagePathForUpload);
396
426
  } catch (error) {
397
- logger.log("Erreur lors du rognage avec tolérance, utilisation de l'image originale:", truncateFields(error));
398
- // En cas d'erreur, on utilise l'image originale
399
427
  imagePathForUpload = silentCaptureResult.path;
400
428
  }
401
429
  }
402
430
 
403
431
  const base64 = await pathToBase64(imagePathForUpload);
404
432
 
405
- logger.log("silentCaptureResult captured", JSON.stringify(truncateFields(silentCaptureResult), null, 2));
406
- // Utiliser l'image originale pour l'affichage (dir) mais l'image rognée avec tolérance pour l'envoi (file)
407
- const newImages = { ...capturedImages, [currentSide]: { dir: silentCaptureResult.path, file: base64, mrz: silentCaptureResult.mrz || "", templatePath: silentCaptureResult.templatePath } };
433
+ // ✅ FIX: Use 'imagePathForUpload' (the cropped image) for the local display directory!
434
+ const newImages = {
435
+ ...capturedImages,
436
+ [currentSide]: {
437
+ dir: imagePathForUpload, // <--- CHANGED THIS LINE
438
+ file: base64,
439
+ mrz: silentCaptureResult.mrz || "",
440
+ templatePath: silentCaptureResult.templatePath
441
+ }
442
+ };
443
+
408
444
  setCapturedImages(newImages);
445
+
409
446
  if (silentCaptureResult.country && silentCaptureResult.documentType) {
410
447
  onValueChange({
411
448
  ...newImages,
@@ -425,10 +462,6 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
425
462
  setShowCamera(false);
426
463
  };
427
464
 
428
-
429
-
430
-
431
-
432
465
  useEffect(() => {
433
466
  actions.showCustomStepper(!showCamera);
434
467
  }, [showCamera]);
@@ -531,7 +564,6 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
531
564
 
532
565
 
533
566
  if (showCamera) {
534
-
535
567
  return (
536
568
  <View style={styles.cameraContainer}>
537
569
  <EnhancedCameraView
@@ -548,54 +580,63 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
548
580
  silentCaptureResult={silentCaptureResult}
549
581
  captureStabilizationDelayMs={3000}
550
582
  enableFlash={cameraConfig.flashMode === 'auto' || cameraConfig.flashMode === 'on'}
551
- overlayComponent={<IdCardOverlay
552
- xMin={cameraConfig.overlay.bbox.xMin}
553
- yMin={cameraConfig.overlay.bbox.yMin}
554
- xMax={cameraConfig.overlay.bbox.xMax}
555
- yMax={cameraConfig.overlay.bbox.yMax}
556
- instructions={cameraConfig.overlay.guideText}
557
- cornerOpacity={cameraConfig.overlay.bbox.cornerRadius || 0 as number}
558
- isSuccess={silentCaptureResult.success}
559
- language={state.currentLanguage}
560
- stepperProps={{
561
- back: () => {
562
- if (currentSide === 'back') {
563
- setCurrentSide('front');
564
- setShowCamera(false);
565
- // Si une image front existe, on la restaure pour l'afficher
566
- if (capturedImages['front']?.dir) {
567
- // Restaurer l'état de capture du front pour afficher l'image
568
- const frontImage = capturedImages['front'];
569
- const frontBbox = bboxBySide['front'];
570
- setSilentCaptureResult((prev) => ({
571
- path: frontImage.dir,
572
- success: true,
573
- isAnalyzing: false,
574
- error: '',
575
- mrz: frontImage.mrz || '',
576
- templatePath: frontImage.templatePath || '',
577
- country: silentCaptureResult.country,
578
- documentType: silentCaptureResult.documentType,
579
- bbox: frontBbox // Restaurer le bbox pour recalculer le cropImageUri
580
- }));
581
- // Le useEffect va automatiquement recalculer le cropImageUri si bbox existe
583
+ overlayComponent={
584
+ <IdCardOverlay
585
+ xMin={cameraConfig.overlay.bbox.xMin}
586
+ yMin={cameraConfig.overlay.bbox.yMin}
587
+ xMax={cameraConfig.overlay.bbox.xMax}
588
+ yMax={cameraConfig.overlay.bbox.yMax}
589
+ instructions={cameraConfig.overlay.guideText}
590
+ cornerOpacity={cameraConfig.overlay.bbox.cornerRadius || 0 as number}
591
+ isSuccess={silentCaptureResult.success}
592
+ language={state.currentLanguage}
593
+ stepperProps={{
594
+ back: () => {
595
+ if (currentSide === 'back') {
596
+ setCurrentSide('front');
597
+ setShowCamera(false);
598
+ // Si une image front existe, on la restaure pour l'afficher
599
+ if (capturedImages['front']?.dir) {
600
+ // Restaurer l'état de capture du front pour afficher l'image
601
+ const frontImage = capturedImages['front'];
602
+ const frontBbox = bboxBySide['front'];
603
+ setSilentCaptureResult((prev) => ({
604
+ path: frontImage.dir,
605
+ success: true,
606
+ isAnalyzing: false,
607
+ error: '',
608
+ mrz: frontImage.mrz || '',
609
+ templatePath: frontImage.templatePath || '',
610
+ country: silentCaptureResult.country,
611
+ documentType: silentCaptureResult.documentType,
612
+ bbox: frontBbox // Restaurer le bbox pour recalculer le cropImageUri
613
+ }));
614
+ } else {
615
+ // Pas d'image front, on réinitialise
616
+ setSilentCaptureResult((prev) => ({ path: '', success: false, isAnalyzing: false, error: '', templatePath: '' }));
617
+ }
582
618
  } else {
583
- // Pas d'image front, on réinitialise
584
- setSilentCaptureResult((prev) => ({ path: '', success: false, isAnalyzing: false, error: '', templatePath: '' }));
619
+ // Retour au composant précédent (country_selection)
620
+ actions.previousComponent();
585
621
  }
586
- } else {
587
- // Retour au composant précédent (country_selection)
588
- actions.previousComponent();
589
- }
590
- },
591
- selectedDocumentType: selectedDocumentType ? (locale === 'en' ? getDocumentTypeInfo(selectedDocumentType.type).name.en : getDocumentTypeInfo(selectedDocumentType.type).name.fr) : '',
592
- step: state.currentComponentIndex + 1,
593
- totalSteps: state.template.components.length,
594
- side: currentSide,
595
- }}
596
- />
622
+ },
623
+ selectedDocumentType: selectedDocumentType ? (locale === 'en' ? getDocumentTypeInfo(selectedDocumentType.type).name.en : getDocumentTypeInfo(selectedDocumentType.type).name.fr) : '',
624
+ step: state.currentComponentIndex + 1,
625
+ totalSteps: state.template.components.length,
626
+ side: currentSide,
627
+ }}
628
+ />
597
629
  }
598
630
  />
631
+
632
+ {silentCaptureResult.error ? (
633
+ <View style={styles.floatingErrorBanner}>
634
+ <Text style={styles.floatingErrorText}>
635
+ {silentCaptureResult.error}
636
+ </Text>
637
+ </View>
638
+ ) : null}
639
+
599
640
  </View>
600
641
  );
601
642
  }
@@ -614,57 +655,62 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
614
655
  </Text>
615
656
 
616
657
  <View style={{ alignItems: 'center', justifyContent: 'center', flexDirection: "column", gap: 16 }}>
617
- <View
658
+ {silentCaptureResult?.error === 'TOO_FAR_AWAY' && (
659
+ <View style={{
660
+ backgroundColor: '#FF9500',
661
+ padding: 12,
662
+ borderRadius: 8,
663
+ width: '100%',
664
+ shadowColor: '#000',
665
+ shadowOffset: { width: 0, height: 2 },
666
+ shadowOpacity: 0.2,
667
+ shadowRadius: 4,
668
+ elevation: 4
669
+ }}>
670
+ <Text style={{ color: 'white', fontWeight: 'bold', textAlign: 'center', fontSize: 16 }}>
671
+ {state.currentLanguage === "en"
672
+ ? "Move the document closer to the camera."
673
+ : "Veuillez rapprocher le document de la caméra."}
674
+ </Text>
675
+ </View>
676
+ )}
677
+
678
+ <View
618
679
  style={{
619
680
  width: '100%',
620
681
  height: 200,
621
682
  borderRadius: 12,
622
683
  padding: 1,
623
684
  overflow: 'hidden',
624
- // Shadow for iOS
625
685
  shadowColor: '#000',
626
686
  shadowOffset: { width: 0, height: 4 },
627
687
  shadowOpacity: 0.18,
628
688
  shadowRadius: 8,
629
- // Shadow for Android
630
689
  elevation: 8,
631
- backgroundColor: '#fff', // Needed for shadow to show on iOS
690
+ backgroundColor: '#000',
632
691
  }}
633
692
  >
634
- {cropImageUri ? (
693
+ {capturedImages[currentSide]?.dir ? (
635
694
  <Image
636
- source={{ uri: cropImageUri }}
695
+ source={{ uri: capturedImages[currentSide].dir }}
637
696
  style={{
638
697
  width: '100%',
639
- height: 200,
698
+ height: '100%',
640
699
  borderRadius: 12,
641
- resizeMode: 'cover',
700
+ resizeMode: 'contain',
642
701
  }}
643
702
  />
644
- ) : null}
645
- {!cropImageUri && silentCaptureResult.path ? (
703
+ ) : silentCaptureResult.path ? (
646
704
  <Image
647
705
  source={{ uri: silentCaptureResult.path }}
648
706
  style={{
649
707
  width: '100%',
650
- height: 200,
651
- borderRadius: 12,
652
- resizeMode: 'cover',
653
- }}
654
- />
655
- ) : null}
656
- {!cropImageUri && !silentCaptureResult.path && capturedImages[currentSide]?.dir ? (
657
- <Image
658
- source={{ uri: capturedImages[currentSide].dir }}
659
- style={{
660
- width: '100%',
661
- height: 200,
708
+ height: '100%',
662
709
  borderRadius: 12,
663
- resizeMode: 'cover',
710
+ resizeMode: 'contain',
664
711
  }}
665
712
  />
666
713
  ) : null}
667
-
668
714
  </View>
669
715
  {/* Capture button si aucune image n'a été capturée */}
670
716
  {!capturedImages[currentSide]?.dir && (
@@ -701,7 +747,7 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
701
747
  setShowCamera(true);
702
748
  setCurrentSide('back');
703
749
  setSilentCaptureResult((prev) => ({ path: '', success: false, isAnalyzing: false, error: '', mrz: '', templatePath: '' }));
704
- setCropImageUri('');
750
+ // setCropImageUri('');
705
751
  }
706
752
  }}
707
753
  variant="primary"
@@ -980,4 +1026,28 @@ const styles = StyleSheet.create({
980
1026
  color: '#666',
981
1027
  fontWeight: '600',
982
1028
  },
1029
+ floatingErrorBanner: {
1030
+ position: 'absolute',
1031
+ top: 60, // Pushes it down slightly from the very top of the screen
1032
+ left: '10%',
1033
+ right: '10%',
1034
+ backgroundColor: 'rgba(220, 38, 38, 0.95)', // Bright red
1035
+ paddingVertical: 12,
1036
+ paddingHorizontal: 16,
1037
+ borderRadius: 8,
1038
+ alignItems: 'center',
1039
+ justifyContent: 'center',
1040
+ shadowColor: '#000',
1041
+ shadowOffset: { width: 0, height: 4 },
1042
+ shadowOpacity: 0.3,
1043
+ shadowRadius: 5,
1044
+ elevation: 8,
1045
+ zIndex: 100,
1046
+ },
1047
+ floatingErrorText: {
1048
+ color: 'white',
1049
+ fontSize: 14,
1050
+ fontWeight: '700',
1051
+ textAlign: 'center',
1052
+ },
983
1053
  });
@@ -76,9 +76,9 @@ export const SelfieCaptureTemplate: React.FC<SelfieCaptureTemplateProps> = ({
76
76
  const getOrientationLabel = (orientation: OrientationType): string => {
77
77
  switch (orientation) {
78
78
  case 'center':
79
- return state.currentLanguage === "en" ? "Front Profil Selfie" : "Selfie de face";
79
+ return state.currentLanguage === "en" ? "Front Profile Selfie" : "Selfie de face";
80
80
  case 'left':
81
- return state.currentLanguage === "en" ? "Left Profil Selfie" : "Selfie profil gauche";
81
+ return state.currentLanguage === "en" ? "Left Profile Selfie" : "Selfie profil gauche";
82
82
  case 'right':
83
83
  return state.currentLanguage === "en" ? "Right Profile Selfie" : "Selfie profil droit";
84
84
  default:
@@ -822,7 +822,7 @@ export const useTemplateKYCFlow = (
822
822
  isProcessing: false,
823
823
  errors: {
824
824
  ...prev.errors,
825
- [currentComp.id]: state.currentLanguage === "en" ? "please complete this step before move on" : " 'Veuillez compléter cette étape avant de continuer'"
825
+ [currentComp.id]: state.currentLanguage === "en" ? "please complete this step before moving on" : " 'Veuillez compléter cette étape avant de continuer'"
826
826
  }
827
827
  }));
828
828
  return;