datakeen-session-react 1.1.140-dev.76 → 1.1.140-dev.78

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 (61) hide show
  1. package/dist/cjs/components/document-collection/DocumentCollection.js +1 -1
  2. package/dist/cjs/components/document-collection/DocumentCollection.js.map +1 -1
  3. package/dist/cjs/components/document-collection/DocumentCollectionUpload.js +9 -1
  4. package/dist/cjs/components/document-collection/DocumentCollectionUpload.js.map +1 -1
  5. package/dist/cjs/components/jdi/JDIDocumentUpload.js +1 -1
  6. package/dist/cjs/components/jdi/JDIDocumentUpload.js.map +1 -1
  7. package/dist/cjs/components/nfc-scan/NfcScanNode.js +89 -0
  8. package/dist/cjs/components/nfc-scan/NfcScanNode.js.map +1 -0
  9. package/dist/cjs/components/nfc-scan/NfcSuccessAnimation.js +40 -0
  10. package/dist/cjs/components/nfc-scan/NfcSuccessAnimation.js.map +1 -0
  11. package/dist/cjs/components/session/DocumentCheck.js +100 -35
  12. package/dist/cjs/components/session/DocumentCheck.js.map +1 -1
  13. package/dist/cjs/components/template/TemplateNodeRenderer.js +1 -1
  14. package/dist/cjs/components/template/TemplateNodeRenderer.js.map +1 -1
  15. package/dist/cjs/hooks/useNfcSseStatus.js +46 -0
  16. package/dist/cjs/hooks/useNfcSseStatus.js.map +1 -0
  17. package/dist/cjs/hooks/useUserInputForm.js +6 -1
  18. package/dist/cjs/hooks/useUserInputForm.js.map +1 -1
  19. package/dist/cjs/i18n/en.json.js +10 -1
  20. package/dist/cjs/i18n/en.json.js.map +1 -1
  21. package/dist/cjs/i18n/fr.json.js +10 -1
  22. package/dist/cjs/i18n/fr.json.js.map +1 -1
  23. package/dist/cjs/index.css.js +1 -1
  24. package/dist/cjs/services/analysis.js +1 -5
  25. package/dist/cjs/services/analysis.js.map +1 -1
  26. package/dist/cjs/services/api.js +1 -0
  27. package/dist/cjs/services/api.js.map +1 -1
  28. package/dist/cjs/services/auditTrailService.js +73 -0
  29. package/dist/cjs/services/auditTrailService.js.map +1 -1
  30. package/dist/cjs/types/session.js.map +1 -1
  31. package/dist/esm/components/document-collection/DocumentCollection.js +1 -1
  32. package/dist/esm/components/document-collection/DocumentCollection.js.map +1 -1
  33. package/dist/esm/components/document-collection/DocumentCollectionUpload.js +9 -1
  34. package/dist/esm/components/document-collection/DocumentCollectionUpload.js.map +1 -1
  35. package/dist/esm/components/jdi/JDIDocumentUpload.js +1 -1
  36. package/dist/esm/components/jdi/JDIDocumentUpload.js.map +1 -1
  37. package/dist/esm/components/nfc-scan/NfcScanNode.js +85 -0
  38. package/dist/esm/components/nfc-scan/NfcScanNode.js.map +1 -0
  39. package/dist/esm/components/nfc-scan/NfcSuccessAnimation.js +36 -0
  40. package/dist/esm/components/nfc-scan/NfcSuccessAnimation.js.map +1 -0
  41. package/dist/esm/components/session/DocumentCheck.js +100 -35
  42. package/dist/esm/components/session/DocumentCheck.js.map +1 -1
  43. package/dist/esm/components/template/TemplateNodeRenderer.js +1 -1
  44. package/dist/esm/components/template/TemplateNodeRenderer.js.map +1 -1
  45. package/dist/esm/hooks/useNfcSseStatus.js +44 -0
  46. package/dist/esm/hooks/useNfcSseStatus.js.map +1 -0
  47. package/dist/esm/hooks/useUserInputForm.js +6 -1
  48. package/dist/esm/hooks/useUserInputForm.js.map +1 -1
  49. package/dist/esm/i18n/en.json.js +10 -2
  50. package/dist/esm/i18n/en.json.js.map +1 -1
  51. package/dist/esm/i18n/fr.json.js +10 -2
  52. package/dist/esm/i18n/fr.json.js.map +1 -1
  53. package/dist/esm/index.css.js +1 -1
  54. package/dist/esm/services/analysis.js +1 -5
  55. package/dist/esm/services/analysis.js.map +1 -1
  56. package/dist/esm/services/api.js +1 -1
  57. package/dist/esm/services/api.js.map +1 -1
  58. package/dist/esm/services/auditTrailService.js +67 -1
  59. package/dist/esm/services/auditTrailService.js.map +1 -1
  60. package/dist/esm/types/session.js.map +1 -1
  61. package/package.json +1 -1
@@ -0,0 +1,85 @@
1
+ import { __awaiter, __generator } from '../../node_modules/tslib/tslib.es6.js';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import { useRef, useState, useMemo, useEffect } from 'react';
4
+ import QRCode from 'qrcode';
5
+ import { useI18n } from '../../hooks/useI18n.js';
6
+ import { useNfcSseStatus } from '../../hooks/useNfcSseStatus.js';
7
+ import { getBaseURL } from '../../services/api.js';
8
+ import MobilePageLayout from '../ui/MobilePageLayout.js';
9
+ import Title from '../ui/Title.js';
10
+ import Subtitle from '../ui/Subtitle.js';
11
+ import NfcSuccessAnimation from './NfcSuccessAnimation.js';
12
+
13
+ var NfcScanStep = function (_a) {
14
+ var sessionId = _a.sessionId, nodeId = _a.nodeId, stepObject = _a.stepObject, template = _a.template, pageTitle = _a.pageTitle, pageDescription = _a.pageDescription;
15
+ var t = useI18n().t;
16
+ var canvasRef = useRef(null);
17
+ var _b = useState(null), qrError = _b[0], setQrError = _b[1];
18
+ var nfcUrl = useMemo(function () {
19
+ var origin = typeof window !== "undefined" ? window.location.origin : "";
20
+ return "".concat(origin, "/scan/").concat(sessionId);
21
+ }, [sessionId]);
22
+ var apiBaseUrl = useMemo(function () { return getBaseURL(); }, []);
23
+ var status = useNfcSseStatus({
24
+ sessionId: sessionId,
25
+ apiBaseUrl: apiBaseUrl,
26
+ onCompleted: function () {
27
+ if (template) {
28
+ stepObject.goToNextStep(nodeId, template);
29
+ }
30
+ else {
31
+ stepObject.setStep(stepObject.step + 1);
32
+ }
33
+ },
34
+ }).status;
35
+ var title = pageTitle || t("nfc_scan.page_title", "Scan NFC de votre document");
36
+ var subtitle = pageDescription ||
37
+ t("nfc_scan.page_description", "Scannez le QR code ci-dessous avec votre iPhone pour lire la puce NFC de votre document d'identité.");
38
+ useEffect(function () {
39
+ if (status !== "pending")
40
+ return;
41
+ var generate = function () { return __awaiter(void 0, void 0, void 0, function () {
42
+ var dataUrl, canvas_1, ctx_1, img_1;
43
+ return __generator(this, function (_b) {
44
+ switch (_b.label) {
45
+ case 0:
46
+ if (!canvasRef.current)
47
+ return [2 /*return*/];
48
+ setQrError(null);
49
+ _b.label = 1;
50
+ case 1:
51
+ _b.trys.push([1, 3, , 4]);
52
+ return [4 /*yield*/, QRCode.toDataURL(nfcUrl, {
53
+ width: 256,
54
+ margin: 2,
55
+ color: { dark: "#000000", light: "#FFFFFF" },
56
+ })];
57
+ case 2:
58
+ dataUrl = _b.sent();
59
+ canvas_1 = canvasRef.current;
60
+ ctx_1 = canvas_1.getContext("2d");
61
+ if (ctx_1) {
62
+ img_1 = new Image();
63
+ img_1.onload = function () {
64
+ canvas_1.width = img_1.width;
65
+ canvas_1.height = img_1.height;
66
+ ctx_1.drawImage(img_1, 0, 0);
67
+ };
68
+ img_1.src = dataUrl;
69
+ }
70
+ return [3 /*break*/, 4];
71
+ case 3:
72
+ _b.sent();
73
+ setQrError(t("qr_code.generation_failed", "Erreur de génération du QR code"));
74
+ return [3 /*break*/, 4];
75
+ case 4: return [2 /*return*/];
76
+ }
77
+ });
78
+ }); };
79
+ generate();
80
+ }, [nfcUrl, status, t]);
81
+ return (jsx(MobilePageLayout, { footer: null, children: jsx("div", { className: "px-4 py-6 pt-11 md:px-8 md:py-8", children: jsxs("div", { className: "w-full max-w-md mx-auto space-y-6", children: [jsxs("div", { className: "text-center space-y-4 mt-16 md:mt-20", children: [jsx(Title, { className: "text-xl md:text-2xl lg:text-3xl", children: title }), jsx(Subtitle, { className: "text-sm md:text-base text-gray-600 leading-relaxed whitespace-pre-line", children: subtitle })] }), jsx("div", { className: "flex-1 flex justify-center items-center", children: status === "success" ? (jsx(NfcSuccessAnimation, {})) : status === "completed" ? (jsxs("div", { className: "flex flex-col items-center gap-4 p-8", children: [jsx("div", { className: "animate-spin w-10 h-10 border-2 border-gray-300 border-t-blue-500 rounded-full" }), jsx("p", { className: "text-sm text-gray-600", children: t("nfc_scan.verifying", "Vérification en cours…") })] })) : status === "opened" ? (jsxs("div", { className: "w-full max-w-sm rounded-2xl border border-emerald-200 bg-emerald-50 p-6 text-center shadow-sm", children: [jsx("div", { className: "mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-full bg-emerald-500 text-white shadow-md shadow-emerald-200", children: jsx("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", className: "h-7 w-7", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("path", { d: "M20 6 9 17l-5-5" }) }) }), jsx("p", { className: "text-base font-semibold text-gray-900", children: t("nfc_scan.qr_opened_title", "QR code scanné") }), jsx("p", { className: "mt-2 text-sm leading-relaxed text-gray-600", children: t("nfc_scan.qr_opened_description", "L'expérience NFC est ouverte sur l'iPhone. Continuez le scan sur le téléphone.") }), jsxs("div", { className: "mt-5 flex items-center justify-center gap-2 text-xs font-medium text-emerald-700", children: [jsx("span", { className: "h-2 w-2 animate-pulse rounded-full bg-emerald-500" }), t("nfc_scan.waiting_completion", "En attente de la lecture NFC")] })] })) : qrError ? (jsx("div", { className: "text-red-500 text-center p-4", children: qrError })) : (jsx("div", { className: "bg-white p-4 rounded-lg shadow-lg border-2 border-gray-200", children: jsx("canvas", { ref: canvasRef }) })) })] }) }) }));
82
+ };
83
+
84
+ export { NfcScanStep as default };
85
+ //# sourceMappingURL=NfcScanNode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NfcScanNode.js","sources":["../../../../../src/components/nfc-scan/NfcScanNode.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport QRCode from \"qrcode\";\nimport type { SessionTemplate, stepObject } from \"../../types/session\";\nimport { useI18n } from \"../../hooks/useI18n\";\nimport { useNfcSseStatus } from \"../../hooks/useNfcSseStatus\";\nimport { getBaseURL } from \"../../services/api\";\nimport MobilePageLayout from \"../ui/MobilePageLayout\";\nimport Title from \"../ui/Title\";\nimport Subtitle from \"../ui/Subtitle\";\nimport NfcSuccessAnimation from \"./NfcSuccessAnimation\";\n\ninterface NfcScanStepProps {\n sessionId: string;\n nodeId: string;\n stepObject: stepObject;\n template?: SessionTemplate;\n pageTitle?: string;\n pageDescription?: string;\n}\n\nconst NfcScanStep: React.FC<NfcScanStepProps> = ({\n sessionId,\n nodeId,\n stepObject,\n template,\n pageTitle,\n pageDescription,\n}) => {\n const { t } = useI18n();\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const [qrError, setQrError] = useState<string | null>(null);\n\n const nfcUrl = useMemo(() => {\n const origin = typeof window !== \"undefined\" ? window.location.origin : \"\";\n return `${origin}/scan/${sessionId}`;\n }, [sessionId]);\n\n const apiBaseUrl = useMemo(() => getBaseURL(), []);\n\n const { status } = useNfcSseStatus({\n sessionId,\n apiBaseUrl,\n onCompleted: () => {\n if (template) {\n stepObject.goToNextStep(nodeId, template);\n } else {\n stepObject.setStep(stepObject.step + 1);\n }\n },\n });\n\n const title =\n pageTitle || t(\"nfc_scan.page_title\", \"Scan NFC de votre document\");\n const subtitle =\n pageDescription ||\n t(\n \"nfc_scan.page_description\",\n \"Scannez le QR code ci-dessous avec votre iPhone pour lire la puce NFC de votre document d'identité.\"\n );\n\n useEffect(() => {\n if (status !== \"pending\") return;\n\n const generate = async () => {\n if (!canvasRef.current) return;\n setQrError(null);\n\n try {\n const dataUrl = await QRCode.toDataURL(nfcUrl, {\n width: 256,\n margin: 2,\n color: { dark: \"#000000\", light: \"#FFFFFF\" },\n });\n const canvas = canvasRef.current;\n const ctx = canvas.getContext(\"2d\");\n if (ctx) {\n const img = new Image();\n img.onload = () => {\n canvas.width = img.width;\n canvas.height = img.height;\n ctx.drawImage(img, 0, 0);\n };\n img.src = dataUrl;\n }\n } catch {\n setQrError(t(\"qr_code.generation_failed\", \"Erreur de génération du QR code\"));\n }\n };\n\n generate();\n }, [nfcUrl, status, t]);\n\n return (\n <MobilePageLayout footer={null}>\n <div className=\"px-4 py-6 pt-11 md:px-8 md:py-8\">\n <div className=\"w-full max-w-md mx-auto space-y-6\">\n <div className=\"text-center space-y-4 mt-16 md:mt-20\">\n <Title className=\"text-xl md:text-2xl lg:text-3xl\">{title}</Title>\n <Subtitle className=\"text-sm md:text-base text-gray-600 leading-relaxed whitespace-pre-line\">\n {subtitle}\n </Subtitle>\n </div>\n\n <div className=\"flex-1 flex justify-center items-center\">\n {status === \"success\" ? (\n <NfcSuccessAnimation />\n ) : status === \"completed\" ? (\n <div className=\"flex flex-col items-center gap-4 p-8\">\n <div className=\"animate-spin w-10 h-10 border-2 border-gray-300 border-t-blue-500 rounded-full\" />\n <p className=\"text-sm text-gray-600\">\n {t(\"nfc_scan.verifying\", \"Vérification en cours…\")}\n </p>\n </div>\n ) : status === \"opened\" ? (\n <div className=\"w-full max-w-sm rounded-2xl border border-emerald-200 bg-emerald-50 p-6 text-center shadow-sm\">\n <div className=\"mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-full bg-emerald-500 text-white shadow-md shadow-emerald-200\">\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n className=\"h-7 w-7\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n </div>\n <p className=\"text-base font-semibold text-gray-900\">\n {t(\"nfc_scan.qr_opened_title\", \"QR code scanné\")}\n </p>\n <p className=\"mt-2 text-sm leading-relaxed text-gray-600\">\n {t(\n \"nfc_scan.qr_opened_description\",\n \"L'expérience NFC est ouverte sur l'iPhone. Continuez le scan sur le téléphone.\"\n )}\n </p>\n <div className=\"mt-5 flex items-center justify-center gap-2 text-xs font-medium text-emerald-700\">\n <span className=\"h-2 w-2 animate-pulse rounded-full bg-emerald-500\" />\n {t(\"nfc_scan.waiting_completion\", \"En attente de la lecture NFC\")}\n </div>\n </div>\n ) : qrError ? (\n <div className=\"text-red-500 text-center p-4\">{qrError}</div>\n ) : (\n <div className=\"bg-white p-4 rounded-lg shadow-lg border-2 border-gray-200\">\n <canvas ref={canvasRef} />\n </div>\n )}\n </div>\n </div>\n </div>\n </MobilePageLayout>\n );\n};\n\nexport default NfcScanStep;\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { useState, useEffect } from 'react';
3
+ import { useI18n } from '../../hooks/useI18n.js';
4
+
5
+ var NfcSuccessAnimation = function () {
6
+ var t = useI18n().t;
7
+ var _a = useState(false), visible = _a[0], setVisible = _a[1];
8
+ useEffect(function () {
9
+ // Déclenche l'animation au prochain frame pour permettre la transition CSS
10
+ var id = requestAnimationFrame(function () { return setVisible(true); });
11
+ return function () { return cancelAnimationFrame(id); };
12
+ }, []);
13
+ return (jsxs("div", { className: "flex flex-col items-center gap-6 p-8", style: {
14
+ opacity: visible ? 1 : 0,
15
+ transform: visible ? "scale(1)" : "scale(0.85)",
16
+ transition: "opacity 0.4s ease, transform 0.4s ease",
17
+ }, children: [jsxs("div", { style: { position: "relative", width: 72, height: 72, flexShrink: 0 }, children: [jsx("div", { style: {
18
+ position: "absolute",
19
+ inset: 0,
20
+ borderRadius: "50%",
21
+ backgroundColor: "var(--uni-primary-color, #11e5c5)",
22
+ transformOrigin: "center center",
23
+ animation: "nfc-pulse 1.6s ease-out infinite",
24
+ pointerEvents: "none",
25
+ } }), jsxs("svg", { width: 72, height: 72, viewBox: "0 0 72 72", fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [jsx("circle", { cx: 36, cy: 36, r: 34, fill: "var(--uni-primary-color, #11e5c5)", style: {
26
+ opacity: visible ? 1 : 0,
27
+ transition: "opacity 0.3s ease 0.1s",
28
+ } }), jsx("polyline", { points: "20,37 30,47 52,25", stroke: "#ffffff", strokeWidth: 5, strokeLinecap: "round", strokeLinejoin: "round", fill: "none", style: {
29
+ strokeDasharray: 50,
30
+ strokeDashoffset: visible ? 0 : 50,
31
+ transition: "stroke-dashoffset 0.45s cubic-bezier(0.4, 0, 0.2, 1) 0.35s",
32
+ } })] })] }), jsxs("div", { className: "text-center space-y-1", children: [jsx("p", { className: "font-semibold text-base", style: { color: "var(--uni-secondary-color, #0a9983)" }, children: t("nfc_scan.success_title", "Documents validés") }), jsx("p", { className: "text-sm text-gray-500", children: t("nfc_scan.success_subtitle", "Lecture NFC confirmée avec succès") })] }), jsx("style", { children: "\n @keyframes nfc-pulse {\n 0% { transform: scale(1); opacity: 0.25; }\n 70% { transform: scale(1.65); opacity: 0.05; }\n 100% { transform: scale(1.65); opacity: 0; }\n }\n " })] }));
33
+ };
34
+
35
+ export { NfcSuccessAnimation as default };
36
+ //# sourceMappingURL=NfcSuccessAnimation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NfcSuccessAnimation.js","sources":["../../../../../src/components/nfc-scan/NfcSuccessAnimation.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport { useI18n } from \"../../hooks/useI18n\";\n\nconst NfcSuccessAnimation: React.FC = () => {\n const { t } = useI18n();\n const [visible, setVisible] = useState(false);\n\n useEffect(() => {\n // Déclenche l'animation au prochain frame pour permettre la transition CSS\n const id = requestAnimationFrame(() => setVisible(true));\n return () => cancelAnimationFrame(id);\n }, []);\n\n return (\n <div\n className=\"flex flex-col items-center gap-6 p-8\"\n style={{\n opacity: visible ? 1 : 0,\n transform: visible ? \"scale(1)\" : \"scale(0.85)\",\n transition: \"opacity 0.4s ease, transform 0.4s ease\",\n }}\n >\n <div style={{ position: \"relative\", width: 72, height: 72, flexShrink: 0 }}>\n {/* Halo pulsant en arrière-plan */}\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n borderRadius: \"50%\",\n backgroundColor: \"var(--uni-primary-color, #11e5c5)\",\n transformOrigin: \"center center\",\n animation: \"nfc-pulse 1.6s ease-out infinite\",\n pointerEvents: \"none\",\n }}\n />\n\n {/* Cercle + check SVG animé */}\n <svg\n width={72}\n height={72}\n viewBox=\"0 0 72 72\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n {/* Cercle de fond rempli */}\n <circle\n cx={36}\n cy={36}\n r={34}\n fill=\"var(--uni-primary-color, #11e5c5)\"\n style={{\n opacity: visible ? 1 : 0,\n transition: \"opacity 0.3s ease 0.1s\",\n }}\n />\n {/* Trait du check — strokeDashoffset animé */}\n <polyline\n points=\"20,37 30,47 52,25\"\n stroke=\"#ffffff\"\n strokeWidth={5}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n fill=\"none\"\n style={{\n strokeDasharray: 50,\n strokeDashoffset: visible ? 0 : 50,\n transition: \"stroke-dashoffset 0.45s cubic-bezier(0.4, 0, 0.2, 1) 0.35s\",\n }}\n />\n </svg>\n </div>\n\n <div className=\"text-center space-y-1\">\n <p\n className=\"font-semibold text-base\"\n style={{ color: \"var(--uni-secondary-color, #0a9983)\" }}\n >\n {t(\"nfc_scan.success_title\", \"Documents validés\")}\n </p>\n <p className=\"text-sm text-gray-500\">\n {t(\"nfc_scan.success_subtitle\", \"Lecture NFC confirmée avec succès\")}\n </p>\n </div>\n\n <style>{`\n @keyframes nfc-pulse {\n 0% { transform: scale(1); opacity: 0.25; }\n 70% { transform: scale(1.65); opacity: 0.05; }\n 100% { transform: scale(1.65); opacity: 0; }\n }\n `}</style>\n </div>\n );\n};\n\nexport default NfcSuccessAnimation;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
@@ -16,6 +16,7 @@ import DocumentVideoCapture from '../document-video/DocumentVideoCapture.js';
16
16
  import { Camera, Upload } from 'lucide-react';
17
17
  import { useDocumentContext } from '../../context/DocumentContext.js';
18
18
  import { useI18n } from '../../hooks/useI18n.js';
19
+ import { logCaptureModeSelected, logPhotosValidated, logPhotoCaptured, logDocumentLoaded, logDocumentsValidated, logDocumentTypeSelected } from '../../services/auditTrailService.js';
19
20
  import ButtonDesktop from '../ui/ButtonDesktop.js';
20
21
  import Title from '../ui/Title.js';
21
22
  import Subtitle from '../ui/Subtitle.js';
@@ -25,8 +26,15 @@ import { getAllDocumentTemplates, getDocumentTemplateId, getDocTypeKey } from '.
25
26
  import { blobToDataUrl, dataUrlToBlob, resizeAfterCapture } from '../../utils/imageProcessing.js';
26
27
  import { getNodeRetryCount, incrementNodeRetryCount } from '../../services/retryService.js';
27
28
  import { getSession } from '../../context/SessionContext.js';
29
+ import { updateSessionUserInput } from '../../services/sessionService.js';
30
+ import NfcScanStep from '../nfc-scan/NfcScanNode.js';
28
31
  import { EUROPEAN_COUNTRY_CODES } from '../../utils/europeanCountries.js';
29
32
 
33
+ var NFC_ELIGIBLE_DOCUMENT_TYPES = new Set([
34
+ "passport",
35
+ "idCard",
36
+ "residencePermit",
37
+ ]);
30
38
  /**
31
39
  * DocumentCheck component manages the multi-step document verification flow for a session.
32
40
  * It handles country and document type selection, document upload or photo capture, processing, and error/success handling.
@@ -105,10 +113,11 @@ var DocumentCheck = function (_a) {
105
113
  var _t = useState(null), fileUploaded = _t[0], setFileUploaded = _t[1];
106
114
  var _u = useState(null), analysisData = _u[0], setAnalysisData = _u[1];
107
115
  var _v = useState(null), errorCode = _v[0], setErrorCode = _v[1];
116
+ var _w = useState(null), nfcPreparationError = _w[0], setNfcPreparationError = _w[1];
108
117
  // Initialize retry count from session data
109
- var _w = useState(function () {
118
+ var _x = useState(function () {
110
119
  return getNodeRetryCount(session, node.id);
111
- }), retryCount = _w[0], setRetryCount = _w[1];
120
+ }), retryCount = _x[0], setRetryCount = _x[1];
112
121
  // Update retry count when session loads/changes
113
122
  useEffect(function () {
114
123
  if (session) {
@@ -148,10 +157,10 @@ var DocumentCheck = function (_a) {
148
157
  setDocStep(6);
149
158
  }
150
159
  }, [retryCount, node.allowResubmission, node.maxResubmissionAttempts]);
151
- var _x = useState({}), capturedImages = _x[0], setCapturedImages = _x[1];
152
- var _y = useState("before-recto"), currentPhotoStep = _y[0], setCurrentPhotoStep = _y[1];
153
- var _z = useState("photo"), videoFlowPhase = _z[0], setVideoFlowPhase = _z[1];
154
- var _0 = useDocumentContext(), selectedDocumentType = _0.selectedDocumentType, setSelectedDocumentType = _0.setSelectedDocumentType;
160
+ var _y = useState({}), capturedImages = _y[0], setCapturedImages = _y[1];
161
+ var _z = useState("before-recto"), currentPhotoStep = _z[0], setCurrentPhotoStep = _z[1];
162
+ var _0 = useState("photo"), videoFlowPhase = _0[0], setVideoFlowPhase = _0[1];
163
+ var _1 = useDocumentContext(), selectedDocumentType = _1.selectedDocumentType, setSelectedDocumentType = _1.setSelectedDocumentType;
155
164
  var finalAcceptedCountries = useMemo(function () {
156
165
  if (loadingTemplates)
157
166
  return acceptedCountries;
@@ -247,6 +256,7 @@ var DocumentCheck = function (_a) {
247
256
  setFileUploaded(null);
248
257
  setAnalysisData(null);
249
258
  setErrorCode(null);
259
+ setNfcPreparationError(null);
250
260
  // Reset retry count to 0 (will be synced to session)
251
261
  setRetryCount(0);
252
262
  setCapturedImages({});
@@ -277,6 +287,7 @@ var DocumentCheck = function (_a) {
277
287
  var _a;
278
288
  return (__assign(__assign({}, prev), (_a = {}, _a[side] = processedDataUrl_1, _a)));
279
289
  });
290
+ logPhotoCaptured(sessionId, side);
280
291
  if (side === "recto") {
281
292
  isSingleSided = (selectedDocumentType === null || selectedDocumentType === void 0 ? void 0 : selectedDocumentType.id) === "passport" ||
282
293
  (selectedDocumentType === null || selectedDocumentType === void 0 ? void 0 : selectedDocumentType.id) === "pinkDriverLicense";
@@ -294,6 +305,7 @@ var DocumentCheck = function (_a) {
294
305
  var _a;
295
306
  return (__assign(__assign({}, prev), (_a = {}, _a[side] = imageData, _a)));
296
307
  });
308
+ logPhotoCaptured(sessionId, side);
297
309
  if (side === "recto") {
298
310
  isSingleSided = (selectedDocumentType === null || selectedDocumentType === void 0 ? void 0 : selectedDocumentType.id) === "passport" ||
299
311
  (selectedDocumentType === null || selectedDocumentType === void 0 ? void 0 : selectedDocumentType.id) === "pinkDriverLicense";
@@ -309,6 +321,7 @@ var DocumentCheck = function (_a) {
309
321
  }); };
310
322
  var handlePhotoConfirmation = function () {
311
323
  if (capturedImages.recto) {
324
+ logPhotosValidated(sessionId);
312
325
  setFileUploaded({
313
326
  front: capturedImages.recto,
314
327
  back: capturedImages.verso || null,
@@ -329,34 +342,72 @@ var DocumentCheck = function (_a) {
329
342
  }
330
343
  handleProcessingComplete(success, undefined, analysisData);
331
344
  };
332
- var handleDocumentTypeSelect = function (documentId) {
333
- var documentTemplateID = loadingTemplates
334
- ? undefined
335
- : getDocumentTemplateId({
336
- acceptedCountries: finalAcceptedCountries,
337
- countryCode: selectedCountry,
338
- documentId: documentId,
339
- documentTemplates: documentTemplates,
340
- });
341
- // Find the selected document details
342
- var selectedDoc = {
343
- id: documentId,
344
- label: t("documentTypes.".concat(documentId)),
345
- hasTwoSides: documentId !== "passport" && documentId !== "pinkDriverLicense",
346
- documentTemplateId: documentTemplateID,
347
- };
348
- setSelectedDocumentType(selectedDoc);
349
- setFileUploaded(null);
350
- setAnalysisData(null);
351
- setErrorCode(null);
352
- // Don't reset retry count when selecting document type
353
- // Keep existing retry count for this node
354
- setCapturedImages({});
355
- setCurrentPhotoStep("before-recto");
356
- setVideoFlowPhase("photo");
357
- setDocStep(3);
358
- };
345
+ var handleDocumentTypeSelect = function (documentId) { return __awaiter(void 0, void 0, void 0, function () {
346
+ var documentLabel, documentTemplateID, selectedDoc, selectedCountryCode, selectedDocumentInput, nfcMode, error_2;
347
+ var _a;
348
+ return __generator(this, function (_b) {
349
+ switch (_b.label) {
350
+ case 0:
351
+ documentLabel = t("documentTypes.".concat(documentId), documentId);
352
+ logDocumentTypeSelected(sessionId, documentId, documentLabel);
353
+ documentTemplateID = loadingTemplates
354
+ ? undefined
355
+ : getDocumentTemplateId({
356
+ acceptedCountries: finalAcceptedCountries,
357
+ countryCode: selectedCountry,
358
+ documentId: documentId,
359
+ documentTemplates: documentTemplates,
360
+ });
361
+ selectedDoc = {
362
+ id: documentId,
363
+ label: t("documentTypes.".concat(documentId)),
364
+ hasTwoSides: documentId !== "passport" && documentId !== "pinkDriverLicense",
365
+ documentTemplateId: documentTemplateID,
366
+ };
367
+ selectedCountryCode = selectedCountry.toUpperCase();
368
+ selectedDocumentInput = {
369
+ countryCode: selectedCountryCode,
370
+ identityDocumentType: documentId,
371
+ identityDocumentTemplateId: documentTemplateID,
372
+ };
373
+ setSelectedDocumentType(selectedDoc);
374
+ setUserInput(function (prev) { return (__assign(__assign({}, prev), selectedDocumentInput)); });
375
+ setFileUploaded(null);
376
+ setAnalysisData(null);
377
+ setErrorCode(null);
378
+ setNfcPreparationError(null);
379
+ setCapturedImages({});
380
+ setCurrentPhotoStep("before-recto");
381
+ setVideoFlowPhase("photo");
382
+ if (!(node.nfcEnabled === true && NFC_ELIGIBLE_DOCUMENT_TYPES.has(documentId))) return [3 /*break*/, 5];
383
+ nfcMode = (_a = node.nfcMode) !== null && _a !== void 0 ? _a : "nfcOnly";
384
+ _b.label = 1;
385
+ case 1:
386
+ _b.trys.push([1, 3, , 4]);
387
+ return [4 /*yield*/, updateSessionUserInput(sessionId, selectedDocumentInput)];
388
+ case 2:
389
+ _b.sent();
390
+ return [3 /*break*/, 4];
391
+ case 3:
392
+ error_2 = _b.sent();
393
+ console.error("Failed to persist NFC document selection:", error_2);
394
+ setNfcPreparationError(t("nfc_scan.preparation_failed", "Impossible de préparer le scan NFC. Veuillez réessayer."));
395
+ return [3 /*break*/, 4];
396
+ case 4:
397
+ setDocStep(nfcMode === "nfcAndApi" ? 3 : 7);
398
+ return [2 /*return*/];
399
+ case 5:
400
+ setDocStep(3);
401
+ return [2 /*return*/];
402
+ }
403
+ });
404
+ }); };
359
405
  var handleDocumentUpload = function (files) {
406
+ logDocumentLoaded(sessionId, "recto");
407
+ if (files.back) {
408
+ logDocumentLoaded(sessionId, "verso");
409
+ }
410
+ logDocumentsValidated(sessionId);
360
411
  setFileUploaded(files);
361
412
  // Check if retry limit is reached before processing
362
413
  if (!isRetryAllowed() && retryCount > 0) {
@@ -369,6 +420,7 @@ var DocumentCheck = function (_a) {
369
420
  }
370
421
  };
371
422
  var handleProcessingComplete = function (success, _retryCount, apiAnalysisData) {
423
+ var _a;
372
424
  if (apiAnalysisData) {
373
425
  setAnalysisData(apiAnalysisData);
374
426
  // Extract and store the error code
@@ -378,6 +430,14 @@ var DocumentCheck = function (_a) {
378
430
  }
379
431
  }
380
432
  if (success) {
433
+ var shouldRunNfcAfterApi = node.nfcEnabled === true &&
434
+ ((_a = node.nfcMode) !== null && _a !== void 0 ? _a : "nfcOnly") === "nfcAndApi" &&
435
+ !!(selectedDocumentType === null || selectedDocumentType === void 0 ? void 0 : selectedDocumentType.id) &&
436
+ NFC_ELIGIBLE_DOCUMENT_TYPES.has(selectedDocumentType.id);
437
+ if (shouldRunNfcAfterApi) {
438
+ setDocStep(7);
439
+ return;
440
+ }
381
441
  // Increment currentStep in database immediately after successful analysis
382
442
  // This prevents double analysis if the user refreshes the page
383
443
  if (template) {
@@ -491,7 +551,7 @@ var DocumentCheck = function (_a) {
491
551
  return (jsxs("div", { className: "flex flex-col items-center justify-center h-full p-4 text-center", children: [jsx("div", { className: "text-red-500 text-4xl mb-4", children: "\u26A0\uFE0F" }), jsx("h2", { className: "text-xl font-bold text-red-600 mb-2", children: t("document_check.selection_error.title", "Erreur de sélection") }), jsx("p", { className: "text-gray-600 mb-4", children: t("document_check.selection_error.description", "Aucun type de document sélectionné. Veuillez revenir à l'étape précédente.") }), jsx(ButtonDesktop, { className: "px-4 py-2 bg-primary text-white rounded hover:bg-primary-dark transition-colors", type: "back", onClick: function () { return setDocStep(2); }, children: t("document_check.selection_error.back", "Retour à la sélection") })] }));
492
552
  }
493
553
  if (isPictureAllowed && isDownloadAllowed && !selectedMethod) {
494
- return (jsx(MobilePageLayout, { footer: jsx("div", { className: "w-full max-w-md mx-auto", children: jsx(ButtonDesktop, { type: "back", onClick: handleBack, className: "w-full text-[#3C3C40] text-center font-poppins text-sm font-medium hover:underline py-2", children: t("buttons.back", "Retour") }) }), children: jsx("div", { className: "px-4 py-6 pt-11 md:px-8 md:py-8", children: jsxs("div", { className: "w-full max-w-md mx-auto space-y-6", children: [jsxs("div", { className: "text-center space-y-4", children: [jsx(Title, { className: "text-xl md:text-2xl lg:text-3xl", children: t("document_check.method_selection.title", "Choisissez une méthode") }), jsx(Subtitle, { className: "text-sm text-gray-600 leading-relaxed", children: t("document_check.method_selection.subtitle", "Comment souhaitez-vous ajouter votre document ?") })] }), jsxs("div", { className: "grid gap-4", children: [jsxs("button", { onClick: function () { return setSelectedMethod("picture"); }, className: "flex items-center p-4 bg-white border-2 border-gray-100 rounded-xl hover:border-teal-500 transition-colors text-left group", children: [jsx("div", { className: "w-12 h-12 bg-teal-50 rounded-lg flex items-center justify-center text-teal-600 group-hover:bg-teal-100 transition-colors mr-4", children: jsx(Camera, { size: 24 }) }), jsxs("div", { children: [jsx("p", { className: "font-semibold text-gray-900", children: t("document_check.method_selection.picture_title", "Prendre une photo") }), jsx("p", { className: "text-sm text-gray-500", children: t("document_check.method_selection.picture_desc", "Utilisez l'appareil photo de votre appareil") })] })] }), jsxs("button", { onClick: function () { return setSelectedMethod("download"); }, className: "flex items-center p-4 bg-white border-2 border-gray-100 rounded-xl hover:border-teal-500 transition-colors text-left group", children: [jsx("div", { className: "w-12 h-12 bg-teal-50 rounded-lg flex items-center justify-center text-teal-600 group-hover:bg-teal-100 transition-colors mr-4", children: jsx(Upload, { size: 24 }) }), jsxs("div", { children: [jsx("p", { className: "font-semibold text-gray-900", children: t("document_check.method_selection.download_title", "Téléverser un fichier") }), jsx("p", { className: "text-sm text-gray-500", children: t("document_check.method_selection.download_desc", "Sélectionnez un fichier sur votre appareil") })] })] })] })] }) }) }));
554
+ return (jsx(MobilePageLayout, { footer: jsx("div", { className: "w-full max-w-md mx-auto", children: jsx(ButtonDesktop, { type: "back", onClick: handleBack, className: "w-full text-[#3C3C40] text-center font-poppins text-sm font-medium hover:underline py-2", children: t("buttons.back", "Retour") }) }), children: jsx("div", { className: "px-4 py-6 pt-11 md:px-8 md:py-8", children: jsxs("div", { className: "w-full max-w-md mx-auto space-y-6", children: [jsxs("div", { className: "text-center space-y-4", children: [jsx(Title, { className: "text-xl md:text-2xl lg:text-3xl", children: t("document_check.method_selection.title", "Choisissez une méthode") }), jsx(Subtitle, { className: "text-sm text-gray-600 leading-relaxed", children: t("document_check.method_selection.subtitle", "Comment souhaitez-vous ajouter votre document ?") })] }), jsxs("div", { className: "grid gap-4", children: [jsxs("button", { onClick: function () { setSelectedMethod("picture"); logCaptureModeSelected(sessionId, "picture"); }, className: "flex items-center p-4 bg-white border-2 border-gray-100 rounded-xl hover:border-teal-500 transition-colors text-left group", children: [jsx("div", { className: "w-12 h-12 bg-teal-50 rounded-lg flex items-center justify-center text-teal-600 group-hover:bg-teal-100 transition-colors mr-4", children: jsx(Camera, { size: 24 }) }), jsxs("div", { children: [jsx("p", { className: "font-semibold text-gray-900", children: t("document_check.method_selection.picture_title", "Prendre une photo") }), jsx("p", { className: "text-sm text-gray-500", children: t("document_check.method_selection.picture_desc", "Utilisez l'appareil photo de votre appareil") })] })] }), jsxs("button", { onClick: function () { setSelectedMethod("download"); logCaptureModeSelected(sessionId, "upload"); }, className: "flex items-center p-4 bg-white border-2 border-gray-100 rounded-xl hover:border-teal-500 transition-colors text-left group", children: [jsx("div", { className: "w-12 h-12 bg-teal-50 rounded-lg flex items-center justify-center text-teal-600 group-hover:bg-teal-100 transition-colors mr-4", children: jsx(Upload, { size: 24 }) }), jsxs("div", { children: [jsx("p", { className: "font-semibold text-gray-900", children: t("document_check.method_selection.download_title", "Téléverser un fichier") }), jsx("p", { className: "text-sm text-gray-500", children: t("document_check.method_selection.download_desc", "Sélectionnez un fichier sur votre appareil") })] })] })] })] }) }) }));
495
555
  }
496
556
  var activeMethod = selectedMethod ||
497
557
  (isPictureAllowed && isMobileCapture ? "picture" : "download");
@@ -535,7 +595,7 @@ var DocumentCheck = function (_a) {
535
595
  else {
536
596
  setDocStep(2);
537
597
  }
538
- }, initialFront: errorCode === "2.5" ? fileUploaded === null || fileUploaded === void 0 ? void 0 : fileUploaded.front : null, initialBack: errorCode === "2.5" ? fileUploaded === null || fileUploaded === void 0 ? void 0 : fileUploaded.back : null }));
598
+ }, initialFront: errorCode === "2.5" ? fileUploaded === null || fileUploaded === void 0 ? void 0 : fileUploaded.front : null, initialBack: errorCode === "2.5" ? fileUploaded === null || fileUploaded === void 0 ? void 0 : fileUploaded.back : null, sessionId: sessionId }));
539
599
  }
540
600
  case 4:
541
601
  return (jsx(JDIProcessing, { documentType: (selectedDocumentType === null || selectedDocumentType === void 0 ? void 0 : selectedDocumentType.id) || documentTypeId, onProcessingComplete: handleProcessingComplete, fileUploaded: fileUploaded, documentTypeId: documentTypeId, retryCount: retryCount, documentTemplateId: selectedDocumentType === null || selectedDocumentType === void 0 ? void 0 : selectedDocumentType.documentTemplateId, nodeId: node.id }));
@@ -543,6 +603,11 @@ var DocumentCheck = function (_a) {
543
603
  return (jsx(JDISuccess, { documentType: (selectedDocumentType === null || selectedDocumentType === void 0 ? void 0 : selectedDocumentType.id) || documentTypeId, onContinue: handleSuccessContinue, errorCode: errorCode || undefined }));
544
604
  case 6:
545
605
  return (jsx(JDIError, { documentType: (selectedDocumentType === null || selectedDocumentType === void 0 ? void 0 : selectedDocumentType.id) || documentTypeId, onRetry: handleRetryFromError, onContinueAnyway: handleContinueAnyway, retryCount: retryCount, predictions: analysisData || undefined, errorCode: errorCode || undefined, allowResubmission: node.allowResubmission, maxResubmissionAttempts: node.maxResubmissionAttempts, isRetryAllowed: isRetryAllowed() }));
606
+ case 7:
607
+ if (nfcPreparationError) {
608
+ return (jsx(MobilePageLayout, { footer: jsx("div", { className: "w-full max-w-md mx-auto", children: jsx(ButtonDesktop, { type: "back", onClick: function () { return setDocStep(2); }, className: "w-full text-[#3C3C40] text-center font-poppins text-sm font-medium hover:underline py-2", children: t("buttons.back", "Retour") }) }), children: jsxs("div", { className: "flex flex-col items-center justify-center h-full p-4 text-center", children: [jsx("div", { className: "text-red-500 text-4xl mb-4", children: "\u26A0\uFE0F" }), jsx("h2", { className: "text-xl font-bold text-red-600 mb-2", children: t("nfc_scan.preparation_error_title", "Erreur de préparation NFC") }), jsx("p", { className: "text-gray-600 mb-4", children: nfcPreparationError })] }) }));
609
+ }
610
+ return (jsx(NfcScanStep, { sessionId: sessionId, nodeId: node.id, stepObject: stepObject, template: template }));
546
611
  default:
547
612
  console.error("Invalid docStep: ".concat(docStep));
548
613
  return (jsxs("div", { className: "flex flex-col items-center justify-center h-full p-4 text-center", children: [jsx("div", { className: "text-red-500 text-4xl mb-4", children: "\u26A0\uFE0F" }), jsx("h2", { className: "text-xl font-bold text-red-600 mb-2", children: t("document_check.navigation_error.title", "Erreur de navigation") }), jsx("p", { className: "text-gray-600 mb-4", children: t("document_check.navigation_error.description", "Étape non valide. Veuillez recommencer.") }), jsx(ButtonDesktop, { className: "px-4 py-2 bg-primary text-white rounded hover:bg-primary-dark transition-colors", type: "back", onClick: function () { return setDocStep(0); }, children: t("document_check.navigation_error.back", "Retour au début") })] }));