datakeen-session-react 1.1.198-rc.0 → 1.1.198-rc.2
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 +4 -2
- 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 +4 -2
- 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/JOURNEY_NODE_BUILDER.md +9 -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":"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"}
|
|
@@ -378,9 +378,11 @@ var ExternalVerificationNodeHandler = function (_a) {
|
|
|
378
378
|
submittedSiren: isPersonneMorale_1 ? submittedSiren : undefined,
|
|
379
379
|
// En mode personne morale, seuls les mandataires personne morale ont
|
|
380
380
|
// un sens (un RBE est toujours une personne physique) ; en mode
|
|
381
|
-
// physique,
|
|
381
|
+
// physique, tous les mandataires sont listés : une société
|
|
382
|
+
// mandataire (ex. holding présidente) explique pourquoi la
|
|
383
|
+
// personne saisie n'apparaît pas en direct au RNE.
|
|
382
384
|
mandataires: ((_r = inpi === null || inpi === void 0 ? void 0 : inpi.mandataires) !== null && _r !== void 0 ? _r : []).filter(function (m) {
|
|
383
|
-
return isPersonneMorale_1 ? m.type === 'personne_morale' :
|
|
385
|
+
return isPersonneMorale_1 ? m.type === 'personne_morale' : true;
|
|
384
386
|
}),
|
|
385
387
|
beneficiairesEffectifs: (_s = inpi === null || inpi === void 0 ? void 0 : inpi.beneficiairesEffectifs) !== null && _s !== void 0 ? _s : [],
|
|
386
388
|
compareTargets: isPersonneMorale_1 ? ['mandataires'] : ((_t = cfg === null || cfg === void 0 ? void 0 : cfg.compareTargets) !== null && _t !== void 0 ? _t : ['mandataires']),
|