datakeen-session-react 1.1.140-dev.97 → 1.1.140-oid4vp-demo.0
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/.gitlab-ci.yml +37 -0
- package/dist/cjs/components/document-collection/DocumentCollection.js +132 -22
- package/dist/cjs/components/document-collection/DocumentCollection.js.map +1 -1
- package/dist/cjs/components/session/DocumentCheck.js +112 -15
- package/dist/cjs/components/session/DocumentCheck.js.map +1 -1
- package/dist/cjs/components/template/TemplateNodeRenderer.js +5 -1
- package/dist/cjs/components/template/TemplateNodeRenderer.js.map +1 -1
- package/dist/cjs/components/wallet/AgeControl.js +75 -0
- package/dist/cjs/components/wallet/AgeControl.js.map +1 -0
- package/dist/cjs/components/wallet/WalletProposal.js +27 -0
- package/dist/cjs/components/wallet/WalletProposal.js.map +1 -0
- package/dist/cjs/components/wallet/WalletSuccessAnimation.js +37 -0
- package/dist/cjs/components/wallet/WalletSuccessAnimation.js.map +1 -0
- package/dist/cjs/components/wallet/WalletVerificationStep.js +132 -0
- package/dist/cjs/components/wallet/WalletVerificationStep.js.map +1 -0
- package/dist/cjs/hooks/useWalletSseStatus.js +67 -0
- package/dist/cjs/hooks/useWalletSseStatus.js.map +1 -0
- package/dist/cjs/i18n/en.json.js +34 -1
- package/dist/cjs/i18n/en.json.js.map +1 -1
- package/dist/cjs/i18n/fr.json.js +34 -1
- package/dist/cjs/i18n/fr.json.js.map +1 -1
- package/dist/cjs/services/sessionService.js +57 -0
- package/dist/cjs/services/sessionService.js.map +1 -1
- package/dist/cjs/types/session.js.map +1 -1
- package/dist/esm/components/document-collection/DocumentCollection.js +132 -22
- package/dist/esm/components/document-collection/DocumentCollection.js.map +1 -1
- package/dist/esm/components/session/DocumentCheck.js +113 -16
- package/dist/esm/components/session/DocumentCheck.js.map +1 -1
- package/dist/esm/components/template/TemplateNodeRenderer.js +5 -1
- package/dist/esm/components/template/TemplateNodeRenderer.js.map +1 -1
- package/dist/esm/components/wallet/AgeControl.js +71 -0
- package/dist/esm/components/wallet/AgeControl.js.map +1 -0
- package/dist/esm/components/wallet/WalletProposal.js +23 -0
- package/dist/esm/components/wallet/WalletProposal.js.map +1 -0
- package/dist/esm/components/wallet/WalletSuccessAnimation.js +33 -0
- package/dist/esm/components/wallet/WalletSuccessAnimation.js.map +1 -0
- package/dist/esm/components/wallet/WalletVerificationStep.js +128 -0
- package/dist/esm/components/wallet/WalletVerificationStep.js.map +1 -0
- package/dist/esm/hooks/useWalletSseStatus.js +65 -0
- package/dist/esm/hooks/useWalletSseStatus.js.map +1 -0
- package/dist/esm/i18n/en.json.js +33 -2
- package/dist/esm/i18n/en.json.js.map +1 -1
- package/dist/esm/i18n/fr.json.js +33 -2
- package/dist/esm/i18n/fr.json.js.map +1 -1
- package/dist/esm/services/sessionService.js +55 -1
- package/dist/esm/services/sessionService.js.map +1 -1
- package/dist/esm/types/session.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
|
+
import { useI18n } from '../../hooks/useI18n.js';
|
|
4
|
+
import { fetchWallets } from '../../services/sessionService.js';
|
|
5
|
+
import WalletProposal from './WalletProposal.js';
|
|
6
|
+
import WalletVerificationStep from './WalletVerificationStep.js';
|
|
7
|
+
import Button from '../ui/Button.js';
|
|
8
|
+
import ButtonDesktop from '../ui/ButtonDesktop.js';
|
|
9
|
+
import useIsMobile from '../../hooks/useIsMobile.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Nœud de vérification d'âge par wallet (eu.europa.ec.av.1) — cf.
|
|
13
|
+
* docs/WALLET_OID4VP_IMPLEMENTATION_PLAN.md §5.5/§7. Contrairement à
|
|
14
|
+
* identity-control, ce nœud est intrinsèquement wallet-first : pas de bascule
|
|
15
|
+
* "walletEnabled", le wallet est tenté systématiquement s'il est disponible
|
|
16
|
+
* pour le pays connu, avec repli automatique et silencieux (§5.5 : "pas de
|
|
17
|
+
* refus explicite") sinon.
|
|
18
|
+
*
|
|
19
|
+
* L'estimation d'âge Unissey de repli n'existe pas encore comme flux dédié
|
|
20
|
+
* dans le SDK (aucun nœud de ce type n'était actif avant cette phase) — le
|
|
21
|
+
* repli affiche donc un écran "en construction" (même patron que
|
|
22
|
+
* JDDWorkInProgress) plutôt que d'improviser un flux non spécifié.
|
|
23
|
+
*/
|
|
24
|
+
var AgeControl = function (_a) {
|
|
25
|
+
var _b, _c, _d;
|
|
26
|
+
var sessionId = _a.sessionId, node = _a.node, stepObject = _a.stepObject, template = _a.template, countryCode = _a.countryCode;
|
|
27
|
+
var t = useI18n().t;
|
|
28
|
+
var isMobile = useIsMobile();
|
|
29
|
+
var _e = useState("checking"), state = _e[0], setState = _e[1];
|
|
30
|
+
useEffect(function () {
|
|
31
|
+
var cancelled = false;
|
|
32
|
+
if (!countryCode) {
|
|
33
|
+
setState("fallback");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
fetchWallets(countryCode, "age_verification")
|
|
37
|
+
.then(function (wallets) {
|
|
38
|
+
if (!cancelled)
|
|
39
|
+
setState(wallets.length > 0 ? "proposal" : "fallback");
|
|
40
|
+
})
|
|
41
|
+
.catch(function () {
|
|
42
|
+
if (!cancelled)
|
|
43
|
+
setState("fallback");
|
|
44
|
+
});
|
|
45
|
+
return function () {
|
|
46
|
+
cancelled = true;
|
|
47
|
+
};
|
|
48
|
+
}, [countryCode]);
|
|
49
|
+
var advance = function () {
|
|
50
|
+
if (template) {
|
|
51
|
+
stepObject.goToNextStep(node.id, template);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
stepObject.setStep(stepObject.step + 1);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
if (state === "checking") {
|
|
58
|
+
return (jsx("div", { className: "flex flex-col items-center justify-center h-full p-8", children: jsx("div", { className: "animate-spin w-10 h-10 border-2 border-gray-300 border-t-blue-500 rounded-full" }) }));
|
|
59
|
+
}
|
|
60
|
+
if (state === "proposal") {
|
|
61
|
+
return (jsx(WalletProposal, { walletMode: "walletOrPhoto", onUseWallet: function () { return setState("verifying"); }, onDecline: function () { return setState("fallback"); } }));
|
|
62
|
+
}
|
|
63
|
+
if (state === "verifying") {
|
|
64
|
+
return (jsx(WalletVerificationStep, { sessionId: sessionId, nodeId: node.id, credentialType: "age_verification", walletMode: "walletOrPhoto", minimumAge: (_b = node.minimumAge) !== null && _b !== void 0 ? _b : 18, onCompleted: advance, onFailedOrDeclined: function () { return setState("fallback"); }, pageTitle: (_c = node.introductionPage) === null || _c === void 0 ? void 0 : _c.title, pageDescription: (_d = node.introductionPage) === null || _d === void 0 ? void 0 : _d.description }));
|
|
65
|
+
}
|
|
66
|
+
// fallback — wallet non disponible / décliné / échoué : repli silencieux
|
|
67
|
+
return (jsxs("div", { className: "flex flex-col justify-between h-full w-full", children: [jsx("div", { className: "flex-1 flex items-start justify-center md:items-center px-4 py-8", children: jsxs("div", { className: "w-full max-w-md mx-auto text-center space-y-6", children: [jsx("h1", { className: "text-2xl md:text-3xl font-bold text-gray-800 mb-4", children: t("age_control.fallback.title", "Vérification d'âge") }), jsx("p", { className: "text-gray-600 text-lg mb-6", children: t("age_control.fallback.subtitle", "Cette vérification sera complétée automatiquement à l'étape suivante.") })] }) }), jsx("div", { className: "flex-shrink-0 p-4 border-t border-gray-200 bg-white", children: isMobile ? (jsx("div", { className: "w-full", "data-cy": "age-control-continue", children: jsx(Button, { onClick: advance, className: "w-full py-3", children: t("age_control.fallback.continue", "Continuer") }) })) : (jsx("div", { className: "flex justify-end max-w-4xl mx-auto", "data-cy": "age-control-continue", children: jsx(ButtonDesktop, { onClick: advance, type: "continue", children: t("age_control.fallback.continue", "Continuer") }) })) })] }));
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export { AgeControl as default };
|
|
71
|
+
//# sourceMappingURL=AgeControl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgeControl.js","sources":["../../../../../src/components/wallet/AgeControl.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport type { SessionTemplate, stepObject } from \"../../types/session\";\nimport { useI18n } from \"../../hooks/useI18n\";\nimport { fetchWallets } from \"../../services/sessionService\";\nimport WalletProposal from \"./WalletProposal\";\nimport WalletVerificationStep from \"./WalletVerificationStep\";\nimport Button from \"../ui/Button\";\nimport ButtonDesktop from \"../ui/ButtonDesktop\";\nimport useIsMobile from \"../../hooks/useIsMobile\";\n\ninterface AgeControlNode {\n id: string;\n minimumAge?: number;\n introductionPage?: {\n title?: string;\n description?: string;\n };\n}\n\ninterface AgeControlProps {\n sessionId: string;\n node: AgeControlNode;\n stepObject: stepObject;\n template?: SessionTemplate;\n /** Pays de l'utilisateur, connu si un nœud identity-control précède ce nœud dans le parcours. */\n countryCode?: string;\n}\n\ntype AgeControlState = \"checking\" | \"proposal\" | \"verifying\" | \"fallback\";\n\n/**\n * Nœud de vérification d'âge par wallet (eu.europa.ec.av.1) — cf.\n * docs/WALLET_OID4VP_IMPLEMENTATION_PLAN.md §5.5/§7. Contrairement à\n * identity-control, ce nœud est intrinsèquement wallet-first : pas de bascule\n * \"walletEnabled\", le wallet est tenté systématiquement s'il est disponible\n * pour le pays connu, avec repli automatique et silencieux (§5.5 : \"pas de\n * refus explicite\") sinon.\n *\n * L'estimation d'âge Unissey de repli n'existe pas encore comme flux dédié\n * dans le SDK (aucun nœud de ce type n'était actif avant cette phase) — le\n * repli affiche donc un écran \"en construction\" (même patron que\n * JDDWorkInProgress) plutôt que d'improviser un flux non spécifié.\n */\nconst AgeControl: React.FC<AgeControlProps> = ({\n sessionId,\n node,\n stepObject,\n template,\n countryCode,\n}) => {\n const { t } = useI18n();\n const isMobile = useIsMobile();\n const [state, setState] = useState<AgeControlState>(\"checking\");\n\n useEffect(() => {\n let cancelled = false;\n if (!countryCode) {\n setState(\"fallback\");\n return;\n }\n fetchWallets(countryCode, \"age_verification\")\n .then((wallets) => {\n if (!cancelled) setState(wallets.length > 0 ? \"proposal\" : \"fallback\");\n })\n .catch(() => {\n if (!cancelled) setState(\"fallback\");\n });\n return () => {\n cancelled = true;\n };\n }, [countryCode]);\n\n const advance = () => {\n if (template) {\n stepObject.goToNextStep(node.id, template);\n } else {\n stepObject.setStep(stepObject.step + 1);\n }\n };\n\n if (state === \"checking\") {\n return (\n <div className=\"flex flex-col items-center justify-center h-full p-8\">\n <div className=\"animate-spin w-10 h-10 border-2 border-gray-300 border-t-blue-500 rounded-full\" />\n </div>\n );\n }\n\n if (state === \"proposal\") {\n return (\n <WalletProposal\n walletMode=\"walletOrPhoto\"\n onUseWallet={() => setState(\"verifying\")}\n onDecline={() => setState(\"fallback\")}\n />\n );\n }\n\n if (state === \"verifying\") {\n return (\n <WalletVerificationStep\n sessionId={sessionId}\n nodeId={node.id}\n credentialType=\"age_verification\"\n walletMode=\"walletOrPhoto\"\n minimumAge={node.minimumAge ?? 18}\n onCompleted={advance}\n onFailedOrDeclined={() => setState(\"fallback\")}\n pageTitle={node.introductionPage?.title}\n pageDescription={node.introductionPage?.description}\n />\n );\n }\n\n // fallback — wallet non disponible / décliné / échoué : repli silencieux\n return (\n <div className=\"flex flex-col justify-between h-full w-full\">\n <div className=\"flex-1 flex items-start justify-center md:items-center px-4 py-8\">\n <div className=\"w-full max-w-md mx-auto text-center space-y-6\">\n <h1 className=\"text-2xl md:text-3xl font-bold text-gray-800 mb-4\">\n {t(\"age_control.fallback.title\", \"Vérification d'âge\")}\n </h1>\n <p className=\"text-gray-600 text-lg mb-6\">\n {t(\n \"age_control.fallback.subtitle\",\n \"Cette vérification sera complétée automatiquement à l'étape suivante.\",\n )}\n </p>\n </div>\n </div>\n <div className=\"flex-shrink-0 p-4 border-t border-gray-200 bg-white\">\n {isMobile ? (\n <div className=\"w-full\" data-cy=\"age-control-continue\">\n <Button onClick={advance} className=\"w-full py-3\">\n {t(\"age_control.fallback.continue\", \"Continuer\")}\n </Button>\n </div>\n ) : (\n <div className=\"flex justify-end max-w-4xl mx-auto\" data-cy=\"age-control-continue\">\n <ButtonDesktop onClick={advance} type=\"continue\">\n {t(\"age_control.fallback.continue\", \"Continuer\")}\n </ButtonDesktop>\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default AgeControl;\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import Title from '../ui/Title.js';
|
|
3
|
+
import Subtitle from '../ui/Subtitle.js';
|
|
4
|
+
import Button from '../ui/Button.js';
|
|
5
|
+
import PageActions from '../ui/PageActions.js';
|
|
6
|
+
import MobilePageLayout from '../ui/MobilePageLayout.js';
|
|
7
|
+
import { useI18n } from '../../hooks/useI18n.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Écran de proposition d'identification par wallet d'identité européen
|
|
11
|
+
* (OpenID4VP), affiché uniquement quand un wallet compatible existe pour le
|
|
12
|
+
* pays et le document choisis (cf. GET /backend/wallets). Modèle : NfcChipGate.
|
|
13
|
+
*/
|
|
14
|
+
var WalletProposal = function (_a) {
|
|
15
|
+
var onUseWallet = _a.onUseWallet, onDecline = _a.onDecline, walletMode = _a.walletMode;
|
|
16
|
+
var t = useI18n().t;
|
|
17
|
+
return (jsx(MobilePageLayout, { footer: jsx(PageActions, { className: "flex-wrap justify-center!", primary: jsx(Button, { onClick: onUseWallet, children: t("wallet.proposal.use_wallet", "Utiliser mon wallet") }), secondary: jsx(Button, { variant: "secondary", onClick: onDecline, className: "whitespace-nowrap", children: walletMode === "walletOrPhoto"
|
|
18
|
+
? t("wallet.proposal.decline_photo", "Continuer avec une photo")
|
|
19
|
+
: t("wallet.proposal.decline_no_wallet", "Je n'ai pas de wallet") }) }), children: jsx("div", { className: "px-4 py-6 pt-11 md:px-8 md:py-8", children: jsx("div", { className: "w-full max-w-md mx-auto space-y-8 text-center", children: jsxs("div", { className: "space-y-4", children: [jsx(Title, { className: "text-xl md:text-2xl lg:text-3xl", children: t("wallet.proposal.title", "Identifiez-vous avec votre wallet d'identité") }), jsx(Subtitle, { className: "text-sm text-gray-600 leading-relaxed whitespace-pre-line", children: t("wallet.proposal.subtitle", "Un wallet d'identité européen est disponible pour ce document. Vous pouvez vous identifier en ligne, sans prendre de photo.") })] }) }) }) }));
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export { WalletProposal as default };
|
|
23
|
+
//# sourceMappingURL=WalletProposal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WalletProposal.js","sources":["../../../../../src/components/wallet/WalletProposal.tsx"],"sourcesContent":["import React from \"react\";\nimport Title from \"../ui/Title\";\nimport Subtitle from \"../ui/Subtitle\";\nimport Button from \"../ui/Button\";\nimport PageActions from \"../ui/PageActions\";\nimport MobilePageLayout from \"../ui/MobilePageLayout\";\nimport { useI18n } from \"../../hooks/useI18n\";\n\ninterface WalletProposalProps {\n /** L'utilisateur choisit de s'identifier par wallet → écran QR/deep-link */\n onUseWallet: () => void;\n /** L'utilisateur décline (photo si walletOrPhoto, saut du nœud si walletOnly) */\n onDecline: () => void;\n /** walletOnly : pas d'alternative photo, le libellé du bouton secondaire change */\n walletMode: \"walletOnly\" | \"walletOrPhoto\";\n}\n\n/**\n * Écran de proposition d'identification par wallet d'identité européen\n * (OpenID4VP), affiché uniquement quand un wallet compatible existe pour le\n * pays et le document choisis (cf. GET /backend/wallets). Modèle : NfcChipGate.\n */\nconst WalletProposal = ({ onUseWallet, onDecline, walletMode }: WalletProposalProps) => {\n const { t } = useI18n();\n\n return (\n <MobilePageLayout\n footer={\n <PageActions\n className=\"flex-wrap justify-center!\"\n primary={\n <Button onClick={onUseWallet}>\n {t(\"wallet.proposal.use_wallet\", \"Utiliser mon wallet\")}\n </Button>\n }\n secondary={\n <Button\n variant=\"secondary\"\n onClick={onDecline}\n className=\"whitespace-nowrap\"\n >\n {walletMode === \"walletOrPhoto\"\n ? t(\"wallet.proposal.decline_photo\", \"Continuer avec une photo\")\n : t(\"wallet.proposal.decline_no_wallet\", \"Je n'ai pas de wallet\")}\n </Button>\n }\n />\n }\n >\n <div className=\"px-4 py-6 pt-11 md:px-8 md:py-8\">\n <div className=\"w-full max-w-md mx-auto space-y-8 text-center\">\n <div className=\"space-y-4\">\n <Title className=\"text-xl md:text-2xl lg:text-3xl\">\n {t(\n \"wallet.proposal.title\",\n \"Identifiez-vous avec votre wallet d'identité\",\n )}\n </Title>\n <Subtitle className=\"text-sm text-gray-600 leading-relaxed whitespace-pre-line\">\n {t(\n \"wallet.proposal.subtitle\",\n \"Un wallet d'identité européen est disponible pour ce document. Vous pouvez vous identifier en ligne, sans prendre de photo.\",\n )}\n </Subtitle>\n </div>\n </div>\n </div>\n </MobilePageLayout>\n );\n};\n\nexport default WalletProposal;\n"],"names":["_jsx","_jsxs"],"mappings":";;;;;;;;AAiBA;;;;AAIG;AACH,IAAM,cAAc,GAAG,UAAC,EAA2D,EAAA;AAAzD,IAAA,IAAA,WAAW,iBAAA,EAAE,SAAS,GAAA,EAAA,CAAA,SAAA,EAAE,UAAU,GAAA,EAAA,CAAA,UAAA;AAClD,IAAA,IAAA,CAAC,GAAK,OAAO,EAAE,EAAd;IAET,QACEA,IAAC,gBAAgB,EAAA,EACf,MAAM,EACJA,GAAA,CAAC,WAAW,EAAA,EACV,SAAS,EAAC,2BAA2B,EACrC,OAAO,EACLA,GAAA,CAAC,MAAM,IAAC,OAAO,EAAE,WAAW,EAAA,QAAA,EACzB,CAAC,CAAC,4BAA4B,EAAE,qBAAqB,CAAC,EAAA,CAChD,EAEX,SAAS,EACPA,GAAA,CAAC,MAAM,EAAA,EACL,OAAO,EAAC,WAAW,EACnB,OAAO,EAAE,SAAS,EAClB,SAAS,EAAC,mBAAmB,EAAA,QAAA,EAE5B,UAAU,KAAK;AACd,sBAAE,CAAC,CAAC,+BAA+B,EAAE,0BAA0B;sBAC7D,CAAC,CAAC,mCAAmC,EAAE,uBAAuB,CAAC,EAAA,CAC5D,EAAA,CAEX,EAAA,QAAA,EAGJA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,iCAAiC,EAAA,QAAA,EAC9CA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,+CAA+C,EAAA,QAAA,EAC5DC,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,WAAW,EAAA,QAAA,EAAA,CACxBD,GAAA,CAAC,KAAK,EAAA,EAAC,SAAS,EAAC,iCAAiC,EAAA,QAAA,EAC/C,CAAC,CACA,uBAAuB,EACvB,8CAA8C,CAC/C,EAAA,CACK,EACRA,GAAA,CAAC,QAAQ,EAAA,EAAC,SAAS,EAAC,2DAA2D,EAAA,QAAA,EAC5E,CAAC,CACA,0BAA0B,EAC1B,6HAA6H,CAC9H,EAAA,CACQ,CAAA,EAAA,CACP,EAAA,CACF,EAAA,CACF,EAAA,CACW;AAEvB;;;;"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
|
+
import { useI18n } from '../../hooks/useI18n.js';
|
|
4
|
+
|
|
5
|
+
/** Même animation visuelle que NfcSuccessAnimation, avec un libellé adapté au wallet. */
|
|
6
|
+
var WalletSuccessAnimation = function () {
|
|
7
|
+
var t = useI18n().t;
|
|
8
|
+
var _a = useState(false), visible = _a[0], setVisible = _a[1];
|
|
9
|
+
useEffect(function () {
|
|
10
|
+
var id = requestAnimationFrame(function () { return setVisible(true); });
|
|
11
|
+
return function () { return cancelAnimationFrame(id); };
|
|
12
|
+
}, []);
|
|
13
|
+
return (jsxs("div", { className: "flex flex-col items-center gap-6 p-8", style: {
|
|
14
|
+
opacity: visible ? 1 : 0,
|
|
15
|
+
transform: visible ? "scale(1)" : "scale(0.85)",
|
|
16
|
+
transition: "opacity 0.4s ease, transform 0.4s ease",
|
|
17
|
+
}, children: [jsxs("div", { style: { position: "relative", width: 72, height: 72, flexShrink: 0 }, children: [jsx("div", { style: {
|
|
18
|
+
position: "absolute",
|
|
19
|
+
inset: 0,
|
|
20
|
+
borderRadius: "50%",
|
|
21
|
+
backgroundColor: "var(--uni-primary-color, #11e5c5)",
|
|
22
|
+
transformOrigin: "center center",
|
|
23
|
+
animation: "wallet-pulse 1.6s ease-out infinite",
|
|
24
|
+
pointerEvents: "none",
|
|
25
|
+
} }), jsxs("svg", { width: 72, height: 72, viewBox: "0 0 72 72", fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [jsx("circle", { cx: 36, cy: 36, r: 34, fill: "var(--uni-primary-color, #11e5c5)", style: { opacity: visible ? 1 : 0, transition: "opacity 0.3s ease 0.1s" } }), jsx("polyline", { points: "20,37 30,47 52,25", stroke: "#ffffff", strokeWidth: 5, strokeLinecap: "round", strokeLinejoin: "round", fill: "none", style: {
|
|
26
|
+
strokeDasharray: 50,
|
|
27
|
+
strokeDashoffset: visible ? 0 : 50,
|
|
28
|
+
transition: "stroke-dashoffset 0.45s cubic-bezier(0.4, 0, 0.2, 1) 0.35s",
|
|
29
|
+
} })] })] }), jsxs("div", { className: "text-center space-y-1", children: [jsx("p", { className: "font-semibold text-base", style: { color: "var(--uni-secondary-color, #0a9983)" }, children: t("wallet.verification.success_title", "Identité vérifiée") }), jsx("p", { className: "text-sm text-gray-500", children: t("wallet.verification.success_subtitle", "Vérification par wallet confirmée avec succès") })] }), jsx("style", { children: "\n @keyframes wallet-pulse {\n 0% { transform: scale(1); opacity: 0.25; }\n 70% { transform: scale(1.65); opacity: 0.05; }\n 100% { transform: scale(1.65); opacity: 0; }\n }\n " })] }));
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export { WalletSuccessAnimation as default };
|
|
33
|
+
//# sourceMappingURL=WalletSuccessAnimation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WalletSuccessAnimation.js","sources":["../../../../../src/components/wallet/WalletSuccessAnimation.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport { useI18n } from \"../../hooks/useI18n\";\n\n/** Même animation visuelle que NfcSuccessAnimation, avec un libellé adapté au wallet. */\nconst WalletSuccessAnimation: React.FC = () => {\n const { t } = useI18n();\n const [visible, setVisible] = useState(false);\n\n useEffect(() => {\n const id = requestAnimationFrame(() => setVisible(true));\n return () => cancelAnimationFrame(id);\n }, []);\n\n return (\n <div\n className=\"flex flex-col items-center gap-6 p-8\"\n style={{\n opacity: visible ? 1 : 0,\n transform: visible ? \"scale(1)\" : \"scale(0.85)\",\n transition: \"opacity 0.4s ease, transform 0.4s ease\",\n }}\n >\n <div style={{ position: \"relative\", width: 72, height: 72, flexShrink: 0 }}>\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n borderRadius: \"50%\",\n backgroundColor: \"var(--uni-primary-color, #11e5c5)\",\n transformOrigin: \"center center\",\n animation: \"wallet-pulse 1.6s ease-out infinite\",\n pointerEvents: \"none\",\n }}\n />\n <svg\n width={72}\n height={72}\n viewBox=\"0 0 72 72\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <circle\n cx={36}\n cy={36}\n r={34}\n fill=\"var(--uni-primary-color, #11e5c5)\"\n style={{ opacity: visible ? 1 : 0, transition: \"opacity 0.3s ease 0.1s\" }}\n />\n <polyline\n points=\"20,37 30,47 52,25\"\n stroke=\"#ffffff\"\n strokeWidth={5}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n fill=\"none\"\n style={{\n strokeDasharray: 50,\n strokeDashoffset: visible ? 0 : 50,\n transition: \"stroke-dashoffset 0.45s cubic-bezier(0.4, 0, 0.2, 1) 0.35s\",\n }}\n />\n </svg>\n </div>\n\n <div className=\"text-center space-y-1\">\n <p\n className=\"font-semibold text-base\"\n style={{ color: \"var(--uni-secondary-color, #0a9983)\" }}\n >\n {t(\"wallet.verification.success_title\", \"Identité vérifiée\")}\n </p>\n <p className=\"text-sm text-gray-500\">\n {t(\"wallet.verification.success_subtitle\", \"Vérification par wallet confirmée avec succès\")}\n </p>\n </div>\n\n <style>{`\n @keyframes wallet-pulse {\n 0% { transform: scale(1); opacity: 0.25; }\n 70% { transform: scale(1.65); opacity: 0.05; }\n 100% { transform: scale(1.65); opacity: 0; }\n }\n `}</style>\n </div>\n );\n};\n\nexport default WalletSuccessAnimation;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { __awaiter, __generator } from '../../node_modules/tslib/tslib.es6.js';
|
|
2
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
+
import { useRef, useState, useMemo, useEffect } from 'react';
|
|
4
|
+
import QRCode from 'qrcode';
|
|
5
|
+
import { useI18n } from '../../hooks/useI18n.js';
|
|
6
|
+
import { useWalletSseStatus } from '../../hooks/useWalletSseStatus.js';
|
|
7
|
+
import { getBaseURL } from '../../services/api.js';
|
|
8
|
+
import { startWalletVerification } from '../../services/sessionService.js';
|
|
9
|
+
import { isMobileDevice } from '../../utils/isMobileDevice.js';
|
|
10
|
+
import MobilePageLayout from '../ui/MobilePageLayout.js';
|
|
11
|
+
import Button from '../ui/Button.js';
|
|
12
|
+
import Title from '../ui/Title.js';
|
|
13
|
+
import Subtitle from '../ui/Subtitle.js';
|
|
14
|
+
import WalletSuccessAnimation from './WalletSuccessAnimation.js';
|
|
15
|
+
|
|
16
|
+
var WalletVerificationStep = function (_a) {
|
|
17
|
+
var sessionId = _a.sessionId, nodeId = _a.nodeId, credentialType = _a.credentialType, walletMode = _a.walletMode, minimumAge = _a.minimumAge, onCompleted = _a.onCompleted, onFailedOrDeclined = _a.onFailedOrDeclined, pageTitle = _a.pageTitle, pageDescription = _a.pageDescription;
|
|
18
|
+
var t = useI18n().t;
|
|
19
|
+
var canvasRef = useRef(null);
|
|
20
|
+
var _b = useState(null), qrError = _b[0], setQrError = _b[1];
|
|
21
|
+
var _c = useState(null), deepLink = _c[0], setDeepLink = _c[1];
|
|
22
|
+
var _d = useState(null), startError = _d[0], setStartError = _d[1];
|
|
23
|
+
var isMobile = useMemo(function () { return isMobileDevice(); }, []);
|
|
24
|
+
var apiBaseUrl = useMemo(function () { return getBaseURL(); }, []);
|
|
25
|
+
useEffect(function () {
|
|
26
|
+
var cancelled = false;
|
|
27
|
+
(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
28
|
+
var result, error_1;
|
|
29
|
+
return __generator(this, function (_a) {
|
|
30
|
+
switch (_a.label) {
|
|
31
|
+
case 0:
|
|
32
|
+
_a.trys.push([0, 2, , 3]);
|
|
33
|
+
return [4 /*yield*/, startWalletVerification(sessionId, {
|
|
34
|
+
nodeId: nodeId,
|
|
35
|
+
credentialType: credentialType,
|
|
36
|
+
minimumAge: minimumAge,
|
|
37
|
+
})];
|
|
38
|
+
case 1:
|
|
39
|
+
result = _a.sent();
|
|
40
|
+
if (!cancelled)
|
|
41
|
+
setDeepLink(result.deepLink);
|
|
42
|
+
return [3 /*break*/, 3];
|
|
43
|
+
case 2:
|
|
44
|
+
error_1 = _a.sent();
|
|
45
|
+
console.error("Failed to start wallet verification:", error_1);
|
|
46
|
+
if (!cancelled) {
|
|
47
|
+
setStartError(t("wallet.verification.start_failed", "Impossible de démarrer la vérification par wallet."));
|
|
48
|
+
}
|
|
49
|
+
return [3 /*break*/, 3];
|
|
50
|
+
case 3: return [2 /*return*/];
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}); })();
|
|
54
|
+
return function () {
|
|
55
|
+
cancelled = true;
|
|
56
|
+
};
|
|
57
|
+
}, [sessionId, nodeId, credentialType, minimumAge, t]);
|
|
58
|
+
var status = useWalletSseStatus({
|
|
59
|
+
sessionId: sessionId,
|
|
60
|
+
apiBaseUrl: apiBaseUrl,
|
|
61
|
+
onCompleted: onCompleted,
|
|
62
|
+
}).status;
|
|
63
|
+
// Sur mobile : ouvrir directement l'app wallet via le deep-link openid4vp://,
|
|
64
|
+
// une seule fois, tant que la vérification n'a pas progressé.
|
|
65
|
+
var hasRedirectedRef = useRef(false);
|
|
66
|
+
useEffect(function () {
|
|
67
|
+
if (!isMobile || !deepLink || status !== "pending" || hasRedirectedRef.current)
|
|
68
|
+
return;
|
|
69
|
+
hasRedirectedRef.current = true;
|
|
70
|
+
window.location.assign(deepLink);
|
|
71
|
+
}, [isMobile, deepLink, status]);
|
|
72
|
+
useEffect(function () {
|
|
73
|
+
if (isMobile)
|
|
74
|
+
return; // pas de QR sur mobile (redirection directe)
|
|
75
|
+
if (!deepLink || status !== "pending")
|
|
76
|
+
return;
|
|
77
|
+
var generate = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
78
|
+
var dataUrl, canvas_1, ctx_1, img_1;
|
|
79
|
+
return __generator(this, function (_b) {
|
|
80
|
+
switch (_b.label) {
|
|
81
|
+
case 0:
|
|
82
|
+
if (!canvasRef.current)
|
|
83
|
+
return [2 /*return*/];
|
|
84
|
+
setQrError(null);
|
|
85
|
+
_b.label = 1;
|
|
86
|
+
case 1:
|
|
87
|
+
_b.trys.push([1, 3, , 4]);
|
|
88
|
+
return [4 /*yield*/, QRCode.toDataURL(deepLink, {
|
|
89
|
+
width: 256,
|
|
90
|
+
margin: 2,
|
|
91
|
+
color: { dark: "#000000", light: "#FFFFFF" },
|
|
92
|
+
})];
|
|
93
|
+
case 2:
|
|
94
|
+
dataUrl = _b.sent();
|
|
95
|
+
canvas_1 = canvasRef.current;
|
|
96
|
+
ctx_1 = canvas_1.getContext("2d");
|
|
97
|
+
if (ctx_1) {
|
|
98
|
+
img_1 = new Image();
|
|
99
|
+
img_1.onload = function () {
|
|
100
|
+
canvas_1.width = img_1.width;
|
|
101
|
+
canvas_1.height = img_1.height;
|
|
102
|
+
ctx_1.drawImage(img_1, 0, 0);
|
|
103
|
+
};
|
|
104
|
+
img_1.src = dataUrl;
|
|
105
|
+
}
|
|
106
|
+
return [3 /*break*/, 4];
|
|
107
|
+
case 3:
|
|
108
|
+
_b.sent();
|
|
109
|
+
setQrError(t("qr_code.generation_failed", "Erreur de génération du QR code"));
|
|
110
|
+
return [3 /*break*/, 4];
|
|
111
|
+
case 4: return [2 /*return*/];
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}); };
|
|
115
|
+
generate();
|
|
116
|
+
}, [deepLink, status, t, isMobile]);
|
|
117
|
+
var title = pageTitle || t("wallet.verification.page_title", "Identification par wallet");
|
|
118
|
+
var subtitle = pageDescription ||
|
|
119
|
+
t("wallet.verification.page_description", "Scannez le QR code ci-dessous avec votre wallet d'identité pour vous identifier en ligne.");
|
|
120
|
+
var declineLabel = walletMode === "walletOrPhoto"
|
|
121
|
+
? t("wallet.verification.continue_with_photo", "Continuer avec une photo")
|
|
122
|
+
: t("wallet.verification.skip", "Passer");
|
|
123
|
+
var footer = status === "failed" || startError ? (jsx(Button, { onClick: onFailedOrDeclined, children: declineLabel })) : null;
|
|
124
|
+
return (jsx(MobilePageLayout, { footer: footer, children: jsx("div", { className: "px-4 py-6 pt-11 md:px-8 md:py-8", children: jsxs("div", { className: "w-full max-w-md mx-auto space-y-6", children: [jsxs("div", { className: "text-center space-y-4 mt-16 md:mt-20", children: [jsx(Title, { className: "text-xl md:text-2xl lg:text-3xl", children: title }), jsx(Subtitle, { className: "text-sm md:text-base text-gray-600 leading-relaxed whitespace-pre-line", children: subtitle })] }), jsx("div", { className: "flex-1 flex justify-center items-center", children: startError ? (jsx("div", { className: "text-red-500 text-center p-4", "data-cy": "wallet-start-error", children: startError })) : status === "success" ? (jsx(WalletSuccessAnimation, {})) : status === "completed" ? (jsxs("div", { className: "flex flex-col items-center gap-4 p-8", children: [jsx("div", { className: "animate-spin w-10 h-10 border-2 border-gray-300 border-t-blue-500 rounded-full" }), jsx("p", { className: "text-sm text-gray-600", children: t("wallet.verification.verifying", "Vérification en cours…") })] })) : status === "failed" ? (jsx("div", { className: "w-full max-w-sm rounded-2xl border border-red-200 bg-red-50 p-6 text-center shadow-sm", "data-cy": "wallet-verification-failed", children: jsx("p", { className: "text-sm leading-relaxed text-red-700", children: t("wallet.verification.failed", "La vérification par wallet a échoué.") }) })) : qrError ? (jsx("div", { className: "text-red-500 text-center p-4", children: qrError })) : isMobile ? (jsxs("div", { className: "flex flex-col items-center gap-4 p-8 text-center", children: [jsx("div", { className: "animate-spin w-10 h-10 border-2 border-gray-300 border-t-blue-500 rounded-full" }), jsx("p", { className: "text-sm text-gray-600", children: t("wallet.verification.opening_app", "Ouverture du wallet…") }), deepLink && (jsx("a", { href: deepLink, className: "text-sm font-medium text-blue-600 underline", children: t("wallet.verification.open_app_link", "Ouvrir mon wallet") }))] })) : deepLink ? (jsx("div", { className: "bg-white p-4 rounded-lg shadow-lg border-2 border-gray-200", "data-cy": "wallet-qr-code", children: jsx("canvas", { ref: canvasRef }) })) : (jsx("div", { className: "flex flex-col items-center gap-4 p-8", children: jsx("div", { className: "animate-spin w-10 h-10 border-2 border-gray-300 border-t-blue-500 rounded-full" }) })) })] }) }) }));
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export { WalletVerificationStep as default };
|
|
128
|
+
//# sourceMappingURL=WalletVerificationStep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WalletVerificationStep.js","sources":["../../../../../src/components/wallet/WalletVerificationStep.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport QRCode from \"qrcode\";\nimport { useI18n } from \"../../hooks/useI18n\";\nimport { useWalletSseStatus } from \"../../hooks/useWalletSseStatus\";\nimport { getBaseURL } from \"../../services/api\";\nimport { startWalletVerification } from \"../../services/sessionService\";\nimport { isMobileDevice } from \"../../utils/isMobileDevice\";\nimport MobilePageLayout from \"../ui/MobilePageLayout\";\nimport Button from \"../ui/Button\";\nimport Title from \"../ui/Title\";\nimport Subtitle from \"../ui/Subtitle\";\nimport WalletSuccessAnimation from \"./WalletSuccessAnimation\";\n\nexport type WalletCredentialType =\n | \"pid\"\n | \"driving_license\"\n | \"vehicle_registration\"\n | \"age_verification\";\n\ninterface WalletVerificationStepProps {\n sessionId: string;\n nodeId: string;\n credentialType: WalletCredentialType;\n walletMode: \"walletOnly\" | \"walletOrPhoto\";\n minimumAge?: number;\n onCompleted: () => void;\n /** Échec de la vérification ou wallet non disponible — le parent décide de la\n * suite (fallback photo en walletOrPhoto, saut du nœud en walletOnly). */\n onFailedOrDeclined: () => void;\n pageTitle?: string;\n pageDescription?: string;\n}\n\nconst WalletVerificationStep: React.FC<WalletVerificationStepProps> = ({\n sessionId,\n nodeId,\n credentialType,\n walletMode,\n minimumAge,\n onCompleted,\n onFailedOrDeclined,\n pageTitle,\n pageDescription,\n}) => {\n const { t } = useI18n();\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const [qrError, setQrError] = useState<string | null>(null);\n const [deepLink, setDeepLink] = useState<string | null>(null);\n const [startError, setStartError] = useState<string | null>(null);\n const isMobile = useMemo(() => isMobileDevice(), []);\n const apiBaseUrl = useMemo(() => getBaseURL(), []);\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n try {\n const result = await startWalletVerification(sessionId, {\n nodeId,\n credentialType,\n minimumAge,\n });\n if (!cancelled) setDeepLink(result.deepLink);\n } catch (error) {\n console.error(\"Failed to start wallet verification:\", error);\n if (!cancelled) {\n setStartError(\n t(\n \"wallet.verification.start_failed\",\n \"Impossible de démarrer la vérification par wallet.\",\n ),\n );\n }\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [sessionId, nodeId, credentialType, minimumAge, t]);\n\n const { status } = useWalletSseStatus({\n sessionId,\n apiBaseUrl,\n onCompleted,\n });\n\n // Sur mobile : ouvrir directement l'app wallet via le deep-link openid4vp://,\n // une seule fois, tant que la vérification n'a pas progressé.\n const hasRedirectedRef = useRef(false);\n useEffect(() => {\n if (!isMobile || !deepLink || status !== \"pending\" || hasRedirectedRef.current) return;\n hasRedirectedRef.current = true;\n window.location.assign(deepLink);\n }, [isMobile, deepLink, status]);\n\n useEffect(() => {\n if (isMobile) return; // pas de QR sur mobile (redirection directe)\n if (!deepLink || status !== \"pending\") return;\n\n const generate = async () => {\n if (!canvasRef.current) return;\n setQrError(null);\n try {\n const dataUrl = await QRCode.toDataURL(deepLink, {\n width: 256,\n margin: 2,\n color: { dark: \"#000000\", light: \"#FFFFFF\" },\n });\n const canvas = canvasRef.current;\n const ctx = canvas.getContext(\"2d\");\n if (ctx) {\n const img = new Image();\n img.onload = () => {\n canvas.width = img.width;\n canvas.height = img.height;\n ctx.drawImage(img, 0, 0);\n };\n img.src = dataUrl;\n }\n } catch {\n setQrError(t(\"qr_code.generation_failed\", \"Erreur de génération du QR code\"));\n }\n };\n\n generate();\n }, [deepLink, status, t, isMobile]);\n\n const title = pageTitle || t(\"wallet.verification.page_title\", \"Identification par wallet\");\n const subtitle =\n pageDescription ||\n t(\n \"wallet.verification.page_description\",\n \"Scannez le QR code ci-dessous avec votre wallet d'identité pour vous identifier en ligne.\",\n );\n\n const declineLabel =\n walletMode === \"walletOrPhoto\"\n ? t(\"wallet.verification.continue_with_photo\", \"Continuer avec une photo\")\n : t(\"wallet.verification.skip\", \"Passer\");\n\n const footer =\n status === \"failed\" || startError ? (\n <Button onClick={onFailedOrDeclined}>\n {declineLabel}\n </Button>\n ) : null;\n\n return (\n <MobilePageLayout footer={footer}>\n <div className=\"px-4 py-6 pt-11 md:px-8 md:py-8\">\n <div className=\"w-full max-w-md mx-auto space-y-6\">\n <div className=\"text-center space-y-4 mt-16 md:mt-20\">\n <Title className=\"text-xl md:text-2xl lg:text-3xl\">{title}</Title>\n <Subtitle className=\"text-sm md:text-base text-gray-600 leading-relaxed whitespace-pre-line\">\n {subtitle}\n </Subtitle>\n </div>\n\n <div className=\"flex-1 flex justify-center items-center\">\n {startError ? (\n <div className=\"text-red-500 text-center p-4\" data-cy=\"wallet-start-error\">\n {startError}\n </div>\n ) : status === \"success\" ? (\n <WalletSuccessAnimation />\n ) : status === \"completed\" ? (\n <div className=\"flex flex-col items-center gap-4 p-8\">\n <div className=\"animate-spin w-10 h-10 border-2 border-gray-300 border-t-blue-500 rounded-full\" />\n <p className=\"text-sm text-gray-600\">\n {t(\"wallet.verification.verifying\", \"Vérification en cours…\")}\n </p>\n </div>\n ) : status === \"failed\" ? (\n <div\n className=\"w-full max-w-sm rounded-2xl border border-red-200 bg-red-50 p-6 text-center shadow-sm\"\n data-cy=\"wallet-verification-failed\"\n >\n <p className=\"text-sm leading-relaxed text-red-700\">\n {t(\n \"wallet.verification.failed\",\n \"La vérification par wallet a échoué.\",\n )}\n </p>\n </div>\n ) : qrError ? (\n <div className=\"text-red-500 text-center p-4\">{qrError}</div>\n ) : isMobile ? (\n <div className=\"flex flex-col items-center gap-4 p-8 text-center\">\n <div className=\"animate-spin w-10 h-10 border-2 border-gray-300 border-t-blue-500 rounded-full\" />\n <p className=\"text-sm text-gray-600\">\n {t(\"wallet.verification.opening_app\", \"Ouverture du wallet…\")}\n </p>\n {deepLink && (\n <a href={deepLink} className=\"text-sm font-medium text-blue-600 underline\">\n {t(\"wallet.verification.open_app_link\", \"Ouvrir mon wallet\")}\n </a>\n )}\n </div>\n ) : deepLink ? (\n <div\n className=\"bg-white p-4 rounded-lg shadow-lg border-2 border-gray-200\"\n data-cy=\"wallet-qr-code\"\n >\n <canvas ref={canvasRef} />\n </div>\n ) : (\n <div className=\"flex flex-col items-center gap-4 p-8\">\n <div className=\"animate-spin w-10 h-10 border-2 border-gray-300 border-t-blue-500 rounded-full\" />\n </div>\n )}\n </div>\n </div>\n </div>\n </MobilePageLayout>\n );\n};\n\nexport default WalletVerificationStep;\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { useState, useRef, useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
var SUCCESS_DISPLAY_DURATION_MS = 2500;
|
|
4
|
+
/**
|
|
5
|
+
* Polls the wallet (OID4VP) verification status via SSE — symmetric to
|
|
6
|
+
* useNfcSseStatus. The backend learns about the wallet response by polling
|
|
7
|
+
* Oid4vpService.getStatus() internally (cf.
|
|
8
|
+
* docs/WALLET_OID4VP_IMPLEMENTATION_PLAN.md §5.2/§7), so from the SDK's point
|
|
9
|
+
* of view this is the same "connect once, react to status pushes" contract.
|
|
10
|
+
*/
|
|
11
|
+
function useWalletSseStatus(_a) {
|
|
12
|
+
var sessionId = _a.sessionId, apiBaseUrl = _a.apiBaseUrl, onCompleted = _a.onCompleted;
|
|
13
|
+
var _b = useState("pending"), status = _b[0], setStatus = _b[1];
|
|
14
|
+
var onCompletedRef = useRef(onCompleted);
|
|
15
|
+
onCompletedRef.current = onCompleted;
|
|
16
|
+
useEffect(function () {
|
|
17
|
+
if (!sessionId || !apiBaseUrl)
|
|
18
|
+
return;
|
|
19
|
+
var url = "".concat(apiBaseUrl, "/session/sdk/").concat(sessionId, "/wallet-status");
|
|
20
|
+
var source = new EventSource(url);
|
|
21
|
+
source.onmessage = function (event) {
|
|
22
|
+
try {
|
|
23
|
+
var data = JSON.parse(event.data);
|
|
24
|
+
if (data.status === "verified") {
|
|
25
|
+
source.close();
|
|
26
|
+
setStatus("success");
|
|
27
|
+
setTimeout(function () {
|
|
28
|
+
setStatus("completed");
|
|
29
|
+
onCompletedRef.current();
|
|
30
|
+
}, SUCCESS_DISPLAY_DURATION_MS);
|
|
31
|
+
}
|
|
32
|
+
else if (data.status === "failed" ||
|
|
33
|
+
data.status === "skipped" ||
|
|
34
|
+
data.status === "pending") {
|
|
35
|
+
setStatus(data.status);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch (_a) {
|
|
39
|
+
// message malformé, on ignore
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
source.onerror = function () {
|
|
43
|
+
// EventSource reconnecte automatiquement — pas d'action requise
|
|
44
|
+
};
|
|
45
|
+
// Fermer le flux quand l'onglet/app se ferme ou passe en arrière-plan, sinon le SSE reste
|
|
46
|
+
// ouvert côté serveur (heartbeat + listener qui fuient). `pagehide` couvre la fermeture
|
|
47
|
+
// (plus fiable que `beforeunload` sur mobile) ; `visibilitychange` couvre le passage en fond.
|
|
48
|
+
var closeSource = function () { return source.close(); };
|
|
49
|
+
var closeOnHide = function () {
|
|
50
|
+
if (document.visibilityState === "hidden")
|
|
51
|
+
source.close();
|
|
52
|
+
};
|
|
53
|
+
window.addEventListener("pagehide", closeSource);
|
|
54
|
+
document.addEventListener("visibilitychange", closeOnHide);
|
|
55
|
+
return function () {
|
|
56
|
+
window.removeEventListener("pagehide", closeSource);
|
|
57
|
+
document.removeEventListener("visibilitychange", closeOnHide);
|
|
58
|
+
source.close();
|
|
59
|
+
};
|
|
60
|
+
}, [sessionId, apiBaseUrl]);
|
|
61
|
+
return { status: status };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { useWalletSseStatus };
|
|
65
|
+
//# sourceMappingURL=useWalletSseStatus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useWalletSseStatus.js","sources":["../../../../src/hooks/useWalletSseStatus.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\n\nexport type WalletStatus = \"pending\" | \"success\" | \"completed\" | \"failed\" | \"skipped\";\n\nconst SUCCESS_DISPLAY_DURATION_MS = 2500;\n\ninterface UseWalletSseStatusOptions {\n sessionId: string;\n apiBaseUrl: string;\n onCompleted: () => void;\n}\n\n/**\n * Polls the wallet (OID4VP) verification status via SSE — symmetric to\n * useNfcSseStatus. The backend learns about the wallet response by polling\n * Oid4vpService.getStatus() internally (cf.\n * docs/WALLET_OID4VP_IMPLEMENTATION_PLAN.md §5.2/§7), so from the SDK's point\n * of view this is the same \"connect once, react to status pushes\" contract.\n */\nexport function useWalletSseStatus({\n sessionId,\n apiBaseUrl,\n onCompleted,\n}: UseWalletSseStatusOptions) {\n const [status, setStatus] = useState<WalletStatus>(\"pending\");\n const onCompletedRef = useRef(onCompleted);\n onCompletedRef.current = onCompleted;\n\n useEffect(() => {\n if (!sessionId || !apiBaseUrl) return;\n\n const url = `${apiBaseUrl}/session/sdk/${sessionId}/wallet-status`;\n const source = new EventSource(url);\n\n source.onmessage = (event) => {\n try {\n const data = JSON.parse(event.data) as { status: string };\n if (data.status === \"verified\") {\n source.close();\n setStatus(\"success\");\n setTimeout(() => {\n setStatus(\"completed\");\n onCompletedRef.current();\n }, SUCCESS_DISPLAY_DURATION_MS);\n } else if (\n data.status === \"failed\" ||\n data.status === \"skipped\" ||\n data.status === \"pending\"\n ) {\n setStatus(data.status);\n }\n } catch {\n // message malformé, on ignore\n }\n };\n\n source.onerror = () => {\n // EventSource reconnecte automatiquement — pas d'action requise\n };\n\n // Fermer le flux quand l'onglet/app se ferme ou passe en arrière-plan, sinon le SSE reste\n // ouvert côté serveur (heartbeat + listener qui fuient). `pagehide` couvre la fermeture\n // (plus fiable que `beforeunload` sur mobile) ; `visibilitychange` couvre le passage en fond.\n const closeSource = () => source.close();\n const closeOnHide = () => {\n if (document.visibilityState === \"hidden\") source.close();\n };\n window.addEventListener(\"pagehide\", closeSource);\n document.addEventListener(\"visibilitychange\", closeOnHide);\n\n return () => {\n window.removeEventListener(\"pagehide\", closeSource);\n document.removeEventListener(\"visibilitychange\", closeOnHide);\n source.close();\n };\n }, [sessionId, apiBaseUrl]);\n\n return { status };\n}\n"],"names":[],"mappings":";;AAIA,IAAM,2BAA2B,GAAG,IAAI;AAQxC;;;;;;AAMG;AACG,SAAU,kBAAkB,CAAC,EAIP,EAAA;AAH1B,IAAA,IAAA,SAAS,eAAA,EACT,UAAU,GAAA,EAAA,CAAA,UAAA,EACV,WAAW,GAAA,EAAA,CAAA,WAAA;IAEL,IAAA,EAAA,GAAsB,QAAQ,CAAe,SAAS,CAAC,EAAtD,MAAM,GAAA,EAAA,CAAA,CAAA,CAAA,EAAE,SAAS,GAAA,EAAA,CAAA,CAAA,CAAqC;AAC7D,IAAA,IAAM,cAAc,GAAG,MAAM,CAAC,WAAW,CAAC;AAC1C,IAAA,cAAc,CAAC,OAAO,GAAG,WAAW;AAEpC,IAAA,SAAS,CAAC,YAAA;AACR,QAAA,IAAI,CAAC,SAAS,IAAI,CAAC,UAAU;YAAE;AAE/B,QAAA,IAAM,GAAG,GAAG,EAAA,CAAA,MAAA,CAAG,UAAU,EAAA,eAAA,CAAA,CAAA,MAAA,CAAgB,SAAS,mBAAgB;AAClE,QAAA,IAAM,MAAM,GAAG,IAAI,WAAW,CAAC,GAAG,CAAC;AAEnC,QAAA,MAAM,CAAC,SAAS,GAAG,UAAC,KAAK,EAAA;AACvB,YAAA,IAAI;gBACF,IAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAuB;AACzD,gBAAA,IAAI,IAAI,CAAC,MAAM,KAAK,UAAU,EAAE;oBAC9B,MAAM,CAAC,KAAK,EAAE;oBACd,SAAS,CAAC,SAAS,CAAC;AACpB,oBAAA,UAAU,CAAC,YAAA;wBACT,SAAS,CAAC,WAAW,CAAC;wBACtB,cAAc,CAAC,OAAO,EAAE;oBAC1B,CAAC,EAAE,2BAA2B,CAAC;gBACjC;AAAO,qBAAA,IACL,IAAI,CAAC,MAAM,KAAK,QAAQ;oBACxB,IAAI,CAAC,MAAM,KAAK,SAAS;AACzB,oBAAA,IAAI,CAAC,MAAM,KAAK,SAAS,EACzB;AACA,oBAAA,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC;gBACxB;YACF;AAAE,YAAA,OAAA,EAAA,EAAM;;YAER;AACF,QAAA,CAAC;QAED,MAAM,CAAC,OAAO,GAAG,YAAA;;AAEjB,QAAA,CAAC;;;;QAKD,IAAM,WAAW,GAAG,YAAA,EAAM,OAAA,MAAM,CAAC,KAAK,EAAE,CAAA,CAAd,CAAc;AACxC,QAAA,IAAM,WAAW,GAAG,YAAA;AAClB,YAAA,IAAI,QAAQ,CAAC,eAAe,KAAK,QAAQ;gBAAE,MAAM,CAAC,KAAK,EAAE;AAC3D,QAAA,CAAC;AACD,QAAA,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,WAAW,CAAC;AAChD,QAAA,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,WAAW,CAAC;QAE1D,OAAO,YAAA;AACL,YAAA,MAAM,CAAC,mBAAmB,CAAC,UAAU,EAAE,WAAW,CAAC;AACnD,YAAA,QAAQ,CAAC,mBAAmB,CAAC,kBAAkB,EAAE,WAAW,CAAC;YAC7D,MAAM,CAAC,KAAK,EAAE;AAChB,QAAA,CAAC;AACH,IAAA,CAAC,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;AAE3B,IAAA,OAAO,EAAE,MAAM,EAAA,MAAA,EAAE;AACnB;;;;"}
|
package/dist/esm/i18n/en.json.js
CHANGED
|
@@ -1069,6 +1069,35 @@ var inpi_verification = {
|
|
|
1069
1069
|
mismatch_correct: "Correct my entry",
|
|
1070
1070
|
mismatch_continue: "Continue anyway"
|
|
1071
1071
|
};
|
|
1072
|
+
var wallet = {
|
|
1073
|
+
proposal: {
|
|
1074
|
+
title: "Identify yourself with your identity wallet",
|
|
1075
|
+
subtitle: "A European identity wallet is available for this document. You can identify yourself online, without taking a photo.",
|
|
1076
|
+
use_wallet: "Use my wallet",
|
|
1077
|
+
decline_photo: "Continue with a photo",
|
|
1078
|
+
decline_no_wallet: "I don't have a wallet"
|
|
1079
|
+
},
|
|
1080
|
+
verification: {
|
|
1081
|
+
page_title: "Wallet identification",
|
|
1082
|
+
page_description: "Scan the QR code below with your identity wallet to identify yourself online.",
|
|
1083
|
+
opening_app: "Opening wallet…",
|
|
1084
|
+
open_app_link: "Open my wallet",
|
|
1085
|
+
verifying: "Verifying…",
|
|
1086
|
+
failed: "Wallet verification failed.",
|
|
1087
|
+
start_failed: "Unable to start wallet verification.",
|
|
1088
|
+
continue_with_photo: "Continue with a photo",
|
|
1089
|
+
skip: "Skip",
|
|
1090
|
+
success_title: "Identity verified",
|
|
1091
|
+
success_subtitle: "Wallet verification confirmed successfully"
|
|
1092
|
+
}
|
|
1093
|
+
};
|
|
1094
|
+
var age_control = {
|
|
1095
|
+
fallback: {
|
|
1096
|
+
title: "Age verification",
|
|
1097
|
+
subtitle: "This check will be completed automatically at the next step.",
|
|
1098
|
+
"continue": "Continue"
|
|
1099
|
+
}
|
|
1100
|
+
};
|
|
1072
1101
|
var enTranslations = {
|
|
1073
1102
|
start: start,
|
|
1074
1103
|
user_input_form: user_input_form,
|
|
@@ -1126,8 +1155,10 @@ var enTranslations = {
|
|
|
1126
1155
|
unissey: unissey,
|
|
1127
1156
|
signature: signature,
|
|
1128
1157
|
nfc_scan: nfc_scan,
|
|
1129
|
-
inpi_verification: inpi_verification
|
|
1158
|
+
inpi_verification: inpi_verification,
|
|
1159
|
+
wallet: wallet,
|
|
1160
|
+
age_control: age_control
|
|
1130
1161
|
};
|
|
1131
1162
|
|
|
1132
|
-
export { CGU, LEGAL_CONSENT, before, before_verso, buttons, camera, custom_form, enTranslations as default, documentTypes, document_check, document_collection, document_upload, document_video, errors, id_check, inpi_verification, jdi, language_selection, loading, nfc_scan, orientation, pdf_generation, photo, powered_by, processing, qr_code, select_component, selfie, session, signature, start, start_verification, success, unissey, user_guidance, user_input_form, validation_points };
|
|
1163
|
+
export { CGU, LEGAL_CONSENT, age_control, before, before_verso, buttons, camera, custom_form, enTranslations as default, documentTypes, document_check, document_collection, document_upload, document_video, errors, id_check, inpi_verification, jdi, language_selection, loading, nfc_scan, orientation, pdf_generation, photo, powered_by, processing, qr_code, select_component, selfie, session, signature, start, start_verification, success, unissey, user_guidance, user_input_form, validation_points, wallet };
|
|
1133
1164
|
//# sourceMappingURL=en.json.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"en.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"en.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/esm/i18n/fr.json.js
CHANGED
|
@@ -1069,6 +1069,35 @@ var inpi_verification = {
|
|
|
1069
1069
|
mismatch_correct: "Corriger ma saisie",
|
|
1070
1070
|
mismatch_continue: "Continuer quand même"
|
|
1071
1071
|
};
|
|
1072
|
+
var wallet = {
|
|
1073
|
+
proposal: {
|
|
1074
|
+
title: "Identifiez-vous avec votre wallet d'identité",
|
|
1075
|
+
subtitle: "Un wallet d'identité européen est disponible pour ce document. Vous pouvez vous identifier en ligne, sans prendre de photo.",
|
|
1076
|
+
use_wallet: "Utiliser mon wallet",
|
|
1077
|
+
decline_photo: "Continuer avec une photo",
|
|
1078
|
+
decline_no_wallet: "Je n'ai pas de wallet"
|
|
1079
|
+
},
|
|
1080
|
+
verification: {
|
|
1081
|
+
page_title: "Identification par wallet",
|
|
1082
|
+
page_description: "Scannez le QR code ci-dessous avec votre wallet d'identité pour vous identifier en ligne.",
|
|
1083
|
+
opening_app: "Ouverture du wallet…",
|
|
1084
|
+
open_app_link: "Ouvrir mon wallet",
|
|
1085
|
+
verifying: "Vérification en cours…",
|
|
1086
|
+
failed: "La vérification par wallet a échoué.",
|
|
1087
|
+
start_failed: "Impossible de démarrer la vérification par wallet.",
|
|
1088
|
+
continue_with_photo: "Continuer avec une photo",
|
|
1089
|
+
skip: "Passer",
|
|
1090
|
+
success_title: "Identité vérifiée",
|
|
1091
|
+
success_subtitle: "Vérification par wallet confirmée avec succès"
|
|
1092
|
+
}
|
|
1093
|
+
};
|
|
1094
|
+
var age_control = {
|
|
1095
|
+
fallback: {
|
|
1096
|
+
title: "Vérification d'âge",
|
|
1097
|
+
subtitle: "Cette vérification sera complétée automatiquement à l'étape suivante.",
|
|
1098
|
+
"continue": "Continuer"
|
|
1099
|
+
}
|
|
1100
|
+
};
|
|
1072
1101
|
var frTranslations = {
|
|
1073
1102
|
start: start,
|
|
1074
1103
|
user_input_form: user_input_form,
|
|
@@ -1126,8 +1155,10 @@ var frTranslations = {
|
|
|
1126
1155
|
unissey: unissey,
|
|
1127
1156
|
signature: signature,
|
|
1128
1157
|
nfc_scan: nfc_scan,
|
|
1129
|
-
inpi_verification: inpi_verification
|
|
1158
|
+
inpi_verification: inpi_verification,
|
|
1159
|
+
wallet: wallet,
|
|
1160
|
+
age_control: age_control
|
|
1130
1161
|
};
|
|
1131
1162
|
|
|
1132
|
-
export { CGU, LEGAL_CONSENT, before, before_verso, buttons, camera, custom_form, frTranslations as default, documentTypes, document_check, document_collection, document_upload, document_video, errors, id_check, inpi_verification, jdi, language_selection, loading, nfc_scan, orientation, pdf_generation, photo, powered_by, processing, qr_code, select_component, selfie, session, signature, start, start_verification, success, unissey, user_guidance, user_input_form, validation_points };
|
|
1163
|
+
export { CGU, LEGAL_CONSENT, age_control, before, before_verso, buttons, camera, custom_form, frTranslations as default, documentTypes, document_check, document_collection, document_upload, document_video, errors, id_check, inpi_verification, jdi, language_selection, loading, nfc_scan, orientation, pdf_generation, photo, powered_by, processing, qr_code, select_component, selfie, session, signature, start, start_verification, success, unissey, user_guidance, user_input_form, validation_points, wallet };
|
|
1133
1164
|
//# sourceMappingURL=fr.json.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fr.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fr.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -101,6 +101,60 @@ var skipNfcWithReason = function (sessionId, payload) { return __awaiter(void 0,
|
|
|
101
101
|
}
|
|
102
102
|
});
|
|
103
103
|
}); };
|
|
104
|
+
/**
|
|
105
|
+
* Starts a wallet (OID4VP) verification for a journey node — cf.
|
|
106
|
+
* docs/WALLET_OID4VP_IMPLEMENTATION_PLAN.md §5.3/§7.
|
|
107
|
+
*
|
|
108
|
+
* @param sessionId - The unique identifier of the session
|
|
109
|
+
* @param payload - The node requesting the verification and the credential type to request
|
|
110
|
+
*/
|
|
111
|
+
var startWalletVerification = function (sessionId, payload) { return __awaiter(void 0, void 0, void 0, function () {
|
|
112
|
+
var response;
|
|
113
|
+
return __generator(this, function (_a) {
|
|
114
|
+
switch (_a.label) {
|
|
115
|
+
case 0: return [4 /*yield*/, apiService.post("/session/sdk/".concat(sessionId, "/wallet-request"), payload)];
|
|
116
|
+
case 1:
|
|
117
|
+
response = _a.sent();
|
|
118
|
+
return [2 /*return*/, response.data.data];
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}); };
|
|
122
|
+
/**
|
|
123
|
+
* Records the wallet fallback reason when the user declares they cannot/do not
|
|
124
|
+
* want to use their wallet, and marks the wallet verification as skipped
|
|
125
|
+
* server-side — symmetric to skipNfcWithReason.
|
|
126
|
+
*
|
|
127
|
+
* @param sessionId - The unique identifier of the session
|
|
128
|
+
* @param payload - The node concerned, the selected reason, and an optional comment
|
|
129
|
+
*/
|
|
130
|
+
var skipWalletWithReason = function (sessionId, payload) { return __awaiter(void 0, void 0, void 0, function () {
|
|
131
|
+
return __generator(this, function (_a) {
|
|
132
|
+
switch (_a.label) {
|
|
133
|
+
case 0: return [4 /*yield*/, apiService.post("/session/sdk/".concat(sessionId, "/wallet-skip"), payload)];
|
|
134
|
+
case 1:
|
|
135
|
+
_a.sent();
|
|
136
|
+
return [2 /*return*/];
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}); };
|
|
140
|
+
/**
|
|
141
|
+
* Fetches the wallets referentiel (public endpoint, no auth — cf.
|
|
142
|
+
* docs/WALLET_OID4VP_IMPLEMENTATION_PLAN.md §5.1), filtered by country and
|
|
143
|
+
* credential type, to decide whether to propose wallet identification.
|
|
144
|
+
*/
|
|
145
|
+
var fetchWallets = function (countryCode, credential) { return __awaiter(void 0, void 0, void 0, function () {
|
|
146
|
+
var response;
|
|
147
|
+
return __generator(this, function (_a) {
|
|
148
|
+
switch (_a.label) {
|
|
149
|
+
case 0: return [4 /*yield*/, apiService.get("/wallets", {
|
|
150
|
+
params: { countryCode: countryCode, credential: credential },
|
|
151
|
+
})];
|
|
152
|
+
case 1:
|
|
153
|
+
response = _a.sent();
|
|
154
|
+
return [2 /*return*/, response.data];
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
}); };
|
|
104
158
|
/**
|
|
105
159
|
* Updates session data with contact information
|
|
106
160
|
*
|
|
@@ -441,5 +495,5 @@ var getRunPrefillData = function (userInput, runIndex) {
|
|
|
441
495
|
return (_a = list[runIndex]) !== null && _a !== void 0 ? _a : null;
|
|
442
496
|
};
|
|
443
497
|
|
|
444
|
-
export { clearSessionSensitiveData, fetchSessionById, findOutgoingEdge, getNextStepIndex, getOrderedJourneySteps, getRunPrefillData, isSessionExpired, reconstructHistoryToStep, sendClientInfo, skipNfcWithReason, storeDocumentOptions, updateSessionContactInfo, updateSessionCurrentStep, updateSessionStatus, updateSessionUserInput };
|
|
498
|
+
export { clearSessionSensitiveData, fetchSessionById, fetchWallets, findOutgoingEdge, getNextStepIndex, getOrderedJourneySteps, getRunPrefillData, isSessionExpired, reconstructHistoryToStep, sendClientInfo, skipNfcWithReason, skipWalletWithReason, startWalletVerification, storeDocumentOptions, updateSessionContactInfo, updateSessionCurrentStep, updateSessionStatus, updateSessionUserInput };
|
|
445
499
|
//# sourceMappingURL=sessionService.js.map
|