datakeen-session-react 1.1.195-dev.1 → 1.1.195-dev.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/session/EndFlow.js +15 -5
- package/dist/cjs/components/session/EndFlow.js.map +1 -1
- package/dist/cjs/components/session/SessionContent.js +5 -3
- package/dist/cjs/components/session/SessionContent.js.map +1 -1
- package/dist/cjs/components/template/ExternalVerificationNodeHandler.js +61 -29
- package/dist/cjs/components/template/ExternalVerificationNodeHandler.js.map +1 -1
- package/dist/cjs/components/template/TemplateNodeRenderer.js +5 -3
- package/dist/cjs/components/template/TemplateNodeRenderer.js.map +1 -1
- package/dist/cjs/hooks/useStepNavigation.js +6 -4
- package/dist/cjs/hooks/useStepNavigation.js.map +1 -1
- package/dist/cjs/utils/sessionStatus.js +28 -0
- package/dist/cjs/utils/sessionStatus.js.map +1 -0
- package/dist/esm/components/session/EndFlow.js +15 -5
- package/dist/esm/components/session/EndFlow.js.map +1 -1
- package/dist/esm/components/session/SessionContent.js +5 -3
- package/dist/esm/components/session/SessionContent.js.map +1 -1
- package/dist/esm/components/template/ExternalVerificationNodeHandler.js +61 -29
- package/dist/esm/components/template/ExternalVerificationNodeHandler.js.map +1 -1
- package/dist/esm/components/template/TemplateNodeRenderer.js +5 -3
- package/dist/esm/components/template/TemplateNodeRenderer.js.map +1 -1
- package/dist/esm/hooks/useStepNavigation.js +4 -2
- package/dist/esm/hooks/useStepNavigation.js.map +1 -1
- package/dist/esm/utils/sessionStatus.js +26 -0
- package/dist/esm/utils/sessionStatus.js.map +1 -0
- package/docs/navigation-history.md +8 -0
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var tslib_es6 = require('../node_modules/tslib/tslib.es6.js');
|
|
4
4
|
var React = require('react');
|
|
5
5
|
var sessionService = require('../services/sessionService.js');
|
|
6
|
+
var sessionStatus = require('../utils/sessionStatus.js');
|
|
6
7
|
|
|
7
8
|
/** Node types that auto-execute and should be skipped when going back */
|
|
8
9
|
var AUTO_EXECUTING_TYPES = new Set(["external-verification", "condition", "complementary-mandate"]);
|
|
@@ -35,7 +36,7 @@ var trimHistoryAfterCommittedNode = function (reconstructedHistory, template) {
|
|
|
35
36
|
}
|
|
36
37
|
return reconstructedHistory.slice(reversibleHistoryStart);
|
|
37
38
|
};
|
|
38
|
-
var useStepNavigation = function (sessionId, sessionStatus, initialStep, template) {
|
|
39
|
+
var useStepNavigation = function (sessionId, sessionStatus$1, initialStep, template) {
|
|
39
40
|
var _a = React.useState(initialStep !== null && initialStep !== void 0 ? initialStep : 0), step = _a[0], setStepState = _a[1];
|
|
40
41
|
var _b = React.useState(initialStep !== undefined ? [initialStep] : [0]), history = _b[0], setHistory = _b[1];
|
|
41
42
|
var hasInitialized = React.useRef(false);
|
|
@@ -146,8 +147,9 @@ var useStepNavigation = function (sessionId, sessionStatus, initialStep, templat
|
|
|
146
147
|
if (!sessionId) {
|
|
147
148
|
return;
|
|
148
149
|
}
|
|
149
|
-
// Check if session is already ended
|
|
150
|
-
|
|
150
|
+
// Check if session is already finished (raw "ended" or a consolidated
|
|
151
|
+
// result status the backend wrote once the session became terminal).
|
|
152
|
+
if (sessionStatus.isSessionFinished(sessionStatus$1)) {
|
|
151
153
|
setStepState(100);
|
|
152
154
|
return;
|
|
153
155
|
}
|
|
@@ -167,7 +169,7 @@ var useStepNavigation = function (sessionId, sessionStatus, initialStep, templat
|
|
|
167
169
|
});
|
|
168
170
|
hasInitialized.current = true;
|
|
169
171
|
}
|
|
170
|
-
}, [sessionId, sessionStatus, initialStep]);
|
|
172
|
+
}, [sessionId, sessionStatus$1, initialStep]);
|
|
171
173
|
var stepObject = {
|
|
172
174
|
setStep: setStep,
|
|
173
175
|
goBack: goBack,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStepNavigation.js","sources":["../../../../src/hooks/useStepNavigation.ts"],"sourcesContent":["import { useState, useEffect, useRef } from \"react\";\nimport {\n updateSessionCurrentStep,\n getNextStepIndex,\n getOrderedJourneySteps,\n reconstructHistoryToStep,\n} from \"../services/sessionService\";\nimport type { SessionTemplate } from \"../types/session\";\n\n/** Node types that auto-execute and should be skipped when going back */\nconst AUTO_EXECUTING_TYPES = new Set([\"external-verification\", \"condition\", \"complementary-mandate\"]);\nconst COMMITTED_NODE_TYPES = new Set([\"selfie-capture\", \"biometric-capture\"]);\n\nconst getNodeTypeAtStep = (\n step: number,\n template: SessionTemplate,\n): string | undefined => getOrderedJourneySteps(template)[step - 1]?.type;\n\n/**\n * Rebuilds only the reversible part of a path after a committed node.\n * Auto-executing nodes immediately following the commit are excluded so the\n * first interactive destination remains the history boundary after reload.\n */\nconst trimHistoryAfterCommittedNode = (\n reconstructedHistory: number[],\n template: SessionTemplate,\n): number[] => {\n let committedHistoryIndex = -1;\n\n for (let index = reconstructedHistory.length - 2; index >= 0; index -= 1) {\n const nodeType = getNodeTypeAtStep(reconstructedHistory[index], template);\n if (nodeType && COMMITTED_NODE_TYPES.has(nodeType)) {\n committedHistoryIndex = index;\n break;\n }\n }\n\n if (committedHistoryIndex === -1) {\n return reconstructedHistory;\n }\n\n let reversibleHistoryStart = committedHistoryIndex + 1;\n while (reversibleHistoryStart < reconstructedHistory.length - 1) {\n const nodeType = getNodeTypeAtStep(\n reconstructedHistory[reversibleHistoryStart],\n template,\n );\n if (!nodeType || !AUTO_EXECUTING_TYPES.has(nodeType)) {\n break;\n }\n reversibleHistoryStart += 1;\n }\n\n return reconstructedHistory.slice(reversibleHistoryStart);\n};\n\nexport const useStepNavigation = (\n sessionId: string,\n sessionStatus?: string,\n initialStep?: number,\n template?: SessionTemplate,\n) => {\n const [step, setStepState] = useState(initialStep ?? 0);\n const [history, setHistory] = useState<number[]>(initialStep !== undefined ? [initialStep] : [0]);\n const hasInitialized = useRef(false);\n const committedNavigationPending = useRef(false);\n\n const setStep = (newStep: number, skipHistory = false) => {\n if (!skipHistory && newStep !== step) {\n setHistory((prev) => {\n if (prev[prev.length - 1] === newStep) return prev;\n return [...prev, newStep];\n });\n }\n setStepState(newStep);\n\n // Update current step in database\n if (sessionId) {\n updateSessionCurrentStep(sessionId, newStep).catch((error) => {\n console.error(\"Failed to update current step in database:\", error);\n // Non-blocking error - the step is still updated locally\n });\n }\n };\n\n const goBack = () => {\n if (history.length > 1) {\n let newHistory = [...history];\n newHistory.pop(); // Remove current step\n\n // Skip auto-executing nodes when going back\n if (template) {\n const orderedNodes = getOrderedJourneySteps(template);\n while (newHistory.length > 1) {\n const candidateStep = newHistory[newHistory.length - 1];\n // steps are 1-indexed (step 0 = start, step 1 = first node, etc.)\n const nodeIndex = candidateStep - 1;\n const candidateNode = orderedNodes[nodeIndex];\n if (candidateNode && AUTO_EXECUTING_TYPES.has(candidateNode.type)) {\n newHistory.pop();\n } else {\n break;\n }\n }\n }\n\n const previousStep = newHistory[newHistory.length - 1];\n setHistory(newHistory);\n setStep(previousStep, true);\n } else {\n console.warn(\"[goBack] BLOCKED — history.length <= 1, history:\", [...history]);\n }\n };\n\n /**\n * Retour arrière vers un nœud précis (ex: bouton \"Corriger ma saisie\").\n * Contrairement à `setStep`, on TRONQUE l'historique jusqu'à la dernière\n * occurrence de `targetStep` au lieu de l'empiler : le nœud cible cesse\n * ainsi d'être compté comme un \"revisit\" (runIndex 0 côté\n * TemplateNodeRenderer → formulaire pré-rempli). Si la cible n'est pas dans\n * l'historique, on retombe sur un `setStep` classique.\n */\n const goBackToStep = (targetStep: number) => {\n const idx = history.lastIndexOf(targetStep);\n if (idx !== -1) {\n const newHistory = history.slice(0, idx + 1);\n setHistory(newHistory);\n setStep(targetStep, true);\n } else {\n console.warn(\"[goBackToStep] target not in history — pushing instead:\", targetStep);\n setStep(targetStep);\n }\n };\n\n const goToNextStep = (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string\n ) => {\n const nextStepIndex = getNextStepIndex(currentNodeId, template, handle);\n\n if (nextStepIndex !== null) {\n if (committedNavigationPending.current) {\n const destinationType = getNodeTypeAtStep(nextStepIndex, template);\n committedNavigationPending.current = Boolean(\n destinationType && AUTO_EXECUTING_TYPES.has(destinationType),\n );\n setHistory([nextStepIndex]);\n setStep(nextStepIndex, true);\n } else {\n setStep(nextStepIndex);\n }\n } else {\n committedNavigationPending.current = false;\n console.warn(\n `[useStepNavigation] Could not find next step for node ${currentNodeId}. Staying on current step.`\n );\n }\n };\n\n /**\n * Navigates through the graph and makes the destination a point of no return.\n * The destination remains persisted by setStep, while prior history is discarded.\n */\n const goToNextStepCommitted = (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n ) => {\n const nextStepIndex = getNextStepIndex(currentNodeId, template, handle);\n\n if (nextStepIndex !== null) {\n const destinationType = getNodeTypeAtStep(nextStepIndex, template);\n committedNavigationPending.current = Boolean(\n destinationType && AUTO_EXECUTING_TYPES.has(destinationType),\n );\n setHistory([nextStepIndex]);\n setStep(nextStepIndex, true);\n } else {\n committedNavigationPending.current = false;\n console.warn(\n `[useStepNavigation] Could not find next step for node ${currentNodeId}. Staying on current step.`,\n );\n }\n };\n\n // Initialize step from session data or status\n useEffect(() => {\n if (!sessionId) {\n return;\n }\n\n // Check if session is already ended\n if (sessionStatus === \"ended\") {\n setStepState(100);\n return;\n }\n\n // Only initialize once when initialStep becomes available\n if (initialStep !== undefined && !hasInitialized.current) {\n setStepState(initialStep);\n setHistory((prev) => {\n // Preserve history if the user already navigated past the initial step\n if (prev.length > 1 && prev[prev.length - 1] === initialStep) {\n return prev;\n }\n // Reconstruct history by following the graph from step 0\n const reconstructed = template\n ? trimHistoryAfterCommittedNode(\n reconstructHistoryToStep(initialStep, template),\n template,\n )\n : initialStep > 0 ? [0, initialStep] : [initialStep];\n return reconstructed;\n });\n hasInitialized.current = true;\n }\n }, [sessionId, sessionStatus, initialStep]);\n\n const stepObject = {\n setStep,\n goBack,\n goBackToStep,\n goToNextStep,\n goToNextStepCommitted,\n step,\n canGoBack: history.length > 1,\n };\n\n return {\n step,\n setStep,\n goBack,\n goBackToStep,\n goToNextStep,\n goToNextStepCommitted,\n stepObject,\n history,\n };\n};\n"],"names":["getOrderedJourneySteps","useState","useRef","__spreadArray","updateSessionCurrentStep","getNextStepIndex","useEffect","reconstructHistoryToStep"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useStepNavigation.js","sources":["../../../../src/hooks/useStepNavigation.ts"],"sourcesContent":["import { useState, useEffect, useRef } from \"react\";\nimport {\n updateSessionCurrentStep,\n getNextStepIndex,\n getOrderedJourneySteps,\n reconstructHistoryToStep,\n} from \"../services/sessionService\";\nimport type { SessionTemplate } from \"../types/session\";\nimport { isSessionFinished } from \"../utils/sessionStatus\";\n\n/** Node types that auto-execute and should be skipped when going back */\nconst AUTO_EXECUTING_TYPES = new Set([\"external-verification\", \"condition\", \"complementary-mandate\"]);\nconst COMMITTED_NODE_TYPES = new Set([\"selfie-capture\", \"biometric-capture\"]);\n\nconst getNodeTypeAtStep = (\n step: number,\n template: SessionTemplate,\n): string | undefined => getOrderedJourneySteps(template)[step - 1]?.type;\n\n/**\n * Rebuilds only the reversible part of a path after a committed node.\n * Auto-executing nodes immediately following the commit are excluded so the\n * first interactive destination remains the history boundary after reload.\n */\nconst trimHistoryAfterCommittedNode = (\n reconstructedHistory: number[],\n template: SessionTemplate,\n): number[] => {\n let committedHistoryIndex = -1;\n\n for (let index = reconstructedHistory.length - 2; index >= 0; index -= 1) {\n const nodeType = getNodeTypeAtStep(reconstructedHistory[index], template);\n if (nodeType && COMMITTED_NODE_TYPES.has(nodeType)) {\n committedHistoryIndex = index;\n break;\n }\n }\n\n if (committedHistoryIndex === -1) {\n return reconstructedHistory;\n }\n\n let reversibleHistoryStart = committedHistoryIndex + 1;\n while (reversibleHistoryStart < reconstructedHistory.length - 1) {\n const nodeType = getNodeTypeAtStep(\n reconstructedHistory[reversibleHistoryStart],\n template,\n );\n if (!nodeType || !AUTO_EXECUTING_TYPES.has(nodeType)) {\n break;\n }\n reversibleHistoryStart += 1;\n }\n\n return reconstructedHistory.slice(reversibleHistoryStart);\n};\n\nexport const useStepNavigation = (\n sessionId: string,\n sessionStatus?: string,\n initialStep?: number,\n template?: SessionTemplate,\n) => {\n const [step, setStepState] = useState(initialStep ?? 0);\n const [history, setHistory] = useState<number[]>(initialStep !== undefined ? [initialStep] : [0]);\n const hasInitialized = useRef(false);\n const committedNavigationPending = useRef(false);\n\n const setStep = (newStep: number, skipHistory = false) => {\n if (!skipHistory && newStep !== step) {\n setHistory((prev) => {\n if (prev[prev.length - 1] === newStep) return prev;\n return [...prev, newStep];\n });\n }\n setStepState(newStep);\n\n // Update current step in database\n if (sessionId) {\n updateSessionCurrentStep(sessionId, newStep).catch((error) => {\n console.error(\"Failed to update current step in database:\", error);\n // Non-blocking error - the step is still updated locally\n });\n }\n };\n\n const goBack = () => {\n if (history.length > 1) {\n let newHistory = [...history];\n newHistory.pop(); // Remove current step\n\n // Skip auto-executing nodes when going back\n if (template) {\n const orderedNodes = getOrderedJourneySteps(template);\n while (newHistory.length > 1) {\n const candidateStep = newHistory[newHistory.length - 1];\n // steps are 1-indexed (step 0 = start, step 1 = first node, etc.)\n const nodeIndex = candidateStep - 1;\n const candidateNode = orderedNodes[nodeIndex];\n if (candidateNode && AUTO_EXECUTING_TYPES.has(candidateNode.type)) {\n newHistory.pop();\n } else {\n break;\n }\n }\n }\n\n const previousStep = newHistory[newHistory.length - 1];\n setHistory(newHistory);\n setStep(previousStep, true);\n } else {\n console.warn(\"[goBack] BLOCKED — history.length <= 1, history:\", [...history]);\n }\n };\n\n /**\n * Retour arrière vers un nœud précis (ex: bouton \"Corriger ma saisie\").\n * Contrairement à `setStep`, on TRONQUE l'historique jusqu'à la dernière\n * occurrence de `targetStep` au lieu de l'empiler : le nœud cible cesse\n * ainsi d'être compté comme un \"revisit\" (runIndex 0 côté\n * TemplateNodeRenderer → formulaire pré-rempli). Si la cible n'est pas dans\n * l'historique, on retombe sur un `setStep` classique.\n */\n const goBackToStep = (targetStep: number) => {\n const idx = history.lastIndexOf(targetStep);\n if (idx !== -1) {\n const newHistory = history.slice(0, idx + 1);\n setHistory(newHistory);\n setStep(targetStep, true);\n } else {\n console.warn(\"[goBackToStep] target not in history — pushing instead:\", targetStep);\n setStep(targetStep);\n }\n };\n\n const goToNextStep = (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string\n ) => {\n const nextStepIndex = getNextStepIndex(currentNodeId, template, handle);\n\n if (nextStepIndex !== null) {\n if (committedNavigationPending.current) {\n const destinationType = getNodeTypeAtStep(nextStepIndex, template);\n committedNavigationPending.current = Boolean(\n destinationType && AUTO_EXECUTING_TYPES.has(destinationType),\n );\n setHistory([nextStepIndex]);\n setStep(nextStepIndex, true);\n } else {\n setStep(nextStepIndex);\n }\n } else {\n committedNavigationPending.current = false;\n console.warn(\n `[useStepNavigation] Could not find next step for node ${currentNodeId}. Staying on current step.`\n );\n }\n };\n\n /**\n * Navigates through the graph and makes the destination a point of no return.\n * The destination remains persisted by setStep, while prior history is discarded.\n */\n const goToNextStepCommitted = (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n ) => {\n const nextStepIndex = getNextStepIndex(currentNodeId, template, handle);\n\n if (nextStepIndex !== null) {\n const destinationType = getNodeTypeAtStep(nextStepIndex, template);\n committedNavigationPending.current = Boolean(\n destinationType && AUTO_EXECUTING_TYPES.has(destinationType),\n );\n setHistory([nextStepIndex]);\n setStep(nextStepIndex, true);\n } else {\n committedNavigationPending.current = false;\n console.warn(\n `[useStepNavigation] Could not find next step for node ${currentNodeId}. Staying on current step.`,\n );\n }\n };\n\n // Initialize step from session data or status\n useEffect(() => {\n if (!sessionId) {\n return;\n }\n\n // Check if session is already finished (raw \"ended\" or a consolidated\n // result status the backend wrote once the session became terminal).\n if (isSessionFinished(sessionStatus)) {\n setStepState(100);\n return;\n }\n\n // Only initialize once when initialStep becomes available\n if (initialStep !== undefined && !hasInitialized.current) {\n setStepState(initialStep);\n setHistory((prev) => {\n // Preserve history if the user already navigated past the initial step\n if (prev.length > 1 && prev[prev.length - 1] === initialStep) {\n return prev;\n }\n // Reconstruct history by following the graph from step 0\n const reconstructed = template\n ? trimHistoryAfterCommittedNode(\n reconstructHistoryToStep(initialStep, template),\n template,\n )\n : initialStep > 0 ? [0, initialStep] : [initialStep];\n return reconstructed;\n });\n hasInitialized.current = true;\n }\n }, [sessionId, sessionStatus, initialStep]);\n\n const stepObject = {\n setStep,\n goBack,\n goBackToStep,\n goToNextStep,\n goToNextStepCommitted,\n step,\n canGoBack: history.length > 1,\n };\n\n return {\n step,\n setStep,\n goBack,\n goBackToStep,\n goToNextStep,\n goToNextStepCommitted,\n stepObject,\n history,\n };\n};\n"],"names":["getOrderedJourneySteps","sessionStatus","useState","useRef","__spreadArray","updateSessionCurrentStep","getNextStepIndex","useEffect","isSessionFinished","reconstructHistoryToStep"],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Statuts de résultat consolidé : le backend réécrit sessions.status avec le
|
|
4
|
+
// résultat consolidé une fois la session terminale (voir
|
|
5
|
+
// ResultUpdaterHelper.updateResult côté backend). Une session rouverte après
|
|
6
|
+
// coup porte donc l'un de ces statuts en base, pas "ended".
|
|
7
|
+
var CONSOLIDATED_RESULT_STATUSES = new Set([
|
|
8
|
+
"verify",
|
|
9
|
+
"ai_approved",
|
|
10
|
+
"ai_rejected",
|
|
11
|
+
"user_approved",
|
|
12
|
+
"user_rejected",
|
|
13
|
+
]);
|
|
14
|
+
/**
|
|
15
|
+
* true si la session est terminée (écran de fin), qu'elle porte encore le
|
|
16
|
+
* statut brut "ended" ou déjà un statut de résultat consolidé.
|
|
17
|
+
*
|
|
18
|
+
* Ne PAS confondre avec "conform" : posé par SignatureElectronic juste après
|
|
19
|
+
* la signature, avant le vrai nœud "end" — ce n'est pas une fin de parcours.
|
|
20
|
+
*/
|
|
21
|
+
var isSessionFinished = function (status) {
|
|
22
|
+
if (!status)
|
|
23
|
+
return false;
|
|
24
|
+
return status === "ended" || CONSOLIDATED_RESULT_STATUSES.has(status);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
exports.isSessionFinished = isSessionFinished;
|
|
28
|
+
//# sourceMappingURL=sessionStatus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionStatus.js","sources":["../../../../src/utils/sessionStatus.ts"],"sourcesContent":["// Statuts de résultat consolidé : le backend réécrit sessions.status avec le\n// résultat consolidé une fois la session terminale (voir\n// ResultUpdaterHelper.updateResult côté backend). Une session rouverte après\n// coup porte donc l'un de ces statuts en base, pas \"ended\".\nconst CONSOLIDATED_RESULT_STATUSES = new Set([\n \"verify\",\n \"ai_approved\",\n \"ai_rejected\",\n \"user_approved\",\n \"user_rejected\",\n]);\n\n/**\n * true si la session est terminée (écran de fin), qu'elle porte encore le\n * statut brut \"ended\" ou déjà un statut de résultat consolidé.\n *\n * Ne PAS confondre avec \"conform\" : posé par SignatureElectronic juste après\n * la signature, avant le vrai nœud \"end\" — ce n'est pas une fin de parcours.\n */\nexport const isSessionFinished = (status?: string | null): boolean => {\n if (!status) return false;\n return status === \"ended\" || CONSOLIDATED_RESULT_STATUSES.has(status);\n};\n"],"names":[],"mappings":";;AAAA;AACA;AACA;AACA;AACA,IAAM,4BAA4B,GAAG,IAAI,GAAG,CAAC;IAC3C,QAAQ;IACR,aAAa;IACb,aAAa;IACb,eAAe;IACf,eAAe;AAChB,CAAA,CAAC;AAEF;;;;;;AAMG;AACI,IAAM,iBAAiB,GAAG,UAAC,MAAsB,EAAA;AACtD,IAAA,IAAI,CAAC,MAAM;AAAE,QAAA,OAAO,KAAK;IACzB,OAAO,MAAM,KAAK,OAAO,IAAI,4BAA4B,CAAC,GAAG,CAAC,MAAM,CAAC;AACvE;;;;"}
|
|
@@ -31,16 +31,19 @@ var ICON_COLOR = "var(--dk-btn-bg, #11e5c5)";
|
|
|
31
31
|
*/
|
|
32
32
|
var EndFlow = function (_a) {
|
|
33
33
|
var _b, _c;
|
|
34
|
-
var sessionId = _a.sessionId, sessionStatus = _a.sessionStatus, callbackURL = _a.callbackURL, endNodeId = _a.endNodeId, expectedResult = _a.expectedResult, compliantCase = _a.compliantCase, nonCompliantCase = _a.nonCompliantCase;
|
|
34
|
+
var sessionId = _a.sessionId, sessionStatus = _a.sessionStatus, callbackURL = _a.callbackURL, endNodeId = _a.endNodeId, expectedResult = _a.expectedResult, compliantCase = _a.compliantCase, nonCompliantCase = _a.nonCompliantCase, alreadyFinished = _a.alreadyFinished;
|
|
35
35
|
var _d = useState(false), isEnding = _d[0], setIsEnding = _d[1];
|
|
36
36
|
var _e = useState(false), isRedirecting = _e[0], setIsRedirecting = _e[1];
|
|
37
37
|
var _f = useState(false), shouldRedirect = _f[0], setShouldRedirect = _f[1];
|
|
38
38
|
// Statut consolidé renvoyé par le backend après updateSessionStatus —
|
|
39
|
-
// sert à détecter un échec « poursuivre quand même » non porté par
|
|
40
|
-
|
|
39
|
+
// sert à détecter un échec « poursuivre quand même » non porté par
|
|
40
|
+
// expectedResult. Si la session était déjà terminée à l'arrivée, on la
|
|
41
|
+
// connaît déjà (sessionStatus) : pas besoin d'attendre le backend.
|
|
42
|
+
var _g = useState(alreadyFinished ? sessionStatus : undefined), backendStatus = _g[0], setBackendStatus = _g[1];
|
|
41
43
|
// Le verdict backend arrive de façon asynchrone (~1-2s). On le marque résolu
|
|
42
44
|
// pour éviter de flasher l'écran succès puis basculer sur l'écran erreur.
|
|
43
|
-
|
|
45
|
+
// Déjà résolu si la session était déjà terminée (pas d'appel réseau à attendre).
|
|
46
|
+
var _h = useState(Boolean(alreadyFinished)), statusResolved = _h[0], setStatusResolved = _h[1];
|
|
44
47
|
var t = useI18n().t;
|
|
45
48
|
var isMobile = useIsMobile(768);
|
|
46
49
|
// Décalage horizontal du bloc d'items réservé au desktop. On le pilote en JS
|
|
@@ -68,8 +71,15 @@ var EndFlow = function (_a) {
|
|
|
68
71
|
// le backend), on affiche un état neutre plutôt que de présumer le succès.
|
|
69
72
|
var isResolving = !expectedError && !statusResolved;
|
|
70
73
|
// Trigger session end as soon as the user reaches this screen,
|
|
71
|
-
// regardless of whether they click the button (e.g. tab close)
|
|
74
|
+
// regardless of whether they click the button (e.g. tab close).
|
|
75
|
+
// Skipped when the session was already finished on arrival: the backend
|
|
76
|
+
// ignores this PATCH anyway (session already consolidated), and resending
|
|
77
|
+
// it risks forcing a phantom "end" node reached only through a resumption
|
|
78
|
+
// index mismatch, not a real navigation.
|
|
72
79
|
useEffect(function () {
|
|
80
|
+
if (alreadyFinished) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
73
83
|
updateSessionStatus(sessionId, "ended", endNodeId)
|
|
74
84
|
.then(function (updatedSession) {
|
|
75
85
|
if (updatedSession === null || updatedSession === void 0 ? void 0 : updatedSession.status) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EndFlow.js","sources":["../../../../../src/components/session/EndFlow.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport { HeartHandshake, Send, Mail } from \"lucide-react\";\nimport checkIcon from \"../../assets/check.svg\";\nimport LoadingState from \"../states/LoadingState\";\nimport Button from \"../ui/Button\";\nimport PageActions from \"../ui/PageActions\";\nimport Title from \"../ui/Title\";\nimport Subtitle from \"../ui/Subtitle\";\nimport {\n clearSessionSensitiveData,\n updateSessionStatus,\n} from \"../../services/sessionService\";\nimport { logSessionEnded } from \"../../services/auditTrailService\";\nimport MobilePageLayout from \"../ui/MobilePageLayout\";\nimport { useI18n } from \"../../hooks/useI18n\";\nimport useIsMobile from \"../../hooks/useIsMobile\";\nimport type { EndScreenCase } from \"../../types/session\";\nimport { resolveEndScreenIcon } from \"./endScreenIcons\";\nimport { replaceLocation } from \"../../utils/navigation\";\n\n// Couleur des icônes = couleur du bouton choisie pour le journey (buttonBgColor).\nconst ICON_COLOR = \"var(--dk-btn-bg, #11e5c5)\";\n\ninterface EndFlowProps {\n sessionId: string;\n sessionStatus?: string; // Ajout du statut de session optionnel\n callbackURL?: string | null;\n endNodeId?: string; // Id du nœud `end` atteint, transmis au backend pour forcer le bon statut\n expectedResult?: string; // Résultat forcé du nœud end atteint (ex: 'non_compliant')\n /** Textes de fin personnalisés (config globale du journey). Vide → fallback standard. */\n compliantCase?: EndScreenCase;\n nonCompliantCase?: EndScreenCase;\n}\n\n/**\n * EndFlow Component\n *\n * Composant affiché à la fin du flux de vérification lorsque toutes les étapes ont été complétées.\n * Affiche un message de confirmation avec une icône de succès.\n *\n * @param {EndFlowProps} props - Propriétés du composant\n * @param {string} props.sessionId - L'identifiant de la session\n * @param {string} props.sessionStatus - Le statut actuel de la session\n * @returns {JSX.Element} Le composant EndFlow\n */\nconst EndFlow: React.FC<EndFlowProps> = ({\n sessionId,\n sessionStatus,\n callbackURL,\n endNodeId,\n expectedResult,\n compliantCase,\n nonCompliantCase,\n}) => {\n const [isEnding, setIsEnding] = useState(false);\n const [isRedirecting, setIsRedirecting] = useState(false);\n const [shouldRedirect, setShouldRedirect] = useState(false);\n // Statut consolidé renvoyé par le backend après updateSessionStatus —\n // sert à détecter un échec « poursuivre quand même » non porté par expectedResult.\n const [backendStatus, setBackendStatus] = useState<string | undefined>(\n undefined,\n );\n // Le verdict backend arrive de façon asynchrone (~1-2s). On le marque résolu\n // pour éviter de flasher l'écran succès puis basculer sur l'écran erreur.\n const [statusResolved, setStatusResolved] = useState(false);\n const { t } = useI18n();\n const isMobile = useIsMobile(768);\n // Décalage horizontal du bloc d'items réservé au desktop. On le pilote en JS\n // (useIsMobile, cohérent avec le composant Button) plutôt que via `md:` Tailwind :\n // les variantes responsive `md:translate-*` ne sont pas fiables dans le bundle SDK.\n // Utilisé uniquement par l'écran d'erreur générique hardcodé ci-dessous.\n const desktopTranslateX = isMobile ? \"\" : \"translate-x-10\";\n // Même décalage, mais via padding plutôt que transform — réservé aux écrans à\n // message personnalisé (renderCustomCase) : un `transform: translateX(...)` ne fait\n // déborder aucune boîte visuellement, mais contribue quand même au \"scrollable\n // overflow\" du conteneur `overflow-y-auto` ancêtre (DatakeenSession), ce qui\n // affichait une scrollbar horizontale fantôme sur desktop. `padding-left` reste\n // contenu dans la largeur déclarée (box-sizing: border-box global du SDK), donc ne\n // peut pas produire ce débordement invisible.\n const desktopOffsetX = isMobile ? \"\" : \"pl-10\";\n\n // Le nœud end peut déjà forcer un résultat non conforme : dans ce cas on\n // connaît l'issue sans attendre le backend.\n const expectedError =\n expectedResult === \"non_compliant\" || expectedResult === \"error\";\n\n // L'écran « erreur conservée » s'affiche si le nœud end force un résultat\n // non conforme, OU si le backend a consolidé un statut d'échec/vérification.\n const isError =\n expectedError ||\n backendStatus === \"ai_rejected\" ||\n backendStatus === \"verify\";\n\n // Tant que le verdict n'est pas connu (ni forcé par le nœud, ni renvoyé par\n // le backend), on affiche un état neutre plutôt que de présumer le succès.\n const isResolving = !expectedError && !statusResolved;\n\n // Trigger session end as soon as the user reaches this screen,\n // regardless of whether they click the button (e.g. tab close)\n useEffect(() => {\n updateSessionStatus(sessionId, \"ended\", endNodeId)\n .then((updatedSession) => {\n if (updatedSession?.status) {\n setBackendStatus(updatedSession.status);\n }\n if (updatedSession && updatedSession.analysisId) {\n logSessionEnded(sessionId).catch((err) => {\n console.error(\"Failed to log session end in audit trail:\", err);\n });\n }\n })\n .catch((error) => {\n console.error(\"Error updating session status on EndFlow mount:\", error);\n })\n .finally(() => {\n // Verdict connu (ou échec d'appel) : on peut afficher l'écran final.\n setStatusResolved(true);\n });\n }, []);\n\n const handleEndSession = async () => {\n setIsEnding(true);\n try {\n clearSessionSensitiveData(sessionId);\n } catch (error) {\n console.error(\"Erreur lors de la finalisation de la session:\", error);\n } finally {\n setIsEnding(false);\n if (callbackURL) {\n setIsRedirecting(true);\n setShouldRedirect(true);\n } else {\n // Forcer la fermeture immédiatement lorsqu'aucune redirection n'est attendue\n closeWindow();\n }\n }\n };\n\n const redirectToCallback = (url: string) => {\n try {\n replaceLocation(url);\n } catch (e) {\n console.error(\"Redirection vers le callback échouée:\", e);\n setIsRedirecting(false);\n closeWindow();\n }\n };\n\n useEffect(() => {\n if (sessionStatus === \"ended\" && callbackURL && !shouldRedirect) {\n setIsRedirecting(true);\n setShouldRedirect(true);\n }\n }, [sessionStatus, callbackURL, shouldRedirect]);\n\n useEffect(() => {\n if (!shouldRedirect || !callbackURL) {\n return;\n }\n\n const REDIRECT_DELAY_MS = 2000;\n const timer = window.setTimeout(\n () => redirectToCallback(callbackURL),\n REDIRECT_DELAY_MS,\n );\n return () => window.clearTimeout(timer);\n }, [shouldRedirect, callbackURL]);\n\n const closeWindow = () => {\n console.log(\"Tentative de fermeture de la fenêtre...\");\n\n // Méthode 1: Si dans un iframe, communiquer avec le parent IMMÉDIATEMENT\n if (window.parent && window.parent !== window) {\n try {\n window.parent.postMessage(\n {\n action: \"closeSession\",\n sessionId,\n status: \"ended\",\n message: \"Session terminée, veuillez fermer cette fenêtre\",\n },\n \"*\",\n );\n console.log(\"Message envoyé au parent pour fermeture\");\n } catch (e) {\n console.log(\"postMessage échoué:\", e);\n }\n }\n\n // Méthode 2: Essayer window.close() avec différentes approches\n try {\n // Essayer close direct\n window.close();\n console.log(\"window.close() direct appelé\");\n } catch (e) {\n console.log(\"window.close() direct échoué:\", e);\n }\n\n // Méthode 3: Si on a un opener, essayer de se fermer via l'opener\n setTimeout(() => {\n try {\n if (window.opener) {\n window.opener.focus();\n window.close();\n console.log(\"Fermeture via opener\");\n }\n } catch (e) {\n console.log(\"Fermeture via opener échouée:\", e);\n }\n }, 100);\n\n // Méthode 4: Forcer avec self.close()\n setTimeout(() => {\n try {\n self.close();\n console.log(\"self.close() appelé\");\n } catch (e) {\n console.log(\"self.close() échoué:\", e);\n }\n }, 200);\n\n // Méthode 5: Essayer de manipuler l'historique pour forcer la fermeture\n setTimeout(() => {\n try {\n window.history.back();\n window.close();\n console.log(\"history.back() + close\");\n } catch (e) {\n console.log(\"history.back() + close échoué:\", e);\n }\n }, 300);\n\n // Méthode 6: Rediriger vers une page de fermeture personnalisée\n setTimeout(() => {\n try {\n // Créer une URL de données avec un script de fermeture automatique\n const closeScript = `\n <html>\n <head><title>Session terminée</title></head>\n <body style=\"margin:0;padding:0;background:#f0f0f0;font-family:Arial,sans-serif;\">\n <div style=\"display:flex;flex-direction:column;justify-content:center;align-items:center;height:100vh;text-align:center;\">\n <h1 style=\"color:#4ade80;margin-bottom:20px;\">✅ Session terminée avec succès</h1>\n <p style=\"color:#666;margin-bottom:30px;\">Cette fenêtre va se fermer automatiquement.</p>\n <button onclick=\"attemptClose()\" style=\"background:#3b82f6;color:white;border:none;padding:12px 24px;border-radius:6px;cursor:pointer;font-size:16px;\">\n Fermer maintenant\n </button>\n </div>\n <script>\n function attemptClose() {\n try {\n window.close();\n self.close();\n if (window.opener) {\n window.opener.focus();\n window.close();\n }\n if (window.parent && window.parent !== window) {\n window.parent.postMessage({action:'closeWindow'}, '*');\n }\n } catch(e) {\n console.log('Fermeture impossible:', e);\n document.body.innerHTML = '<div style=\"text-align:center;padding:50px;\"><h2>Veuillez fermer cette fenêtre manuellement</h2><p>Appuyez sur Alt+F4 ou cliquez sur le X</p></div>';\n }\n }\n // Essayer de fermer automatiquement après 1 seconde\n setTimeout(attemptClose, 1000);\n </script>\n </body>\n </html>\n `;\n const dataUrl =\n \"data:text/html;charset=utf-8,\" + encodeURIComponent(closeScript);\n replaceLocation(dataUrl);\n console.log(\"Redirection vers page de fermeture personnalisée\");\n } catch (e) {\n console.log(\"Redirection vers page personnalisée échouée:\", e);\n }\n }, 500);\n };\n\n // Rendu d'un jeu de textes de fin personnalisé (titre ancré en haut,\n // items centrés verticalement, icônes à la couleur du bouton du journey).\n const renderCustomCase = (config: EndScreenCase, fallbackTitle: string) => (\n <div className=\"flex flex-1 flex-col items-center h-full px-4 pt-10 pb-8 md:px-8\">\n <Title className=\"text-2xl md:text-3xl text-center\">\n {config.title?.trim() || fallbackTitle}\n </Title>\n <div className=\"flex flex-1 items-center w-full max-w-md mx-auto\">\n {/* Padding appliqué uniquement sur desktop (md+) ; sur mobile il\n décalait le texte hors écran et le tronquait. */}\n <div\n className={`flex w-full flex-col items-start gap-7 -translate-y-20 ${desktopOffsetX}`}\n >\n {config.items.map((item, index) => {\n const Icon = resolveEndScreenIcon(item.icon);\n return (\n <div\n key={index}\n className=\"flex w-full items-center gap-4 text-left\"\n >\n <Icon\n className=\"w-7 h-7 shrink-0\"\n style={{ color: ICON_COLOR }}\n />\n <span className=\"flex-1 text-base md:text-lg text-[#3C3C40]\">\n {item.text}\n </span>\n </div>\n );\n })}\n </div>\n </div>\n </div>\n );\n\n const hasCustomError = !!nonCompliantCase?.items?.length;\n const hasCustomSuccess = !!compliantCase?.items?.length;\n\n // En attente du verdict backend : éviter le flash de l'écran succès.\n if (isResolving) {\n return (\n <LoadingState\n message={t(\"session.end.finalizing\", \"Finalisation du parcours...\")}\n subtitle=\"\"\n />\n );\n }\n\n return (\n <MobilePageLayout\n footer={\n <PageActions\n primary={\n <Button\n onClick={handleEndSession}\n disabled={isEnding || isRedirecting}\n >\n {isRedirecting\n ? t(\"session.end.button_redirecting\", \"Redirection...\")\n : isEnding\n ? t(\"session.end.button_finalizing\", \"Finalisation...\")\n : t(\"session.end.button_end\", \"Terminer\")}\n </Button>\n }\n />\n }\n >\n {isError ? (\n hasCustomError ? (\n renderCustomCase(\n nonCompliantCase as EndScreenCase,\n t(\"session.end.error_title\", \"Les prochaines étapes\"),\n )\n ) : (\n <div className=\"flex flex-1 flex-col items-center h-full px-4 pt-10 pb-8 md:px-8\">\n {/* Titre ancré en haut */}\n <Title className=\"text-2xl md:text-3xl text-center\">\n {t(\"session.end.error_title\", \"Les prochaines étapes\")}\n </Title>\n\n {/* Liste centrée verticalement dans l'espace restant */}\n <div className=\"flex flex-1 items-center w-full max-w-md mx-auto\">\n {/* Translate desktop-only : sur mobile il tronquait le texte. */}\n <div\n className={`flex w-full flex-col items-start gap-7 -translate-y-20 ${desktopTranslateX}`}\n >\n {[\n {\n Icon: HeartHandshake,\n key: \"session.end.error_step_thanks\",\n fallback: \"Nous vous remercions pour ces informations\",\n },\n {\n Icon: Send,\n key: \"session.end.error_step_transmitted\",\n fallback: \"Votre dossier a été transmis à notre équipe\",\n },\n {\n Icon: Mail,\n key: \"session.end.error_step_contact\",\n fallback: \"Nous vous recontacterons si nécessaire\",\n },\n ].map(({ Icon, key, fallback }) => (\n <div\n key={key}\n className=\"flex w-full items-center gap-4 text-left\"\n >\n <Icon\n className=\"w-7 h-7 shrink-0\"\n style={{ color: ICON_COLOR }}\n />\n <span className=\"flex-1 text-base md:text-lg text-[#3C3C40]\">\n {t(key, fallback)}\n </span>\n </div>\n ))}\n </div>\n </div>\n </div>\n )\n ) : hasCustomSuccess ? (\n renderCustomCase(\n compliantCase as EndScreenCase,\n t(\"session.end.title\", \"C'est tout bon !\"),\n )\n ) : (\n <div className=\"flex flex-1 flex-col items-center justify-center h-full px-4 py-8 md:px-8\">\n <div className=\"w-full max-w-md mx-auto text-center space-y-6\">\n {/* Icon - shown on top for both mobile and desktop */}\n <div className=\"flex justify-center\">\n <img\n src={checkIcon}\n alt={t(\"session.end.image_alt\", \"Vérification terminée\")}\n className=\"w-48 h-48\"\n />\n </div>\n\n {/* Text content */}\n <div className=\"space-y-4\">\n <Title className=\"text-xl md:text-2xl lg:text-3xl\">\n {t(\"session.end.title\", \"C'est tout bon !\")}\n </Title>\n <Subtitle className=\"text-sm md:text-base text-gray-600 leading-relaxed\">\n {t(\n \"session.end.subtitle\",\n \"Merci d'avoir terminé ce parcours, vous pouvez quitter cette fenêtre.\",\n )}\n </Subtitle>\n </div>\n </div>\n </div>\n )}\n </MobilePageLayout>\n );\n};\n\nexport default EndFlow;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EndFlow.js","sources":["../../../../../src/components/session/EndFlow.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport { HeartHandshake, Send, Mail } from \"lucide-react\";\nimport checkIcon from \"../../assets/check.svg\";\nimport LoadingState from \"../states/LoadingState\";\nimport Button from \"../ui/Button\";\nimport PageActions from \"../ui/PageActions\";\nimport Title from \"../ui/Title\";\nimport Subtitle from \"../ui/Subtitle\";\nimport {\n clearSessionSensitiveData,\n updateSessionStatus,\n} from \"../../services/sessionService\";\nimport { logSessionEnded } from \"../../services/auditTrailService\";\nimport MobilePageLayout from \"../ui/MobilePageLayout\";\nimport { useI18n } from \"../../hooks/useI18n\";\nimport useIsMobile from \"../../hooks/useIsMobile\";\nimport type { EndScreenCase } from \"../../types/session\";\nimport { resolveEndScreenIcon } from \"./endScreenIcons\";\nimport { replaceLocation } from \"../../utils/navigation\";\n\n// Couleur des icônes = couleur du bouton choisie pour le journey (buttonBgColor).\nconst ICON_COLOR = \"var(--dk-btn-bg, #11e5c5)\";\n\ninterface EndFlowProps {\n sessionId: string;\n sessionStatus?: string; // Ajout du statut de session optionnel\n callbackURL?: string | null;\n endNodeId?: string; // Id du nœud `end` atteint, transmis au backend pour forcer le bon statut\n expectedResult?: string; // Résultat forcé du nœud end atteint (ex: 'non_compliant')\n /** Textes de fin personnalisés (config globale du journey). Vide → fallback standard. */\n compliantCase?: EndScreenCase;\n nonCompliantCase?: EndScreenCase;\n /**\n * true si la session était déjà terminée à l'arrivée sur ce composant\n * (reprise d'une session déjà consolidée, ex: sessionStatus=\"verify\").\n * Dans ce cas on n'appelle pas updateSessionStatus au montage — la session\n * a déjà un résultat, renvoyer \"ended\" + endNodeId ré-ouvrirait une\n * décision déjà prise et risquerait de forcer un nœud \"end\" jamais\n * légitimement atteint (bug de reprise par index). L'écran affiché reflète\n * directement le statut déjà connu de la session.\n */\n alreadyFinished?: boolean;\n}\n\n/**\n * EndFlow Component\n *\n * Composant affiché à la fin du flux de vérification lorsque toutes les étapes ont été complétées.\n * Affiche un message de confirmation avec une icône de succès.\n *\n * @param {EndFlowProps} props - Propriétés du composant\n * @param {string} props.sessionId - L'identifiant de la session\n * @param {string} props.sessionStatus - Le statut actuel de la session\n * @returns {JSX.Element} Le composant EndFlow\n */\nconst EndFlow: React.FC<EndFlowProps> = ({\n sessionId,\n sessionStatus,\n callbackURL,\n endNodeId,\n expectedResult,\n compliantCase,\n nonCompliantCase,\n alreadyFinished,\n}) => {\n const [isEnding, setIsEnding] = useState(false);\n const [isRedirecting, setIsRedirecting] = useState(false);\n const [shouldRedirect, setShouldRedirect] = useState(false);\n // Statut consolidé renvoyé par le backend après updateSessionStatus —\n // sert à détecter un échec « poursuivre quand même » non porté par\n // expectedResult. Si la session était déjà terminée à l'arrivée, on la\n // connaît déjà (sessionStatus) : pas besoin d'attendre le backend.\n const [backendStatus, setBackendStatus] = useState<string | undefined>(\n alreadyFinished ? sessionStatus : undefined,\n );\n // Le verdict backend arrive de façon asynchrone (~1-2s). On le marque résolu\n // pour éviter de flasher l'écran succès puis basculer sur l'écran erreur.\n // Déjà résolu si la session était déjà terminée (pas d'appel réseau à attendre).\n const [statusResolved, setStatusResolved] = useState(\n Boolean(alreadyFinished),\n );\n const { t } = useI18n();\n const isMobile = useIsMobile(768);\n // Décalage horizontal du bloc d'items réservé au desktop. On le pilote en JS\n // (useIsMobile, cohérent avec le composant Button) plutôt que via `md:` Tailwind :\n // les variantes responsive `md:translate-*` ne sont pas fiables dans le bundle SDK.\n // Utilisé uniquement par l'écran d'erreur générique hardcodé ci-dessous.\n const desktopTranslateX = isMobile ? \"\" : \"translate-x-10\";\n // Même décalage, mais via padding plutôt que transform — réservé aux écrans à\n // message personnalisé (renderCustomCase) : un `transform: translateX(...)` ne fait\n // déborder aucune boîte visuellement, mais contribue quand même au \"scrollable\n // overflow\" du conteneur `overflow-y-auto` ancêtre (DatakeenSession), ce qui\n // affichait une scrollbar horizontale fantôme sur desktop. `padding-left` reste\n // contenu dans la largeur déclarée (box-sizing: border-box global du SDK), donc ne\n // peut pas produire ce débordement invisible.\n const desktopOffsetX = isMobile ? \"\" : \"pl-10\";\n\n // Le nœud end peut déjà forcer un résultat non conforme : dans ce cas on\n // connaît l'issue sans attendre le backend.\n const expectedError =\n expectedResult === \"non_compliant\" || expectedResult === \"error\";\n\n // L'écran « erreur conservée » s'affiche si le nœud end force un résultat\n // non conforme, OU si le backend a consolidé un statut d'échec/vérification.\n const isError =\n expectedError ||\n backendStatus === \"ai_rejected\" ||\n backendStatus === \"verify\";\n\n // Tant que le verdict n'est pas connu (ni forcé par le nœud, ni renvoyé par\n // le backend), on affiche un état neutre plutôt que de présumer le succès.\n const isResolving = !expectedError && !statusResolved;\n\n // Trigger session end as soon as the user reaches this screen,\n // regardless of whether they click the button (e.g. tab close).\n // Skipped when the session was already finished on arrival: the backend\n // ignores this PATCH anyway (session already consolidated), and resending\n // it risks forcing a phantom \"end\" node reached only through a resumption\n // index mismatch, not a real navigation.\n useEffect(() => {\n if (alreadyFinished) {\n return;\n }\n updateSessionStatus(sessionId, \"ended\", endNodeId)\n .then((updatedSession) => {\n if (updatedSession?.status) {\n setBackendStatus(updatedSession.status);\n }\n if (updatedSession && updatedSession.analysisId) {\n logSessionEnded(sessionId).catch((err) => {\n console.error(\"Failed to log session end in audit trail:\", err);\n });\n }\n })\n .catch((error) => {\n console.error(\"Error updating session status on EndFlow mount:\", error);\n })\n .finally(() => {\n // Verdict connu (ou échec d'appel) : on peut afficher l'écran final.\n setStatusResolved(true);\n });\n }, []);\n\n const handleEndSession = async () => {\n setIsEnding(true);\n try {\n clearSessionSensitiveData(sessionId);\n } catch (error) {\n console.error(\"Erreur lors de la finalisation de la session:\", error);\n } finally {\n setIsEnding(false);\n if (callbackURL) {\n setIsRedirecting(true);\n setShouldRedirect(true);\n } else {\n // Forcer la fermeture immédiatement lorsqu'aucune redirection n'est attendue\n closeWindow();\n }\n }\n };\n\n const redirectToCallback = (url: string) => {\n try {\n replaceLocation(url);\n } catch (e) {\n console.error(\"Redirection vers le callback échouée:\", e);\n setIsRedirecting(false);\n closeWindow();\n }\n };\n\n useEffect(() => {\n if (sessionStatus === \"ended\" && callbackURL && !shouldRedirect) {\n setIsRedirecting(true);\n setShouldRedirect(true);\n }\n }, [sessionStatus, callbackURL, shouldRedirect]);\n\n useEffect(() => {\n if (!shouldRedirect || !callbackURL) {\n return;\n }\n\n const REDIRECT_DELAY_MS = 2000;\n const timer = window.setTimeout(\n () => redirectToCallback(callbackURL),\n REDIRECT_DELAY_MS,\n );\n return () => window.clearTimeout(timer);\n }, [shouldRedirect, callbackURL]);\n\n const closeWindow = () => {\n console.log(\"Tentative de fermeture de la fenêtre...\");\n\n // Méthode 1: Si dans un iframe, communiquer avec le parent IMMÉDIATEMENT\n if (window.parent && window.parent !== window) {\n try {\n window.parent.postMessage(\n {\n action: \"closeSession\",\n sessionId,\n status: \"ended\",\n message: \"Session terminée, veuillez fermer cette fenêtre\",\n },\n \"*\",\n );\n console.log(\"Message envoyé au parent pour fermeture\");\n } catch (e) {\n console.log(\"postMessage échoué:\", e);\n }\n }\n\n // Méthode 2: Essayer window.close() avec différentes approches\n try {\n // Essayer close direct\n window.close();\n console.log(\"window.close() direct appelé\");\n } catch (e) {\n console.log(\"window.close() direct échoué:\", e);\n }\n\n // Méthode 3: Si on a un opener, essayer de se fermer via l'opener\n setTimeout(() => {\n try {\n if (window.opener) {\n window.opener.focus();\n window.close();\n console.log(\"Fermeture via opener\");\n }\n } catch (e) {\n console.log(\"Fermeture via opener échouée:\", e);\n }\n }, 100);\n\n // Méthode 4: Forcer avec self.close()\n setTimeout(() => {\n try {\n self.close();\n console.log(\"self.close() appelé\");\n } catch (e) {\n console.log(\"self.close() échoué:\", e);\n }\n }, 200);\n\n // Méthode 5: Essayer de manipuler l'historique pour forcer la fermeture\n setTimeout(() => {\n try {\n window.history.back();\n window.close();\n console.log(\"history.back() + close\");\n } catch (e) {\n console.log(\"history.back() + close échoué:\", e);\n }\n }, 300);\n\n // Méthode 6: Rediriger vers une page de fermeture personnalisée\n setTimeout(() => {\n try {\n // Créer une URL de données avec un script de fermeture automatique\n const closeScript = `\n <html>\n <head><title>Session terminée</title></head>\n <body style=\"margin:0;padding:0;background:#f0f0f0;font-family:Arial,sans-serif;\">\n <div style=\"display:flex;flex-direction:column;justify-content:center;align-items:center;height:100vh;text-align:center;\">\n <h1 style=\"color:#4ade80;margin-bottom:20px;\">✅ Session terminée avec succès</h1>\n <p style=\"color:#666;margin-bottom:30px;\">Cette fenêtre va se fermer automatiquement.</p>\n <button onclick=\"attemptClose()\" style=\"background:#3b82f6;color:white;border:none;padding:12px 24px;border-radius:6px;cursor:pointer;font-size:16px;\">\n Fermer maintenant\n </button>\n </div>\n <script>\n function attemptClose() {\n try {\n window.close();\n self.close();\n if (window.opener) {\n window.opener.focus();\n window.close();\n }\n if (window.parent && window.parent !== window) {\n window.parent.postMessage({action:'closeWindow'}, '*');\n }\n } catch(e) {\n console.log('Fermeture impossible:', e);\n document.body.innerHTML = '<div style=\"text-align:center;padding:50px;\"><h2>Veuillez fermer cette fenêtre manuellement</h2><p>Appuyez sur Alt+F4 ou cliquez sur le X</p></div>';\n }\n }\n // Essayer de fermer automatiquement après 1 seconde\n setTimeout(attemptClose, 1000);\n </script>\n </body>\n </html>\n `;\n const dataUrl =\n \"data:text/html;charset=utf-8,\" + encodeURIComponent(closeScript);\n replaceLocation(dataUrl);\n console.log(\"Redirection vers page de fermeture personnalisée\");\n } catch (e) {\n console.log(\"Redirection vers page personnalisée échouée:\", e);\n }\n }, 500);\n };\n\n // Rendu d'un jeu de textes de fin personnalisé (titre ancré en haut,\n // items centrés verticalement, icônes à la couleur du bouton du journey).\n const renderCustomCase = (config: EndScreenCase, fallbackTitle: string) => (\n <div className=\"flex flex-1 flex-col items-center h-full px-4 pt-10 pb-8 md:px-8\">\n <Title className=\"text-2xl md:text-3xl text-center\">\n {config.title?.trim() || fallbackTitle}\n </Title>\n <div className=\"flex flex-1 items-center w-full max-w-md mx-auto\">\n {/* Padding appliqué uniquement sur desktop (md+) ; sur mobile il\n décalait le texte hors écran et le tronquait. */}\n <div\n className={`flex w-full flex-col items-start gap-7 -translate-y-20 ${desktopOffsetX}`}\n >\n {config.items.map((item, index) => {\n const Icon = resolveEndScreenIcon(item.icon);\n return (\n <div\n key={index}\n className=\"flex w-full items-center gap-4 text-left\"\n >\n <Icon\n className=\"w-7 h-7 shrink-0\"\n style={{ color: ICON_COLOR }}\n />\n <span className=\"flex-1 text-base md:text-lg text-[#3C3C40]\">\n {item.text}\n </span>\n </div>\n );\n })}\n </div>\n </div>\n </div>\n );\n\n const hasCustomError = !!nonCompliantCase?.items?.length;\n const hasCustomSuccess = !!compliantCase?.items?.length;\n\n // En attente du verdict backend : éviter le flash de l'écran succès.\n if (isResolving) {\n return (\n <LoadingState\n message={t(\"session.end.finalizing\", \"Finalisation du parcours...\")}\n subtitle=\"\"\n />\n );\n }\n\n return (\n <MobilePageLayout\n footer={\n <PageActions\n primary={\n <Button\n onClick={handleEndSession}\n disabled={isEnding || isRedirecting}\n >\n {isRedirecting\n ? t(\"session.end.button_redirecting\", \"Redirection...\")\n : isEnding\n ? t(\"session.end.button_finalizing\", \"Finalisation...\")\n : t(\"session.end.button_end\", \"Terminer\")}\n </Button>\n }\n />\n }\n >\n {isError ? (\n hasCustomError ? (\n renderCustomCase(\n nonCompliantCase as EndScreenCase,\n t(\"session.end.error_title\", \"Les prochaines étapes\"),\n )\n ) : (\n <div className=\"flex flex-1 flex-col items-center h-full px-4 pt-10 pb-8 md:px-8\">\n {/* Titre ancré en haut */}\n <Title className=\"text-2xl md:text-3xl text-center\">\n {t(\"session.end.error_title\", \"Les prochaines étapes\")}\n </Title>\n\n {/* Liste centrée verticalement dans l'espace restant */}\n <div className=\"flex flex-1 items-center w-full max-w-md mx-auto\">\n {/* Translate desktop-only : sur mobile il tronquait le texte. */}\n <div\n className={`flex w-full flex-col items-start gap-7 -translate-y-20 ${desktopTranslateX}`}\n >\n {[\n {\n Icon: HeartHandshake,\n key: \"session.end.error_step_thanks\",\n fallback: \"Nous vous remercions pour ces informations\",\n },\n {\n Icon: Send,\n key: \"session.end.error_step_transmitted\",\n fallback: \"Votre dossier a été transmis à notre équipe\",\n },\n {\n Icon: Mail,\n key: \"session.end.error_step_contact\",\n fallback: \"Nous vous recontacterons si nécessaire\",\n },\n ].map(({ Icon, key, fallback }) => (\n <div\n key={key}\n className=\"flex w-full items-center gap-4 text-left\"\n >\n <Icon\n className=\"w-7 h-7 shrink-0\"\n style={{ color: ICON_COLOR }}\n />\n <span className=\"flex-1 text-base md:text-lg text-[#3C3C40]\">\n {t(key, fallback)}\n </span>\n </div>\n ))}\n </div>\n </div>\n </div>\n )\n ) : hasCustomSuccess ? (\n renderCustomCase(\n compliantCase as EndScreenCase,\n t(\"session.end.title\", \"C'est tout bon !\"),\n )\n ) : (\n <div className=\"flex flex-1 flex-col items-center justify-center h-full px-4 py-8 md:px-8\">\n <div className=\"w-full max-w-md mx-auto text-center space-y-6\">\n {/* Icon - shown on top for both mobile and desktop */}\n <div className=\"flex justify-center\">\n <img\n src={checkIcon}\n alt={t(\"session.end.image_alt\", \"Vérification terminée\")}\n className=\"w-48 h-48\"\n />\n </div>\n\n {/* Text content */}\n <div className=\"space-y-4\">\n <Title className=\"text-xl md:text-2xl lg:text-3xl\">\n {t(\"session.end.title\", \"C'est tout bon !\")}\n </Title>\n <Subtitle className=\"text-sm md:text-base text-gray-600 leading-relaxed\">\n {t(\n \"session.end.subtitle\",\n \"Merci d'avoir terminé ce parcours, vous pouvez quitter cette fenêtre.\",\n )}\n </Subtitle>\n </div>\n </div>\n </div>\n )}\n </MobilePageLayout>\n );\n};\n\nexport default EndFlow;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ import EndFlow from './EndFlow.js';
|
|
|
6
6
|
import LoadingState from '../states/LoadingState.js';
|
|
7
7
|
import TemplateNodeRenderer from '../template/TemplateNodeRenderer.js';
|
|
8
8
|
import { getOrderedJourneySteps } from '../../services/sessionService.js';
|
|
9
|
+
import { isSessionFinished } from '../../utils/sessionStatus.js';
|
|
9
10
|
import { useI18n } from '../../hooks/useI18n.js';
|
|
10
11
|
|
|
11
12
|
var SessionContent = function (_a) {
|
|
@@ -63,9 +64,10 @@ var SessionContent = function (_a) {
|
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
}, []);
|
|
66
|
-
// Special check:
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
// Special check: if the session is already finished, display EndFlow
|
|
68
|
+
// directly (raw "ended" or a consolidated result status).
|
|
69
|
+
if (isSessionFinished(session === null || session === void 0 ? void 0 : session.status)) {
|
|
70
|
+
return (jsx(EndFlow, { sessionId: sessionId, sessionStatus: session === null || session === void 0 ? void 0 : session.status, callbackURL: session === null || session === void 0 ? void 0 : session.callbackURL, compliantCase: (_k = (_j = session === null || session === void 0 ? void 0 : session.template) === null || _j === void 0 ? void 0 : _j.endScreenConfig) === null || _k === void 0 ? void 0 : _k.compliant, nonCompliantCase: (_m = (_l = session === null || session === void 0 ? void 0 : session.template) === null || _l === void 0 ? void 0 : _l.endScreenConfig) === null || _m === void 0 ? void 0 : _m.nonCompliant, alreadyFinished: (session === null || session === void 0 ? void 0 : session.status) !== "ended" }));
|
|
69
71
|
}
|
|
70
72
|
// Render step content
|
|
71
73
|
switch (step) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionContent.js","sources":["../../../../../src/components/session/SessionContent.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport StartSession from \"../session/StartSession\";\nimport MobileRedirect from \"../session/MobileRedirect\";\nimport EndFlow from \"../session/EndFlow\";\nimport LoadingState from \"../states/LoadingState\";\nimport TemplateNodeRenderer from \"../template/TemplateNodeRenderer\";\nimport { getOrderedJourneySteps } from \"../../services/sessionService\";\nimport type { SessionData, stepObject } from \"../../types/session\";\nimport type { UserInput } from \"../../types/userInput\";\nimport type { ContactInfo } from \"../../types/contactInfo\";\nimport { useI18n } from \"../../hooks/useI18n\";\n\ninterface SessionContentProps {\n step: number;\n loading: boolean;\n session: SessionData | null;\n sessionId: string;\n stepObject: stepObject;\n stepHistory: number[];\n userInput: UserInput;\n setUserInput: React.Dispatch<React.SetStateAction<UserInput>>;\n contactInfo: ContactInfo;\n setContactInfo: React.Dispatch<React.SetStateAction<ContactInfo>>;\n}\n\nconst SessionContent: React.FC<SessionContentProps> = ({\n step,\n loading,\n session,\n sessionId,\n stepObject,\n stepHistory,\n userInput,\n setUserInput,\n contactInfo,\n setContactInfo,\n}) => {\n const { setLanguage, currentLanguage, t } = useI18n();\n // If is mobile template, isMobileCapture should be true for document-selection nodes\n const isMobileTemplate = session?.template?.platforms?.mobile === true;\n const showQRCodeInstructions =\n isMobileTemplate && session?.template?.showQRCode === true;\n const isDesktopAllowed = session?.template?.platforms?.desktop === true;\n\n // Get QR code title and description from Start node\n const startNode = session?.template?.nodes?.find(\n (node: any) => node.type === \"start\"\n );\n const qrCodeTitle = startNode?.qrCodeTitle;\n const qrCodeDescription = startNode?.qrCodeDescription;\n\n // Handle template step progression\n const handleContinueOnPC = () => {\n if (!session?.template) return;\n\n const templateNodes = getOrderedJourneySteps(session.template);\n // When user clicks \"Continue on PC\" from MobileRedirect (step 0.5), go to step 1\n // For other steps, calculate templateIndex normally\n const templateIndex =\n step === 0.5 ? 0 : showQRCodeInstructions ? step - 1.5 : step - 1;\n\n if (templateIndex < templateNodes.length - 1) {\n const nextStep =\n step === 0.5\n ? 1\n : showQRCodeInstructions\n ? templateIndex + 2.5\n : templateIndex + 2;\n stepObject.setStep(nextStep);\n } else {\n // Last step, finish the process\n const endNode = session.template.nodes.find(\n (node: { type: string }) => node.type === \"end\"\n );\n if (endNode) {\n // Continue to the next node which will be the \"end\" node\n stepObject.setStep(\n step === 0.5\n ? 1\n : showQRCodeInstructions\n ? templateIndex + 2.5\n : templateIndex + 2\n );\n } else {\n stepObject.setStep(0);\n }\n }\n };\n\n // Change languages dynamically based on session template\n useEffect(() => {\n if (session?.template?.languages && session.template.languages.length > 0) {\n const language = session.template.languages[0]; // Use the first language\n\n // Check if language is different from current\n if (language !== currentLanguage) {\n setLanguage(language);\n }\n }\n }, []);\n\n // Special check: If session is ended, display EndFlow directly\n if (session?.status === \"ended\") {\n return (\n <EndFlow\n sessionId={sessionId}\n sessionStatus={session.status}\n callbackURL={session?.callbackURL}\n compliantCase={session?.template?.endScreenConfig?.compliant}\n nonCompliantCase={session?.template?.endScreenConfig?.nonCompliant}\n />\n );\n }\n\n // Render step content\n switch (step) {\n case 0:\n return (\n <StartSession\n stepObject={stepObject}\n session={session}\n showQRCodeInstructions={showQRCodeInstructions}\n />\n );\n\n case 0.5:\n // MobileRedirect step - only shown if showQRCodeInstructions is true\n return (\n <MobileRedirect\n sessionId={sessionId}\n onBack={() => stepObject.setStep(0)}\n onContinueOnPC={handleContinueOnPC}\n isDesktopAllowed={isDesktopAllowed}\n title={qrCodeTitle}\n subtitle={qrCodeDescription}\n />\n );\n\n default:\n // From step 1 onwards, use dynamic logic based on template\n if (step >= 1) {\n if (loading) {\n return (\n <LoadingState\n message={t(\"loading.document\")}\n subtitle={t(\"loading.preparing_document\")}\n />\n );\n }\n\n if (session?.template) {\n return (\n <TemplateNodeRenderer\n session={session}\n sessionId={sessionId}\n stepObject={stepObject}\n stepHistory={stepHistory}\n templateIndex={step - 1}\n onContinueOnPC={handleContinueOnPC}\n userInput={userInput}\n setUserInput={setUserInput}\n contactInfo={contactInfo}\n setContactInfo={setContactInfo}\n isMobileTemplate={isMobileTemplate}\n />\n );\n } else {\n console.log(\n \"❌ SessionContent - No template found, showing fallback\"\n );\n // Fallback if template is not available\n return (\n <div className=\"flex flex-col items-center justify-center h-full p-4 text-center\">\n <div className=\"animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-primary mb-4\"></div>\n <h2 className=\"text-xl font-bold text-gray-700 mb-2\">\n {t(\"session_content.preparing_verification\")}\n </h2>\n <p className=\"text-gray-600 mb-4\">\n {t(\"session_content.please_wait\")}\n </p>\n <div className=\"bg-blue-50 border border-blue-200 rounded-lg p-3 mt-4 max-w-xs mx-auto\">\n <p className=\"text-sm text-blue-600\">\n {t(\"session_content.configuring_steps\")}\n </p>\n <button\n onClick={() => window.location.reload()}\n className=\"mt-2 px-3 py-1 bg-blue-600 text-white text-xs rounded\"\n >\n Actualiser si nécessaire\n </button>\n </div>\n </div>\n );\n }\n }\n\n return null;\n }\n};\n\nexport default SessionContent;\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SessionContent.js","sources":["../../../../../src/components/session/SessionContent.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport StartSession from \"../session/StartSession\";\nimport MobileRedirect from \"../session/MobileRedirect\";\nimport EndFlow from \"../session/EndFlow\";\nimport LoadingState from \"../states/LoadingState\";\nimport TemplateNodeRenderer from \"../template/TemplateNodeRenderer\";\nimport { getOrderedJourneySteps } from \"../../services/sessionService\";\nimport { isSessionFinished } from \"../../utils/sessionStatus\";\nimport type { SessionData, stepObject } from \"../../types/session\";\nimport type { UserInput } from \"../../types/userInput\";\nimport type { ContactInfo } from \"../../types/contactInfo\";\nimport { useI18n } from \"../../hooks/useI18n\";\n\ninterface SessionContentProps {\n step: number;\n loading: boolean;\n session: SessionData | null;\n sessionId: string;\n stepObject: stepObject;\n stepHistory: number[];\n userInput: UserInput;\n setUserInput: React.Dispatch<React.SetStateAction<UserInput>>;\n contactInfo: ContactInfo;\n setContactInfo: React.Dispatch<React.SetStateAction<ContactInfo>>;\n}\n\nconst SessionContent: React.FC<SessionContentProps> = ({\n step,\n loading,\n session,\n sessionId,\n stepObject,\n stepHistory,\n userInput,\n setUserInput,\n contactInfo,\n setContactInfo,\n}) => {\n const { setLanguage, currentLanguage, t } = useI18n();\n // If is mobile template, isMobileCapture should be true for document-selection nodes\n const isMobileTemplate = session?.template?.platforms?.mobile === true;\n const showQRCodeInstructions =\n isMobileTemplate && session?.template?.showQRCode === true;\n const isDesktopAllowed = session?.template?.platforms?.desktop === true;\n\n // Get QR code title and description from Start node\n const startNode = session?.template?.nodes?.find(\n (node: any) => node.type === \"start\"\n );\n const qrCodeTitle = startNode?.qrCodeTitle;\n const qrCodeDescription = startNode?.qrCodeDescription;\n\n // Handle template step progression\n const handleContinueOnPC = () => {\n if (!session?.template) return;\n\n const templateNodes = getOrderedJourneySteps(session.template);\n // When user clicks \"Continue on PC\" from MobileRedirect (step 0.5), go to step 1\n // For other steps, calculate templateIndex normally\n const templateIndex =\n step === 0.5 ? 0 : showQRCodeInstructions ? step - 1.5 : step - 1;\n\n if (templateIndex < templateNodes.length - 1) {\n const nextStep =\n step === 0.5\n ? 1\n : showQRCodeInstructions\n ? templateIndex + 2.5\n : templateIndex + 2;\n stepObject.setStep(nextStep);\n } else {\n // Last step, finish the process\n const endNode = session.template.nodes.find(\n (node: { type: string }) => node.type === \"end\"\n );\n if (endNode) {\n // Continue to the next node which will be the \"end\" node\n stepObject.setStep(\n step === 0.5\n ? 1\n : showQRCodeInstructions\n ? templateIndex + 2.5\n : templateIndex + 2\n );\n } else {\n stepObject.setStep(0);\n }\n }\n };\n\n // Change languages dynamically based on session template\n useEffect(() => {\n if (session?.template?.languages && session.template.languages.length > 0) {\n const language = session.template.languages[0]; // Use the first language\n\n // Check if language is different from current\n if (language !== currentLanguage) {\n setLanguage(language);\n }\n }\n }, []);\n\n // Special check: if the session is already finished, display EndFlow\n // directly (raw \"ended\" or a consolidated result status).\n if (isSessionFinished(session?.status)) {\n return (\n <EndFlow\n sessionId={sessionId}\n sessionStatus={session?.status}\n callbackURL={session?.callbackURL}\n compliantCase={session?.template?.endScreenConfig?.compliant}\n nonCompliantCase={session?.template?.endScreenConfig?.nonCompliant}\n alreadyFinished={session?.status !== \"ended\"}\n />\n );\n }\n\n // Render step content\n switch (step) {\n case 0:\n return (\n <StartSession\n stepObject={stepObject}\n session={session}\n showQRCodeInstructions={showQRCodeInstructions}\n />\n );\n\n case 0.5:\n // MobileRedirect step - only shown if showQRCodeInstructions is true\n return (\n <MobileRedirect\n sessionId={sessionId}\n onBack={() => stepObject.setStep(0)}\n onContinueOnPC={handleContinueOnPC}\n isDesktopAllowed={isDesktopAllowed}\n title={qrCodeTitle}\n subtitle={qrCodeDescription}\n />\n );\n\n default:\n // From step 1 onwards, use dynamic logic based on template\n if (step >= 1) {\n if (loading) {\n return (\n <LoadingState\n message={t(\"loading.document\")}\n subtitle={t(\"loading.preparing_document\")}\n />\n );\n }\n\n if (session?.template) {\n return (\n <TemplateNodeRenderer\n session={session}\n sessionId={sessionId}\n stepObject={stepObject}\n stepHistory={stepHistory}\n templateIndex={step - 1}\n onContinueOnPC={handleContinueOnPC}\n userInput={userInput}\n setUserInput={setUserInput}\n contactInfo={contactInfo}\n setContactInfo={setContactInfo}\n isMobileTemplate={isMobileTemplate}\n />\n );\n } else {\n console.log(\n \"❌ SessionContent - No template found, showing fallback\"\n );\n // Fallback if template is not available\n return (\n <div className=\"flex flex-col items-center justify-center h-full p-4 text-center\">\n <div className=\"animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-primary mb-4\"></div>\n <h2 className=\"text-xl font-bold text-gray-700 mb-2\">\n {t(\"session_content.preparing_verification\")}\n </h2>\n <p className=\"text-gray-600 mb-4\">\n {t(\"session_content.please_wait\")}\n </p>\n <div className=\"bg-blue-50 border border-blue-200 rounded-lg p-3 mt-4 max-w-xs mx-auto\">\n <p className=\"text-sm text-blue-600\">\n {t(\"session_content.configuring_steps\")}\n </p>\n <button\n onClick={() => window.location.reload()}\n className=\"mt-2 px-3 py-1 bg-blue-600 text-white text-xs rounded\"\n >\n Actualiser si nécessaire\n </button>\n </div>\n </div>\n );\n }\n }\n\n return null;\n }\n};\n\nexport default SessionContent;\n"],"names":["_jsx","_jsxs"],"mappings":";;;;;;;;;;;AA0BA,IAAM,cAAc,GAAkC,UAAC,EAWtD,EAAA;;QAVC,IAAI,GAAA,EAAA,CAAA,IAAA,EACJ,OAAO,GAAA,EAAA,CAAA,OAAA,EACP,OAAO,GAAA,EAAA,CAAA,OAAA,EACP,SAAS,GAAA,EAAA,CAAA,SAAA,EACT,UAAU,GAAA,EAAA,CAAA,UAAA,EACV,WAAW,GAAA,EAAA,CAAA,WAAA,EACX,SAAS,GAAA,EAAA,CAAA,SAAA,EACT,YAAY,GAAA,EAAA,CAAA,YAAA,EACZ,WAAW,GAAA,EAAA,CAAA,WAAA,EACX,cAAc,GAAA,EAAA,CAAA,cAAA;AAER,IAAA,IAAA,EAAA,GAAsC,OAAO,EAAE,EAA7C,WAAW,GAAA,EAAA,CAAA,WAAA,EAAE,eAAe,GAAA,EAAA,CAAA,eAAA,EAAE,CAAC,GAAA,EAAA,CAAA,CAAc;;AAErD,IAAA,IAAM,gBAAgB,GAAG,CAAA,MAAA,CAAA,EAAA,GAAA,OAAO,aAAP,OAAO,KAAA,MAAA,GAAA,MAAA,GAAP,OAAO,CAAE,QAAQ,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAE,SAAS,0CAAE,MAAM,MAAK,IAAI;AACtE,IAAA,IAAM,sBAAsB,GAC1B,gBAAgB,IAAI,CAAA,MAAA,OAAO,KAAA,IAAA,IAAP,OAAO,KAAA,MAAA,GAAA,MAAA,GAAP,OAAO,CAAE,QAAQ,0CAAE,UAAU,MAAK,IAAI;AAC5D,IAAA,IAAM,gBAAgB,GAAG,CAAA,MAAA,CAAA,EAAA,GAAA,OAAO,aAAP,OAAO,KAAA,MAAA,GAAA,MAAA,GAAP,OAAO,CAAE,QAAQ,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAE,SAAS,0CAAE,OAAO,MAAK,IAAI;;AAGvE,IAAA,IAAM,SAAS,GAAG,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA,OAAO,KAAA,IAAA,IAAP,OAAO,KAAA,MAAA,GAAA,MAAA,GAAP,OAAO,CAAE,QAAQ,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAE,KAAK,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAE,IAAI,CAC9C,UAAC,IAAS,EAAA,EAAK,OAAA,IAAI,CAAC,IAAI,KAAK,OAAO,CAAA,CAArB,CAAqB,CACrC;IACD,IAAM,WAAW,GAAG,SAAS,KAAA,IAAA,IAAT,SAAS,KAAA,MAAA,GAAA,MAAA,GAAT,SAAS,CAAE,WAAW;IAC1C,IAAM,iBAAiB,GAAG,SAAS,KAAA,IAAA,IAAT,SAAS,KAAA,MAAA,GAAA,MAAA,GAAT,SAAS,CAAE,iBAAiB;;AAGtD,IAAA,IAAM,kBAAkB,GAAG,YAAA;QACzB,IAAI,EAAC,OAAO,KAAA,IAAA,IAAP,OAAO,KAAA,MAAA,GAAA,MAAA,GAAP,OAAO,CAAE,QAAQ,CAAA;YAAE;QAExB,IAAM,aAAa,GAAG,sBAAsB,CAAC,OAAO,CAAC,QAAQ,CAAC;;;QAG9D,IAAM,aAAa,GACjB,IAAI,KAAK,GAAG,GAAG,CAAC,GAAG,sBAAsB,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,CAAC;QAEnE,IAAI,aAAa,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE;AAC5C,YAAA,IAAM,QAAQ,GACZ,IAAI,KAAK;AACP,kBAAE;AACF,kBAAE;sBACA,aAAa,GAAG;AAClB,sBAAE,aAAa,GAAG,CAAC;AACvB,YAAA,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC9B;aAAO;;YAEL,IAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CACzC,UAAC,IAAsB,EAAA,EAAK,OAAA,IAAI,CAAC,IAAI,KAAK,KAAK,CAAA,CAAnB,CAAmB,CAChD;YACD,IAAI,OAAO,EAAE;;AAEX,gBAAA,UAAU,CAAC,OAAO,CAChB,IAAI,KAAK;AACP,sBAAE;AACF,sBAAE;0BACA,aAAa,GAAG;AAClB,0BAAE,aAAa,GAAG,CAAC,CACtB;YACH;iBAAO;AACL,gBAAA,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;YACvB;QACF;AACF,IAAA,CAAC;;AAGD,IAAA,SAAS,CAAC,YAAA;;QACR,IAAI,CAAA,MAAA,OAAO,KAAA,IAAA,IAAP,OAAO,KAAA,MAAA,GAAA,MAAA,GAAP,OAAO,CAAE,QAAQ,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAE,SAAS,KAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;AACzE,YAAA,IAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;;AAG/C,YAAA,IAAI,QAAQ,KAAK,eAAe,EAAE;gBAChC,WAAW,CAAC,QAAQ,CAAC;YACvB;QACF;IACF,CAAC,EAAE,EAAE,CAAC;;;IAIN,IAAI,iBAAiB,CAAC,OAAO,KAAA,IAAA,IAAP,OAAO,KAAA,MAAA,GAAA,MAAA,GAAP,OAAO,CAAE,MAAM,CAAC,EAAE;AACtC,QAAA,QACEA,GAAA,CAAC,OAAO,EAAA,EACN,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,OAAO,KAAA,IAAA,IAAP,OAAO,KAAA,MAAA,GAAA,MAAA,GAAP,OAAO,CAAE,MAAM,EAC9B,WAAW,EAAE,OAAO,KAAA,IAAA,IAAP,OAAO,KAAA,MAAA,GAAA,MAAA,GAAP,OAAO,CAAE,WAAW,EACjC,aAAa,EAAE,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA,OAAO,KAAA,IAAA,IAAP,OAAO,KAAA,MAAA,GAAA,MAAA,GAAP,OAAO,CAAE,QAAQ,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAE,eAAe,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAE,SAAS,EAC5D,gBAAgB,EAAE,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA,OAAO,KAAA,IAAA,IAAP,OAAO,KAAA,MAAA,GAAA,MAAA,GAAP,OAAO,CAAE,QAAQ,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAE,eAAe,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAE,YAAY,EAClE,eAAe,EAAE,CAAA,OAAO,KAAA,IAAA,IAAP,OAAO,KAAA,MAAA,GAAA,MAAA,GAAP,OAAO,CAAE,MAAM,MAAK,OAAO,EAAA,CAC5C;IAEN;;IAGA,QAAQ,IAAI;AACV,QAAA,KAAK,CAAC;AACJ,YAAA,QACEA,GAAA,CAAC,YAAY,EAAA,EACX,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,OAAO,EAChB,sBAAsB,EAAE,sBAAsB,EAAA,CAC9C;AAGN,QAAA,KAAK,GAAG;;AAEN,YAAA,QACEA,GAAA,CAAC,cAAc,EAAA,EACb,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,cAAM,OAAA,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA,CAArB,CAAqB,EACnC,cAAc,EAAE,kBAAkB,EAClC,gBAAgB,EAAE,gBAAgB,EAClC,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,iBAAiB,EAAA,CAC3B;AAGN,QAAA;;AAEE,YAAA,IAAI,IAAI,IAAI,CAAC,EAAE;gBACb,IAAI,OAAO,EAAE;AACX,oBAAA,QACEA,GAAA,CAAC,YAAY,IACX,OAAO,EAAE,CAAC,CAAC,kBAAkB,CAAC,EAC9B,QAAQ,EAAE,CAAC,CAAC,4BAA4B,CAAC,EAAA,CACzC;gBAEN;gBAEA,IAAI,OAAO,aAAP,OAAO,KAAA,MAAA,GAAA,MAAA,GAAP,OAAO,CAAE,QAAQ,EAAE;oBACrB,QACEA,IAAC,oBAAoB,EAAA,EACnB,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,WAAW,EACxB,aAAa,EAAE,IAAI,GAAG,CAAC,EACvB,cAAc,EAAE,kBAAkB,EAClC,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,WAAW,EACxB,cAAc,EAAE,cAAc,EAC9B,gBAAgB,EAAE,gBAAgB,EAAA,CAClC;gBAEN;qBAAO;AACL,oBAAA,OAAO,CAAC,GAAG,CACT,wDAAwD,CACzD;;AAED,oBAAA,QACEC,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,kEAAkE,EAAA,QAAA,EAAA,CAC/ED,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,+EAA+E,EAAA,CAAO,EACrGA,GAAA,CAAA,IAAA,EAAA,EAAI,SAAS,EAAC,sCAAsC,EAAA,QAAA,EACjD,CAAC,CAAC,wCAAwC,CAAC,EAAA,CACzC,EACLA,GAAA,CAAA,GAAA,EAAA,EAAG,SAAS,EAAC,oBAAoB,YAC9B,CAAC,CAAC,6BAA6B,CAAC,GAC/B,EACJC,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,wEAAwE,EAAA,QAAA,EAAA,CACrFD,GAAA,CAAA,GAAA,EAAA,EAAG,SAAS,EAAC,uBAAuB,EAAA,QAAA,EACjC,CAAC,CAAC,mCAAmC,CAAC,EAAA,CACrC,EACJA,GAAA,CAAA,QAAA,EAAA,EACE,OAAO,EAAE,YAAA,EAAM,OAAA,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAA,CAAxB,CAAwB,EACvC,SAAS,EAAC,uDAAuD,EAAA,QAAA,EAAA,+BAAA,EAAA,CAG1D,CAAA,EAAA,CACL,CAAA,EAAA,CACF;gBAEV;YACF;AAEA,YAAA,OAAO,IAAI;;AAEjB;;;;"}
|
|
@@ -9,6 +9,7 @@ import LoadingState from '../states/LoadingState.js';
|
|
|
9
9
|
import Title from '../ui/Title.js';
|
|
10
10
|
import Subtitle from '../ui/Subtitle.js';
|
|
11
11
|
import Button from '../ui/Button.js';
|
|
12
|
+
import { labelToKey } from '../../utils/labelToKey.js';
|
|
12
13
|
|
|
13
14
|
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
14
15
|
var FIELD_ALIASES = {
|
|
@@ -101,6 +102,36 @@ var findValueByKeyName = function (sources, referenceField) {
|
|
|
101
102
|
return undefined;
|
|
102
103
|
};
|
|
103
104
|
var expandFieldKey = function (key) { var _a; return __spreadArray([key], ((_a = STANDARD_FIELD_ALIASES[key]) !== null && _a !== void 0 ? _a : []), true); };
|
|
105
|
+
/**
|
|
106
|
+
* Clés (clé aplatie dérivée du label + id du champ custom) des champs du nœud
|
|
107
|
+
* `nodeId` — et lui seul — qui correspondent au type recherché (siren/siret).
|
|
108
|
+
*
|
|
109
|
+
* Sans ce filtrage par nœud, la résolution retombe sur une recherche globale
|
|
110
|
+
* par nom de clé canonique (`findValueByKeyName` / repli 9-14 chiffres) qui
|
|
111
|
+
* ne sait pas distinguer deux nœuds ayant chacun un champ SIREN : un nœud
|
|
112
|
+
* "Identification de la société mère" (champ "SIREN" → clé `siren`) a ainsi
|
|
113
|
+
* capté la résolution d'un nœud "Votre entreprise" (champ "N° de SIREN" →
|
|
114
|
+
* clé `n_de_siren`) configuré comme référence, car `siren` matchait en
|
|
115
|
+
* premier la clé canonique — l'appel INPI est parti sur le mauvais SIREN.
|
|
116
|
+
*/
|
|
117
|
+
var getNodeScopedFieldKeys = function (templateNodes, nodeId, referenceField) {
|
|
118
|
+
var _a;
|
|
119
|
+
var node = templateNodes === null || templateNodes === void 0 ? void 0 : templateNodes.find(function (n) { return n.id === nodeId; });
|
|
120
|
+
var keys = [];
|
|
121
|
+
var _loop_2 = function (field) {
|
|
122
|
+
var normalized = normalizeKeyName(labelToKey(field.label));
|
|
123
|
+
if (!normalized.includes(referenceField))
|
|
124
|
+
return "continue";
|
|
125
|
+
if (THIRD_PARTY_KEY_MARKERS.some(function (marker) { return normalized.includes(marker); }))
|
|
126
|
+
return "continue";
|
|
127
|
+
keys.push(labelToKey(field.label), field.id);
|
|
128
|
+
};
|
|
129
|
+
for (var _i = 0, _b = (_a = node === null || node === void 0 ? void 0 : node.customFields) !== null && _a !== void 0 ? _a : []; _i < _b.length; _i++) {
|
|
130
|
+
var field = _b[_i];
|
|
131
|
+
_loop_2(field);
|
|
132
|
+
}
|
|
133
|
+
return keys;
|
|
134
|
+
};
|
|
104
135
|
// ─── Component ────────────────────────────────────────────────────────────────
|
|
105
136
|
var ExternalVerificationNodeHandler = function (_a) {
|
|
106
137
|
var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
@@ -158,10 +189,10 @@ var ExternalVerificationNodeHandler = function (_a) {
|
|
|
158
189
|
useEffect(function () {
|
|
159
190
|
var abortController = new AbortController();
|
|
160
191
|
var run = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
161
|
-
var result, referenceField, referenceValueMasked, resolvedReferenceValue, referenceNodeId, referenceVariable, submittedFirstName, submittedLastName, submittedSiren, nodeInput, userInputFlat, lookupKeys, referenceValue, allCustomFields, _i, _a, _b, value, str, comparisonConfig, cfg, personNodeInput, flat, isPersonneMorale, sirenKeys, firstNameKeys, lastNameKeys, birthDateKeys, dateOfBirth, response, res, apiErr_1, apiResult, inpi, cfg, isPersonneMorale_1;
|
|
162
|
-
var _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
|
|
163
|
-
return __generator(this, function (
|
|
164
|
-
switch (
|
|
192
|
+
var result, referenceField, referenceValueMasked, resolvedReferenceValue, referenceNodeId, referenceVariable, submittedFirstName, submittedLastName, submittedSiren, nodeInput, userInputFlat, nodeScopedKeys, lookupKeys, referenceValue, allCustomFields, _i, _a, _b, value, str, comparisonConfig, cfg, personNodeInput, flat, isPersonneMorale, sirenKeys, firstNameKeys, lastNameKeys, birthDateKeys, dateOfBirth, response, res, apiErr_1, apiResult, inpi, cfg, isPersonneMorale_1;
|
|
193
|
+
var _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
|
|
194
|
+
return __generator(this, function (_w) {
|
|
195
|
+
switch (_w.label) {
|
|
165
196
|
case 0:
|
|
166
197
|
result = {
|
|
167
198
|
isVerified: false,
|
|
@@ -175,9 +206,9 @@ var ExternalVerificationNodeHandler = function (_a) {
|
|
|
175
206
|
submittedFirstName = '';
|
|
176
207
|
submittedLastName = '';
|
|
177
208
|
submittedSiren = '';
|
|
178
|
-
|
|
209
|
+
_w.label = 1;
|
|
179
210
|
case 1:
|
|
180
|
-
|
|
211
|
+
_w.trys.push([1, 9, , 10]);
|
|
181
212
|
if (!(session === null || session === void 0 ? void 0 : session.id))
|
|
182
213
|
throw new Error('Session ID is missing');
|
|
183
214
|
referenceField = normalizeReferenceField(String(nodeData.referenceField || referenceVariable || ''));
|
|
@@ -192,7 +223,8 @@ var ExternalVerificationNodeHandler = function (_a) {
|
|
|
192
223
|
case 2:
|
|
193
224
|
nodeInput = userInput[referenceNodeId];
|
|
194
225
|
userInputFlat = userInput;
|
|
195
|
-
|
|
226
|
+
nodeScopedKeys = getNodeScopedFieldKeys((_c = session === null || session === void 0 ? void 0 : session.template) === null || _c === void 0 ? void 0 : _c.nodes, referenceNodeId, referenceField);
|
|
227
|
+
lookupKeys = Array.from(new Set(__spreadArray(__spreadArray(__spreadArray([], nodeScopedKeys, true), [referenceVariable, referenceField], false), FIELD_ALIASES[referenceField], true).filter(Boolean)));
|
|
196
228
|
referenceValue = resolveFieldValue(nodeInput, userInputFlat, lookupKeys);
|
|
197
229
|
// 2e passe : la clé porte le nom du champ sans être canonique
|
|
198
230
|
// (cas de tout formulaire personnalisé).
|
|
@@ -235,14 +267,14 @@ var ExternalVerificationNodeHandler = function (_a) {
|
|
|
235
267
|
resolvedReferenceValue = referenceValue;
|
|
236
268
|
referenceValueMasked = maskReferenceValue(referenceValue);
|
|
237
269
|
comparisonConfig = void 0;
|
|
238
|
-
if (isInpiRbe && ((
|
|
270
|
+
if (isInpiRbe && ((_d = nodeData.comparisonConfig) === null || _d === void 0 ? void 0 : _d.personReferenceNodeId)) {
|
|
239
271
|
cfg = nodeData.comparisonConfig;
|
|
240
|
-
personNodeInput = (
|
|
272
|
+
personNodeInput = (_e = userInput[cfg.personReferenceNodeId]) !== null && _e !== void 0 ? _e : {};
|
|
241
273
|
flat = userInput;
|
|
242
274
|
isPersonneMorale = cfg.personType === 'MORALE';
|
|
243
275
|
if (isPersonneMorale) {
|
|
244
|
-
sirenKeys = expandFieldKey((
|
|
245
|
-
submittedSiren = (
|
|
276
|
+
sirenKeys = expandFieldKey((_f = cfg.personSirenField) !== null && _f !== void 0 ? _f : '').filter(Boolean);
|
|
277
|
+
submittedSiren = (_g = resolveFieldValue(personNodeInput, flat, sirenKeys)) !== null && _g !== void 0 ? _g : '';
|
|
246
278
|
if (submittedSiren) {
|
|
247
279
|
comparisonConfig = {
|
|
248
280
|
personType: 'MORALE',
|
|
@@ -255,46 +287,46 @@ var ExternalVerificationNodeHandler = function (_a) {
|
|
|
255
287
|
}
|
|
256
288
|
}
|
|
257
289
|
else {
|
|
258
|
-
firstNameKeys = expandFieldKey((
|
|
259
|
-
lastNameKeys = expandFieldKey((
|
|
290
|
+
firstNameKeys = expandFieldKey((_h = cfg.personFirstNameField) !== null && _h !== void 0 ? _h : '').filter(Boolean);
|
|
291
|
+
lastNameKeys = expandFieldKey((_j = cfg.personLastNameField) !== null && _j !== void 0 ? _j : '').filter(Boolean);
|
|
260
292
|
birthDateKeys = cfg.personBirthDateField
|
|
261
293
|
? expandFieldKey(cfg.personBirthDateField).filter(Boolean)
|
|
262
294
|
: [];
|
|
263
|
-
submittedFirstName = (
|
|
264
|
-
submittedLastName = (
|
|
295
|
+
submittedFirstName = (_k = resolveFieldValue(personNodeInput, flat, firstNameKeys)) !== null && _k !== void 0 ? _k : '';
|
|
296
|
+
submittedLastName = (_l = resolveFieldValue(personNodeInput, flat, lastNameKeys)) !== null && _l !== void 0 ? _l : '';
|
|
265
297
|
dateOfBirth = cfg.compareBirthDate && birthDateKeys.length
|
|
266
298
|
? resolveFieldValue(personNodeInput, flat, birthDateKeys)
|
|
267
299
|
: undefined;
|
|
268
300
|
if (submittedFirstName && submittedLastName) {
|
|
269
|
-
comparisonConfig = __assign({ firstName: submittedFirstName, lastName: submittedLastName, compareTargets: (
|
|
301
|
+
comparisonConfig = __assign({ firstName: submittedFirstName, lastName: submittedLastName, compareTargets: (_m = cfg.compareTargets) !== null && _m !== void 0 ? _m : ['mandataires'] }, (dateOfBirth ? { dateOfBirth: dateOfBirth } : {}));
|
|
270
302
|
}
|
|
271
303
|
}
|
|
272
304
|
}
|
|
273
305
|
if (isInpiRbe)
|
|
274
306
|
advanceStep(1);
|
|
275
|
-
|
|
307
|
+
_w.label = 4;
|
|
276
308
|
case 4:
|
|
277
|
-
|
|
309
|
+
_w.trys.push([4, 7, , 8]);
|
|
278
310
|
return [4 /*yield*/, apiService.post("/session/sdk/".concat(session.id, "/verify-external/").concat(node.id), __assign({ apiType: apiType, referenceValue: referenceValue, referenceField: referenceField, enableRnaFallback: isInpiRbe && nodeData.rnaFallbackEnabled === true, enableInseeFallback: isInpiRbe && nodeData.enableInseeFallback === true }, (comparisonConfig ? { comparisonConfig: comparisonConfig } : {})), { signal: abortController.signal })];
|
|
279
311
|
case 5:
|
|
280
|
-
response =
|
|
312
|
+
response = _w.sent();
|
|
281
313
|
if (isInpiRbe)
|
|
282
314
|
advanceStep(2);
|
|
283
315
|
return [4 /*yield*/, new Promise(function (r) { return setTimeout(r, 600); })];
|
|
284
316
|
case 6:
|
|
285
|
-
|
|
286
|
-
res = (
|
|
317
|
+
_w.sent();
|
|
318
|
+
res = (_o = response.data) === null || _o === void 0 ? void 0 : _o.data;
|
|
287
319
|
if (res && typeof res.isVerified === 'boolean') {
|
|
288
320
|
result = res;
|
|
289
321
|
}
|
|
290
322
|
return [3 /*break*/, 8];
|
|
291
323
|
case 7:
|
|
292
|
-
apiErr_1 =
|
|
324
|
+
apiErr_1 = _w.sent();
|
|
293
325
|
if (abortController.signal.aborted)
|
|
294
326
|
return [2 /*return*/];
|
|
295
327
|
if (isInpiRbe)
|
|
296
328
|
advanceStep(2);
|
|
297
|
-
apiResult = (
|
|
329
|
+
apiResult = (_q = (_p = apiErr_1 === null || apiErr_1 === void 0 ? void 0 : apiErr_1.response) === null || _p === void 0 ? void 0 : _p.data) === null || _q === void 0 ? void 0 : _q.data;
|
|
298
330
|
if (apiResult && typeof apiResult.isVerified === 'boolean') {
|
|
299
331
|
result = apiResult;
|
|
300
332
|
}
|
|
@@ -309,7 +341,7 @@ var ExternalVerificationNodeHandler = function (_a) {
|
|
|
309
341
|
return [3 /*break*/, 8];
|
|
310
342
|
case 8: return [3 /*break*/, 10];
|
|
311
343
|
case 9:
|
|
312
|
-
|
|
344
|
+
_w.sent();
|
|
313
345
|
result = {
|
|
314
346
|
isVerified: false,
|
|
315
347
|
status: 'external_error',
|
|
@@ -347,13 +379,13 @@ var ExternalVerificationNodeHandler = function (_a) {
|
|
|
347
379
|
// En mode personne morale, seuls les mandataires personne morale ont
|
|
348
380
|
// un sens (un RBE est toujours une personne physique) ; en mode
|
|
349
381
|
// physique, comportement inchangé (mandataires individus uniquement).
|
|
350
|
-
mandataires: ((
|
|
382
|
+
mandataires: ((_r = inpi === null || inpi === void 0 ? void 0 : inpi.mandataires) !== null && _r !== void 0 ? _r : []).filter(function (m) {
|
|
351
383
|
return isPersonneMorale_1 ? m.type === 'personne_morale' : m.type === 'individu';
|
|
352
384
|
}),
|
|
353
|
-
beneficiairesEffectifs: (
|
|
354
|
-
compareTargets: isPersonneMorale_1 ? ['mandataires'] : ((
|
|
355
|
-
personNodeId: (
|
|
356
|
-
targetDenomination: (
|
|
385
|
+
beneficiairesEffectifs: (_s = inpi === null || inpi === void 0 ? void 0 : inpi.beneficiairesEffectifs) !== null && _s !== void 0 ? _s : [],
|
|
386
|
+
compareTargets: isPersonneMorale_1 ? ['mandataires'] : ((_t = cfg === null || cfg === void 0 ? void 0 : cfg.compareTargets) !== null && _t !== void 0 ? _t : ['mandataires']),
|
|
387
|
+
personNodeId: (_u = cfg === null || cfg === void 0 ? void 0 : cfg.personReferenceNodeId) !== null && _u !== void 0 ? _u : '',
|
|
388
|
+
targetDenomination: (_v = inpi === null || inpi === void 0 ? void 0 : inpi.identite) === null || _v === void 0 ? void 0 : _v.denomination,
|
|
357
389
|
siren: resolvedReferenceValue,
|
|
358
390
|
sirenNodeId: referenceNodeId,
|
|
359
391
|
source: inpi === null || inpi === void 0 ? void 0 : inpi.source,
|