datakeen-session-react 1.1.140-dev.103 → 1.1.140-dev.104

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.
@@ -9,6 +9,7 @@ var QRCode = require('qrcode');
9
9
  var useI18n = require('../../hooks/useI18n.js');
10
10
  var useNfcSseStatus = require('../../hooks/useNfcSseStatus.js');
11
11
  var api = require('../../services/api.js');
12
+ var sessionService = require('../../services/sessionService.js');
12
13
  var isMobileDevice = require('../../utils/isMobileDevice.js');
13
14
  var MobilePageLayout = require('../ui/MobilePageLayout.js');
14
15
  var Button = require('../ui/Button.js');
@@ -22,6 +23,8 @@ var NfcScanStep = function (_a) {
22
23
  var t = useI18n.useI18n().t;
23
24
  var canvasRef = React.useRef(null);
24
25
  var _b = React.useState(null), qrError = _b[0], setQrError = _b[1];
26
+ var _c = React.useState(null), resetError = _c[0], setResetError = _c[1];
27
+ var _d = React.useState(false), isResetting = _d[0], setIsResetting = _d[1];
25
28
  // Sur mobile, on ouvre directement l'app de scan au lieu d'afficher un QR code inutile.
26
29
  var isMobile = React.useMemo(function () { return isMobileDevice.isMobileDevice(); }, []);
27
30
  var nfcUrl = React.useMemo(function () {
@@ -99,12 +102,43 @@ var NfcScanStep = function (_a) {
99
102
  }); };
100
103
  generate();
101
104
  }, [nfcUrl, status, t, isMobile]);
105
+ var handleBack = function () { return tslib_es6.__awaiter(void 0, void 0, void 0, function () {
106
+ return tslib_es6.__generator(this, function (_b) {
107
+ switch (_b.label) {
108
+ case 0:
109
+ if (!onBack)
110
+ return [2 /*return*/];
111
+ if (status !== "failed") {
112
+ onBack();
113
+ return [2 /*return*/];
114
+ }
115
+ setResetError(null);
116
+ setIsResetting(true);
117
+ _b.label = 1;
118
+ case 1:
119
+ _b.trys.push([1, 3, 4, 5]);
120
+ return [4 /*yield*/, sessionService.resetNfcScan(sessionId)];
121
+ case 2:
122
+ _b.sent();
123
+ onBack();
124
+ return [3 /*break*/, 5];
125
+ case 3:
126
+ _b.sent();
127
+ setResetError(t("nfc_scan.reset_failed", "Impossible de réinitialiser le scan NFC. Veuillez réessayer."));
128
+ return [3 /*break*/, 5];
129
+ case 4:
130
+ setIsResetting(false);
131
+ return [7 /*endfinally*/];
132
+ case 5: return [2 /*return*/];
133
+ }
134
+ });
135
+ }); };
102
136
  // Footer : sur l'échec définitif ('failed'), les actions dédiées (revenir au choix / poursuivre
103
137
  // sans puce) sont rendues via PageActions, comme les autres écrans NFC (NfcChipGate). Sinon, un
104
138
  // simple "Retour" tant que le scan n'a pas commencé/abouti.
105
139
  var canGoBack = !!onBack && (status === "pending" || status === "opened");
106
- var footer = status === "failed" ? (jsxRuntime.jsx(PageActions.default, { primary: onBack ? (jsxRuntime.jsx(Button.default, { onClick: onBack, children: t("nfc_scan.failed_back_to_selection", "Revenir au choix du document") })) : null, secondary: onContinueWithoutChip ? (jsxRuntime.jsx(Button.default, { variant: "secondary", onClick: onContinueWithoutChip, children: t("nfc_scan.failed_continue_without_chip", "Poursuivre sans puce") })) : null })) : canGoBack ? (jsxRuntime.jsx(Button.default, { variant: "secondary", onClick: onBack, children: t("common.back", "Retour") })) : null;
107
- return (jsxRuntime.jsx(MobilePageLayout.default, { footer: footer, children: jsxRuntime.jsx("div", { className: "px-4 py-6 pt-11 md:px-8 md:py-8", children: jsxRuntime.jsxs("div", { className: "w-full max-w-md mx-auto space-y-6", children: [jsxRuntime.jsxs("div", { className: "text-center space-y-4 mt-16 md:mt-20", children: [jsxRuntime.jsx(Title.default, { className: "text-xl md:text-2xl lg:text-3xl", children: title }), jsxRuntime.jsx(Subtitle.default, { className: "text-sm md:text-base text-gray-600 leading-relaxed whitespace-pre-line", children: subtitle })] }), jsxRuntime.jsx("div", { className: "flex-1 flex flex-col justify-center items-center gap-4", children: status === "success" ? (jsxRuntime.jsx(NfcSuccessAnimation.default, {})) : status === "completed" ? (jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-4 p-8", children: [jsxRuntime.jsx("div", { className: "animate-spin w-10 h-10 border-2 border-gray-300 border-t-blue-500 rounded-full" }), jsxRuntime.jsx("p", { className: "text-sm text-gray-600", children: t("nfc_scan.verifying", "Vérification en cours…") })] })) : status === "failed" ? (jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2 p-8 text-center", children: [jsxRuntime.jsx("p", { className: "text-base font-semibold text-red-600", children: t("nfc_scan.failed_title", "Le scan n'a pas pu être vérifié") }), jsxRuntime.jsx("p", { className: "text-sm text-gray-600 leading-relaxed", children: t("nfc_scan.failed_description", "Après plusieurs tentatives, la lecture de votre document n'a pas pu être validée.") })] })) : (
140
+ var footer = status === "failed" ? (jsxRuntime.jsx(PageActions.default, { primary: onBack ? (jsxRuntime.jsx(Button.default, { onClick: function () { return void handleBack(); }, disabled: isResetting, children: t("nfc_scan.failed_back_to_selection", "Revenir au choix du document") })) : null, secondary: onContinueWithoutChip ? (jsxRuntime.jsx(Button.default, { variant: "secondary", onClick: onContinueWithoutChip, children: t("nfc_scan.failed_continue_without_chip", "Poursuivre sans puce") })) : null })) : canGoBack ? (jsxRuntime.jsx(Button.default, { variant: "secondary", onClick: onBack, children: t("common.back", "Retour") })) : null;
141
+ return (jsxRuntime.jsx(MobilePageLayout.default, { footer: footer, children: jsxRuntime.jsx("div", { className: "px-4 py-6 pt-11 md:px-8 md:py-8", children: jsxRuntime.jsxs("div", { className: "w-full max-w-md mx-auto space-y-6", children: [jsxRuntime.jsxs("div", { className: "text-center space-y-4 mt-16 md:mt-20", children: [jsxRuntime.jsx(Title.default, { className: "text-xl md:text-2xl lg:text-3xl", children: title }), jsxRuntime.jsx(Subtitle.default, { className: "text-sm md:text-base text-gray-600 leading-relaxed whitespace-pre-line", children: subtitle })] }), jsxRuntime.jsx("div", { className: "flex-1 flex flex-col justify-center items-center gap-4", children: status === "success" ? (jsxRuntime.jsx(NfcSuccessAnimation.default, {})) : status === "completed" ? (jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-4 p-8", children: [jsxRuntime.jsx("div", { className: "animate-spin w-10 h-10 border-2 border-gray-300 border-t-blue-500 rounded-full" }), jsxRuntime.jsx("p", { className: "text-sm text-gray-600", children: t("nfc_scan.verifying", "Vérification en cours…") })] })) : status === "failed" ? (jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2 p-8 text-center", children: [jsxRuntime.jsx("p", { className: "text-base font-semibold text-red-600", children: t("nfc_scan.failed_title", "Le scan n'a pas pu être vérifié") }), jsxRuntime.jsx("p", { className: "text-sm text-gray-600 leading-relaxed", children: t("nfc_scan.failed_description", "Après plusieurs tentatives, la lecture de votre document n'a pas pu être validée.") }), resetError && (jsxRuntime.jsx("p", { className: "text-sm text-red-600", role: "alert", children: resetError }))] })) : (
108
142
  // Contenu principal QR/mobile — reste monté pour "pending" ET "opened", pour ne
109
143
  // jamais démonter le canvas déjà généré.
110
144
  jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [qrError ? (jsxRuntime.jsx("div", { className: "text-red-500 text-center p-4", children: qrError })) : isMobile ? (jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-4 p-8 text-center", children: [jsxRuntime.jsx("div", { className: "animate-spin w-10 h-10 border-2 border-gray-300 border-t-blue-500 rounded-full" }), jsxRuntime.jsx("p", { className: "text-sm text-gray-600", children: t("nfc_scan.opening_app", "Ouverture de l'application…") }), jsxRuntime.jsx("a", { href: nfcUrl, className: "text-sm font-medium text-blue-600 underline", children: t("nfc_scan.open_app_link", "Ouvrir l'application") })] })) : (jsxRuntime.jsx("div", { className: "bg-white p-4 rounded-lg shadow-lg border-2 border-gray-200", children: jsxRuntime.jsx("canvas", { ref: canvasRef }) })), status === "opened" && (jsxRuntime.jsxs("div", { className: "text-center space-y-1", children: [jsxRuntime.jsx("p", { className: "text-sm font-semibold", style: { color: "var(--uni-secondary-color, #0a9983)" }, children: t("nfc_scan.qr_opened_title", "QR code scanné") }), jsxRuntime.jsx("p", { className: "text-xs text-gray-500 leading-relaxed", children: t("nfc_scan.qr_opened_description", "L'expérience NFC est ouverte sur votre smartphone. Continuez le scan sur votre téléphone.") }), jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-2 text-xs text-gray-500 pt-1", children: [jsxRuntime.jsx("span", { className: "h-2 w-2 rounded-full animate-pulse", style: { backgroundColor: "var(--uni-primary-color, #11e5c5)" } }), t("nfc_scan.waiting_completion", "En attente de la lecture NFC")] })] }))] })) })] }) }) }));
@@ -1 +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 { isMobileDevice } from \"../../utils/isMobileDevice\";\nimport MobilePageLayout from \"../ui/MobilePageLayout\";\nimport Button from \"../ui/Button\";\nimport PageActions from \"../ui/PageActions\";\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 /** Retour vers la sélection du document (pour corriger un mauvais choix). */\n onBack?: () => void;\n /**\n * Fallback \"poursuivre sans puce\" proposé sur l'échec définitif (nfcStatus 'failed'). Ouvre le\n * questionnaire de raison côté web (NfcFallbackSurvey) ; la reprise (photo/API ou saut de nœud)\n * est décidée par l'orchestrateur selon nfcMode. Absent = bouton masqué.\n */\n onContinueWithoutChip?: () => void;\n}\n\nconst NfcScanStep: React.FC<NfcScanStepProps> = ({\n sessionId,\n nodeId,\n stepObject,\n template,\n pageTitle,\n pageDescription,\n onBack,\n onContinueWithoutChip,\n}) => {\n const { t } = useI18n();\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const [qrError, setQrError] = useState<string | null>(null);\n // Sur mobile, on ouvre directement l'app de scan au lieu d'afficher un QR code inutile.\n const isMobile = useMemo(() => isMobileDevice(), []);\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 smartphone pour lire la puce électronique de votre document d'identité.\"\n );\n\n // Sur mobile : ouvrir directement l'application de scan (pas de QR à se scanner soi-même).\n // Une seule fois, tant que le scan n'a pas progressé. Le SSE reste actif pour faire avancer\n // le parcours quand la lecture est terminée.\n const hasRedirectedRef = useRef(false);\n useEffect(() => {\n if (!isMobile || status !== \"pending\" || hasRedirectedRef.current) return;\n hasRedirectedRef.current = true;\n window.location.assign(nfcUrl);\n }, [isMobile, status, nfcUrl]);\n\n useEffect(() => {\n if (isMobile) return; // pas de QR sur mobile (redirection directe)\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, isMobile]);\n\n // Footer : sur l'échec définitif ('failed'), les actions dédiées (revenir au choix / poursuivre\n // sans puce) sont rendues via PageActions, comme les autres écrans NFC (NfcChipGate). Sinon, un\n // simple \"Retour\" tant que le scan n'a pas commencé/abouti.\n const canGoBack = !!onBack && (status === \"pending\" || status === \"opened\");\n const footer =\n status === \"failed\" ? (\n <PageActions\n primary={\n onBack ? (\n <Button onClick={onBack}>\n {t(\"nfc_scan.failed_back_to_selection\", \"Revenir au choix du document\")}\n </Button>\n ) : null\n }\n secondary={\n onContinueWithoutChip ? (\n <Button variant=\"secondary\" onClick={onContinueWithoutChip}>\n {t(\"nfc_scan.failed_continue_without_chip\", \"Poursuivre sans puce\")}\n </Button>\n ) : null\n }\n />\n ) : canGoBack ? (\n <Button variant=\"secondary\" onClick={onBack}>\n {t(\"common.back\", \"Retour\")}\n </Button>\n ) : null;\n\n return (\n <MobilePageLayout footer={footer}>\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 flex-col justify-center items-center gap-4\">\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 === \"failed\" ? (\n <div className=\"flex flex-col items-center gap-2 p-8 text-center\">\n <p className=\"text-base font-semibold text-red-600\">\n {t(\"nfc_scan.failed_title\", \"Le scan n'a pas pu être vérifié\")}\n </p>\n <p className=\"text-sm text-gray-600 leading-relaxed\">\n {t(\n \"nfc_scan.failed_description\",\n \"Après plusieurs tentatives, la lecture de votre document n'a pas pu être validée.\"\n )}\n </p>\n </div>\n ) : (\n // Contenu principal QR/mobile — reste monté pour \"pending\" ET \"opened\", pour ne\n // jamais démonter le canvas déjà généré.\n <>\n {qrError ? (\n <div className=\"text-red-500 text-center p-4\">{qrError}</div>\n ) : isMobile ? (\n <div className=\"flex flex-col items-center gap-4 p-8 text-center\">\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.opening_app\", \"Ouverture de l'application…\")}\n </p>\n <a\n href={nfcUrl}\n className=\"text-sm font-medium text-blue-600 underline\"\n >\n {t(\"nfc_scan.open_app_link\", \"Ouvrir l'application\")}\n </a>\n </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\n {status === \"opened\" && (\n <div className=\"text-center space-y-1\">\n <p\n className=\"text-sm font-semibold\"\n style={{ color: \"var(--uni-secondary-color, #0a9983)\" }}\n >\n {t(\"nfc_scan.qr_opened_title\", \"QR code scanné\")}\n </p>\n <p className=\"text-xs text-gray-500 leading-relaxed\">\n {t(\n \"nfc_scan.qr_opened_description\",\n \"L'expérience NFC est ouverte sur votre smartphone. Continuez le scan sur votre téléphone.\"\n )}\n </p>\n <div className=\"flex items-center justify-center gap-2 text-xs text-gray-500 pt-1\">\n <span\n className=\"h-2 w-2 rounded-full animate-pulse\"\n style={{ backgroundColor: \"var(--uni-primary-color, #11e5c5)\" }}\n />\n {t(\"nfc_scan.waiting_completion\", \"En attente de la lecture NFC\")}\n </div>\n </div>\n )}\n </>\n )}\n </div>\n </div>\n </div>\n </MobilePageLayout>\n );\n};\n\nexport default NfcScanStep;\n"],"names":["useI18n","useRef","useState","useMemo","isMobileDevice","getBaseURL","useNfcSseStatus","useEffect","__awaiter","_jsx","PageActions","Button","MobilePageLayout","_jsxs","Title","Subtitle","NfcSuccessAnimation","_Fragment"],"mappings":"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"}
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 { resetNfcScan } from \"../../services/sessionService\";\nimport { isMobileDevice } from \"../../utils/isMobileDevice\";\nimport MobilePageLayout from \"../ui/MobilePageLayout\";\nimport Button from \"../ui/Button\";\nimport PageActions from \"../ui/PageActions\";\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 /** Retour vers la sélection du document (pour corriger un mauvais choix). */\n onBack?: () => void;\n /**\n * Fallback \"poursuivre sans puce\" proposé sur l'échec définitif (nfcStatus 'failed'). Ouvre le\n * questionnaire de raison côté web (NfcFallbackSurvey) ; la reprise (photo/API ou saut de nœud)\n * est décidée par l'orchestrateur selon nfcMode. Absent = bouton masqué.\n */\n onContinueWithoutChip?: () => void;\n}\n\nconst NfcScanStep: React.FC<NfcScanStepProps> = ({\n sessionId,\n nodeId,\n stepObject,\n template,\n pageTitle,\n pageDescription,\n onBack,\n onContinueWithoutChip,\n}) => {\n const { t } = useI18n();\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const [qrError, setQrError] = useState<string | null>(null);\n const [resetError, setResetError] = useState<string | null>(null);\n const [isResetting, setIsResetting] = useState(false);\n // Sur mobile, on ouvre directement l'app de scan au lieu d'afficher un QR code inutile.\n const isMobile = useMemo(() => isMobileDevice(), []);\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 smartphone pour lire la puce électronique de votre document d'identité.\"\n );\n\n // Sur mobile : ouvrir directement l'application de scan (pas de QR à se scanner soi-même).\n // Une seule fois, tant que le scan n'a pas progressé. Le SSE reste actif pour faire avancer\n // le parcours quand la lecture est terminée.\n const hasRedirectedRef = useRef(false);\n useEffect(() => {\n if (!isMobile || status !== \"pending\" || hasRedirectedRef.current) return;\n hasRedirectedRef.current = true;\n window.location.assign(nfcUrl);\n }, [isMobile, status, nfcUrl]);\n\n useEffect(() => {\n if (isMobile) return; // pas de QR sur mobile (redirection directe)\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, isMobile]);\n\n const handleBack = async () => {\n if (!onBack) return;\n\n if (status !== \"failed\") {\n onBack();\n return;\n }\n\n setResetError(null);\n setIsResetting(true);\n try {\n await resetNfcScan(sessionId);\n onBack();\n } catch {\n setResetError(\n t(\n \"nfc_scan.reset_failed\",\n \"Impossible de réinitialiser le scan NFC. Veuillez réessayer.\",\n ),\n );\n } finally {\n setIsResetting(false);\n }\n };\n\n // Footer : sur l'échec définitif ('failed'), les actions dédiées (revenir au choix / poursuivre\n // sans puce) sont rendues via PageActions, comme les autres écrans NFC (NfcChipGate). Sinon, un\n // simple \"Retour\" tant que le scan n'a pas commencé/abouti.\n const canGoBack = !!onBack && (status === \"pending\" || status === \"opened\");\n const footer =\n status === \"failed\" ? (\n <PageActions\n primary={\n onBack ? (\n <Button onClick={() => void handleBack()} disabled={isResetting}>\n {t(\"nfc_scan.failed_back_to_selection\", \"Revenir au choix du document\")}\n </Button>\n ) : null\n }\n secondary={\n onContinueWithoutChip ? (\n <Button variant=\"secondary\" onClick={onContinueWithoutChip}>\n {t(\"nfc_scan.failed_continue_without_chip\", \"Poursuivre sans puce\")}\n </Button>\n ) : null\n }\n />\n ) : canGoBack ? (\n <Button variant=\"secondary\" onClick={onBack}>\n {t(\"common.back\", \"Retour\")}\n </Button>\n ) : null;\n\n return (\n <MobilePageLayout footer={footer}>\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 flex-col justify-center items-center gap-4\">\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 === \"failed\" ? (\n <div className=\"flex flex-col items-center gap-2 p-8 text-center\">\n <p className=\"text-base font-semibold text-red-600\">\n {t(\"nfc_scan.failed_title\", \"Le scan n'a pas pu être vérifié\")}\n </p>\n <p className=\"text-sm text-gray-600 leading-relaxed\">\n {t(\n \"nfc_scan.failed_description\",\n \"Après plusieurs tentatives, la lecture de votre document n'a pas pu être validée.\"\n )}\n </p>\n {resetError && (\n <p className=\"text-sm text-red-600\" role=\"alert\">\n {resetError}\n </p>\n )}\n </div>\n ) : (\n // Contenu principal QR/mobile — reste monté pour \"pending\" ET \"opened\", pour ne\n // jamais démonter le canvas déjà généré.\n <>\n {qrError ? (\n <div className=\"text-red-500 text-center p-4\">{qrError}</div>\n ) : isMobile ? (\n <div className=\"flex flex-col items-center gap-4 p-8 text-center\">\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.opening_app\", \"Ouverture de l'application…\")}\n </p>\n <a\n href={nfcUrl}\n className=\"text-sm font-medium text-blue-600 underline\"\n >\n {t(\"nfc_scan.open_app_link\", \"Ouvrir l'application\")}\n </a>\n </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\n {status === \"opened\" && (\n <div className=\"text-center space-y-1\">\n <p\n className=\"text-sm font-semibold\"\n style={{ color: \"var(--uni-secondary-color, #0a9983)\" }}\n >\n {t(\"nfc_scan.qr_opened_title\", \"QR code scanné\")}\n </p>\n <p className=\"text-xs text-gray-500 leading-relaxed\">\n {t(\n \"nfc_scan.qr_opened_description\",\n \"L'expérience NFC est ouverte sur votre smartphone. Continuez le scan sur votre téléphone.\"\n )}\n </p>\n <div className=\"flex items-center justify-center gap-2 text-xs text-gray-500 pt-1\">\n <span\n className=\"h-2 w-2 rounded-full animate-pulse\"\n style={{ backgroundColor: \"var(--uni-primary-color, #11e5c5)\" }}\n />\n {t(\"nfc_scan.waiting_completion\", \"En attente de la lecture NFC\")}\n </div>\n </div>\n )}\n </>\n )}\n </div>\n </div>\n </div>\n </MobilePageLayout>\n );\n};\n\nexport default NfcScanStep;\n"],"names":["useI18n","useRef","useState","useMemo","isMobileDevice","getBaseURL","useNfcSseStatus","useEffect","__awaiter","resetNfcScan","_jsx","PageActions","Button","MobilePageLayout","_jsxs","Title","Subtitle","NfcSuccessAnimation","_Fragment"],"mappings":"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"}
@@ -1035,6 +1035,7 @@ var nfc_scan = {
1035
1035
  failed_description: "After several attempts, your document could not be validated.",
1036
1036
  failed_back_to_selection: "Back to document selection",
1037
1037
  failed_continue_without_chip: "Continue without chip",
1038
+ reset_failed: "Unable to reset the NFC scan. Please try again.",
1038
1039
  success_title: "Documents validated",
1039
1040
  success_subtitle: "NFC reading confirmed successfully",
1040
1041
  onboarding: {
@@ -1 +1 @@
1
- {"version":3,"file":"en.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"en.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1035,6 +1035,7 @@ var nfc_scan = {
1035
1035
  failed_description: "Después de varios intentos, no se pudo validar tu documento.",
1036
1036
  failed_back_to_selection: "Volver a la selección de documento",
1037
1037
  failed_continue_without_chip: "Continuar sin chip",
1038
+ reset_failed: "No se ha podido reiniciar el escaneo NFC. Inténtalo de nuevo.",
1038
1039
  success_title: "Documentos validados",
1039
1040
  success_subtitle: "Lectura NFC confirmada correctamente",
1040
1041
  onboarding: {
@@ -1 +1 @@
1
- {"version":3,"file":"es.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"es.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1035,6 +1035,7 @@ var nfc_scan = {
1035
1035
  failed_description: "Après plusieurs tentatives, la lecture de votre document n'a pas pu être validée.",
1036
1036
  failed_back_to_selection: "Revenir au choix du document",
1037
1037
  failed_continue_without_chip: "Poursuivre sans puce",
1038
+ reset_failed: "Impossible de réinitialiser le scan NFC. Veuillez réessayer.",
1038
1039
  success_title: "Documents validés",
1039
1040
  success_subtitle: "Lecture NFC confirmée avec succès",
1040
1041
  onboarding: {
@@ -1 +1 @@
1
- {"version":3,"file":"fr.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"fr.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -103,6 +103,21 @@ var skipNfcWithReason = function (sessionId, payload) { return tslib_es6.__await
103
103
  }
104
104
  });
105
105
  }); };
106
+ /**
107
+ * Resets a terminal NFC failure before the user starts again with another
108
+ * document. The backend keeps completed scans immutable and treats this call
109
+ * as a no-op when the status is not terminal.
110
+ */
111
+ var resetNfcScan = function (sessionId) { return tslib_es6.__awaiter(void 0, void 0, void 0, function () {
112
+ return tslib_es6.__generator(this, function (_a) {
113
+ switch (_a.label) {
114
+ case 0: return [4 /*yield*/, api.apiService.post("/session/sdk/".concat(sessionId, "/nfc-reset"))];
115
+ case 1:
116
+ _a.sent();
117
+ return [2 /*return*/];
118
+ }
119
+ });
120
+ }); };
106
121
  /**
107
122
  * Updates session data with contact information
108
123
  *
@@ -451,6 +466,7 @@ exports.getOrderedJourneySteps = getOrderedJourneySteps;
451
466
  exports.getRunPrefillData = getRunPrefillData;
452
467
  exports.isSessionExpired = isSessionExpired;
453
468
  exports.reconstructHistoryToStep = reconstructHistoryToStep;
469
+ exports.resetNfcScan = resetNfcScan;
454
470
  exports.sendClientInfo = sendClientInfo;
455
471
  exports.skipNfcWithReason = skipNfcWithReason;
456
472
  exports.storeDocumentOptions = storeDocumentOptions;
@@ -1 +1 @@
1
- {"version":3,"file":"sessionService.js","sources":["../../../../src/services/sessionService.ts"],"sourcesContent":["/**\n * Session Service\n *\n * Service for interacting with the Datakeen Session API.\n * Handles fetching session data by ID.\n */\n\nimport type {\n ClientInfo,\n SessionData,\n SessionTemplate,\n SessionTemplateNode,\n} from \"../types/session\";\nimport { apiService } from \"./api\";\nimport { logStatusModified } from \"./auditTrailService\";\nimport { clearSessionMemory } from \"./sessionMemoryStore\";\n\n/**\n * Fetches session data by ID from the Datakeen backend\n *\n * @param sessionId - The unique identifier of the session\n * @returns The session data\n */\nexport const fetchSessionById = async (\n sessionId: string,\n): Promise<SessionData> => {\n try {\n const response = await apiService.get(`/session/sdk/${sessionId}`);\n return response.data;\n } catch (error) {\n console.error(\"Error fetching session data:\", error);\n throw error;\n }\n};\n\n/** Sends client information (IP, device, browser, OS) to the backend for a specific session\n *\n * @param sessionId - The unique identifier of the session\n * @param clientInfo - The client information to send\n */\nexport const sendClientInfo = async (\n sessionId: string,\n clientInfo: ClientInfo,\n): Promise<void> => {\n try {\n await apiService.post(`/session/sdk/${sessionId}/client-info`, clientInfo);\n } catch (error) {\n console.error(\"Error sending client info:\", error);\n throw error;\n }\n};\n\n/**\n * Determines if the session template has a specific type of node\n *\n * @param template - The session template\n * @param nodeType - The type of node to check for\n * @returns true if the template has a node of the specified type, false otherwise\n */\nexport const hasNodeType = (\n template: SessionTemplate,\n nodeType: string,\n): boolean => {\n return template.nodes.some((node) => node.type === nodeType);\n};\n\n/**\n * Determines if the session template has a node with a specific requiredDocumentType\n *\n * @param template - The session template\n * @param requiredDocumentType - The requiredDocumentType to check for\n * @returns true if the template has a node with the specified requiredDocumentType, false otherwise\n */\nexport const hasDocumentTypeNode = (\n template: SessionTemplate,\n requiredDocumentType: string,\n): boolean => {\n return template.nodes.some(\n (node) => node.requiredDocumentType === requiredDocumentType,\n );\n};\n\n/**\n * Gets all nodes of a specific type\n *\n * @param template - The session template\n * @param nodeType - The type of node to get\n * @returns Array of nodes matching the type\n */\nexport const getNodesByType = (\n template: SessionTemplate,\n nodeType: string,\n): SessionTemplateNode[] => {\n return template.nodes.filter((node) => node.type === nodeType);\n};\n\n/**\n * Gets all nodes with a specific requiredDocumentType\n *\n * @param template - The session template\n * @param requiredDocumentType - The requiredDocumentType to get\n * @returns Array of nodes matching the requiredDocumentType\n */\nexport const getNodesByDocumentType = (\n template: SessionTemplate,\n requiredDocumentType: string,\n): SessionTemplateNode[] => {\n return template.nodes.filter(\n (node) => node.requiredDocumentType === requiredDocumentType,\n );\n};\n\n/**\n * Get document options for a specific document type\n *\n * @param template - The session template\n * @param requiredDocumentType - The document type to get options for\n * @returns Array of document options (empty if none found)\n */\nexport const getDocumentOptions = (\n template: SessionTemplate,\n requiredDocumentType: string,\n): string[] => {\n const node = template.nodes.find(\n (node) => node.requiredDocumentType === requiredDocumentType,\n );\n return node?.selectedOptions || [];\n};\n\n/**\n * Determines if the session template has a selfie step\n *\n * @param template - The session template\n * @returns true if the template has a selfie step, false otherwise\n */\nexport const hasSelfieCaptureStep = (template: SessionTemplate): boolean => {\n return hasNodeType(template, \"selfie-capture\");\n};\n\n/**\n * Determines if the session template has an ID document step\n *\n * @param template - The session template\n * @returns true if the template has an ID document step, false otherwise\n */\nexport const hasDocumentStep = (template: SessionTemplate): boolean => {\n // Check if there's any document-selection node with requiredDocumentType \"id-card\"\n // or if none specified, just check for document-selection nodes\n const hasIDCard = hasDocumentTypeNode(template, \"id-card\");\n return hasIDCard || hasNodeType(template, \"document-selection\");\n};\n\n/**\n * Determines if the session template has a JDD (proof of address) step\n *\n * @param template - The session template\n * @returns true if the template has a JDD step, false otherwise\n */\nexport const hasJDDStep = (template: SessionTemplate): boolean => {\n return hasDocumentTypeNode(template, \"jdd\");\n};\n\n/**\n * Determines if the session template has a proof of funds step\n *\n * @param template - The session template\n * @returns true if the template has a proof of funds step, false otherwise\n */\nexport const hasProofOfFundsStep = (template: SessionTemplate): boolean => {\n return hasDocumentTypeNode(template, \"income-proof\");\n};\n\n/**\n * Determines if the session template has a document collection step\n *\n * @param template - The session template\n * @returns true if the template has a document collection step, false otherwise\n */\nexport const hasDocumentCollectionStep = (\n template: SessionTemplate,\n): boolean => {\n return hasNodeType(template, \"document-collection\");\n};\n\n/**\n * Gets all node types in the template\n *\n * @param template - The session template\n * @returns Array of node types in the template\n */\nexport const getNodeTypes = (template: SessionTemplate): string[] => {\n return Array.from(new Set(template.nodes.map((node) => node.type)));\n};\n\n/**\n * Gets all document types required in the template\n *\n * @param template - The session template\n * @returns Array of document types required in the template\n */\nexport const getRequiredDocumentTypes = (\n template: SessionTemplate,\n): string[] => {\n return Array.from(\n new Set(\n template.nodes\n .filter((node) => node.requiredDocumentType)\n .map((node) => node.requiredDocumentType!),\n ),\n );\n};\n\n/**\n * Converts template document type to internal document type\n * This helps standardize document types between the template and the application\n *\n * @param templateDocType - The document type as defined in the template\n * @returns The internal document type used by the application\n */\nexport const convertTemplateDocTypeToInternal = (\n templateDocType: string,\n): string => {\n if (!templateDocType) return \"\";\n\n // Mapping between template document types and internal document types\n const typeMap: Record<string, string> = {\n \"id-card\": \"id-card\",\n jdd: \"jdd\",\n \"income-proof\": \"income-proof\", // Using consistent naming\n };\n\n return typeMap[templateDocType] || templateDocType;\n};\n\n/**\n * Converts internal document type to template document type\n *\n * @param internalDocType - The document type used internally by the application\n * @returns The document type as expected in the template\n */\nexport const convertInternalDocTypeToTemplate = (\n internalDocType: string,\n): string => {\n if (!internalDocType) return \"\";\n\n // Mapping between internal document types and template document types\n const typeMap: Record<string, string> = {\n \"id-card\": \"id-card\",\n jdd: \"jdd\",\n funds: \"income-proof\", // Map funds to income-proof for backwards compatibility\n \"income-proof\": \"income-proof\",\n };\n\n return typeMap[internalDocType] || internalDocType;\n};\n\n/**\n * Updates session data with user input information\n *\n * @param sessionId - The unique identifier of the session\n * @param userInput - The user input data (firstName, lastName, birthDate)\n * @returns The updated session data\n */\nexport const updateSessionUserInput = async (\n sessionId: string,\n userInput: {\n firstName?: string;\n lastName?: string;\n birthDate?: string;\n [key: string]: unknown;\n },\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n userInput,\n });\n return response.data;\n } catch (error) {\n console.error(\"Error updating session data:\", error);\n throw error;\n }\n};\n\n/**\n * Records the NFC fallback reason when the user declares they cannot use the\n * contactless scan, and marks the NFC scan as skipped server-side.\n *\n * @param sessionId - The unique identifier of the session\n * @param payload - The selected reason (technical key), its human-readable label,\n * and an optional free-text comment.\n */\nexport const skipNfcWithReason = async (\n sessionId: string,\n payload: { reason: string; label: string; comment?: string },\n): Promise<void> => {\n await apiService.post(`/session/sdk/${sessionId}/nfc-skip`, payload);\n};\n\n/**\n * Updates session data with contact information\n *\n * @param sessionId - The unique identifier of the session\n * @param contactInfo - The contact information data (email, phoneNumber)\n * @returns The updated session data\n */\nexport const updateSessionContactInfo = async (\n sessionId: string,\n contactInfo: {\n email: string;\n phoneNumber: string;\n [key: string]: unknown;\n },\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n contactInfo,\n });\n return response.data;\n } catch (error) {\n console.error(\"Error updating contact information:\", error);\n throw error;\n }\n};\n\n/**\n * Updates session status\n *\n * @param sessionId - The unique identifier of the session\n * @param status - The new status for the session\n * @param reachedEndNodeId - Id of the end node actually reached (when status is \"ended\"),\n * so the backend can force the correct final status with multiple end nodes.\n * @returns The updated session data\n */\nexport const updateSessionStatus = async (\n sessionId: string,\n status: string,\n reachedEndNodeId?: string,\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n status,\n ...(reachedEndNodeId ? { reachedEndNodeId } : {}),\n });\n\n // Log status modification in audit trail\n if (response.data && response.data.analysisId) {\n try {\n await logStatusModified(\n sessionId,\n status,\n response.data.clientInfoId || undefined,\n );\n } catch (err) {\n console.error(\"Failed to log status modification in audit trail:\", err);\n // Non-blocking error - continue session\n }\n }\n\n return response.data;\n } catch (error) {\n console.error(\"Error updating session status:\", error);\n throw error;\n }\n};\n\n/**\n * Updates the current step in the session\n *\n * @param sessionId - The unique identifier of the session\n * @param currentStep - The current step index in the workflow\n * @returns The updated session data\n */\nexport const updateSessionCurrentStep = async (\n sessionId: string,\n currentStep: number,\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n currentStep,\n });\n return response.data;\n } catch (error) {\n console.error(\"Error updating session current step:\", error);\n throw error;\n }\n};\n\n/**\n * Gets the journey steps from the template in order\n *\n * @param template - The session template\n * @returns Array of ordered steps\n */\nexport const getOrderedJourneySteps = (\n template: SessionTemplate,\n): SessionTemplateNode[] => {\n // Filter out only start nodes, keep end nodes for proper journey completion, then sort by order.\n // Tiebreaker on id keeps the ordering deterministic when several nodes share the same `order`\n // (e.g. parallel branches of a condition), independently of their position in template.nodes.\n return template.nodes\n .filter((node) => node.type !== \"start\")\n .sort((a, b) => a.order - b.order || a.id.localeCompare(b.id));\n};\n\nconst normalizeHandle = (value?: string): string => {\n return (value || \"\").trim().toLowerCase();\n};\n\n/**\n * Finds the outgoing edge to follow from a node.\n *\n * Resolution order:\n * 1. Exact handle match via sourceHandle/conditionValue.\n * 2. For condition:false loops, fallback to targetHandle=right.\n * 3. First outgoing edge as final fallback.\n */\nexport const findOutgoingEdge = (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n): SessionTemplate[\"edges\"][number] | null => {\n const outgoingEdges = (template.edges || []).filter(\n (edge) => edge.source === currentNodeId,\n );\n\n if (outgoingEdges.length === 0) {\n return null;\n }\n\n if (!handle) {\n return outgoingEdges[0];\n }\n\n const normalizedHandle = normalizeHandle(handle);\n const edgeByHandle = outgoingEdges.find((edge) => {\n return (\n normalizeHandle(edge.sourceHandle) === normalizedHandle ||\n normalizeHandle(edge.conditionValue) === normalizedHandle\n );\n });\n\n if (edgeByHandle) {\n return edgeByHandle;\n }\n\n const currentNode = template.nodes.find((node) => node.id === currentNodeId);\n if (currentNode?.type === \"condition\" && normalizedHandle === \"false\") {\n const rightHandleLoopEdge = outgoingEdges.find(\n (edge) => normalizeHandle(edge.targetHandle) === \"right\",\n );\n if (rightHandleLoopEdge) {\n return rightHandleLoopEdge;\n }\n }\n\n return outgoingEdges[0];\n};\n\n/**\n * Gets the next step index by following the graph edge from the current node\n *\n * @param currentNodeId - The ID of the current node\n * @param template - The session template\n * @returns The next step index (1-based) or null if no edge found\n */\nexport const getNextStepIndex = (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n): number | null => {\n const orderedNodes = getOrderedJourneySteps(template);\n const edge = findOutgoingEdge(currentNodeId, template, handle);\n\n if (!edge) {\n console.debug(\n `[sessionService] No outgoing edge found for node ${currentNodeId}${handle ? ` with handle ${handle}` : \"\"}`,\n );\n return null;\n }\n\n const targetId = edge.target;\n const targetIndex = orderedNodes.findIndex((n) => n.id === targetId);\n\n if (targetIndex === -1) {\n console.debug(\n `[sessionService] Target node ${targetId} not found in ordered steps`,\n );\n return null;\n }\n\n // steps are 1-indexed in the SDK (0 is StartSession)\n return 1 + targetIndex;\n};\n\n/**\n * Reconstructs the navigation history by following the graph from step 0\n * up to (and including) targetStep. Returns [0, ...stepIndices].\n * If the graph path cannot reach targetStep, falls back to [0, targetStep].\n */\nexport const reconstructHistoryToStep = (\n targetStep: number,\n template: SessionTemplate,\n): number[] => {\n if (targetStep <= 0) return [0];\n\n const orderedNodes = getOrderedJourneySteps(template);\n const history: number[] = [0];\n let currentStep = 1; // first node is step 1\n\n // Follow the default (first) edge from each node in sequence\n for (let safetyLimit = 0; safetyLimit < orderedNodes.length + 1; safetyLimit++) {\n if (currentStep === targetStep) {\n history.push(currentStep);\n break;\n }\n if (currentStep > targetStep) break;\n\n const nodeIndex = currentStep - 1;\n const currentNode = orderedNodes[nodeIndex];\n if (!currentNode) break;\n\n history.push(currentStep);\n\n const nextStep = getNextStepIndex(currentNode.id, template);\n if (nextStep === null) break;\n currentStep = nextStep;\n }\n\n // Fallback: if we couldn't reach targetStep via graph, use simple seed\n if (history[history.length - 1] !== targetStep) {\n return [0, targetStep];\n }\n\n return history;\n};\n\n/**\n * Maps a template node type to a step component type\n *\n * @param node - The session template node\n * @returns The step component type\n */\nexport const getStepComponentType = (node: SessionTemplateNode): string => {\n // Map from template node types to component types\n const typeMap: Record<string, string> = {\n \"document-selection\": \"document\",\n \"document-collection\": \"document-collection\",\n \"selfie-capture\": \"selfie\",\n \"contact-info\": \"contact-info\",\n \"user-input\": \"user-input\",\n \"otp-verification\": \"otp\",\n };\n\n // First check the node type\n if (node.type in typeMap) {\n return typeMap[node.type];\n }\n\n // Then check the requiredDocumentType\n if (node.requiredDocumentType) {\n return node.requiredDocumentType;\n }\n\n // Default fallback\n return node.type;\n};\n\n/**\n * Checks if a session has expired\n *\n * @param session - The session data to check\n * @returns true if the session has expired, false otherwise\n */\nexport const isSessionExpired = (session: SessionData): boolean => {\n if (!session.expireTime) {\n return false;\n }\n\n const currentTime = Date.now();\n return currentTime > session.expireTime;\n};\n\n/**\n * Stores document options in localStorage for a specific document type\n *\n * @param sessionId - The session ID\n * @param documentTypeId - The document type ID (e.g., 'jdd', 'income-proof')\n * @param options - The options to store\n */\nexport const storeDocumentOptions = (\n sessionId: string,\n documentTypeId: string,\n options: string[],\n): void => {\n if (!sessionId || !documentTypeId || !options || options.length === 0) {\n console.warn(\"Missing data for storeDocumentOptions:\", {\n sessionId,\n documentTypeId,\n options,\n });\n return;\n }\n\n // Create a consistent key format based on document type\n let storageKey = \"\";\n\n switch (documentTypeId) {\n case \"jdd\":\n storageKey = `jddOptions_${sessionId}`;\n break;\n case \"income-proof\":\n storageKey = `fundsOptions_${sessionId}`;\n break;\n case \"id-card\":\n storageKey = `idOptions_${sessionId}`;\n break;\n case \"document-collection\":\n storageKey = `documentCollectionOptions_${sessionId}`;\n break;\n default:\n storageKey = `${documentTypeId}Options_${sessionId}`;\n }\n\n localStorage.setItem(storageKey, JSON.stringify(options));\n};\n\n/**\n * Retrieves document options from localStorage for a specific document type\n *\n * @param sessionId - The session ID\n * @param documentTypeId - The document type ID (e.g., 'jdd', 'income-proof')\n * @returns Array of options or default options if none found\n */\nexport const retrieveDocumentOptions = (\n sessionId: string,\n documentTypeId: string,\n): string[] => {\n if (!sessionId || !documentTypeId) {\n console.warn(\"Missing data for retrieveDocumentOptions:\", {\n sessionId,\n documentTypeId,\n });\n return [];\n }\n\n // Create consistent key formats to check\n const possibleKeys = [\n `${documentTypeId}Options_${sessionId}`,\n documentTypeId === \"jdd\" ? `jddOptions_${sessionId}` : \"\",\n documentTypeId === \"income-proof\" ? `fundsOptions_${sessionId}` : \"\",\n documentTypeId === \"id-card\" ? `idOptions_${sessionId}` : \"\",\n documentTypeId === \"document-collection\"\n ? `documentCollectionOptions_${sessionId}`\n : \"\",\n ].filter(Boolean);\n\n // Try each possible key\n for (const key of possibleKeys) {\n const savedOptions = localStorage.getItem(key);\n if (savedOptions) {\n try {\n const parsedOptions = JSON.parse(savedOptions);\n\n return parsedOptions;\n } catch (e) {\n console.error(\n `Error parsing options for ${documentTypeId} with key ${key}:`,\n e,\n );\n }\n }\n }\n\n // Return default options if none found\n console.warn(`No options found for ${documentTypeId}, using defaults`);\n if (documentTypeId === \"jdd\") {\n return [\n \"Facture d'électricité (< 3 mois)\",\n \"Facture de gaz (< 3 mois)\",\n \"Facture d'eau (< 3 mois)\",\n \"Quittance de loyer (< 3 mois)\",\n \"Facture téléphone/internet (< 3 mois)\",\n \"Attestation d'assurance habitation (< 3 mois)\",\n ];\n } else if (documentTypeId === \"income-proof\") {\n return [\n \"Bulletin de salaire\",\n \"Avis d'imposition\",\n \"Relevé de compte bancaire\",\n \"Attestation de revenus\",\n \"Contrat de travail\",\n ];\n } else if (documentTypeId === \"id-card\") {\n return [\"Carte nationale d'identité\", \"Passeport\", \"Permis de conduire\"];\n } else if (documentTypeId === \"document-collection\") {\n return [\"Document administratif\", \"Justificatif\", \"Attestation\"];\n }\n\n return [];\n};\n\nconst clearStorageBySessionId = (sessionId: string): void => {\n const scopedKeys = [\n `userInput_${sessionId}`,\n `contactInfo_${sessionId}`,\n `sessionData_${sessionId}`,\n ];\n\n scopedKeys.forEach((key) => {\n localStorage.removeItem(key);\n sessionStorage.removeItem(key);\n });\n\n for (let i = localStorage.length - 1; i >= 0; i -= 1) {\n const key = localStorage.key(i);\n if (!key) {\n continue;\n }\n if (key.endsWith(`_${sessionId}`)) {\n localStorage.removeItem(key);\n }\n }\n\n for (let i = sessionStorage.length - 1; i >= 0; i -= 1) {\n const key = sessionStorage.key(i);\n if (!key) {\n continue;\n }\n if (key.endsWith(`_${sessionId}`)) {\n sessionStorage.removeItem(key);\n }\n }\n\n if (localStorage.getItem(\"sessionId\") === sessionId) {\n localStorage.removeItem(\"sessionId\");\n }\n if (sessionStorage.getItem(\"sessionId\") === sessionId) {\n sessionStorage.removeItem(\"sessionId\");\n }\n};\n\n/**\n * Clears all client-side session traces (memory + browser storage)\n * for a given session. This is intentionally aggressive for security.\n */\nexport const clearSessionSensitiveData = (sessionId?: string): void => {\n clearSessionMemory(sessionId);\n\n if (sessionId) {\n clearStorageBySessionId(sessionId);\n return;\n }\n\n localStorage.removeItem(\"sessionId\");\n sessionStorage.removeItem(\"sessionId\");\n\n for (let i = localStorage.length - 1; i >= 0; i -= 1) {\n const key = localStorage.key(i);\n if (!key) {\n continue;\n }\n if (\n key.startsWith(\"userInput_\") ||\n key.startsWith(\"contactInfo_\") ||\n key.includes(\"Options_\")\n ) {\n localStorage.removeItem(key);\n }\n }\n\n for (let i = sessionStorage.length - 1; i >= 0; i -= 1) {\n const key = sessionStorage.key(i);\n if (!key) {\n continue;\n }\n if (\n key.startsWith(\"userInput_\") ||\n key.startsWith(\"contactInfo_\") ||\n key.includes(\"Options_\")\n ) {\n sessionStorage.removeItem(key);\n }\n }\n};\n\n/**\n * Returns the pre-fill data for a given run index from a `userInput` object\n * that contains a `_list` array.\n *\n * Convention: when the integrator wants to pre-fill different data per run\n * (e.g. multiple persons in a loop), they pass `userInput: { _list: [...] }`\n * at session creation. Each element in `_list` corresponds to a run (0-indexed).\n *\n * @param userInput - The session's userInput object\n * @param runIndex - The current run index (0 = first pass, 1 = second pass, …)\n * @returns The pre-fill data for that run, or null if not defined\n */\nexport const getRunPrefillData = (\n userInput: Record<string, unknown>,\n runIndex: number,\n): Record<string, unknown> | null => {\n const list = userInput?._list;\n if (!Array.isArray(list)) return null;\n return (list[runIndex] as Record<string, unknown>) ?? null;\n};\n"],"names":["__awaiter","apiService","__assign","logStatusModified","clearSessionMemory"],"mappings":"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"}
1
+ {"version":3,"file":"sessionService.js","sources":["../../../../src/services/sessionService.ts"],"sourcesContent":["/**\n * Session Service\n *\n * Service for interacting with the Datakeen Session API.\n * Handles fetching session data by ID.\n */\n\nimport type {\n ClientInfo,\n SessionData,\n SessionTemplate,\n SessionTemplateNode,\n} from \"../types/session\";\nimport { apiService } from \"./api\";\nimport { logStatusModified } from \"./auditTrailService\";\nimport { clearSessionMemory } from \"./sessionMemoryStore\";\n\n/**\n * Fetches session data by ID from the Datakeen backend\n *\n * @param sessionId - The unique identifier of the session\n * @returns The session data\n */\nexport const fetchSessionById = async (\n sessionId: string,\n): Promise<SessionData> => {\n try {\n const response = await apiService.get(`/session/sdk/${sessionId}`);\n return response.data;\n } catch (error) {\n console.error(\"Error fetching session data:\", error);\n throw error;\n }\n};\n\n/** Sends client information (IP, device, browser, OS) to the backend for a specific session\n *\n * @param sessionId - The unique identifier of the session\n * @param clientInfo - The client information to send\n */\nexport const sendClientInfo = async (\n sessionId: string,\n clientInfo: ClientInfo,\n): Promise<void> => {\n try {\n await apiService.post(`/session/sdk/${sessionId}/client-info`, clientInfo);\n } catch (error) {\n console.error(\"Error sending client info:\", error);\n throw error;\n }\n};\n\n/**\n * Determines if the session template has a specific type of node\n *\n * @param template - The session template\n * @param nodeType - The type of node to check for\n * @returns true if the template has a node of the specified type, false otherwise\n */\nexport const hasNodeType = (\n template: SessionTemplate,\n nodeType: string,\n): boolean => {\n return template.nodes.some((node) => node.type === nodeType);\n};\n\n/**\n * Determines if the session template has a node with a specific requiredDocumentType\n *\n * @param template - The session template\n * @param requiredDocumentType - The requiredDocumentType to check for\n * @returns true if the template has a node with the specified requiredDocumentType, false otherwise\n */\nexport const hasDocumentTypeNode = (\n template: SessionTemplate,\n requiredDocumentType: string,\n): boolean => {\n return template.nodes.some(\n (node) => node.requiredDocumentType === requiredDocumentType,\n );\n};\n\n/**\n * Gets all nodes of a specific type\n *\n * @param template - The session template\n * @param nodeType - The type of node to get\n * @returns Array of nodes matching the type\n */\nexport const getNodesByType = (\n template: SessionTemplate,\n nodeType: string,\n): SessionTemplateNode[] => {\n return template.nodes.filter((node) => node.type === nodeType);\n};\n\n/**\n * Gets all nodes with a specific requiredDocumentType\n *\n * @param template - The session template\n * @param requiredDocumentType - The requiredDocumentType to get\n * @returns Array of nodes matching the requiredDocumentType\n */\nexport const getNodesByDocumentType = (\n template: SessionTemplate,\n requiredDocumentType: string,\n): SessionTemplateNode[] => {\n return template.nodes.filter(\n (node) => node.requiredDocumentType === requiredDocumentType,\n );\n};\n\n/**\n * Get document options for a specific document type\n *\n * @param template - The session template\n * @param requiredDocumentType - The document type to get options for\n * @returns Array of document options (empty if none found)\n */\nexport const getDocumentOptions = (\n template: SessionTemplate,\n requiredDocumentType: string,\n): string[] => {\n const node = template.nodes.find(\n (node) => node.requiredDocumentType === requiredDocumentType,\n );\n return node?.selectedOptions || [];\n};\n\n/**\n * Determines if the session template has a selfie step\n *\n * @param template - The session template\n * @returns true if the template has a selfie step, false otherwise\n */\nexport const hasSelfieCaptureStep = (template: SessionTemplate): boolean => {\n return hasNodeType(template, \"selfie-capture\");\n};\n\n/**\n * Determines if the session template has an ID document step\n *\n * @param template - The session template\n * @returns true if the template has an ID document step, false otherwise\n */\nexport const hasDocumentStep = (template: SessionTemplate): boolean => {\n // Check if there's any document-selection node with requiredDocumentType \"id-card\"\n // or if none specified, just check for document-selection nodes\n const hasIDCard = hasDocumentTypeNode(template, \"id-card\");\n return hasIDCard || hasNodeType(template, \"document-selection\");\n};\n\n/**\n * Determines if the session template has a JDD (proof of address) step\n *\n * @param template - The session template\n * @returns true if the template has a JDD step, false otherwise\n */\nexport const hasJDDStep = (template: SessionTemplate): boolean => {\n return hasDocumentTypeNode(template, \"jdd\");\n};\n\n/**\n * Determines if the session template has a proof of funds step\n *\n * @param template - The session template\n * @returns true if the template has a proof of funds step, false otherwise\n */\nexport const hasProofOfFundsStep = (template: SessionTemplate): boolean => {\n return hasDocumentTypeNode(template, \"income-proof\");\n};\n\n/**\n * Determines if the session template has a document collection step\n *\n * @param template - The session template\n * @returns true if the template has a document collection step, false otherwise\n */\nexport const hasDocumentCollectionStep = (\n template: SessionTemplate,\n): boolean => {\n return hasNodeType(template, \"document-collection\");\n};\n\n/**\n * Gets all node types in the template\n *\n * @param template - The session template\n * @returns Array of node types in the template\n */\nexport const getNodeTypes = (template: SessionTemplate): string[] => {\n return Array.from(new Set(template.nodes.map((node) => node.type)));\n};\n\n/**\n * Gets all document types required in the template\n *\n * @param template - The session template\n * @returns Array of document types required in the template\n */\nexport const getRequiredDocumentTypes = (\n template: SessionTemplate,\n): string[] => {\n return Array.from(\n new Set(\n template.nodes\n .filter((node) => node.requiredDocumentType)\n .map((node) => node.requiredDocumentType!),\n ),\n );\n};\n\n/**\n * Converts template document type to internal document type\n * This helps standardize document types between the template and the application\n *\n * @param templateDocType - The document type as defined in the template\n * @returns The internal document type used by the application\n */\nexport const convertTemplateDocTypeToInternal = (\n templateDocType: string,\n): string => {\n if (!templateDocType) return \"\";\n\n // Mapping between template document types and internal document types\n const typeMap: Record<string, string> = {\n \"id-card\": \"id-card\",\n jdd: \"jdd\",\n \"income-proof\": \"income-proof\", // Using consistent naming\n };\n\n return typeMap[templateDocType] || templateDocType;\n};\n\n/**\n * Converts internal document type to template document type\n *\n * @param internalDocType - The document type used internally by the application\n * @returns The document type as expected in the template\n */\nexport const convertInternalDocTypeToTemplate = (\n internalDocType: string,\n): string => {\n if (!internalDocType) return \"\";\n\n // Mapping between internal document types and template document types\n const typeMap: Record<string, string> = {\n \"id-card\": \"id-card\",\n jdd: \"jdd\",\n funds: \"income-proof\", // Map funds to income-proof for backwards compatibility\n \"income-proof\": \"income-proof\",\n };\n\n return typeMap[internalDocType] || internalDocType;\n};\n\n/**\n * Updates session data with user input information\n *\n * @param sessionId - The unique identifier of the session\n * @param userInput - The user input data (firstName, lastName, birthDate)\n * @returns The updated session data\n */\nexport const updateSessionUserInput = async (\n sessionId: string,\n userInput: {\n firstName?: string;\n lastName?: string;\n birthDate?: string;\n [key: string]: unknown;\n },\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n userInput,\n });\n return response.data;\n } catch (error) {\n console.error(\"Error updating session data:\", error);\n throw error;\n }\n};\n\n/**\n * Records the NFC fallback reason when the user declares they cannot use the\n * contactless scan, and marks the NFC scan as skipped server-side.\n *\n * @param sessionId - The unique identifier of the session\n * @param payload - The selected reason (technical key), its human-readable label,\n * and an optional free-text comment.\n */\nexport const skipNfcWithReason = async (\n sessionId: string,\n payload: { reason: string; label: string; comment?: string },\n): Promise<void> => {\n await apiService.post(`/session/sdk/${sessionId}/nfc-skip`, payload);\n};\n\n/**\n * Resets a terminal NFC failure before the user starts again with another\n * document. The backend keeps completed scans immutable and treats this call\n * as a no-op when the status is not terminal.\n */\nexport const resetNfcScan = async (sessionId: string): Promise<void> => {\n await apiService.post(`/session/sdk/${sessionId}/nfc-reset`);\n};\n\n/**\n * Updates session data with contact information\n *\n * @param sessionId - The unique identifier of the session\n * @param contactInfo - The contact information data (email, phoneNumber)\n * @returns The updated session data\n */\nexport const updateSessionContactInfo = async (\n sessionId: string,\n contactInfo: {\n email: string;\n phoneNumber: string;\n [key: string]: unknown;\n },\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n contactInfo,\n });\n return response.data;\n } catch (error) {\n console.error(\"Error updating contact information:\", error);\n throw error;\n }\n};\n\n/**\n * Updates session status\n *\n * @param sessionId - The unique identifier of the session\n * @param status - The new status for the session\n * @param reachedEndNodeId - Id of the end node actually reached (when status is \"ended\"),\n * so the backend can force the correct final status with multiple end nodes.\n * @returns The updated session data\n */\nexport const updateSessionStatus = async (\n sessionId: string,\n status: string,\n reachedEndNodeId?: string,\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n status,\n ...(reachedEndNodeId ? { reachedEndNodeId } : {}),\n });\n\n // Log status modification in audit trail\n if (response.data && response.data.analysisId) {\n try {\n await logStatusModified(\n sessionId,\n status,\n response.data.clientInfoId || undefined,\n );\n } catch (err) {\n console.error(\"Failed to log status modification in audit trail:\", err);\n // Non-blocking error - continue session\n }\n }\n\n return response.data;\n } catch (error) {\n console.error(\"Error updating session status:\", error);\n throw error;\n }\n};\n\n/**\n * Updates the current step in the session\n *\n * @param sessionId - The unique identifier of the session\n * @param currentStep - The current step index in the workflow\n * @returns The updated session data\n */\nexport const updateSessionCurrentStep = async (\n sessionId: string,\n currentStep: number,\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n currentStep,\n });\n return response.data;\n } catch (error) {\n console.error(\"Error updating session current step:\", error);\n throw error;\n }\n};\n\n/**\n * Gets the journey steps from the template in order\n *\n * @param template - The session template\n * @returns Array of ordered steps\n */\nexport const getOrderedJourneySteps = (\n template: SessionTemplate,\n): SessionTemplateNode[] => {\n // Filter out only start nodes, keep end nodes for proper journey completion, then sort by order.\n // Tiebreaker on id keeps the ordering deterministic when several nodes share the same `order`\n // (e.g. parallel branches of a condition), independently of their position in template.nodes.\n return template.nodes\n .filter((node) => node.type !== \"start\")\n .sort((a, b) => a.order - b.order || a.id.localeCompare(b.id));\n};\n\nconst normalizeHandle = (value?: string): string => {\n return (value || \"\").trim().toLowerCase();\n};\n\n/**\n * Finds the outgoing edge to follow from a node.\n *\n * Resolution order:\n * 1. Exact handle match via sourceHandle/conditionValue.\n * 2. For condition:false loops, fallback to targetHandle=right.\n * 3. First outgoing edge as final fallback.\n */\nexport const findOutgoingEdge = (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n): SessionTemplate[\"edges\"][number] | null => {\n const outgoingEdges = (template.edges || []).filter(\n (edge) => edge.source === currentNodeId,\n );\n\n if (outgoingEdges.length === 0) {\n return null;\n }\n\n if (!handle) {\n return outgoingEdges[0];\n }\n\n const normalizedHandle = normalizeHandle(handle);\n const edgeByHandle = outgoingEdges.find((edge) => {\n return (\n normalizeHandle(edge.sourceHandle) === normalizedHandle ||\n normalizeHandle(edge.conditionValue) === normalizedHandle\n );\n });\n\n if (edgeByHandle) {\n return edgeByHandle;\n }\n\n const currentNode = template.nodes.find((node) => node.id === currentNodeId);\n if (currentNode?.type === \"condition\" && normalizedHandle === \"false\") {\n const rightHandleLoopEdge = outgoingEdges.find(\n (edge) => normalizeHandle(edge.targetHandle) === \"right\",\n );\n if (rightHandleLoopEdge) {\n return rightHandleLoopEdge;\n }\n }\n\n return outgoingEdges[0];\n};\n\n/**\n * Gets the next step index by following the graph edge from the current node\n *\n * @param currentNodeId - The ID of the current node\n * @param template - The session template\n * @returns The next step index (1-based) or null if no edge found\n */\nexport const getNextStepIndex = (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n): number | null => {\n const orderedNodes = getOrderedJourneySteps(template);\n const edge = findOutgoingEdge(currentNodeId, template, handle);\n\n if (!edge) {\n console.debug(\n `[sessionService] No outgoing edge found for node ${currentNodeId}${handle ? ` with handle ${handle}` : \"\"}`,\n );\n return null;\n }\n\n const targetId = edge.target;\n const targetIndex = orderedNodes.findIndex((n) => n.id === targetId);\n\n if (targetIndex === -1) {\n console.debug(\n `[sessionService] Target node ${targetId} not found in ordered steps`,\n );\n return null;\n }\n\n // steps are 1-indexed in the SDK (0 is StartSession)\n return 1 + targetIndex;\n};\n\n/**\n * Reconstructs the navigation history by following the graph from step 0\n * up to (and including) targetStep. Returns [0, ...stepIndices].\n * If the graph path cannot reach targetStep, falls back to [0, targetStep].\n */\nexport const reconstructHistoryToStep = (\n targetStep: number,\n template: SessionTemplate,\n): number[] => {\n if (targetStep <= 0) return [0];\n\n const orderedNodes = getOrderedJourneySteps(template);\n const history: number[] = [0];\n let currentStep = 1; // first node is step 1\n\n // Follow the default (first) edge from each node in sequence\n for (let safetyLimit = 0; safetyLimit < orderedNodes.length + 1; safetyLimit++) {\n if (currentStep === targetStep) {\n history.push(currentStep);\n break;\n }\n if (currentStep > targetStep) break;\n\n const nodeIndex = currentStep - 1;\n const currentNode = orderedNodes[nodeIndex];\n if (!currentNode) break;\n\n history.push(currentStep);\n\n const nextStep = getNextStepIndex(currentNode.id, template);\n if (nextStep === null) break;\n currentStep = nextStep;\n }\n\n // Fallback: if we couldn't reach targetStep via graph, use simple seed\n if (history[history.length - 1] !== targetStep) {\n return [0, targetStep];\n }\n\n return history;\n};\n\n/**\n * Maps a template node type to a step component type\n *\n * @param node - The session template node\n * @returns The step component type\n */\nexport const getStepComponentType = (node: SessionTemplateNode): string => {\n // Map from template node types to component types\n const typeMap: Record<string, string> = {\n \"document-selection\": \"document\",\n \"document-collection\": \"document-collection\",\n \"selfie-capture\": \"selfie\",\n \"contact-info\": \"contact-info\",\n \"user-input\": \"user-input\",\n \"otp-verification\": \"otp\",\n };\n\n // First check the node type\n if (node.type in typeMap) {\n return typeMap[node.type];\n }\n\n // Then check the requiredDocumentType\n if (node.requiredDocumentType) {\n return node.requiredDocumentType;\n }\n\n // Default fallback\n return node.type;\n};\n\n/**\n * Checks if a session has expired\n *\n * @param session - The session data to check\n * @returns true if the session has expired, false otherwise\n */\nexport const isSessionExpired = (session: SessionData): boolean => {\n if (!session.expireTime) {\n return false;\n }\n\n const currentTime = Date.now();\n return currentTime > session.expireTime;\n};\n\n/**\n * Stores document options in localStorage for a specific document type\n *\n * @param sessionId - The session ID\n * @param documentTypeId - The document type ID (e.g., 'jdd', 'income-proof')\n * @param options - The options to store\n */\nexport const storeDocumentOptions = (\n sessionId: string,\n documentTypeId: string,\n options: string[],\n): void => {\n if (!sessionId || !documentTypeId || !options || options.length === 0) {\n console.warn(\"Missing data for storeDocumentOptions:\", {\n sessionId,\n documentTypeId,\n options,\n });\n return;\n }\n\n // Create a consistent key format based on document type\n let storageKey = \"\";\n\n switch (documentTypeId) {\n case \"jdd\":\n storageKey = `jddOptions_${sessionId}`;\n break;\n case \"income-proof\":\n storageKey = `fundsOptions_${sessionId}`;\n break;\n case \"id-card\":\n storageKey = `idOptions_${sessionId}`;\n break;\n case \"document-collection\":\n storageKey = `documentCollectionOptions_${sessionId}`;\n break;\n default:\n storageKey = `${documentTypeId}Options_${sessionId}`;\n }\n\n localStorage.setItem(storageKey, JSON.stringify(options));\n};\n\n/**\n * Retrieves document options from localStorage for a specific document type\n *\n * @param sessionId - The session ID\n * @param documentTypeId - The document type ID (e.g., 'jdd', 'income-proof')\n * @returns Array of options or default options if none found\n */\nexport const retrieveDocumentOptions = (\n sessionId: string,\n documentTypeId: string,\n): string[] => {\n if (!sessionId || !documentTypeId) {\n console.warn(\"Missing data for retrieveDocumentOptions:\", {\n sessionId,\n documentTypeId,\n });\n return [];\n }\n\n // Create consistent key formats to check\n const possibleKeys = [\n `${documentTypeId}Options_${sessionId}`,\n documentTypeId === \"jdd\" ? `jddOptions_${sessionId}` : \"\",\n documentTypeId === \"income-proof\" ? `fundsOptions_${sessionId}` : \"\",\n documentTypeId === \"id-card\" ? `idOptions_${sessionId}` : \"\",\n documentTypeId === \"document-collection\"\n ? `documentCollectionOptions_${sessionId}`\n : \"\",\n ].filter(Boolean);\n\n // Try each possible key\n for (const key of possibleKeys) {\n const savedOptions = localStorage.getItem(key);\n if (savedOptions) {\n try {\n const parsedOptions = JSON.parse(savedOptions);\n\n return parsedOptions;\n } catch (e) {\n console.error(\n `Error parsing options for ${documentTypeId} with key ${key}:`,\n e,\n );\n }\n }\n }\n\n // Return default options if none found\n console.warn(`No options found for ${documentTypeId}, using defaults`);\n if (documentTypeId === \"jdd\") {\n return [\n \"Facture d'électricité (< 3 mois)\",\n \"Facture de gaz (< 3 mois)\",\n \"Facture d'eau (< 3 mois)\",\n \"Quittance de loyer (< 3 mois)\",\n \"Facture téléphone/internet (< 3 mois)\",\n \"Attestation d'assurance habitation (< 3 mois)\",\n ];\n } else if (documentTypeId === \"income-proof\") {\n return [\n \"Bulletin de salaire\",\n \"Avis d'imposition\",\n \"Relevé de compte bancaire\",\n \"Attestation de revenus\",\n \"Contrat de travail\",\n ];\n } else if (documentTypeId === \"id-card\") {\n return [\"Carte nationale d'identité\", \"Passeport\", \"Permis de conduire\"];\n } else if (documentTypeId === \"document-collection\") {\n return [\"Document administratif\", \"Justificatif\", \"Attestation\"];\n }\n\n return [];\n};\n\nconst clearStorageBySessionId = (sessionId: string): void => {\n const scopedKeys = [\n `userInput_${sessionId}`,\n `contactInfo_${sessionId}`,\n `sessionData_${sessionId}`,\n ];\n\n scopedKeys.forEach((key) => {\n localStorage.removeItem(key);\n sessionStorage.removeItem(key);\n });\n\n for (let i = localStorage.length - 1; i >= 0; i -= 1) {\n const key = localStorage.key(i);\n if (!key) {\n continue;\n }\n if (key.endsWith(`_${sessionId}`)) {\n localStorage.removeItem(key);\n }\n }\n\n for (let i = sessionStorage.length - 1; i >= 0; i -= 1) {\n const key = sessionStorage.key(i);\n if (!key) {\n continue;\n }\n if (key.endsWith(`_${sessionId}`)) {\n sessionStorage.removeItem(key);\n }\n }\n\n if (localStorage.getItem(\"sessionId\") === sessionId) {\n localStorage.removeItem(\"sessionId\");\n }\n if (sessionStorage.getItem(\"sessionId\") === sessionId) {\n sessionStorage.removeItem(\"sessionId\");\n }\n};\n\n/**\n * Clears all client-side session traces (memory + browser storage)\n * for a given session. This is intentionally aggressive for security.\n */\nexport const clearSessionSensitiveData = (sessionId?: string): void => {\n clearSessionMemory(sessionId);\n\n if (sessionId) {\n clearStorageBySessionId(sessionId);\n return;\n }\n\n localStorage.removeItem(\"sessionId\");\n sessionStorage.removeItem(\"sessionId\");\n\n for (let i = localStorage.length - 1; i >= 0; i -= 1) {\n const key = localStorage.key(i);\n if (!key) {\n continue;\n }\n if (\n key.startsWith(\"userInput_\") ||\n key.startsWith(\"contactInfo_\") ||\n key.includes(\"Options_\")\n ) {\n localStorage.removeItem(key);\n }\n }\n\n for (let i = sessionStorage.length - 1; i >= 0; i -= 1) {\n const key = sessionStorage.key(i);\n if (!key) {\n continue;\n }\n if (\n key.startsWith(\"userInput_\") ||\n key.startsWith(\"contactInfo_\") ||\n key.includes(\"Options_\")\n ) {\n sessionStorage.removeItem(key);\n }\n }\n};\n\n/**\n * Returns the pre-fill data for a given run index from a `userInput` object\n * that contains a `_list` array.\n *\n * Convention: when the integrator wants to pre-fill different data per run\n * (e.g. multiple persons in a loop), they pass `userInput: { _list: [...] }`\n * at session creation. Each element in `_list` corresponds to a run (0-indexed).\n *\n * @param userInput - The session's userInput object\n * @param runIndex - The current run index (0 = first pass, 1 = second pass, …)\n * @returns The pre-fill data for that run, or null if not defined\n */\nexport const getRunPrefillData = (\n userInput: Record<string, unknown>,\n runIndex: number,\n): Record<string, unknown> | null => {\n const list = userInput?._list;\n if (!Array.isArray(list)) return null;\n return (list[runIndex] as Record<string, unknown>) ?? null;\n};\n"],"names":["__awaiter","apiService","__assign","logStatusModified","clearSessionMemory"],"mappings":"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"}
@@ -5,6 +5,7 @@ import QRCode from 'qrcode';
5
5
  import { useI18n } from '../../hooks/useI18n.js';
6
6
  import { useNfcSseStatus } from '../../hooks/useNfcSseStatus.js';
7
7
  import { getBaseURL } from '../../services/api.js';
8
+ import { resetNfcScan } from '../../services/sessionService.js';
8
9
  import { isMobileDevice } from '../../utils/isMobileDevice.js';
9
10
  import MobilePageLayout from '../ui/MobilePageLayout.js';
10
11
  import Button from '../ui/Button.js';
@@ -18,6 +19,8 @@ var NfcScanStep = function (_a) {
18
19
  var t = useI18n().t;
19
20
  var canvasRef = useRef(null);
20
21
  var _b = useState(null), qrError = _b[0], setQrError = _b[1];
22
+ var _c = useState(null), resetError = _c[0], setResetError = _c[1];
23
+ var _d = useState(false), isResetting = _d[0], setIsResetting = _d[1];
21
24
  // Sur mobile, on ouvre directement l'app de scan au lieu d'afficher un QR code inutile.
22
25
  var isMobile = useMemo(function () { return isMobileDevice(); }, []);
23
26
  var nfcUrl = useMemo(function () {
@@ -95,12 +98,43 @@ var NfcScanStep = function (_a) {
95
98
  }); };
96
99
  generate();
97
100
  }, [nfcUrl, status, t, isMobile]);
101
+ var handleBack = function () { return __awaiter(void 0, void 0, void 0, function () {
102
+ return __generator(this, function (_b) {
103
+ switch (_b.label) {
104
+ case 0:
105
+ if (!onBack)
106
+ return [2 /*return*/];
107
+ if (status !== "failed") {
108
+ onBack();
109
+ return [2 /*return*/];
110
+ }
111
+ setResetError(null);
112
+ setIsResetting(true);
113
+ _b.label = 1;
114
+ case 1:
115
+ _b.trys.push([1, 3, 4, 5]);
116
+ return [4 /*yield*/, resetNfcScan(sessionId)];
117
+ case 2:
118
+ _b.sent();
119
+ onBack();
120
+ return [3 /*break*/, 5];
121
+ case 3:
122
+ _b.sent();
123
+ setResetError(t("nfc_scan.reset_failed", "Impossible de réinitialiser le scan NFC. Veuillez réessayer."));
124
+ return [3 /*break*/, 5];
125
+ case 4:
126
+ setIsResetting(false);
127
+ return [7 /*endfinally*/];
128
+ case 5: return [2 /*return*/];
129
+ }
130
+ });
131
+ }); };
98
132
  // Footer : sur l'échec définitif ('failed'), les actions dédiées (revenir au choix / poursuivre
99
133
  // sans puce) sont rendues via PageActions, comme les autres écrans NFC (NfcChipGate). Sinon, un
100
134
  // simple "Retour" tant que le scan n'a pas commencé/abouti.
101
135
  var canGoBack = !!onBack && (status === "pending" || status === "opened");
102
- var footer = status === "failed" ? (jsx(PageActions, { primary: onBack ? (jsx(Button, { onClick: onBack, children: t("nfc_scan.failed_back_to_selection", "Revenir au choix du document") })) : null, secondary: onContinueWithoutChip ? (jsx(Button, { variant: "secondary", onClick: onContinueWithoutChip, children: t("nfc_scan.failed_continue_without_chip", "Poursuivre sans puce") })) : null })) : canGoBack ? (jsx(Button, { variant: "secondary", onClick: onBack, children: t("common.back", "Retour") })) : null;
103
- return (jsx(MobilePageLayout, { footer: footer, 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 flex-col justify-center items-center gap-4", 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 === "failed" ? (jsxs("div", { className: "flex flex-col items-center gap-2 p-8 text-center", children: [jsx("p", { className: "text-base font-semibold text-red-600", children: t("nfc_scan.failed_title", "Le scan n'a pas pu être vérifié") }), jsx("p", { className: "text-sm text-gray-600 leading-relaxed", children: t("nfc_scan.failed_description", "Après plusieurs tentatives, la lecture de votre document n'a pas pu être validée.") })] })) : (
136
+ var footer = status === "failed" ? (jsx(PageActions, { primary: onBack ? (jsx(Button, { onClick: function () { return void handleBack(); }, disabled: isResetting, children: t("nfc_scan.failed_back_to_selection", "Revenir au choix du document") })) : null, secondary: onContinueWithoutChip ? (jsx(Button, { variant: "secondary", onClick: onContinueWithoutChip, children: t("nfc_scan.failed_continue_without_chip", "Poursuivre sans puce") })) : null })) : canGoBack ? (jsx(Button, { variant: "secondary", onClick: onBack, children: t("common.back", "Retour") })) : null;
137
+ return (jsx(MobilePageLayout, { footer: footer, 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 flex-col justify-center items-center gap-4", 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 === "failed" ? (jsxs("div", { className: "flex flex-col items-center gap-2 p-8 text-center", children: [jsx("p", { className: "text-base font-semibold text-red-600", children: t("nfc_scan.failed_title", "Le scan n'a pas pu être vérifié") }), jsx("p", { className: "text-sm text-gray-600 leading-relaxed", children: t("nfc_scan.failed_description", "Après plusieurs tentatives, la lecture de votre document n'a pas pu être validée.") }), resetError && (jsx("p", { className: "text-sm text-red-600", role: "alert", children: resetError }))] })) : (
104
138
  // Contenu principal QR/mobile — reste monté pour "pending" ET "opened", pour ne
105
139
  // jamais démonter le canvas déjà généré.
106
140
  jsxs(Fragment, { children: [qrError ? (jsx("div", { className: "text-red-500 text-center p-4", children: qrError })) : isMobile ? (jsxs("div", { className: "flex flex-col items-center gap-4 p-8 text-center", 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.opening_app", "Ouverture de l'application…") }), jsx("a", { href: nfcUrl, className: "text-sm font-medium text-blue-600 underline", children: t("nfc_scan.open_app_link", "Ouvrir l'application") })] })) : (jsx("div", { className: "bg-white p-4 rounded-lg shadow-lg border-2 border-gray-200", children: jsx("canvas", { ref: canvasRef }) })), status === "opened" && (jsxs("div", { className: "text-center space-y-1", children: [jsx("p", { className: "text-sm font-semibold", style: { color: "var(--uni-secondary-color, #0a9983)" }, children: t("nfc_scan.qr_opened_title", "QR code scanné") }), jsx("p", { className: "text-xs text-gray-500 leading-relaxed", children: t("nfc_scan.qr_opened_description", "L'expérience NFC est ouverte sur votre smartphone. Continuez le scan sur votre téléphone.") }), jsxs("div", { className: "flex items-center justify-center gap-2 text-xs text-gray-500 pt-1", children: [jsx("span", { className: "h-2 w-2 rounded-full animate-pulse", style: { backgroundColor: "var(--uni-primary-color, #11e5c5)" } }), t("nfc_scan.waiting_completion", "En attente de la lecture NFC")] })] }))] })) })] }) }) }));
@@ -1 +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 { isMobileDevice } from \"../../utils/isMobileDevice\";\nimport MobilePageLayout from \"../ui/MobilePageLayout\";\nimport Button from \"../ui/Button\";\nimport PageActions from \"../ui/PageActions\";\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 /** Retour vers la sélection du document (pour corriger un mauvais choix). */\n onBack?: () => void;\n /**\n * Fallback \"poursuivre sans puce\" proposé sur l'échec définitif (nfcStatus 'failed'). Ouvre le\n * questionnaire de raison côté web (NfcFallbackSurvey) ; la reprise (photo/API ou saut de nœud)\n * est décidée par l'orchestrateur selon nfcMode. Absent = bouton masqué.\n */\n onContinueWithoutChip?: () => void;\n}\n\nconst NfcScanStep: React.FC<NfcScanStepProps> = ({\n sessionId,\n nodeId,\n stepObject,\n template,\n pageTitle,\n pageDescription,\n onBack,\n onContinueWithoutChip,\n}) => {\n const { t } = useI18n();\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const [qrError, setQrError] = useState<string | null>(null);\n // Sur mobile, on ouvre directement l'app de scan au lieu d'afficher un QR code inutile.\n const isMobile = useMemo(() => isMobileDevice(), []);\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 smartphone pour lire la puce électronique de votre document d'identité.\"\n );\n\n // Sur mobile : ouvrir directement l'application de scan (pas de QR à se scanner soi-même).\n // Une seule fois, tant que le scan n'a pas progressé. Le SSE reste actif pour faire avancer\n // le parcours quand la lecture est terminée.\n const hasRedirectedRef = useRef(false);\n useEffect(() => {\n if (!isMobile || status !== \"pending\" || hasRedirectedRef.current) return;\n hasRedirectedRef.current = true;\n window.location.assign(nfcUrl);\n }, [isMobile, status, nfcUrl]);\n\n useEffect(() => {\n if (isMobile) return; // pas de QR sur mobile (redirection directe)\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, isMobile]);\n\n // Footer : sur l'échec définitif ('failed'), les actions dédiées (revenir au choix / poursuivre\n // sans puce) sont rendues via PageActions, comme les autres écrans NFC (NfcChipGate). Sinon, un\n // simple \"Retour\" tant que le scan n'a pas commencé/abouti.\n const canGoBack = !!onBack && (status === \"pending\" || status === \"opened\");\n const footer =\n status === \"failed\" ? (\n <PageActions\n primary={\n onBack ? (\n <Button onClick={onBack}>\n {t(\"nfc_scan.failed_back_to_selection\", \"Revenir au choix du document\")}\n </Button>\n ) : null\n }\n secondary={\n onContinueWithoutChip ? (\n <Button variant=\"secondary\" onClick={onContinueWithoutChip}>\n {t(\"nfc_scan.failed_continue_without_chip\", \"Poursuivre sans puce\")}\n </Button>\n ) : null\n }\n />\n ) : canGoBack ? (\n <Button variant=\"secondary\" onClick={onBack}>\n {t(\"common.back\", \"Retour\")}\n </Button>\n ) : null;\n\n return (\n <MobilePageLayout footer={footer}>\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 flex-col justify-center items-center gap-4\">\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 === \"failed\" ? (\n <div className=\"flex flex-col items-center gap-2 p-8 text-center\">\n <p className=\"text-base font-semibold text-red-600\">\n {t(\"nfc_scan.failed_title\", \"Le scan n'a pas pu être vérifié\")}\n </p>\n <p className=\"text-sm text-gray-600 leading-relaxed\">\n {t(\n \"nfc_scan.failed_description\",\n \"Après plusieurs tentatives, la lecture de votre document n'a pas pu être validée.\"\n )}\n </p>\n </div>\n ) : (\n // Contenu principal QR/mobile — reste monté pour \"pending\" ET \"opened\", pour ne\n // jamais démonter le canvas déjà généré.\n <>\n {qrError ? (\n <div className=\"text-red-500 text-center p-4\">{qrError}</div>\n ) : isMobile ? (\n <div className=\"flex flex-col items-center gap-4 p-8 text-center\">\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.opening_app\", \"Ouverture de l'application…\")}\n </p>\n <a\n href={nfcUrl}\n className=\"text-sm font-medium text-blue-600 underline\"\n >\n {t(\"nfc_scan.open_app_link\", \"Ouvrir l'application\")}\n </a>\n </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\n {status === \"opened\" && (\n <div className=\"text-center space-y-1\">\n <p\n className=\"text-sm font-semibold\"\n style={{ color: \"var(--uni-secondary-color, #0a9983)\" }}\n >\n {t(\"nfc_scan.qr_opened_title\", \"QR code scanné\")}\n </p>\n <p className=\"text-xs text-gray-500 leading-relaxed\">\n {t(\n \"nfc_scan.qr_opened_description\",\n \"L'expérience NFC est ouverte sur votre smartphone. Continuez le scan sur votre téléphone.\"\n )}\n </p>\n <div className=\"flex items-center justify-center gap-2 text-xs text-gray-500 pt-1\">\n <span\n className=\"h-2 w-2 rounded-full animate-pulse\"\n style={{ backgroundColor: \"var(--uni-primary-color, #11e5c5)\" }}\n />\n {t(\"nfc_scan.waiting_completion\", \"En attente de la lecture NFC\")}\n </div>\n </div>\n )}\n </>\n )}\n </div>\n </div>\n </div>\n </MobilePageLayout>\n );\n};\n\nexport default NfcScanStep;\n"],"names":["_jsx","_jsxs","_Fragment"],"mappings":"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"}
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 { resetNfcScan } from \"../../services/sessionService\";\nimport { isMobileDevice } from \"../../utils/isMobileDevice\";\nimport MobilePageLayout from \"../ui/MobilePageLayout\";\nimport Button from \"../ui/Button\";\nimport PageActions from \"../ui/PageActions\";\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 /** Retour vers la sélection du document (pour corriger un mauvais choix). */\n onBack?: () => void;\n /**\n * Fallback \"poursuivre sans puce\" proposé sur l'échec définitif (nfcStatus 'failed'). Ouvre le\n * questionnaire de raison côté web (NfcFallbackSurvey) ; la reprise (photo/API ou saut de nœud)\n * est décidée par l'orchestrateur selon nfcMode. Absent = bouton masqué.\n */\n onContinueWithoutChip?: () => void;\n}\n\nconst NfcScanStep: React.FC<NfcScanStepProps> = ({\n sessionId,\n nodeId,\n stepObject,\n template,\n pageTitle,\n pageDescription,\n onBack,\n onContinueWithoutChip,\n}) => {\n const { t } = useI18n();\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const [qrError, setQrError] = useState<string | null>(null);\n const [resetError, setResetError] = useState<string | null>(null);\n const [isResetting, setIsResetting] = useState(false);\n // Sur mobile, on ouvre directement l'app de scan au lieu d'afficher un QR code inutile.\n const isMobile = useMemo(() => isMobileDevice(), []);\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 smartphone pour lire la puce électronique de votre document d'identité.\"\n );\n\n // Sur mobile : ouvrir directement l'application de scan (pas de QR à se scanner soi-même).\n // Une seule fois, tant que le scan n'a pas progressé. Le SSE reste actif pour faire avancer\n // le parcours quand la lecture est terminée.\n const hasRedirectedRef = useRef(false);\n useEffect(() => {\n if (!isMobile || status !== \"pending\" || hasRedirectedRef.current) return;\n hasRedirectedRef.current = true;\n window.location.assign(nfcUrl);\n }, [isMobile, status, nfcUrl]);\n\n useEffect(() => {\n if (isMobile) return; // pas de QR sur mobile (redirection directe)\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, isMobile]);\n\n const handleBack = async () => {\n if (!onBack) return;\n\n if (status !== \"failed\") {\n onBack();\n return;\n }\n\n setResetError(null);\n setIsResetting(true);\n try {\n await resetNfcScan(sessionId);\n onBack();\n } catch {\n setResetError(\n t(\n \"nfc_scan.reset_failed\",\n \"Impossible de réinitialiser le scan NFC. Veuillez réessayer.\",\n ),\n );\n } finally {\n setIsResetting(false);\n }\n };\n\n // Footer : sur l'échec définitif ('failed'), les actions dédiées (revenir au choix / poursuivre\n // sans puce) sont rendues via PageActions, comme les autres écrans NFC (NfcChipGate). Sinon, un\n // simple \"Retour\" tant que le scan n'a pas commencé/abouti.\n const canGoBack = !!onBack && (status === \"pending\" || status === \"opened\");\n const footer =\n status === \"failed\" ? (\n <PageActions\n primary={\n onBack ? (\n <Button onClick={() => void handleBack()} disabled={isResetting}>\n {t(\"nfc_scan.failed_back_to_selection\", \"Revenir au choix du document\")}\n </Button>\n ) : null\n }\n secondary={\n onContinueWithoutChip ? (\n <Button variant=\"secondary\" onClick={onContinueWithoutChip}>\n {t(\"nfc_scan.failed_continue_without_chip\", \"Poursuivre sans puce\")}\n </Button>\n ) : null\n }\n />\n ) : canGoBack ? (\n <Button variant=\"secondary\" onClick={onBack}>\n {t(\"common.back\", \"Retour\")}\n </Button>\n ) : null;\n\n return (\n <MobilePageLayout footer={footer}>\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 flex-col justify-center items-center gap-4\">\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 === \"failed\" ? (\n <div className=\"flex flex-col items-center gap-2 p-8 text-center\">\n <p className=\"text-base font-semibold text-red-600\">\n {t(\"nfc_scan.failed_title\", \"Le scan n'a pas pu être vérifié\")}\n </p>\n <p className=\"text-sm text-gray-600 leading-relaxed\">\n {t(\n \"nfc_scan.failed_description\",\n \"Après plusieurs tentatives, la lecture de votre document n'a pas pu être validée.\"\n )}\n </p>\n {resetError && (\n <p className=\"text-sm text-red-600\" role=\"alert\">\n {resetError}\n </p>\n )}\n </div>\n ) : (\n // Contenu principal QR/mobile — reste monté pour \"pending\" ET \"opened\", pour ne\n // jamais démonter le canvas déjà généré.\n <>\n {qrError ? (\n <div className=\"text-red-500 text-center p-4\">{qrError}</div>\n ) : isMobile ? (\n <div className=\"flex flex-col items-center gap-4 p-8 text-center\">\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.opening_app\", \"Ouverture de l'application…\")}\n </p>\n <a\n href={nfcUrl}\n className=\"text-sm font-medium text-blue-600 underline\"\n >\n {t(\"nfc_scan.open_app_link\", \"Ouvrir l'application\")}\n </a>\n </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\n {status === \"opened\" && (\n <div className=\"text-center space-y-1\">\n <p\n className=\"text-sm font-semibold\"\n style={{ color: \"var(--uni-secondary-color, #0a9983)\" }}\n >\n {t(\"nfc_scan.qr_opened_title\", \"QR code scanné\")}\n </p>\n <p className=\"text-xs text-gray-500 leading-relaxed\">\n {t(\n \"nfc_scan.qr_opened_description\",\n \"L'expérience NFC est ouverte sur votre smartphone. Continuez le scan sur votre téléphone.\"\n )}\n </p>\n <div className=\"flex items-center justify-center gap-2 text-xs text-gray-500 pt-1\">\n <span\n className=\"h-2 w-2 rounded-full animate-pulse\"\n style={{ backgroundColor: \"var(--uni-primary-color, #11e5c5)\" }}\n />\n {t(\"nfc_scan.waiting_completion\", \"En attente de la lecture NFC\")}\n </div>\n </div>\n )}\n </>\n )}\n </div>\n </div>\n </div>\n </MobilePageLayout>\n );\n};\n\nexport default NfcScanStep;\n"],"names":["_jsx","_jsxs","_Fragment"],"mappings":"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"}
@@ -1031,6 +1031,7 @@ var nfc_scan = {
1031
1031
  failed_description: "After several attempts, your document could not be validated.",
1032
1032
  failed_back_to_selection: "Back to document selection",
1033
1033
  failed_continue_without_chip: "Continue without chip",
1034
+ reset_failed: "Unable to reset the NFC scan. Please try again.",
1034
1035
  success_title: "Documents validated",
1035
1036
  success_subtitle: "NFC reading confirmed successfully",
1036
1037
  onboarding: {
@@ -1 +1 @@
1
- {"version":3,"file":"en.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"en.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1031,6 +1031,7 @@ var nfc_scan = {
1031
1031
  failed_description: "Después de varios intentos, no se pudo validar tu documento.",
1032
1032
  failed_back_to_selection: "Volver a la selección de documento",
1033
1033
  failed_continue_without_chip: "Continuar sin chip",
1034
+ reset_failed: "No se ha podido reiniciar el escaneo NFC. Inténtalo de nuevo.",
1034
1035
  success_title: "Documentos validados",
1035
1036
  success_subtitle: "Lectura NFC confirmada correctamente",
1036
1037
  onboarding: {
@@ -1 +1 @@
1
- {"version":3,"file":"es.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"es.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1031,6 +1031,7 @@ var nfc_scan = {
1031
1031
  failed_description: "Après plusieurs tentatives, la lecture de votre document n'a pas pu être validée.",
1032
1032
  failed_back_to_selection: "Revenir au choix du document",
1033
1033
  failed_continue_without_chip: "Poursuivre sans puce",
1034
+ reset_failed: "Impossible de réinitialiser le scan NFC. Veuillez réessayer.",
1034
1035
  success_title: "Documents validés",
1035
1036
  success_subtitle: "Lecture NFC confirmée avec succès",
1036
1037
  onboarding: {
@@ -1 +1 @@
1
- {"version":3,"file":"fr.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"fr.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -101,6 +101,21 @@ var skipNfcWithReason = function (sessionId, payload) { return __awaiter(void 0,
101
101
  }
102
102
  });
103
103
  }); };
104
+ /**
105
+ * Resets a terminal NFC failure before the user starts again with another
106
+ * document. The backend keeps completed scans immutable and treats this call
107
+ * as a no-op when the status is not terminal.
108
+ */
109
+ var resetNfcScan = function (sessionId) { return __awaiter(void 0, void 0, void 0, function () {
110
+ return __generator(this, function (_a) {
111
+ switch (_a.label) {
112
+ case 0: return [4 /*yield*/, apiService.post("/session/sdk/".concat(sessionId, "/nfc-reset"))];
113
+ case 1:
114
+ _a.sent();
115
+ return [2 /*return*/];
116
+ }
117
+ });
118
+ }); };
104
119
  /**
105
120
  * Updates session data with contact information
106
121
  *
@@ -441,5 +456,5 @@ var getRunPrefillData = function (userInput, runIndex) {
441
456
  return (_a = list[runIndex]) !== null && _a !== void 0 ? _a : null;
442
457
  };
443
458
 
444
- export { clearSessionSensitiveData, fetchSessionById, findOutgoingEdge, getNextStepIndex, getOrderedJourneySteps, getRunPrefillData, isSessionExpired, reconstructHistoryToStep, sendClientInfo, skipNfcWithReason, storeDocumentOptions, updateSessionContactInfo, updateSessionCurrentStep, updateSessionStatus, updateSessionUserInput };
459
+ export { clearSessionSensitiveData, fetchSessionById, findOutgoingEdge, getNextStepIndex, getOrderedJourneySteps, getRunPrefillData, isSessionExpired, reconstructHistoryToStep, resetNfcScan, sendClientInfo, skipNfcWithReason, storeDocumentOptions, updateSessionContactInfo, updateSessionCurrentStep, updateSessionStatus, updateSessionUserInput };
445
460
  //# sourceMappingURL=sessionService.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sessionService.js","sources":["../../../../src/services/sessionService.ts"],"sourcesContent":["/**\n * Session Service\n *\n * Service for interacting with the Datakeen Session API.\n * Handles fetching session data by ID.\n */\n\nimport type {\n ClientInfo,\n SessionData,\n SessionTemplate,\n SessionTemplateNode,\n} from \"../types/session\";\nimport { apiService } from \"./api\";\nimport { logStatusModified } from \"./auditTrailService\";\nimport { clearSessionMemory } from \"./sessionMemoryStore\";\n\n/**\n * Fetches session data by ID from the Datakeen backend\n *\n * @param sessionId - The unique identifier of the session\n * @returns The session data\n */\nexport const fetchSessionById = async (\n sessionId: string,\n): Promise<SessionData> => {\n try {\n const response = await apiService.get(`/session/sdk/${sessionId}`);\n return response.data;\n } catch (error) {\n console.error(\"Error fetching session data:\", error);\n throw error;\n }\n};\n\n/** Sends client information (IP, device, browser, OS) to the backend for a specific session\n *\n * @param sessionId - The unique identifier of the session\n * @param clientInfo - The client information to send\n */\nexport const sendClientInfo = async (\n sessionId: string,\n clientInfo: ClientInfo,\n): Promise<void> => {\n try {\n await apiService.post(`/session/sdk/${sessionId}/client-info`, clientInfo);\n } catch (error) {\n console.error(\"Error sending client info:\", error);\n throw error;\n }\n};\n\n/**\n * Determines if the session template has a specific type of node\n *\n * @param template - The session template\n * @param nodeType - The type of node to check for\n * @returns true if the template has a node of the specified type, false otherwise\n */\nexport const hasNodeType = (\n template: SessionTemplate,\n nodeType: string,\n): boolean => {\n return template.nodes.some((node) => node.type === nodeType);\n};\n\n/**\n * Determines if the session template has a node with a specific requiredDocumentType\n *\n * @param template - The session template\n * @param requiredDocumentType - The requiredDocumentType to check for\n * @returns true if the template has a node with the specified requiredDocumentType, false otherwise\n */\nexport const hasDocumentTypeNode = (\n template: SessionTemplate,\n requiredDocumentType: string,\n): boolean => {\n return template.nodes.some(\n (node) => node.requiredDocumentType === requiredDocumentType,\n );\n};\n\n/**\n * Gets all nodes of a specific type\n *\n * @param template - The session template\n * @param nodeType - The type of node to get\n * @returns Array of nodes matching the type\n */\nexport const getNodesByType = (\n template: SessionTemplate,\n nodeType: string,\n): SessionTemplateNode[] => {\n return template.nodes.filter((node) => node.type === nodeType);\n};\n\n/**\n * Gets all nodes with a specific requiredDocumentType\n *\n * @param template - The session template\n * @param requiredDocumentType - The requiredDocumentType to get\n * @returns Array of nodes matching the requiredDocumentType\n */\nexport const getNodesByDocumentType = (\n template: SessionTemplate,\n requiredDocumentType: string,\n): SessionTemplateNode[] => {\n return template.nodes.filter(\n (node) => node.requiredDocumentType === requiredDocumentType,\n );\n};\n\n/**\n * Get document options for a specific document type\n *\n * @param template - The session template\n * @param requiredDocumentType - The document type to get options for\n * @returns Array of document options (empty if none found)\n */\nexport const getDocumentOptions = (\n template: SessionTemplate,\n requiredDocumentType: string,\n): string[] => {\n const node = template.nodes.find(\n (node) => node.requiredDocumentType === requiredDocumentType,\n );\n return node?.selectedOptions || [];\n};\n\n/**\n * Determines if the session template has a selfie step\n *\n * @param template - The session template\n * @returns true if the template has a selfie step, false otherwise\n */\nexport const hasSelfieCaptureStep = (template: SessionTemplate): boolean => {\n return hasNodeType(template, \"selfie-capture\");\n};\n\n/**\n * Determines if the session template has an ID document step\n *\n * @param template - The session template\n * @returns true if the template has an ID document step, false otherwise\n */\nexport const hasDocumentStep = (template: SessionTemplate): boolean => {\n // Check if there's any document-selection node with requiredDocumentType \"id-card\"\n // or if none specified, just check for document-selection nodes\n const hasIDCard = hasDocumentTypeNode(template, \"id-card\");\n return hasIDCard || hasNodeType(template, \"document-selection\");\n};\n\n/**\n * Determines if the session template has a JDD (proof of address) step\n *\n * @param template - The session template\n * @returns true if the template has a JDD step, false otherwise\n */\nexport const hasJDDStep = (template: SessionTemplate): boolean => {\n return hasDocumentTypeNode(template, \"jdd\");\n};\n\n/**\n * Determines if the session template has a proof of funds step\n *\n * @param template - The session template\n * @returns true if the template has a proof of funds step, false otherwise\n */\nexport const hasProofOfFundsStep = (template: SessionTemplate): boolean => {\n return hasDocumentTypeNode(template, \"income-proof\");\n};\n\n/**\n * Determines if the session template has a document collection step\n *\n * @param template - The session template\n * @returns true if the template has a document collection step, false otherwise\n */\nexport const hasDocumentCollectionStep = (\n template: SessionTemplate,\n): boolean => {\n return hasNodeType(template, \"document-collection\");\n};\n\n/**\n * Gets all node types in the template\n *\n * @param template - The session template\n * @returns Array of node types in the template\n */\nexport const getNodeTypes = (template: SessionTemplate): string[] => {\n return Array.from(new Set(template.nodes.map((node) => node.type)));\n};\n\n/**\n * Gets all document types required in the template\n *\n * @param template - The session template\n * @returns Array of document types required in the template\n */\nexport const getRequiredDocumentTypes = (\n template: SessionTemplate,\n): string[] => {\n return Array.from(\n new Set(\n template.nodes\n .filter((node) => node.requiredDocumentType)\n .map((node) => node.requiredDocumentType!),\n ),\n );\n};\n\n/**\n * Converts template document type to internal document type\n * This helps standardize document types between the template and the application\n *\n * @param templateDocType - The document type as defined in the template\n * @returns The internal document type used by the application\n */\nexport const convertTemplateDocTypeToInternal = (\n templateDocType: string,\n): string => {\n if (!templateDocType) return \"\";\n\n // Mapping between template document types and internal document types\n const typeMap: Record<string, string> = {\n \"id-card\": \"id-card\",\n jdd: \"jdd\",\n \"income-proof\": \"income-proof\", // Using consistent naming\n };\n\n return typeMap[templateDocType] || templateDocType;\n};\n\n/**\n * Converts internal document type to template document type\n *\n * @param internalDocType - The document type used internally by the application\n * @returns The document type as expected in the template\n */\nexport const convertInternalDocTypeToTemplate = (\n internalDocType: string,\n): string => {\n if (!internalDocType) return \"\";\n\n // Mapping between internal document types and template document types\n const typeMap: Record<string, string> = {\n \"id-card\": \"id-card\",\n jdd: \"jdd\",\n funds: \"income-proof\", // Map funds to income-proof for backwards compatibility\n \"income-proof\": \"income-proof\",\n };\n\n return typeMap[internalDocType] || internalDocType;\n};\n\n/**\n * Updates session data with user input information\n *\n * @param sessionId - The unique identifier of the session\n * @param userInput - The user input data (firstName, lastName, birthDate)\n * @returns The updated session data\n */\nexport const updateSessionUserInput = async (\n sessionId: string,\n userInput: {\n firstName?: string;\n lastName?: string;\n birthDate?: string;\n [key: string]: unknown;\n },\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n userInput,\n });\n return response.data;\n } catch (error) {\n console.error(\"Error updating session data:\", error);\n throw error;\n }\n};\n\n/**\n * Records the NFC fallback reason when the user declares they cannot use the\n * contactless scan, and marks the NFC scan as skipped server-side.\n *\n * @param sessionId - The unique identifier of the session\n * @param payload - The selected reason (technical key), its human-readable label,\n * and an optional free-text comment.\n */\nexport const skipNfcWithReason = async (\n sessionId: string,\n payload: { reason: string; label: string; comment?: string },\n): Promise<void> => {\n await apiService.post(`/session/sdk/${sessionId}/nfc-skip`, payload);\n};\n\n/**\n * Updates session data with contact information\n *\n * @param sessionId - The unique identifier of the session\n * @param contactInfo - The contact information data (email, phoneNumber)\n * @returns The updated session data\n */\nexport const updateSessionContactInfo = async (\n sessionId: string,\n contactInfo: {\n email: string;\n phoneNumber: string;\n [key: string]: unknown;\n },\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n contactInfo,\n });\n return response.data;\n } catch (error) {\n console.error(\"Error updating contact information:\", error);\n throw error;\n }\n};\n\n/**\n * Updates session status\n *\n * @param sessionId - The unique identifier of the session\n * @param status - The new status for the session\n * @param reachedEndNodeId - Id of the end node actually reached (when status is \"ended\"),\n * so the backend can force the correct final status with multiple end nodes.\n * @returns The updated session data\n */\nexport const updateSessionStatus = async (\n sessionId: string,\n status: string,\n reachedEndNodeId?: string,\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n status,\n ...(reachedEndNodeId ? { reachedEndNodeId } : {}),\n });\n\n // Log status modification in audit trail\n if (response.data && response.data.analysisId) {\n try {\n await logStatusModified(\n sessionId,\n status,\n response.data.clientInfoId || undefined,\n );\n } catch (err) {\n console.error(\"Failed to log status modification in audit trail:\", err);\n // Non-blocking error - continue session\n }\n }\n\n return response.data;\n } catch (error) {\n console.error(\"Error updating session status:\", error);\n throw error;\n }\n};\n\n/**\n * Updates the current step in the session\n *\n * @param sessionId - The unique identifier of the session\n * @param currentStep - The current step index in the workflow\n * @returns The updated session data\n */\nexport const updateSessionCurrentStep = async (\n sessionId: string,\n currentStep: number,\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n currentStep,\n });\n return response.data;\n } catch (error) {\n console.error(\"Error updating session current step:\", error);\n throw error;\n }\n};\n\n/**\n * Gets the journey steps from the template in order\n *\n * @param template - The session template\n * @returns Array of ordered steps\n */\nexport const getOrderedJourneySteps = (\n template: SessionTemplate,\n): SessionTemplateNode[] => {\n // Filter out only start nodes, keep end nodes for proper journey completion, then sort by order.\n // Tiebreaker on id keeps the ordering deterministic when several nodes share the same `order`\n // (e.g. parallel branches of a condition), independently of their position in template.nodes.\n return template.nodes\n .filter((node) => node.type !== \"start\")\n .sort((a, b) => a.order - b.order || a.id.localeCompare(b.id));\n};\n\nconst normalizeHandle = (value?: string): string => {\n return (value || \"\").trim().toLowerCase();\n};\n\n/**\n * Finds the outgoing edge to follow from a node.\n *\n * Resolution order:\n * 1. Exact handle match via sourceHandle/conditionValue.\n * 2. For condition:false loops, fallback to targetHandle=right.\n * 3. First outgoing edge as final fallback.\n */\nexport const findOutgoingEdge = (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n): SessionTemplate[\"edges\"][number] | null => {\n const outgoingEdges = (template.edges || []).filter(\n (edge) => edge.source === currentNodeId,\n );\n\n if (outgoingEdges.length === 0) {\n return null;\n }\n\n if (!handle) {\n return outgoingEdges[0];\n }\n\n const normalizedHandle = normalizeHandle(handle);\n const edgeByHandle = outgoingEdges.find((edge) => {\n return (\n normalizeHandle(edge.sourceHandle) === normalizedHandle ||\n normalizeHandle(edge.conditionValue) === normalizedHandle\n );\n });\n\n if (edgeByHandle) {\n return edgeByHandle;\n }\n\n const currentNode = template.nodes.find((node) => node.id === currentNodeId);\n if (currentNode?.type === \"condition\" && normalizedHandle === \"false\") {\n const rightHandleLoopEdge = outgoingEdges.find(\n (edge) => normalizeHandle(edge.targetHandle) === \"right\",\n );\n if (rightHandleLoopEdge) {\n return rightHandleLoopEdge;\n }\n }\n\n return outgoingEdges[0];\n};\n\n/**\n * Gets the next step index by following the graph edge from the current node\n *\n * @param currentNodeId - The ID of the current node\n * @param template - The session template\n * @returns The next step index (1-based) or null if no edge found\n */\nexport const getNextStepIndex = (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n): number | null => {\n const orderedNodes = getOrderedJourneySteps(template);\n const edge = findOutgoingEdge(currentNodeId, template, handle);\n\n if (!edge) {\n console.debug(\n `[sessionService] No outgoing edge found for node ${currentNodeId}${handle ? ` with handle ${handle}` : \"\"}`,\n );\n return null;\n }\n\n const targetId = edge.target;\n const targetIndex = orderedNodes.findIndex((n) => n.id === targetId);\n\n if (targetIndex === -1) {\n console.debug(\n `[sessionService] Target node ${targetId} not found in ordered steps`,\n );\n return null;\n }\n\n // steps are 1-indexed in the SDK (0 is StartSession)\n return 1 + targetIndex;\n};\n\n/**\n * Reconstructs the navigation history by following the graph from step 0\n * up to (and including) targetStep. Returns [0, ...stepIndices].\n * If the graph path cannot reach targetStep, falls back to [0, targetStep].\n */\nexport const reconstructHistoryToStep = (\n targetStep: number,\n template: SessionTemplate,\n): number[] => {\n if (targetStep <= 0) return [0];\n\n const orderedNodes = getOrderedJourneySteps(template);\n const history: number[] = [0];\n let currentStep = 1; // first node is step 1\n\n // Follow the default (first) edge from each node in sequence\n for (let safetyLimit = 0; safetyLimit < orderedNodes.length + 1; safetyLimit++) {\n if (currentStep === targetStep) {\n history.push(currentStep);\n break;\n }\n if (currentStep > targetStep) break;\n\n const nodeIndex = currentStep - 1;\n const currentNode = orderedNodes[nodeIndex];\n if (!currentNode) break;\n\n history.push(currentStep);\n\n const nextStep = getNextStepIndex(currentNode.id, template);\n if (nextStep === null) break;\n currentStep = nextStep;\n }\n\n // Fallback: if we couldn't reach targetStep via graph, use simple seed\n if (history[history.length - 1] !== targetStep) {\n return [0, targetStep];\n }\n\n return history;\n};\n\n/**\n * Maps a template node type to a step component type\n *\n * @param node - The session template node\n * @returns The step component type\n */\nexport const getStepComponentType = (node: SessionTemplateNode): string => {\n // Map from template node types to component types\n const typeMap: Record<string, string> = {\n \"document-selection\": \"document\",\n \"document-collection\": \"document-collection\",\n \"selfie-capture\": \"selfie\",\n \"contact-info\": \"contact-info\",\n \"user-input\": \"user-input\",\n \"otp-verification\": \"otp\",\n };\n\n // First check the node type\n if (node.type in typeMap) {\n return typeMap[node.type];\n }\n\n // Then check the requiredDocumentType\n if (node.requiredDocumentType) {\n return node.requiredDocumentType;\n }\n\n // Default fallback\n return node.type;\n};\n\n/**\n * Checks if a session has expired\n *\n * @param session - The session data to check\n * @returns true if the session has expired, false otherwise\n */\nexport const isSessionExpired = (session: SessionData): boolean => {\n if (!session.expireTime) {\n return false;\n }\n\n const currentTime = Date.now();\n return currentTime > session.expireTime;\n};\n\n/**\n * Stores document options in localStorage for a specific document type\n *\n * @param sessionId - The session ID\n * @param documentTypeId - The document type ID (e.g., 'jdd', 'income-proof')\n * @param options - The options to store\n */\nexport const storeDocumentOptions = (\n sessionId: string,\n documentTypeId: string,\n options: string[],\n): void => {\n if (!sessionId || !documentTypeId || !options || options.length === 0) {\n console.warn(\"Missing data for storeDocumentOptions:\", {\n sessionId,\n documentTypeId,\n options,\n });\n return;\n }\n\n // Create a consistent key format based on document type\n let storageKey = \"\";\n\n switch (documentTypeId) {\n case \"jdd\":\n storageKey = `jddOptions_${sessionId}`;\n break;\n case \"income-proof\":\n storageKey = `fundsOptions_${sessionId}`;\n break;\n case \"id-card\":\n storageKey = `idOptions_${sessionId}`;\n break;\n case \"document-collection\":\n storageKey = `documentCollectionOptions_${sessionId}`;\n break;\n default:\n storageKey = `${documentTypeId}Options_${sessionId}`;\n }\n\n localStorage.setItem(storageKey, JSON.stringify(options));\n};\n\n/**\n * Retrieves document options from localStorage for a specific document type\n *\n * @param sessionId - The session ID\n * @param documentTypeId - The document type ID (e.g., 'jdd', 'income-proof')\n * @returns Array of options or default options if none found\n */\nexport const retrieveDocumentOptions = (\n sessionId: string,\n documentTypeId: string,\n): string[] => {\n if (!sessionId || !documentTypeId) {\n console.warn(\"Missing data for retrieveDocumentOptions:\", {\n sessionId,\n documentTypeId,\n });\n return [];\n }\n\n // Create consistent key formats to check\n const possibleKeys = [\n `${documentTypeId}Options_${sessionId}`,\n documentTypeId === \"jdd\" ? `jddOptions_${sessionId}` : \"\",\n documentTypeId === \"income-proof\" ? `fundsOptions_${sessionId}` : \"\",\n documentTypeId === \"id-card\" ? `idOptions_${sessionId}` : \"\",\n documentTypeId === \"document-collection\"\n ? `documentCollectionOptions_${sessionId}`\n : \"\",\n ].filter(Boolean);\n\n // Try each possible key\n for (const key of possibleKeys) {\n const savedOptions = localStorage.getItem(key);\n if (savedOptions) {\n try {\n const parsedOptions = JSON.parse(savedOptions);\n\n return parsedOptions;\n } catch (e) {\n console.error(\n `Error parsing options for ${documentTypeId} with key ${key}:`,\n e,\n );\n }\n }\n }\n\n // Return default options if none found\n console.warn(`No options found for ${documentTypeId}, using defaults`);\n if (documentTypeId === \"jdd\") {\n return [\n \"Facture d'électricité (< 3 mois)\",\n \"Facture de gaz (< 3 mois)\",\n \"Facture d'eau (< 3 mois)\",\n \"Quittance de loyer (< 3 mois)\",\n \"Facture téléphone/internet (< 3 mois)\",\n \"Attestation d'assurance habitation (< 3 mois)\",\n ];\n } else if (documentTypeId === \"income-proof\") {\n return [\n \"Bulletin de salaire\",\n \"Avis d'imposition\",\n \"Relevé de compte bancaire\",\n \"Attestation de revenus\",\n \"Contrat de travail\",\n ];\n } else if (documentTypeId === \"id-card\") {\n return [\"Carte nationale d'identité\", \"Passeport\", \"Permis de conduire\"];\n } else if (documentTypeId === \"document-collection\") {\n return [\"Document administratif\", \"Justificatif\", \"Attestation\"];\n }\n\n return [];\n};\n\nconst clearStorageBySessionId = (sessionId: string): void => {\n const scopedKeys = [\n `userInput_${sessionId}`,\n `contactInfo_${sessionId}`,\n `sessionData_${sessionId}`,\n ];\n\n scopedKeys.forEach((key) => {\n localStorage.removeItem(key);\n sessionStorage.removeItem(key);\n });\n\n for (let i = localStorage.length - 1; i >= 0; i -= 1) {\n const key = localStorage.key(i);\n if (!key) {\n continue;\n }\n if (key.endsWith(`_${sessionId}`)) {\n localStorage.removeItem(key);\n }\n }\n\n for (let i = sessionStorage.length - 1; i >= 0; i -= 1) {\n const key = sessionStorage.key(i);\n if (!key) {\n continue;\n }\n if (key.endsWith(`_${sessionId}`)) {\n sessionStorage.removeItem(key);\n }\n }\n\n if (localStorage.getItem(\"sessionId\") === sessionId) {\n localStorage.removeItem(\"sessionId\");\n }\n if (sessionStorage.getItem(\"sessionId\") === sessionId) {\n sessionStorage.removeItem(\"sessionId\");\n }\n};\n\n/**\n * Clears all client-side session traces (memory + browser storage)\n * for a given session. This is intentionally aggressive for security.\n */\nexport const clearSessionSensitiveData = (sessionId?: string): void => {\n clearSessionMemory(sessionId);\n\n if (sessionId) {\n clearStorageBySessionId(sessionId);\n return;\n }\n\n localStorage.removeItem(\"sessionId\");\n sessionStorage.removeItem(\"sessionId\");\n\n for (let i = localStorage.length - 1; i >= 0; i -= 1) {\n const key = localStorage.key(i);\n if (!key) {\n continue;\n }\n if (\n key.startsWith(\"userInput_\") ||\n key.startsWith(\"contactInfo_\") ||\n key.includes(\"Options_\")\n ) {\n localStorage.removeItem(key);\n }\n }\n\n for (let i = sessionStorage.length - 1; i >= 0; i -= 1) {\n const key = sessionStorage.key(i);\n if (!key) {\n continue;\n }\n if (\n key.startsWith(\"userInput_\") ||\n key.startsWith(\"contactInfo_\") ||\n key.includes(\"Options_\")\n ) {\n sessionStorage.removeItem(key);\n }\n }\n};\n\n/**\n * Returns the pre-fill data for a given run index from a `userInput` object\n * that contains a `_list` array.\n *\n * Convention: when the integrator wants to pre-fill different data per run\n * (e.g. multiple persons in a loop), they pass `userInput: { _list: [...] }`\n * at session creation. Each element in `_list` corresponds to a run (0-indexed).\n *\n * @param userInput - The session's userInput object\n * @param runIndex - The current run index (0 = first pass, 1 = second pass, …)\n * @returns The pre-fill data for that run, or null if not defined\n */\nexport const getRunPrefillData = (\n userInput: Record<string, unknown>,\n runIndex: number,\n): Record<string, unknown> | null => {\n const list = userInput?._list;\n if (!Array.isArray(list)) return null;\n return (list[runIndex] as Record<string, unknown>) ?? null;\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sessionService.js","sources":["../../../../src/services/sessionService.ts"],"sourcesContent":["/**\n * Session Service\n *\n * Service for interacting with the Datakeen Session API.\n * Handles fetching session data by ID.\n */\n\nimport type {\n ClientInfo,\n SessionData,\n SessionTemplate,\n SessionTemplateNode,\n} from \"../types/session\";\nimport { apiService } from \"./api\";\nimport { logStatusModified } from \"./auditTrailService\";\nimport { clearSessionMemory } from \"./sessionMemoryStore\";\n\n/**\n * Fetches session data by ID from the Datakeen backend\n *\n * @param sessionId - The unique identifier of the session\n * @returns The session data\n */\nexport const fetchSessionById = async (\n sessionId: string,\n): Promise<SessionData> => {\n try {\n const response = await apiService.get(`/session/sdk/${sessionId}`);\n return response.data;\n } catch (error) {\n console.error(\"Error fetching session data:\", error);\n throw error;\n }\n};\n\n/** Sends client information (IP, device, browser, OS) to the backend for a specific session\n *\n * @param sessionId - The unique identifier of the session\n * @param clientInfo - The client information to send\n */\nexport const sendClientInfo = async (\n sessionId: string,\n clientInfo: ClientInfo,\n): Promise<void> => {\n try {\n await apiService.post(`/session/sdk/${sessionId}/client-info`, clientInfo);\n } catch (error) {\n console.error(\"Error sending client info:\", error);\n throw error;\n }\n};\n\n/**\n * Determines if the session template has a specific type of node\n *\n * @param template - The session template\n * @param nodeType - The type of node to check for\n * @returns true if the template has a node of the specified type, false otherwise\n */\nexport const hasNodeType = (\n template: SessionTemplate,\n nodeType: string,\n): boolean => {\n return template.nodes.some((node) => node.type === nodeType);\n};\n\n/**\n * Determines if the session template has a node with a specific requiredDocumentType\n *\n * @param template - The session template\n * @param requiredDocumentType - The requiredDocumentType to check for\n * @returns true if the template has a node with the specified requiredDocumentType, false otherwise\n */\nexport const hasDocumentTypeNode = (\n template: SessionTemplate,\n requiredDocumentType: string,\n): boolean => {\n return template.nodes.some(\n (node) => node.requiredDocumentType === requiredDocumentType,\n );\n};\n\n/**\n * Gets all nodes of a specific type\n *\n * @param template - The session template\n * @param nodeType - The type of node to get\n * @returns Array of nodes matching the type\n */\nexport const getNodesByType = (\n template: SessionTemplate,\n nodeType: string,\n): SessionTemplateNode[] => {\n return template.nodes.filter((node) => node.type === nodeType);\n};\n\n/**\n * Gets all nodes with a specific requiredDocumentType\n *\n * @param template - The session template\n * @param requiredDocumentType - The requiredDocumentType to get\n * @returns Array of nodes matching the requiredDocumentType\n */\nexport const getNodesByDocumentType = (\n template: SessionTemplate,\n requiredDocumentType: string,\n): SessionTemplateNode[] => {\n return template.nodes.filter(\n (node) => node.requiredDocumentType === requiredDocumentType,\n );\n};\n\n/**\n * Get document options for a specific document type\n *\n * @param template - The session template\n * @param requiredDocumentType - The document type to get options for\n * @returns Array of document options (empty if none found)\n */\nexport const getDocumentOptions = (\n template: SessionTemplate,\n requiredDocumentType: string,\n): string[] => {\n const node = template.nodes.find(\n (node) => node.requiredDocumentType === requiredDocumentType,\n );\n return node?.selectedOptions || [];\n};\n\n/**\n * Determines if the session template has a selfie step\n *\n * @param template - The session template\n * @returns true if the template has a selfie step, false otherwise\n */\nexport const hasSelfieCaptureStep = (template: SessionTemplate): boolean => {\n return hasNodeType(template, \"selfie-capture\");\n};\n\n/**\n * Determines if the session template has an ID document step\n *\n * @param template - The session template\n * @returns true if the template has an ID document step, false otherwise\n */\nexport const hasDocumentStep = (template: SessionTemplate): boolean => {\n // Check if there's any document-selection node with requiredDocumentType \"id-card\"\n // or if none specified, just check for document-selection nodes\n const hasIDCard = hasDocumentTypeNode(template, \"id-card\");\n return hasIDCard || hasNodeType(template, \"document-selection\");\n};\n\n/**\n * Determines if the session template has a JDD (proof of address) step\n *\n * @param template - The session template\n * @returns true if the template has a JDD step, false otherwise\n */\nexport const hasJDDStep = (template: SessionTemplate): boolean => {\n return hasDocumentTypeNode(template, \"jdd\");\n};\n\n/**\n * Determines if the session template has a proof of funds step\n *\n * @param template - The session template\n * @returns true if the template has a proof of funds step, false otherwise\n */\nexport const hasProofOfFundsStep = (template: SessionTemplate): boolean => {\n return hasDocumentTypeNode(template, \"income-proof\");\n};\n\n/**\n * Determines if the session template has a document collection step\n *\n * @param template - The session template\n * @returns true if the template has a document collection step, false otherwise\n */\nexport const hasDocumentCollectionStep = (\n template: SessionTemplate,\n): boolean => {\n return hasNodeType(template, \"document-collection\");\n};\n\n/**\n * Gets all node types in the template\n *\n * @param template - The session template\n * @returns Array of node types in the template\n */\nexport const getNodeTypes = (template: SessionTemplate): string[] => {\n return Array.from(new Set(template.nodes.map((node) => node.type)));\n};\n\n/**\n * Gets all document types required in the template\n *\n * @param template - The session template\n * @returns Array of document types required in the template\n */\nexport const getRequiredDocumentTypes = (\n template: SessionTemplate,\n): string[] => {\n return Array.from(\n new Set(\n template.nodes\n .filter((node) => node.requiredDocumentType)\n .map((node) => node.requiredDocumentType!),\n ),\n );\n};\n\n/**\n * Converts template document type to internal document type\n * This helps standardize document types between the template and the application\n *\n * @param templateDocType - The document type as defined in the template\n * @returns The internal document type used by the application\n */\nexport const convertTemplateDocTypeToInternal = (\n templateDocType: string,\n): string => {\n if (!templateDocType) return \"\";\n\n // Mapping between template document types and internal document types\n const typeMap: Record<string, string> = {\n \"id-card\": \"id-card\",\n jdd: \"jdd\",\n \"income-proof\": \"income-proof\", // Using consistent naming\n };\n\n return typeMap[templateDocType] || templateDocType;\n};\n\n/**\n * Converts internal document type to template document type\n *\n * @param internalDocType - The document type used internally by the application\n * @returns The document type as expected in the template\n */\nexport const convertInternalDocTypeToTemplate = (\n internalDocType: string,\n): string => {\n if (!internalDocType) return \"\";\n\n // Mapping between internal document types and template document types\n const typeMap: Record<string, string> = {\n \"id-card\": \"id-card\",\n jdd: \"jdd\",\n funds: \"income-proof\", // Map funds to income-proof for backwards compatibility\n \"income-proof\": \"income-proof\",\n };\n\n return typeMap[internalDocType] || internalDocType;\n};\n\n/**\n * Updates session data with user input information\n *\n * @param sessionId - The unique identifier of the session\n * @param userInput - The user input data (firstName, lastName, birthDate)\n * @returns The updated session data\n */\nexport const updateSessionUserInput = async (\n sessionId: string,\n userInput: {\n firstName?: string;\n lastName?: string;\n birthDate?: string;\n [key: string]: unknown;\n },\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n userInput,\n });\n return response.data;\n } catch (error) {\n console.error(\"Error updating session data:\", error);\n throw error;\n }\n};\n\n/**\n * Records the NFC fallback reason when the user declares they cannot use the\n * contactless scan, and marks the NFC scan as skipped server-side.\n *\n * @param sessionId - The unique identifier of the session\n * @param payload - The selected reason (technical key), its human-readable label,\n * and an optional free-text comment.\n */\nexport const skipNfcWithReason = async (\n sessionId: string,\n payload: { reason: string; label: string; comment?: string },\n): Promise<void> => {\n await apiService.post(`/session/sdk/${sessionId}/nfc-skip`, payload);\n};\n\n/**\n * Resets a terminal NFC failure before the user starts again with another\n * document. The backend keeps completed scans immutable and treats this call\n * as a no-op when the status is not terminal.\n */\nexport const resetNfcScan = async (sessionId: string): Promise<void> => {\n await apiService.post(`/session/sdk/${sessionId}/nfc-reset`);\n};\n\n/**\n * Updates session data with contact information\n *\n * @param sessionId - The unique identifier of the session\n * @param contactInfo - The contact information data (email, phoneNumber)\n * @returns The updated session data\n */\nexport const updateSessionContactInfo = async (\n sessionId: string,\n contactInfo: {\n email: string;\n phoneNumber: string;\n [key: string]: unknown;\n },\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n contactInfo,\n });\n return response.data;\n } catch (error) {\n console.error(\"Error updating contact information:\", error);\n throw error;\n }\n};\n\n/**\n * Updates session status\n *\n * @param sessionId - The unique identifier of the session\n * @param status - The new status for the session\n * @param reachedEndNodeId - Id of the end node actually reached (when status is \"ended\"),\n * so the backend can force the correct final status with multiple end nodes.\n * @returns The updated session data\n */\nexport const updateSessionStatus = async (\n sessionId: string,\n status: string,\n reachedEndNodeId?: string,\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n status,\n ...(reachedEndNodeId ? { reachedEndNodeId } : {}),\n });\n\n // Log status modification in audit trail\n if (response.data && response.data.analysisId) {\n try {\n await logStatusModified(\n sessionId,\n status,\n response.data.clientInfoId || undefined,\n );\n } catch (err) {\n console.error(\"Failed to log status modification in audit trail:\", err);\n // Non-blocking error - continue session\n }\n }\n\n return response.data;\n } catch (error) {\n console.error(\"Error updating session status:\", error);\n throw error;\n }\n};\n\n/**\n * Updates the current step in the session\n *\n * @param sessionId - The unique identifier of the session\n * @param currentStep - The current step index in the workflow\n * @returns The updated session data\n */\nexport const updateSessionCurrentStep = async (\n sessionId: string,\n currentStep: number,\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n currentStep,\n });\n return response.data;\n } catch (error) {\n console.error(\"Error updating session current step:\", error);\n throw error;\n }\n};\n\n/**\n * Gets the journey steps from the template in order\n *\n * @param template - The session template\n * @returns Array of ordered steps\n */\nexport const getOrderedJourneySteps = (\n template: SessionTemplate,\n): SessionTemplateNode[] => {\n // Filter out only start nodes, keep end nodes for proper journey completion, then sort by order.\n // Tiebreaker on id keeps the ordering deterministic when several nodes share the same `order`\n // (e.g. parallel branches of a condition), independently of their position in template.nodes.\n return template.nodes\n .filter((node) => node.type !== \"start\")\n .sort((a, b) => a.order - b.order || a.id.localeCompare(b.id));\n};\n\nconst normalizeHandle = (value?: string): string => {\n return (value || \"\").trim().toLowerCase();\n};\n\n/**\n * Finds the outgoing edge to follow from a node.\n *\n * Resolution order:\n * 1. Exact handle match via sourceHandle/conditionValue.\n * 2. For condition:false loops, fallback to targetHandle=right.\n * 3. First outgoing edge as final fallback.\n */\nexport const findOutgoingEdge = (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n): SessionTemplate[\"edges\"][number] | null => {\n const outgoingEdges = (template.edges || []).filter(\n (edge) => edge.source === currentNodeId,\n );\n\n if (outgoingEdges.length === 0) {\n return null;\n }\n\n if (!handle) {\n return outgoingEdges[0];\n }\n\n const normalizedHandle = normalizeHandle(handle);\n const edgeByHandle = outgoingEdges.find((edge) => {\n return (\n normalizeHandle(edge.sourceHandle) === normalizedHandle ||\n normalizeHandle(edge.conditionValue) === normalizedHandle\n );\n });\n\n if (edgeByHandle) {\n return edgeByHandle;\n }\n\n const currentNode = template.nodes.find((node) => node.id === currentNodeId);\n if (currentNode?.type === \"condition\" && normalizedHandle === \"false\") {\n const rightHandleLoopEdge = outgoingEdges.find(\n (edge) => normalizeHandle(edge.targetHandle) === \"right\",\n );\n if (rightHandleLoopEdge) {\n return rightHandleLoopEdge;\n }\n }\n\n return outgoingEdges[0];\n};\n\n/**\n * Gets the next step index by following the graph edge from the current node\n *\n * @param currentNodeId - The ID of the current node\n * @param template - The session template\n * @returns The next step index (1-based) or null if no edge found\n */\nexport const getNextStepIndex = (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n): number | null => {\n const orderedNodes = getOrderedJourneySteps(template);\n const edge = findOutgoingEdge(currentNodeId, template, handle);\n\n if (!edge) {\n console.debug(\n `[sessionService] No outgoing edge found for node ${currentNodeId}${handle ? ` with handle ${handle}` : \"\"}`,\n );\n return null;\n }\n\n const targetId = edge.target;\n const targetIndex = orderedNodes.findIndex((n) => n.id === targetId);\n\n if (targetIndex === -1) {\n console.debug(\n `[sessionService] Target node ${targetId} not found in ordered steps`,\n );\n return null;\n }\n\n // steps are 1-indexed in the SDK (0 is StartSession)\n return 1 + targetIndex;\n};\n\n/**\n * Reconstructs the navigation history by following the graph from step 0\n * up to (and including) targetStep. Returns [0, ...stepIndices].\n * If the graph path cannot reach targetStep, falls back to [0, targetStep].\n */\nexport const reconstructHistoryToStep = (\n targetStep: number,\n template: SessionTemplate,\n): number[] => {\n if (targetStep <= 0) return [0];\n\n const orderedNodes = getOrderedJourneySteps(template);\n const history: number[] = [0];\n let currentStep = 1; // first node is step 1\n\n // Follow the default (first) edge from each node in sequence\n for (let safetyLimit = 0; safetyLimit < orderedNodes.length + 1; safetyLimit++) {\n if (currentStep === targetStep) {\n history.push(currentStep);\n break;\n }\n if (currentStep > targetStep) break;\n\n const nodeIndex = currentStep - 1;\n const currentNode = orderedNodes[nodeIndex];\n if (!currentNode) break;\n\n history.push(currentStep);\n\n const nextStep = getNextStepIndex(currentNode.id, template);\n if (nextStep === null) break;\n currentStep = nextStep;\n }\n\n // Fallback: if we couldn't reach targetStep via graph, use simple seed\n if (history[history.length - 1] !== targetStep) {\n return [0, targetStep];\n }\n\n return history;\n};\n\n/**\n * Maps a template node type to a step component type\n *\n * @param node - The session template node\n * @returns The step component type\n */\nexport const getStepComponentType = (node: SessionTemplateNode): string => {\n // Map from template node types to component types\n const typeMap: Record<string, string> = {\n \"document-selection\": \"document\",\n \"document-collection\": \"document-collection\",\n \"selfie-capture\": \"selfie\",\n \"contact-info\": \"contact-info\",\n \"user-input\": \"user-input\",\n \"otp-verification\": \"otp\",\n };\n\n // First check the node type\n if (node.type in typeMap) {\n return typeMap[node.type];\n }\n\n // Then check the requiredDocumentType\n if (node.requiredDocumentType) {\n return node.requiredDocumentType;\n }\n\n // Default fallback\n return node.type;\n};\n\n/**\n * Checks if a session has expired\n *\n * @param session - The session data to check\n * @returns true if the session has expired, false otherwise\n */\nexport const isSessionExpired = (session: SessionData): boolean => {\n if (!session.expireTime) {\n return false;\n }\n\n const currentTime = Date.now();\n return currentTime > session.expireTime;\n};\n\n/**\n * Stores document options in localStorage for a specific document type\n *\n * @param sessionId - The session ID\n * @param documentTypeId - The document type ID (e.g., 'jdd', 'income-proof')\n * @param options - The options to store\n */\nexport const storeDocumentOptions = (\n sessionId: string,\n documentTypeId: string,\n options: string[],\n): void => {\n if (!sessionId || !documentTypeId || !options || options.length === 0) {\n console.warn(\"Missing data for storeDocumentOptions:\", {\n sessionId,\n documentTypeId,\n options,\n });\n return;\n }\n\n // Create a consistent key format based on document type\n let storageKey = \"\";\n\n switch (documentTypeId) {\n case \"jdd\":\n storageKey = `jddOptions_${sessionId}`;\n break;\n case \"income-proof\":\n storageKey = `fundsOptions_${sessionId}`;\n break;\n case \"id-card\":\n storageKey = `idOptions_${sessionId}`;\n break;\n case \"document-collection\":\n storageKey = `documentCollectionOptions_${sessionId}`;\n break;\n default:\n storageKey = `${documentTypeId}Options_${sessionId}`;\n }\n\n localStorage.setItem(storageKey, JSON.stringify(options));\n};\n\n/**\n * Retrieves document options from localStorage for a specific document type\n *\n * @param sessionId - The session ID\n * @param documentTypeId - The document type ID (e.g., 'jdd', 'income-proof')\n * @returns Array of options or default options if none found\n */\nexport const retrieveDocumentOptions = (\n sessionId: string,\n documentTypeId: string,\n): string[] => {\n if (!sessionId || !documentTypeId) {\n console.warn(\"Missing data for retrieveDocumentOptions:\", {\n sessionId,\n documentTypeId,\n });\n return [];\n }\n\n // Create consistent key formats to check\n const possibleKeys = [\n `${documentTypeId}Options_${sessionId}`,\n documentTypeId === \"jdd\" ? `jddOptions_${sessionId}` : \"\",\n documentTypeId === \"income-proof\" ? `fundsOptions_${sessionId}` : \"\",\n documentTypeId === \"id-card\" ? `idOptions_${sessionId}` : \"\",\n documentTypeId === \"document-collection\"\n ? `documentCollectionOptions_${sessionId}`\n : \"\",\n ].filter(Boolean);\n\n // Try each possible key\n for (const key of possibleKeys) {\n const savedOptions = localStorage.getItem(key);\n if (savedOptions) {\n try {\n const parsedOptions = JSON.parse(savedOptions);\n\n return parsedOptions;\n } catch (e) {\n console.error(\n `Error parsing options for ${documentTypeId} with key ${key}:`,\n e,\n );\n }\n }\n }\n\n // Return default options if none found\n console.warn(`No options found for ${documentTypeId}, using defaults`);\n if (documentTypeId === \"jdd\") {\n return [\n \"Facture d'électricité (< 3 mois)\",\n \"Facture de gaz (< 3 mois)\",\n \"Facture d'eau (< 3 mois)\",\n \"Quittance de loyer (< 3 mois)\",\n \"Facture téléphone/internet (< 3 mois)\",\n \"Attestation d'assurance habitation (< 3 mois)\",\n ];\n } else if (documentTypeId === \"income-proof\") {\n return [\n \"Bulletin de salaire\",\n \"Avis d'imposition\",\n \"Relevé de compte bancaire\",\n \"Attestation de revenus\",\n \"Contrat de travail\",\n ];\n } else if (documentTypeId === \"id-card\") {\n return [\"Carte nationale d'identité\", \"Passeport\", \"Permis de conduire\"];\n } else if (documentTypeId === \"document-collection\") {\n return [\"Document administratif\", \"Justificatif\", \"Attestation\"];\n }\n\n return [];\n};\n\nconst clearStorageBySessionId = (sessionId: string): void => {\n const scopedKeys = [\n `userInput_${sessionId}`,\n `contactInfo_${sessionId}`,\n `sessionData_${sessionId}`,\n ];\n\n scopedKeys.forEach((key) => {\n localStorage.removeItem(key);\n sessionStorage.removeItem(key);\n });\n\n for (let i = localStorage.length - 1; i >= 0; i -= 1) {\n const key = localStorage.key(i);\n if (!key) {\n continue;\n }\n if (key.endsWith(`_${sessionId}`)) {\n localStorage.removeItem(key);\n }\n }\n\n for (let i = sessionStorage.length - 1; i >= 0; i -= 1) {\n const key = sessionStorage.key(i);\n if (!key) {\n continue;\n }\n if (key.endsWith(`_${sessionId}`)) {\n sessionStorage.removeItem(key);\n }\n }\n\n if (localStorage.getItem(\"sessionId\") === sessionId) {\n localStorage.removeItem(\"sessionId\");\n }\n if (sessionStorage.getItem(\"sessionId\") === sessionId) {\n sessionStorage.removeItem(\"sessionId\");\n }\n};\n\n/**\n * Clears all client-side session traces (memory + browser storage)\n * for a given session. This is intentionally aggressive for security.\n */\nexport const clearSessionSensitiveData = (sessionId?: string): void => {\n clearSessionMemory(sessionId);\n\n if (sessionId) {\n clearStorageBySessionId(sessionId);\n return;\n }\n\n localStorage.removeItem(\"sessionId\");\n sessionStorage.removeItem(\"sessionId\");\n\n for (let i = localStorage.length - 1; i >= 0; i -= 1) {\n const key = localStorage.key(i);\n if (!key) {\n continue;\n }\n if (\n key.startsWith(\"userInput_\") ||\n key.startsWith(\"contactInfo_\") ||\n key.includes(\"Options_\")\n ) {\n localStorage.removeItem(key);\n }\n }\n\n for (let i = sessionStorage.length - 1; i >= 0; i -= 1) {\n const key = sessionStorage.key(i);\n if (!key) {\n continue;\n }\n if (\n key.startsWith(\"userInput_\") ||\n key.startsWith(\"contactInfo_\") ||\n key.includes(\"Options_\")\n ) {\n sessionStorage.removeItem(key);\n }\n }\n};\n\n/**\n * Returns the pre-fill data for a given run index from a `userInput` object\n * that contains a `_list` array.\n *\n * Convention: when the integrator wants to pre-fill different data per run\n * (e.g. multiple persons in a loop), they pass `userInput: { _list: [...] }`\n * at session creation. Each element in `_list` corresponds to a run (0-indexed).\n *\n * @param userInput - The session's userInput object\n * @param runIndex - The current run index (0 = first pass, 1 = second pass, …)\n * @returns The pre-fill data for that run, or null if not defined\n */\nexport const getRunPrefillData = (\n userInput: Record<string, unknown>,\n runIndex: number,\n): Record<string, unknown> | null => {\n const list = userInput?._list;\n if (!Array.isArray(list)) return null;\n return (list[runIndex] as Record<string, unknown>) ?? null;\n};\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "datakeen-session-react",
3
- "version": "1.1.140-dev.103",
3
+ "version": "1.1.140-dev.104",
4
4
  "description": "React SDK component to manage and render Datakeen session experiences easily.",
5
5
  "publishConfig": {
6
6
  "access": "public",