@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.
Files changed (216) hide show
  1. package/build/api/axios.d.ts +30 -0
  2. package/build/api/axios.d.ts.map +1 -0
  3. package/build/api/axios.js +92 -0
  4. package/build/api/axios.js.map +1 -0
  5. package/build/components/EnhancedCameraView.d.ts +1 -41
  6. package/build/components/EnhancedCameraView.d.ts.map +1 -1
  7. package/build/components/EnhancedCameraView.js +75 -34
  8. package/build/components/EnhancedCameraView.js.map +1 -1
  9. package/build/components/EnhancedCameraView.web.d.ts +1 -41
  10. package/build/components/EnhancedCameraView.web.d.ts.map +1 -1
  11. package/build/components/EnhancedCameraView.web.js +28 -4
  12. package/build/components/EnhancedCameraView.web.js.map +1 -1
  13. package/build/components/KYCElements/CountrySelectionTemplate.d.ts +2 -2
  14. package/build/components/KYCElements/CountrySelectionTemplate.d.ts.map +1 -1
  15. package/build/components/KYCElements/CountrySelectionTemplate.js +77 -114
  16. package/build/components/KYCElements/CountrySelectionTemplate.js.map +1 -1
  17. package/build/components/KYCElements/FileUploadTemplate.d.ts.map +1 -1
  18. package/build/components/KYCElements/FileUploadTemplate.js +7 -3
  19. package/build/components/KYCElements/FileUploadTemplate.js.map +1 -1
  20. package/build/components/KYCElements/IDCardCapture.d.ts +7 -2
  21. package/build/components/KYCElements/IDCardCapture.d.ts.map +1 -1
  22. package/build/components/KYCElements/IDCardCapture.js +253 -104
  23. package/build/components/KYCElements/IDCardCapture.js.map +1 -1
  24. package/build/components/KYCElements/InitializationStep.d.ts +5 -0
  25. package/build/components/KYCElements/InitializationStep.d.ts.map +1 -0
  26. package/build/components/KYCElements/InitializationStep.js +41 -0
  27. package/build/components/KYCElements/InitializationStep.js.map +1 -0
  28. package/build/components/KYCElements/LocationCaptureTemplate.d.ts.map +1 -1
  29. package/build/components/KYCElements/LocationCaptureTemplate.js +15 -13
  30. package/build/components/KYCElements/LocationCaptureTemplate.js.map +1 -1
  31. package/build/components/KYCElements/OrientationVideoCapture.d.ts +2 -2
  32. package/build/components/KYCElements/OrientationVideoCapture.d.ts.map +1 -1
  33. package/build/components/KYCElements/OrientationVideoCapture.js.map +1 -1
  34. package/build/components/KYCElements/OrientationVideoCaptureEnhanced.d.ts +2 -2
  35. package/build/components/KYCElements/OrientationVideoCaptureEnhanced.d.ts.map +1 -1
  36. package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js.map +1 -1
  37. package/build/components/KYCElements/OrientationVideoCaptureFinal.d.ts +2 -2
  38. package/build/components/KYCElements/OrientationVideoCaptureFinal.d.ts.map +1 -1
  39. package/build/components/KYCElements/OrientationVideoCaptureFinal.js.map +1 -1
  40. package/build/components/KYCElements/ReviewSubmitTemplate.d.ts +12 -0
  41. package/build/components/KYCElements/ReviewSubmitTemplate.d.ts.map +1 -0
  42. package/build/components/KYCElements/ReviewSubmitTemplate.js +171 -0
  43. package/build/components/KYCElements/ReviewSubmitTemplate.js.map +1 -0
  44. package/build/components/KYCElements/SelfieCaptureTemplate.d.ts +6 -2
  45. package/build/components/KYCElements/SelfieCaptureTemplate.d.ts.map +1 -1
  46. package/build/components/KYCElements/SelfieCaptureTemplate.js +137 -38
  47. package/build/components/KYCElements/SelfieCaptureTemplate.js.map +1 -1
  48. package/build/components/KYCElements/VerificationProgressTemplate.d.ts +12 -0
  49. package/build/components/KYCElements/VerificationProgressTemplate.d.ts.map +1 -0
  50. package/build/components/KYCElements/VerificationProgressTemplate.js +194 -0
  51. package/build/components/KYCElements/VerificationProgressTemplate.js.map +1 -0
  52. package/build/components/OverLay/IdCard.d.ts +1 -1
  53. package/build/components/OverLay/IdCard.d.ts.map +1 -1
  54. package/build/components/OverLay/IdCard.js +10 -6
  55. package/build/components/OverLay/IdCard.js.map +1 -1
  56. package/build/components/OverLay/SelfieOverlay.d.ts +1 -1
  57. package/build/components/OverLay/SelfieOverlay.d.ts.map +1 -1
  58. package/build/components/OverLay/SelfieOverlay.js +5 -4
  59. package/build/components/OverLay/SelfieOverlay.js.map +1 -1
  60. package/build/components/OverLay/type.d.ts +71 -1
  61. package/build/components/OverLay/type.d.ts.map +1 -1
  62. package/build/components/OverLay/type.js.map +1 -1
  63. package/build/components/TemplateKYCExample.d.ts +4 -1
  64. package/build/components/TemplateKYCExample.d.ts.map +1 -1
  65. package/build/components/TemplateKYCExample.js +74 -199
  66. package/build/components/TemplateKYCExample.js.map +1 -1
  67. package/build/components/TemplateKYCFlowRefactored.d.ts +3 -2
  68. package/build/components/TemplateKYCFlowRefactored.d.ts.map +1 -1
  69. package/build/components/TemplateKYCFlowRefactored.js +64 -40
  70. package/build/components/TemplateKYCFlowRefactored.js.map +1 -1
  71. package/build/components/example/OrientationVideoExample.d.ts.map +1 -1
  72. package/build/components/example/OrientationVideoExample.js +1 -5
  73. package/build/components/example/OrientationVideoExample.js.map +1 -1
  74. package/build/config/countriesData.d.ts +3 -0
  75. package/build/config/countriesData.d.ts.map +1 -0
  76. package/build/config/countriesData.js +79 -0
  77. package/build/config/countriesData.js.map +1 -0
  78. package/build/config/region_mapping.d.ts +3 -0
  79. package/build/config/region_mapping.d.ts.map +1 -0
  80. package/build/config/region_mapping.js +687 -0
  81. package/build/config/region_mapping.js.map +1 -0
  82. package/build/hooks/useI18n.d.ts +11 -0
  83. package/build/hooks/useI18n.d.ts.map +1 -0
  84. package/build/hooks/useI18n.js +37 -0
  85. package/build/hooks/useI18n.js.map +1 -0
  86. package/build/hooks/useOrientationVideo.d.ts +1 -2
  87. package/build/hooks/useOrientationVideo.d.ts.map +1 -1
  88. package/build/hooks/useOrientationVideo.js +2 -1
  89. package/build/hooks/useOrientationVideo.js.map +1 -1
  90. package/build/hooks/useRealtimeVerifier.d.ts +28 -0
  91. package/build/hooks/useRealtimeVerifier.d.ts.map +1 -0
  92. package/build/hooks/useRealtimeVerifier.js +91 -0
  93. package/build/hooks/useRealtimeVerifier.js.map +1 -0
  94. package/build/hooks/useTemplateKYCFlow.d.ts +6 -3
  95. package/build/hooks/useTemplateKYCFlow.d.ts.map +1 -1
  96. package/build/hooks/useTemplateKYCFlow.js +356 -42
  97. package/build/hooks/useTemplateKYCFlow.js.map +1 -1
  98. package/build/i18n/en/index.d.ts +168 -0
  99. package/build/i18n/en/index.d.ts.map +1 -0
  100. package/build/i18n/en/index.js +195 -0
  101. package/build/i18n/en/index.js.map +1 -0
  102. package/build/i18n/fr/index.d.ts +168 -0
  103. package/build/i18n/fr/index.d.ts.map +1 -0
  104. package/build/i18n/fr/index.js +194 -0
  105. package/build/i18n/fr/index.js.map +1 -0
  106. package/build/i18n/index.d.ts +10 -0
  107. package/build/i18n/index.d.ts.map +1 -0
  108. package/build/i18n/index.js +56 -0
  109. package/build/i18n/index.js.map +1 -0
  110. package/build/i18n/types.d.ts +153 -0
  111. package/build/i18n/types.d.ts.map +1 -0
  112. package/build/i18n/types.js +3 -0
  113. package/build/i18n/types.js.map +1 -0
  114. package/build/i18n/usage-example.d.ts +4 -0
  115. package/build/i18n/usage-example.d.ts.map +1 -0
  116. package/build/i18n/usage-example.js +189 -0
  117. package/build/i18n/usage-example.js.map +1 -0
  118. package/build/index.d.ts +1 -0
  119. package/build/index.d.ts.map +1 -1
  120. package/build/index.js +2 -0
  121. package/build/index.js.map +1 -1
  122. package/build/modules/api/CardAuthentification.d.ts +22 -0
  123. package/build/modules/api/CardAuthentification.d.ts.map +1 -0
  124. package/build/modules/api/CardAuthentification.js +107 -0
  125. package/build/modules/api/CardAuthentification.js.map +1 -0
  126. package/build/modules/api/KYCService.d.ts +58 -1
  127. package/build/modules/api/KYCService.d.ts.map +1 -1
  128. package/build/modules/api/KYCService.js +304 -27
  129. package/build/modules/api/KYCService.js.map +1 -1
  130. package/build/modules/api/SelfieVerification.d.ts +3 -0
  131. package/build/modules/api/SelfieVerification.d.ts.map +1 -0
  132. package/build/modules/api/SelfieVerification.js +9 -0
  133. package/build/modules/api/SelfieVerification.js.map +1 -0
  134. package/build/modules/api/backendApi.d.ts +2 -0
  135. package/build/modules/api/backendApi.d.ts.map +1 -0
  136. package/build/modules/api/backendApi.js +6 -0
  137. package/build/modules/api/backendApi.js.map +1 -0
  138. package/build/modules/api/types.d.ts +45 -0
  139. package/build/modules/api/types.d.ts.map +1 -0
  140. package/build/modules/api/types.js +2 -0
  141. package/build/modules/api/types.js.map +1 -0
  142. package/build/types/KYC.types.d.ts +56 -7
  143. package/build/types/KYC.types.d.ts.map +1 -1
  144. package/build/types/KYC.types.js +9 -1
  145. package/build/types/KYC.types.js.map +1 -1
  146. package/build/utils/cropByObb.d.ts +11 -0
  147. package/build/utils/cropByObb.d.ts.map +1 -0
  148. package/build/utils/cropByObb.js +78 -0
  149. package/build/utils/cropByObb.js.map +1 -0
  150. package/build/utils/get-document-type-info.d.ts +13 -0
  151. package/build/utils/get-document-type-info.d.ts.map +1 -0
  152. package/build/utils/get-document-type-info.js +59 -0
  153. package/build/utils/get-document-type-info.js.map +1 -0
  154. package/build/utils/pathToBase64.d.ts +3 -0
  155. package/build/utils/pathToBase64.d.ts.map +1 -0
  156. package/build/utils/pathToBase64.js +47 -0
  157. package/build/utils/pathToBase64.js.map +1 -0
  158. package/build/utils/remove-duplicate.d.ts +2 -0
  159. package/build/utils/remove-duplicate.d.ts.map +1 -0
  160. package/build/utils/remove-duplicate.js +4 -0
  161. package/build/utils/remove-duplicate.js.map +1 -0
  162. package/build/web/WebKYCEntry.d.ts +9 -0
  163. package/build/web/WebKYCEntry.d.ts.map +1 -0
  164. package/build/web/WebKYCEntry.js +156 -0
  165. package/build/web/WebKYCEntry.js.map +1 -0
  166. package/build/web/index.d.ts +2 -0
  167. package/build/web/index.d.ts.map +1 -0
  168. package/build/web/index.js +2 -0
  169. package/build/web/index.js.map +1 -0
  170. package/package.json +3 -1
  171. package/src/api/axios.ts +144 -0
  172. package/src/components/EnhancedCameraView.tsx +96 -78
  173. package/src/components/EnhancedCameraView.web.tsx +41 -40
  174. package/src/components/KYCElements/CountrySelectionTemplate.tsx +111 -136
  175. package/src/components/KYCElements/FileUploadTemplate.tsx +14 -8
  176. package/src/components/KYCElements/IDCardCapture.tsx +311 -115
  177. package/src/components/KYCElements/InitializationStep.tsx +53 -0
  178. package/src/components/KYCElements/LocationCaptureTemplate.tsx +17 -15
  179. package/src/components/KYCElements/OrientationVideoCapture.tsx +2 -2
  180. package/src/components/KYCElements/OrientationVideoCaptureEnhanced.tsx +2 -2
  181. package/src/components/KYCElements/OrientationVideoCaptureFinal.tsx +2 -2
  182. package/src/components/KYCElements/ReviewSubmitTemplate.tsx +201 -0
  183. package/src/components/KYCElements/SelfieCaptureTemplate.tsx +174 -57
  184. package/src/components/KYCElements/VerificationProgressTemplate.tsx +246 -0
  185. package/src/components/OverLay/IdCard.tsx +17 -9
  186. package/src/components/OverLay/SelfieOverlay.tsx +6 -5
  187. package/src/components/OverLay/type.ts +64 -2
  188. package/src/components/TemplateKYCExample.tsx +80 -200
  189. package/src/components/TemplateKYCFlowRefactored.tsx +80 -48
  190. package/src/components/example/OrientationVideoExample.tsx +3 -7
  191. package/src/config/countriesData.ts +84 -0
  192. package/src/config/region_mapping.ts +688 -0
  193. package/src/hooks/useI18n.ts +53 -0
  194. package/src/hooks/useOrientationVideo.ts +2 -2
  195. package/src/hooks/useRealtimeVerifier.ts +128 -0
  196. package/src/hooks/useTemplateKYCFlow.tsx +407 -57
  197. package/src/i18n/README.md +288 -0
  198. package/src/i18n/en/index.ts +206 -0
  199. package/src/i18n/fr/index.ts +205 -0
  200. package/src/i18n/index.ts +65 -0
  201. package/src/i18n/types.ts +172 -0
  202. package/src/i18n/usage-example.tsx +202 -0
  203. package/src/index.ts +3 -0
  204. package/src/modules/api/CardAuthentification.ts +114 -0
  205. package/src/modules/api/KYCService.ts +350 -30
  206. package/src/modules/api/SelfieVerification.ts +11 -0
  207. package/src/modules/api/backendApi.ts +8 -0
  208. package/src/modules/api/types.ts +51 -0
  209. package/src/types/KYC.types.ts +82 -14
  210. package/src/utils/cropByObb.ts +99 -0
  211. package/src/utils/get-document-type-info.ts +62 -0
  212. package/src/utils/pathToBase64.ts +47 -0
  213. package/src/utils/remove-duplicate.ts +3 -0
  214. package/src/web/WebKYCEntry.tsx +215 -0
  215. package/src/web/index.ts +1 -0
  216. package/src/types/nativewind.d.ts +0 -2
@@ -1,7 +1,9 @@
1
- import React, { useState, useCallback, useMemo, createContext, useContext } from 'react';
1
+ import React, { useState, useCallback, useMemo, createContext, useContext, useEffect } from 'react';
2
+ import kycService, { authentification, truncateFields } from '../modules/api/KYCService';
3
+ import useI18n from './useI18n';
2
4
  const TemplateKYCFlowContext = createContext(undefined);
3
- export const TemplateKYCFlowProvider = ({ children, template, onComplete, onError, initialLanguage = 'en', }) => {
4
- const hookResult = useTemplateKYCFlow(template, onComplete, onError, initialLanguage);
5
+ export const TemplateKYCFlowProvider = ({ children, template, onComplete, onError, onCancel, initialLanguage = 'en', apiKey, }) => {
6
+ const hookResult = useTemplateKYCFlow(template, onComplete, onError, onCancel, initialLanguage, apiKey);
5
7
  return (<TemplateKYCFlowContext.Provider value={hookResult}>
6
8
  {children}
7
9
  </TemplateKYCFlowContext.Provider>);
@@ -14,10 +16,62 @@ export const useTemplateKYCFlowContext = () => {
14
16
  }
15
17
  return context;
16
18
  };
17
- export const useTemplateKYCFlow = (template, onComplete, onError, initialLanguage = 'en') => {
19
+ export const useTemplateKYCFlow = (template, onComplete, onError, onCancel, initialLanguage = 'en', apiKey) => {
20
+ const { setLocale } = useI18n();
21
+ useEffect(() => {
22
+ setLocale(initialLanguage);
23
+ }, [initialLanguage]);
24
+ // Helpers to align SDK steps with backend actions/templates
25
+ const isUiOnlyStep = useCallback((type) => {
26
+ return type === 'verification_progress';
27
+ }, []);
28
+ const ensureReviewSubmitStep = useCallback((tpl) => {
29
+ const hasReview = tpl.components.some(c => c.type === 'review_submit');
30
+ if (hasReview)
31
+ return tpl;
32
+ const lastOrder = tpl.components.reduce((acc, c) => Math.max(acc, c.order ?? 0), 0);
33
+ const lastId = tpl.components.reduce((acc, c) => Math.max(acc, c.id), 0);
34
+ const reviewComponent = {
35
+ id: lastId + 1,
36
+ type: 'review_submit',
37
+ order: lastOrder + 1,
38
+ labels: { en: 'Review & Submit', fr: 'Revoir & Soumettre' },
39
+ instructions: { en: 'Confirm and submit', fr: 'Confirmer et soumettre' },
40
+ ui: { buttonText: { en: 'Complete Verification', fr: 'Terminer la vérification' } },
41
+ // @ts-ignore - config unused for review component
42
+ config: {},
43
+ };
44
+ return {
45
+ ...tpl,
46
+ components: [...tpl.components, reviewComponent],
47
+ };
48
+ }, []);
49
+ const ensureVerificationProgressStep = useCallback((tpl) => {
50
+ const hasVerification = tpl.components.some(c => c.type === 'verification_progress');
51
+ if (hasVerification)
52
+ return tpl;
53
+ const lastOrder = tpl.components.reduce((acc, c) => Math.max(acc, c.order ?? 0), 0);
54
+ const lastId = tpl.components.reduce((acc, c) => Math.max(acc, c.id), 0);
55
+ const verificationComponent = {
56
+ id: lastId + 2,
57
+ type: 'verification_progress',
58
+ order: lastOrder + 2,
59
+ labels: { en: 'Verification', fr: 'Vérification' },
60
+ instructions: { en: 'We\'re reviewing your documents', fr: 'Nous analysons vos documents' },
61
+ ui: { buttonText: { en: '', fr: '' } },
62
+ // @ts-ignore - config unused for progress component
63
+ config: {},
64
+ };
65
+ return {
66
+ ...tpl,
67
+ components: [...tpl.components, verificationComponent],
68
+ };
69
+ }, []);
70
+ const templateWithReview = useMemo(() => ensureReviewSubmitStep(template), [template, ensureReviewSubmitStep]);
71
+ const templateWithReviewAndVerification = useMemo(() => ensureVerificationProgressStep(templateWithReview), [templateWithReview, ensureVerificationProgressStep]);
18
72
  // État du flux
19
73
  const [state, setState] = useState({
20
- template,
74
+ template: templateWithReviewAndVerification,
21
75
  currentComponentIndex: 0,
22
76
  completedComponents: [],
23
77
  componentData: {},
@@ -25,35 +79,183 @@ export const useTemplateKYCFlow = (template, onComplete, onError, initialLanguag
25
79
  isProcessing: false,
26
80
  currentLanguage: initialLanguage,
27
81
  showCustomStepper: true,
82
+ session: {
83
+ session_id: '',
84
+ token: '',
85
+ isInitialized: false,
86
+ isProcessing: false,
87
+ error: null,
88
+ },
89
+ verification: {
90
+ status: 'idle',
91
+ },
28
92
  });
93
+ const mapComponentTypeToAction = useCallback((type) => {
94
+ switch (type) {
95
+ case 'id_card':
96
+ case 'file_upload':
97
+ return 'document_upload';
98
+ case 'selfie':
99
+ return 'selfie_capture';
100
+ case 'location':
101
+ return 'location_permission';
102
+ case 'review_submit':
103
+ return 'final_submit';
104
+ case 'country_selection':
105
+ // No direct backend action; pack into metadata of next actionable step
106
+ return null;
107
+ case 'initialization':
108
+ return 'initialize_session';
109
+ case 'verification_progress':
110
+ return null; // UI-only
111
+ default:
112
+ return null;
113
+ }
114
+ }, []);
115
+ const chooseTemplateId = useCallback((tpl) => {
116
+ const types = tpl.components.map(c => c.type);
117
+ const hasLocation = types.includes('location');
118
+ const hasSelfie = types.includes('selfie');
119
+ const hasIdDoc = types.includes('id_card') || types.includes('file_upload');
120
+ // Simple heuristic to map to backend examples
121
+ if (hasLocation && hasSelfie && hasIdDoc)
122
+ return 'enhanced_id';
123
+ if (hasSelfie && hasIdDoc)
124
+ return 'standard_passport';
125
+ return 'standard_passport';
126
+ }, []);
127
+ const computeServerStepIndex = useCallback((tpl, upToIndex) => {
128
+ // Count actionable steps before the current component (exclude UI-only and country_selection)
129
+ const actionable = tpl.components
130
+ .slice(0, upToIndex)
131
+ .filter(c => !isUiOnlyStep(c.type) && mapComponentTypeToAction(c.type) !== null);
132
+ return actionable.length; // 0-based
133
+ }, [isUiOnlyStep, mapComponentTypeToAction]);
134
+ // Build backend-friendly payloads per action
135
+ const buildPayloadForComponent = useCallback((action, component, rawData, templateId, step) => {
136
+ const base = { template_id: null, step: component.order, permissionGranted: true };
137
+ if (!action) {
138
+ return base;
139
+ }
140
+ // Document upload expects an array of documents with base64 and metadata
141
+ if (action === 'document_upload') {
142
+ const documents = {};
143
+ if (rawData && typeof rawData === 'object') {
144
+ Object.keys(rawData).forEach((key) => {
145
+ documents[key] = rawData[key];
146
+ });
147
+ }
148
+ return {
149
+ ...base,
150
+ documents,
151
+ };
152
+ }
153
+ if (action === 'selfie_capture') {
154
+ const documents = {};
155
+ if (rawData && typeof rawData === 'object') {
156
+ Object.keys(rawData).forEach((key) => {
157
+ documents[key] = rawData[key];
158
+ });
159
+ }
160
+ const idCardID = Object.keys(state.componentData).find((c) => c === "1");
161
+ if (idCardID) {
162
+ const _idCardData = state.componentData[idCardID];
163
+ return { ...base, documents, country: _idCardData?.country || '', documentType: _idCardData?.documentType || 'identity_card' };
164
+ }
165
+ // return { ...base, documents };
166
+ }
167
+ if (action === 'location_permission') {
168
+ return { ...base, ...({ metadata: rawData || {} }), ...({ permissionGranted: true, }) };
169
+ }
170
+ // Default: wrap as metadata
171
+ return { ...base, metadata: { ...(rawData || {}) } };
172
+ }, [state.componentData]);
173
+ // Ensure the template contains a final review step
29
174
  // Composant actuel
30
175
  const currentComponent = useMemo(() => {
31
- return template.components[state.currentComponentIndex] || null;
32
- }, [template.components, state.currentComponentIndex]);
176
+ return state.template.components[state.currentComponentIndex] || null;
177
+ }, [state.template.components, state.currentComponentIndex]);
33
178
  // Progression du flux
34
179
  const progress = useMemo(() => {
35
- return template.components.length > 0
36
- ? ((state.currentComponentIndex + 1) / template.components.length) * 100
180
+ return state.template.components.length > 0
181
+ ? ((state.currentComponentIndex + 1) / state.template.components.length) * 100
37
182
  : 0;
38
- }, [state.currentComponentIndex, template.components.length]);
183
+ }, [state.currentComponentIndex, state.template.components.length]);
39
184
  // Vérifications de navigation
40
185
  const canGoNext = useMemo(() => {
41
- return state.currentComponentIndex < template.components.length - 1;
42
- }, [state.currentComponentIndex, template.components.length]);
186
+ return state.currentComponentIndex < state.template.components.length - 1;
187
+ }, [state.currentComponentIndex, state.template.components.length]);
43
188
  const canGoPrevious = useMemo(() => {
44
189
  return state.currentComponentIndex > 0;
45
190
  }, [state.currentComponentIndex]);
46
191
  const isComplete = useMemo(() => {
47
- return state.currentComponentIndex === template.components.length - 1 &&
48
- state.completedComponents.length === template.components.length;
49
- }, [state.currentComponentIndex, state.completedComponents.length, template.components.length]);
192
+ const atReview = state.template.components[state.currentComponentIndex]?.type === 'review_submit';
193
+ const nonReviewCount = state.template.components.filter(c => c.type !== 'review_submit').length;
194
+ const completedNonReview = state.completedComponents.length >= nonReviewCount;
195
+ return atReview && completedNonReview;
196
+ }, [state.currentComponentIndex, state.completedComponents.length, state.template.components]);
50
197
  // Fonction pour obtenir le texte localisé
51
198
  const getLocalizedText = useCallback((text) => {
52
199
  return text[state.currentLanguage] || text.en || '';
53
200
  }, [state.currentLanguage]);
201
+ const initializeSession = useCallback(async () => {
202
+ try {
203
+ setState(prev => ({
204
+ ...prev,
205
+ session: {
206
+ ...prev.session,
207
+ isInitialized: false,
208
+ isProcessing: true,
209
+ error: null,
210
+ },
211
+ }));
212
+ console.log('Initializing session');
213
+ const token = await authentification();
214
+ const session = await kycService.newSession(token);
215
+ // Align backend flow from step 0 with initialize_session
216
+ try {
217
+ const templateId = chooseTemplateId(templateWithReviewAndVerification);
218
+ await kycService.verificationSession({
219
+ session_id: session.session_id,
220
+ step: 0,
221
+ data: { template_id: templateId, metadata: { language: initialLanguage } },
222
+ templateId: templateId,
223
+ token: token,
224
+ action: 'initialize_session'
225
+ });
226
+ }
227
+ catch (e) {
228
+ console.error('Error initializing session:', JSON.stringify(e, null, 2));
229
+ // Non-fatal: we will surface errors via state below if needed
230
+ }
231
+ setState(prev => ({
232
+ ...prev,
233
+ session: {
234
+ ...prev.session,
235
+ session_id: session.session_id,
236
+ token: token,
237
+ isInitialized: true,
238
+ isProcessing: false,
239
+ error: null,
240
+ }
241
+ }));
242
+ }
243
+ catch (error) {
244
+ console.error('Error initializing session:', JSON.stringify(error, null, 2));
245
+ setState(prev => ({
246
+ ...prev,
247
+ session: {
248
+ ...prev.session,
249
+ isInitialized: false,
250
+ isProcessing: false,
251
+ error: "Erreur lors de l'initialisation de la session",
252
+ },
253
+ }));
254
+ }
255
+ }, []);
54
256
  // Validation d'un composant
55
257
  const validateComponent = useCallback((componentId) => {
56
- const component = template.components.find(c => c.id === componentId);
258
+ const component = state.template.components.find(c => c.id === componentId);
57
259
  if (!component)
58
260
  return false;
59
261
  const componentData = state.componentData[componentId];
@@ -74,54 +276,144 @@ export const useTemplateKYCFlow = (template, onComplete, onError, initialLanguag
74
276
  return componentData && componentData.latitude && componentData.longitude;
75
277
  case 'country_selection':
76
278
  // Vérifier si un pays a été sélectionné
77
- return componentData && componentData.country;
279
+ console.log("componentData", truncateFields(componentData), componentId);
280
+ return componentData && componentData.code && componentData.regionMapping;
281
+ case 'review_submit':
282
+ return true;
78
283
  default:
79
284
  return false;
80
285
  }
81
- }, [template.components, state.componentData]);
286
+ }, [state.template.components, state.componentData]);
82
287
  // Actions du flux
83
288
  const actions = {
84
289
  // Initialiser le template
85
290
  initializeTemplate: useCallback((newTemplate) => {
291
+ const withReview = ensureReviewSubmitStep(newTemplate);
292
+ const withVerification = ensureVerificationProgressStep(withReview);
86
293
  setState(prev => ({
87
294
  ...prev,
88
- template: newTemplate,
295
+ template: withVerification,
89
296
  currentComponentIndex: 0,
90
297
  completedComponents: [],
91
298
  componentData: {},
92
299
  errors: {},
93
300
  isProcessing: false,
301
+ verification: { status: 'idle', result: undefined },
94
302
  }));
95
- }, []),
303
+ }, [ensureReviewSubmitStep, ensureVerificationProgressStep]),
96
304
  // Passer au composant suivant
97
- nextComponent: useCallback(() => {
305
+ nextComponent: useCallback(async () => {
98
306
  if (!canGoNext)
99
307
  return;
100
- const currentComp = template.components[state.currentComponentIndex];
308
+ const currentComp = state.template.components[state.currentComponentIndex];
101
309
  if (!currentComp)
102
310
  return;
311
+ setState(prev => ({
312
+ ...prev,
313
+ isProcessing: true,
314
+ }));
103
315
  // Valider le composant actuel
104
316
  if (!validateComponent(currentComp.id)) {
105
317
  setState(prev => ({
106
318
  ...prev,
319
+ isProcessing: false,
107
320
  errors: {
108
321
  ...prev.errors,
109
- [currentComp.id]: 'Veuillez compléter cette étape avant de continuer'
322
+ [currentComp.id]: state.currentLanguage === "en" ? "please complete this step before move on" : " 'Veuillez compléter cette étape avant de continuer'"
110
323
  }
111
324
  }));
112
325
  return;
113
326
  }
114
- // Marquer comme complété et passer au suivant
115
- setState(prev => ({
116
- ...prev,
117
- currentComponentIndex: prev.currentComponentIndex + 1,
118
- completedComponents: [...prev.completedComponents, currentComp.id],
119
- errors: {
120
- ...prev.errors,
121
- [currentComp.id]: ''
327
+ try {
328
+ const component = state.template.components.find(c => c.id === currentComp.id);
329
+ if (!component)
330
+ return;
331
+ if (component.type === 'review_submit') {
332
+ // Move to verification screen and mark verification in progress
333
+ setState(prev => ({
334
+ ...prev,
335
+ currentComponentIndex: prev.currentComponentIndex + 1,
336
+ completedComponents: [...prev.completedComponents, currentComp.id],
337
+ isProcessing: false,
338
+ verification: { status: 'in_progress' },
339
+ errors: {
340
+ ...prev.errors,
341
+ [currentComp.id]: ''
342
+ }
343
+ }));
344
+ return;
122
345
  }
123
- }));
124
- }, [canGoNext, state.currentComponentIndex, template.components, validateComponent]),
346
+ // Determine backend action and step index
347
+ const action = mapComponentTypeToAction(component.type);
348
+ const templateId = chooseTemplateId(state.template);
349
+ const serverStep = computeServerStepIndex(state.template, state.currentComponentIndex);
350
+ // Optionally send initialize_session at step 0 before first actionable action
351
+ if (serverStep === 0) {
352
+ try {
353
+ // await kycService.verificationSession({
354
+ // sessionId: state.session.session_id,
355
+ // step: 0,
356
+ // data: { template_id: templateId, metadata: { language: state.currentLanguage } },
357
+ // templateId: templateId,
358
+ // token: state.session.token,
359
+ // action: 'initialize_session'
360
+ // });
361
+ }
362
+ catch (e) {
363
+ // if init fails, surface error below in the main call handling
364
+ }
365
+ }
366
+ // Skip UI-only and data-only steps that have no backend action
367
+ if (!action) {
368
+ setState(prev => ({
369
+ ...prev,
370
+ currentComponentIndex: prev.currentComponentIndex + 1,
371
+ completedComponents: [...prev.completedComponents, currentComp.id],
372
+ isProcessing: false,
373
+ errors: {
374
+ ...prev.errors,
375
+ [currentComp.id]: ''
376
+ }
377
+ }));
378
+ return;
379
+ }
380
+ const step = serverStep === 0 && action !== 'initialize_session' ? 1 : serverStep;
381
+ // Build payload data per action
382
+ const payloadData = buildPayloadForComponent(action, component, state.componentData[currentComp.id], templateId, step);
383
+ await kycService.verificationSession({
384
+ session_id: state.session.session_id,
385
+ step: step,
386
+ data: payloadData,
387
+ templateId: null,
388
+ token: state.session.token,
389
+ action: action
390
+ });
391
+ console.log("currentComp state", truncateFields(state));
392
+ // Marquer comme complété et passer au suivant
393
+ setState(prev => ({
394
+ ...prev,
395
+ currentComponentIndex: prev.currentComponentIndex + 1,
396
+ completedComponents: [...prev.completedComponents, currentComp.id],
397
+ isProcessing: false,
398
+ ...(action === "location_permission" ? { permissionGranted: true } : {}),
399
+ errors: {
400
+ ...prev.errors,
401
+ [currentComp.id]: ''
402
+ }
403
+ }));
404
+ }
405
+ catch (error) {
406
+ // console.error('Error validating component:', error);
407
+ setState(prev => ({
408
+ ...prev,
409
+ isProcessing: false,
410
+ errors: {
411
+ ...prev.errors,
412
+ [currentComp.id]: 'Erreur lors de la validation du composant'
413
+ }
414
+ }));
415
+ }
416
+ }, [canGoNext, state.currentComponentIndex, state.template.components, validateComponent]),
125
417
  // Retourner au composant précédent
126
418
  previousComponent: useCallback(() => {
127
419
  if (!canGoPrevious)
@@ -133,16 +425,17 @@ export const useTemplateKYCFlow = (template, onComplete, onError, initialLanguag
133
425
  }, [canGoPrevious]),
134
426
  // Aller à un composant spécifique
135
427
  goToComponent: useCallback((componentId) => {
136
- const componentIndex = template.components.findIndex(c => c.id === componentId);
428
+ const componentIndex = state.template.components.findIndex(c => c.id === componentId);
137
429
  if (componentIndex !== -1) {
138
430
  setState(prev => ({
139
431
  ...prev,
140
432
  currentComponentIndex: componentIndex,
141
433
  }));
142
434
  }
143
- }, [template.components]),
435
+ }, [state.template.components]),
144
436
  // Mettre à jour les données d'un composant
145
437
  updateComponentData: useCallback((componentId, data) => {
438
+ console.log("updateComponentData", componentId, truncateFields(data));
146
439
  setState(prev => ({
147
440
  ...prev,
148
441
  componentData: {
@@ -159,28 +452,41 @@ export const useTemplateKYCFlow = (template, onComplete, onError, initialLanguag
159
452
  validateComponent: useCallback((componentId) => {
160
453
  return validateComponent(componentId);
161
454
  }, [validateComponent]),
455
+ // complet verification
456
+ submitVerification: useCallback(async () => {
457
+ setState(prev => ({ ...prev, isProcessing: true }));
458
+ try {
459
+ onComplete?.(state.verification);
460
+ }
461
+ catch (error) {
462
+ setState(prev => ({ ...prev, isProcessing: false }));
463
+ }
464
+ }, [state.session.session_id, state.verification, onComplete]),
162
465
  // Soumettre le template complet
163
466
  submitTemplate: useCallback(async () => {
164
- if (!isComplete) {
467
+ // Allow submission when on the review step and all previous steps are valid
468
+ const atReview = state.template.components[state.currentComponentIndex]?.type === 'review_submit';
469
+ const allValid = state.template.components
470
+ .filter(c => c.type !== 'review_submit')
471
+ .every(comp => validateComponent(comp.id));
472
+ if (!(atReview && allValid)) {
165
473
  onError?.('Le flux KYC n\'est pas encore terminé');
166
474
  return;
167
475
  }
168
476
  setState(prev => ({ ...prev, isProcessing: true }));
169
477
  try {
170
- // Vérifier que tous les composants sont validés
171
- const allValid = template.components.every(comp => validateComponent(comp.id));
172
- if (!allValid) {
478
+ // Vérifier que tous les composants (hors review) sont validés
479
+ if (!allValid)
173
480
  throw new Error('Certaines étapes ne sont pas complètes');
174
- }
175
481
  // Appeler le callback de completion
176
- onComplete?.(state.componentData);
482
+ // onComplete?.(state.componentData);
177
483
  setState(prev => ({ ...prev, isProcessing: false }));
178
484
  }
179
485
  catch (error) {
180
486
  setState(prev => ({ ...prev, isProcessing: false }));
181
487
  onError?.(error instanceof Error ? error.message : 'Erreur lors de la soumission');
182
488
  }
183
- }, [isComplete, template.components, validateComponent, state.componentData, onComplete, onError]),
489
+ }, [state.template.components, state.verification, state.currentComponentIndex, validateComponent, state.componentData, onComplete, onError]),
184
490
  // Réinitialiser le template
185
491
  resetTemplate: useCallback(() => {
186
492
  setState(prev => ({
@@ -190,6 +496,7 @@ export const useTemplateKYCFlow = (template, onComplete, onError, initialLanguag
190
496
  componentData: {},
191
497
  errors: {},
192
498
  isProcessing: false,
499
+ verification: { status: 'idle', result: undefined },
193
500
  }));
194
501
  }, []),
195
502
  // Changer la langue
@@ -206,6 +513,12 @@ export const useTemplateKYCFlow = (template, onComplete, onError, initialLanguag
206
513
  showCustomStepper: show,
207
514
  }));
208
515
  }, []),
516
+ setVerificationState: useCallback((verificationState) => {
517
+ setState(prev => ({
518
+ ...prev,
519
+ verification: verificationState,
520
+ }));
521
+ }, []),
209
522
  };
210
523
  return {
211
524
  state,
@@ -216,6 +529,7 @@ export const useTemplateKYCFlow = (template, onComplete, onError, initialLanguag
216
529
  canGoPrevious,
217
530
  isComplete,
218
531
  getLocalizedText,
532
+ initializeSession,
219
533
  };
220
534
  };
221
535
  //# sourceMappingURL=useTemplateKYCFlow.js.map