@ollaid/native-sso 1.0.7 → 2.1.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/README.md +427 -66
- package/dist/components/LoginModal.d.ts +3 -1
- package/dist/components/PhoneInput.d.ts +1 -1
- package/dist/components/SignupModal.d.ts +3 -1
- package/dist/components/ui.d.ts +10 -0
- package/dist/hooks/useLogout.d.ts +41 -0
- package/dist/hooks/useMobileRegistration.d.ts +1 -1
- package/dist/hooks/useTokenHealthCheck.d.ts +11 -5
- package/dist/index.cjs +711 -407
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +711 -407
- package/dist/index.js.map +1 -1
- package/dist/services/api.d.ts +26 -0
- package/dist/services/nativeAuth.d.ts +1 -1
- package/dist/types/native.d.ts +5 -3
- package/dist/utils/countries.d.ts +1 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -127,8 +127,13 @@ function DialogContent({ children, className = "" }) {
|
|
|
127
127
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
128
128
|
"div",
|
|
129
129
|
{
|
|
130
|
-
style: {
|
|
131
|
-
|
|
130
|
+
style: {
|
|
131
|
+
position: "fixed",
|
|
132
|
+
inset: 0,
|
|
133
|
+
backgroundColor: "rgba(0,0,0,0.5)",
|
|
134
|
+
backdropFilter: "blur(4px)",
|
|
135
|
+
animation: "ollaid-overlay-in 0.25s ease-out"
|
|
136
|
+
}
|
|
132
137
|
}
|
|
133
138
|
),
|
|
134
139
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -141,19 +146,21 @@ function DialogContent({ children, className = "" }) {
|
|
|
141
146
|
width: "100%",
|
|
142
147
|
maxWidth: "28rem",
|
|
143
148
|
margin: "1rem",
|
|
144
|
-
padding: "
|
|
149
|
+
padding: "1rem",
|
|
145
150
|
borderRadius: "0.75rem",
|
|
146
151
|
backgroundColor: "white",
|
|
147
152
|
boxShadow: "0 25px 50px -12px rgba(0,0,0,0.25)",
|
|
148
153
|
maxHeight: "90vh",
|
|
149
|
-
|
|
154
|
+
display: "flex",
|
|
155
|
+
flexDirection: "column",
|
|
156
|
+
animation: "ollaid-modal-in 0.3s ease-out"
|
|
150
157
|
},
|
|
151
158
|
children: [
|
|
152
159
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
153
160
|
"button",
|
|
154
161
|
{
|
|
155
162
|
onClick: () => onOpenChange(false),
|
|
156
|
-
style: { position: "absolute", right: "
|
|
163
|
+
style: { position: "absolute", right: "0.75rem", top: "0.75rem", background: "none", border: "none", cursor: "pointer", fontSize: "1.25rem", color: "#9ca3af", lineHeight: 1, zIndex: 2 },
|
|
157
164
|
"aria-label": "Close",
|
|
158
165
|
children: "✕"
|
|
159
166
|
}
|
|
@@ -164,8 +171,14 @@ function DialogContent({ children, className = "" }) {
|
|
|
164
171
|
)
|
|
165
172
|
] });
|
|
166
173
|
}
|
|
174
|
+
function DialogBody({ children, className = "", style }) {
|
|
175
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { flex: 1, overflowY: "auto", paddingBottom: "0.5rem", minHeight: 0, ...style }, children });
|
|
176
|
+
}
|
|
177
|
+
function DialogFooter({ children, className = "", style }) {
|
|
178
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { flexShrink: 0, paddingTop: "0.75rem", borderTop: "1px solid #e5e7eb", display: "flex", flexDirection: "column", gap: "0.5rem", ...style }, children });
|
|
179
|
+
}
|
|
167
180
|
function DialogHeader({ children, className = "", style }) {
|
|
168
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { marginBottom: "0.5rem", ...style }, children });
|
|
181
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { marginBottom: "0.5rem", flexShrink: 0, ...style }, children });
|
|
169
182
|
}
|
|
170
183
|
function DialogTitle({ children, className = "" }) {
|
|
171
184
|
return /* @__PURE__ */ jsxRuntime.jsx("h2", { className, style: { fontSize: "1.25rem", fontWeight: 600, color: "#111827" }, children });
|
|
@@ -265,7 +278,7 @@ if (typeof document !== "undefined") {
|
|
|
265
278
|
if (!document.getElementById(styleId)) {
|
|
266
279
|
const style = document.createElement("style");
|
|
267
280
|
style.id = styleId;
|
|
268
|
-
style.textContent = `@keyframes spin { to { transform: rotate(360deg); } }`;
|
|
281
|
+
style.textContent = `@keyframes spin { to { transform: rotate(360deg); } } @keyframes ollaid-overlay-in { from { opacity: 0; } to { opacity: 1; } } @keyframes ollaid-modal-in { from { opacity: 0; transform: translateY(20px) scale(0.97); } to { opacity: 1; transform: translateY(0) scale(1); } }`;
|
|
269
282
|
document.head.appendChild(style);
|
|
270
283
|
}
|
|
271
284
|
}
|
|
@@ -483,7 +496,8 @@ const STORAGE = {
|
|
|
483
496
|
TOKEN: "token",
|
|
484
497
|
USER: "user",
|
|
485
498
|
ACCOUNT_TYPE: "account_type",
|
|
486
|
-
ALIAS_REFERENCE: "alias_reference"
|
|
499
|
+
ALIAS_REFERENCE: "alias_reference",
|
|
500
|
+
APP_ACCESS_TOKEN_REF: "app_access_token_ref"
|
|
487
501
|
};
|
|
488
502
|
const setAuthToken = (token) => {
|
|
489
503
|
if (typeof localStorage !== "undefined") {
|
|
@@ -502,8 +516,14 @@ const clearAuthToken = () => {
|
|
|
502
516
|
localStorage.removeItem(STORAGE.USER);
|
|
503
517
|
localStorage.removeItem(STORAGE.ACCOUNT_TYPE);
|
|
504
518
|
localStorage.removeItem(STORAGE.ALIAS_REFERENCE);
|
|
519
|
+
localStorage.removeItem(STORAGE.APP_ACCESS_TOKEN_REF);
|
|
505
520
|
}
|
|
506
521
|
};
|
|
522
|
+
const logout = async () => {
|
|
523
|
+
const { nativeAuthService: nativeAuthService2 } = await Promise.resolve().then(() => nativeAuth);
|
|
524
|
+
const token = getAuthToken();
|
|
525
|
+
return nativeAuthService2.logout(token || void 0);
|
|
526
|
+
};
|
|
507
527
|
const setAuthUser = (user) => {
|
|
508
528
|
if (typeof localStorage !== "undefined") {
|
|
509
529
|
localStorage.setItem(STORAGE.USER, JSON.stringify(user));
|
|
@@ -797,7 +817,7 @@ const nativeAuthService = {
|
|
|
797
817
|
);
|
|
798
818
|
},
|
|
799
819
|
async exchange(callbackToken) {
|
|
800
|
-
var _a;
|
|
820
|
+
var _a, _b;
|
|
801
821
|
const config2 = getNativeAuthConfig();
|
|
802
822
|
if (!config2.saasApiUrl) {
|
|
803
823
|
throw new ApiError("saasApiUrl non configurée", "unknown");
|
|
@@ -819,9 +839,16 @@ const nativeAuthService = {
|
|
|
819
839
|
if (response.user) {
|
|
820
840
|
setAuthUser(response.user);
|
|
821
841
|
}
|
|
842
|
+
if (response.app_access_token_ref && typeof localStorage !== "undefined") {
|
|
843
|
+
localStorage.setItem(STORAGE.APP_ACCESS_TOKEN_REF, response.app_access_token_ref);
|
|
844
|
+
}
|
|
845
|
+
const aliasRef = ((_a = response.user) == null ? void 0 : _a.alias_reference) || response.alias_reference;
|
|
846
|
+
if (aliasRef && typeof localStorage !== "undefined") {
|
|
847
|
+
localStorage.setItem(STORAGE.ALIAS_REFERENCE, aliasRef);
|
|
848
|
+
}
|
|
822
849
|
}
|
|
823
850
|
if (isDebugMode()) {
|
|
824
|
-
console.log("✅ [SaaS] Session établie:", { user: (
|
|
851
|
+
console.log("✅ [SaaS] Session établie:", { user: (_b = response.user) == null ? void 0 : _b.name });
|
|
825
852
|
}
|
|
826
853
|
return response;
|
|
827
854
|
},
|
|
@@ -842,7 +869,13 @@ const nativeAuthService = {
|
|
|
842
869
|
},
|
|
843
870
|
1e4
|
|
844
871
|
);
|
|
845
|
-
|
|
872
|
+
if (response.status === "connected" && response.user) {
|
|
873
|
+
return { valid: true, user: response.user };
|
|
874
|
+
}
|
|
875
|
+
if (response.success !== false) {
|
|
876
|
+
return { valid: true, user: response.user };
|
|
877
|
+
}
|
|
878
|
+
return { valid: false };
|
|
846
879
|
} catch (err) {
|
|
847
880
|
if (err instanceof ApiError && err.statusCode === 401) {
|
|
848
881
|
return { valid: false };
|
|
@@ -852,28 +885,53 @@ const nativeAuthService = {
|
|
|
852
885
|
},
|
|
853
886
|
async logout(token) {
|
|
854
887
|
const config2 = getNativeAuthConfig();
|
|
855
|
-
|
|
856
|
-
|
|
888
|
+
const iamToken = typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE.AUTH_TOKEN) || localStorage.getItem(STORAGE.TOKEN) : null;
|
|
889
|
+
const appAccessTokenRef = typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE.APP_ACCESS_TOKEN_REF) : null;
|
|
890
|
+
const promises = [];
|
|
891
|
+
if (config2.saasApiUrl && token) {
|
|
892
|
+
promises.push(
|
|
893
|
+
fetchWithTimeout(
|
|
894
|
+
`${config2.saasApiUrl}/native/logout`,
|
|
895
|
+
{
|
|
896
|
+
method: "POST",
|
|
897
|
+
headers: getHeaders(token, true)
|
|
898
|
+
},
|
|
899
|
+
config2.timeout || 3e4
|
|
900
|
+
).catch((err) => {
|
|
901
|
+
if (isDebugMode()) {
|
|
902
|
+
console.warn("⚠️ [SaaS] Échec logout (non-bloquant):", err instanceof Error ? err.message : err);
|
|
903
|
+
}
|
|
904
|
+
})
|
|
905
|
+
);
|
|
857
906
|
}
|
|
858
|
-
|
|
859
|
-
const
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
907
|
+
if (config2.iamApiUrl && (iamToken || appAccessTokenRef)) {
|
|
908
|
+
const payload = {};
|
|
909
|
+
if (iamToken) payload.sanctum_token = iamToken;
|
|
910
|
+
if (appAccessTokenRef) payload.app_access_token_ref = appAccessTokenRef;
|
|
911
|
+
promises.push(
|
|
912
|
+
fetchWithTimeout(
|
|
913
|
+
`${config2.iamApiUrl}/iam/disconnect`,
|
|
914
|
+
{
|
|
915
|
+
method: "POST",
|
|
916
|
+
headers: { "Content-Type": "application/json", "Accept": "application/json" },
|
|
917
|
+
body: JSON.stringify(payload)
|
|
918
|
+
},
|
|
919
|
+
5e3
|
|
920
|
+
).catch((err) => {
|
|
921
|
+
if (isDebugMode()) {
|
|
922
|
+
console.warn("⚠️ [IAM] Échec disconnect (non-bloquant):", err instanceof Error ? err.message : err);
|
|
923
|
+
}
|
|
924
|
+
})
|
|
866
925
|
);
|
|
867
|
-
clearAuthToken();
|
|
868
|
-
credentials = null;
|
|
869
|
-
credentialsLoadedAt = 0;
|
|
870
|
-
return response;
|
|
871
|
-
} catch {
|
|
872
|
-
clearAuthToken();
|
|
873
|
-
credentials = null;
|
|
874
|
-
credentialsLoadedAt = 0;
|
|
875
|
-
return { success: true };
|
|
876
926
|
}
|
|
927
|
+
await Promise.allSettled(promises);
|
|
928
|
+
if (isDebugMode()) {
|
|
929
|
+
console.log("✅ [Logout] Double revocation terminée — nettoyage local");
|
|
930
|
+
}
|
|
931
|
+
clearAuthToken();
|
|
932
|
+
credentials = null;
|
|
933
|
+
credentialsLoadedAt = 0;
|
|
934
|
+
return { success: true };
|
|
877
935
|
},
|
|
878
936
|
clearCredentials() {
|
|
879
937
|
credentials = null;
|
|
@@ -934,6 +992,10 @@ const nativeAuthService = {
|
|
|
934
992
|
return this.init(native_token);
|
|
935
993
|
}
|
|
936
994
|
};
|
|
995
|
+
const nativeAuth = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
996
|
+
__proto__: null,
|
|
997
|
+
nativeAuthService
|
|
998
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
937
999
|
function getIAMHeaders() {
|
|
938
1000
|
const creds = nativeAuthService.getCredentials();
|
|
939
1001
|
if (!creds) {
|
|
@@ -941,7 +1003,8 @@ function getIAMHeaders() {
|
|
|
941
1003
|
}
|
|
942
1004
|
return {
|
|
943
1005
|
"Content-Type": "application/json",
|
|
944
|
-
"Accept": "application/json"
|
|
1006
|
+
"Accept": "application/json",
|
|
1007
|
+
"X-IAM-App-Key": creds.appKey
|
|
945
1008
|
};
|
|
946
1009
|
}
|
|
947
1010
|
const mobilePasswordService = {
|
|
@@ -1429,7 +1492,7 @@ function PasswordRecoveryModal({ open, onOpenChange, onSuccess, saasApiUrl, iamA
|
|
|
1429
1492
|
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Mot de passe modifié !" }),
|
|
1430
1493
|
/* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: "Votre mot de passe a été changé avec succès." })
|
|
1431
1494
|
] }),
|
|
1432
|
-
/* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: handleBackToLogin, style: { width: "100%"
|
|
1495
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogFooter, { style: { borderTop: "none" }, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: handleBackToLogin, style: { width: "100%" }, children: "Retour à la connexion" }) })
|
|
1433
1496
|
] }) });
|
|
1434
1497
|
}
|
|
1435
1498
|
return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { children: [
|
|
@@ -1449,49 +1512,35 @@ function PasswordRecoveryModal({ open, onOpenChange, onSuccess, saasApiUrl, iamA
|
|
|
1449
1512
|
step === "password" && "Définissez votre nouveau mot de passe"
|
|
1450
1513
|
] })
|
|
1451
1514
|
] }),
|
|
1452
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
|
|
1515
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogBody, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "1rem" }, children: [
|
|
1453
1516
|
error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "0.75rem", borderRadius: "0.375rem", backgroundColor: C$3.redBg, color: C$3.red, fontSize: "0.875rem" }, children: error }),
|
|
1454
|
-
step === "email" && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1455
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1456
|
-
|
|
1457
|
-
/* @__PURE__ */ jsxRuntime.jsx(Input, { id: "recovery-email", type: "email", placeholder: "vous@exemple.com", value: email, onChange: (e) => setEmail(e.target.value), disabled: pwLoading })
|
|
1458
|
-
] }),
|
|
1459
|
-
/* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: handleEmailSubmit, disabled: pwLoading, style: { width: "100%" }, children: pwLoading ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
1460
|
-
/* @__PURE__ */ jsxRuntime.jsx(IconLoader2, { style: { width: "1rem", height: "1rem" } }),
|
|
1461
|
-
" Vérification..."
|
|
1462
|
-
] }) : "Continuer" }),
|
|
1463
|
-
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", onClick: handleBackToLogin, style: { width: "100%" }, children: "Retour à la connexion" })
|
|
1517
|
+
step === "email" && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1518
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "recovery-email", children: "Adresse email" }),
|
|
1519
|
+
/* @__PURE__ */ jsxRuntime.jsx(Input, { id: "recovery-email", type: "email", placeholder: "vous@exemple.com", value: email, onChange: (e) => setEmail(e.target.value), disabled: pwLoading })
|
|
1464
1520
|
] }),
|
|
1465
|
-
step === "method-choice" && /* @__PURE__ */ jsxRuntime.
|
|
1466
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1467
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1468
|
-
|
|
1469
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1470
|
-
|
|
1471
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "0.75rem", color: C$3.gray500 }, children: maskedEmail })
|
|
1472
|
-
] })
|
|
1473
|
-
] }),
|
|
1474
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.75rem", padding: "1rem", borderRadius: "0.5rem", border: `2px solid ${selectedMethod === "phone" ? C$3.primary : C$3.gray200}`, cursor: "pointer" }, onClick: () => setSelectedMethod("phone"), children: [
|
|
1475
|
-
/* @__PURE__ */ jsxRuntime.jsx(RadioGroupItem, { value: "phone", id: "method-phone" }),
|
|
1476
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1477
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontWeight: 500 }, children: "Par SMS" }),
|
|
1478
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "0.75rem", color: C$3.gray500 }, children: maskedPhone })
|
|
1479
|
-
] })
|
|
1521
|
+
step === "method-choice" && /* @__PURE__ */ jsxRuntime.jsx(RadioGroup, { value: selectedMethod, onValueChange: (v) => setSelectedMethod(v), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
|
|
1522
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.75rem", padding: "1rem", borderRadius: "0.5rem", border: `2px solid ${selectedMethod === "email" ? C$3.primary : C$3.gray200}`, cursor: "pointer" }, onClick: () => setSelectedMethod("email"), children: [
|
|
1523
|
+
/* @__PURE__ */ jsxRuntime.jsx(RadioGroupItem, { value: "email", id: "method-email" }),
|
|
1524
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1525
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontWeight: 500 }, children: "Par email" }),
|
|
1526
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "0.75rem", color: C$3.gray500 }, children: maskedEmail })
|
|
1480
1527
|
] })
|
|
1481
|
-
] })
|
|
1482
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1483
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1484
|
-
"
|
|
1485
|
-
|
|
1486
|
-
|
|
1528
|
+
] }),
|
|
1529
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.75rem", padding: "1rem", borderRadius: "0.5rem", border: `2px solid ${selectedMethod === "phone" ? C$3.primary : C$3.gray200}`, cursor: "pointer" }, onClick: () => setSelectedMethod("phone"), children: [
|
|
1530
|
+
/* @__PURE__ */ jsxRuntime.jsx(RadioGroupItem, { value: "phone", id: "method-phone" }),
|
|
1531
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1532
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontWeight: 500 }, children: "Par SMS" }),
|
|
1533
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "0.75rem", color: C$3.gray500 }, children: maskedPhone })
|
|
1534
|
+
] })
|
|
1535
|
+
] })
|
|
1536
|
+
] }) }),
|
|
1487
1537
|
step === "otp" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1488
1538
|
/* @__PURE__ */ jsxRuntime.jsx(OTPInput, { value: otp, onChange: setOtp, disabled: pwLoading }),
|
|
1489
1539
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", fontSize: "0.875rem" }, children: resendCooldown > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: C$3.gray500 }, children: [
|
|
1490
1540
|
"Renvoyer dans ",
|
|
1491
1541
|
resendCooldown,
|
|
1492
1542
|
"s"
|
|
1493
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: { color: C$3.primary, background: "none", border: "none", cursor: "pointer", textDecoration: "underline" }, onClick: handleResendOTP, children: "Code non reçu ? Renvoyer" }) })
|
|
1494
|
-
/* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: handleOTPSubmit, disabled: otp.length !== 6, style: { width: "100%" }, children: "Vérifier" })
|
|
1543
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: { color: C$3.primary, background: "none", border: "none", cursor: "pointer", textDecoration: "underline" }, onClick: handleResendOTP, children: "Code non reçu ? Renvoyer" }) })
|
|
1495
1544
|
] }),
|
|
1496
1545
|
step === "password" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1497
1546
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
@@ -1501,17 +1550,31 @@ function PasswordRecoveryModal({ open, onOpenChange, onSuccess, saasApiUrl, iamA
|
|
|
1501
1550
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1502
1551
|
/* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Confirmer le mot de passe" }),
|
|
1503
1552
|
/* @__PURE__ */ jsxRuntime.jsx(Input, { type: "password", placeholder: "Retapez votre mot de passe", value: confirmPassword, onChange: (e) => setConfirmPassword(e.target.value), disabled: pwLoading })
|
|
1504
|
-
] })
|
|
1505
|
-
/* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: handlePasswordSubmit, disabled: pwLoading || !password || !confirmPassword, style: { width: "100%" }, children: pwLoading ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
1506
|
-
/* @__PURE__ */ jsxRuntime.jsx(IconLoader2, { style: { width: "1rem", height: "1rem" } }),
|
|
1507
|
-
" Modification..."
|
|
1508
|
-
] }) : "Modifier le mot de passe" })
|
|
1553
|
+
] })
|
|
1509
1554
|
] })
|
|
1555
|
+
] }) }),
|
|
1556
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogFooter, { children: [
|
|
1557
|
+
step === "email" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1558
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: handleEmailSubmit, disabled: pwLoading, style: { width: "100%" }, children: pwLoading ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
1559
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconLoader2, { style: { width: "1rem", height: "1rem" } }),
|
|
1560
|
+
" Vérification..."
|
|
1561
|
+
] }) : "Continuer" }),
|
|
1562
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", onClick: handleBackToLogin, style: { width: "100%" }, children: "Retour à la connexion" })
|
|
1563
|
+
] }),
|
|
1564
|
+
step === "method-choice" && /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: handleMethodSubmit, disabled: pwLoading, style: { width: "100%" }, children: pwLoading ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
1565
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconLoader2, { style: { width: "1rem", height: "1rem" } }),
|
|
1566
|
+
" Envoi..."
|
|
1567
|
+
] }) : "Envoyer le code" }),
|
|
1568
|
+
step === "otp" && /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: handleOTPSubmit, disabled: otp.length !== 6, style: { width: "100%" }, children: "Vérifier" }),
|
|
1569
|
+
step === "password" && /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: handlePasswordSubmit, disabled: pwLoading || !password || !confirmPassword, style: { width: "100%" }, children: pwLoading ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
1570
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconLoader2, { style: { width: "1rem", height: "1rem" } }),
|
|
1571
|
+
" Modification..."
|
|
1572
|
+
] }) : "Modifier le mot de passe" })
|
|
1510
1573
|
] })
|
|
1511
1574
|
] }) });
|
|
1512
1575
|
}
|
|
1513
|
-
const FIRST_CHECK_DELAY =
|
|
1514
|
-
const INTERVAL_DELAY =
|
|
1576
|
+
const FIRST_CHECK_DELAY = 60 * 1e3;
|
|
1577
|
+
const INTERVAL_DELAY = 2 * 60 * 1e3;
|
|
1515
1578
|
async function checkTokenValidity(saasApiUrl, token, debug) {
|
|
1516
1579
|
if (typeof navigator !== "undefined" && !navigator.onLine) {
|
|
1517
1580
|
if (debug) console.log("🔄 [HealthCheck] Offline — skip");
|
|
@@ -1531,7 +1594,7 @@ async function checkTokenValidity(saasApiUrl, token, debug) {
|
|
|
1531
1594
|
});
|
|
1532
1595
|
clearTimeout(timeoutId);
|
|
1533
1596
|
if (response.status === 401) {
|
|
1534
|
-
if (debug) console.log("🔄 [HealthCheck] Token invalide (401)");
|
|
1597
|
+
if (debug) console.log("🔄 [HealthCheck] Token invalide (401) — déconnexion");
|
|
1535
1598
|
return { valid: false };
|
|
1536
1599
|
}
|
|
1537
1600
|
if (!response.ok) {
|
|
@@ -1539,11 +1602,15 @@ async function checkTokenValidity(saasApiUrl, token, debug) {
|
|
|
1539
1602
|
throw new Error(`server_error_${response.status}`);
|
|
1540
1603
|
}
|
|
1541
1604
|
const data = await response.json();
|
|
1542
|
-
if (
|
|
1543
|
-
|
|
1544
|
-
valid: data.
|
|
1545
|
-
|
|
1546
|
-
|
|
1605
|
+
if (data.status === "connected" && data.user) {
|
|
1606
|
+
if (debug) console.log("🔄 [HealthCheck] Token valide ✅ — user_infos mis à jour");
|
|
1607
|
+
return { valid: true, user: data.user };
|
|
1608
|
+
}
|
|
1609
|
+
if (data.success !== false) {
|
|
1610
|
+
if (debug) console.log("🔄 [HealthCheck] Token valide ✅");
|
|
1611
|
+
return { valid: true, user: data.user };
|
|
1612
|
+
}
|
|
1613
|
+
return { valid: false };
|
|
1547
1614
|
} catch (error) {
|
|
1548
1615
|
clearTimeout(timeoutId);
|
|
1549
1616
|
if (error instanceof Error && error.message === "offline") {
|
|
@@ -1556,8 +1623,34 @@ async function checkTokenValidity(saasApiUrl, token, debug) {
|
|
|
1556
1623
|
throw error;
|
|
1557
1624
|
}
|
|
1558
1625
|
}
|
|
1626
|
+
function revokeOnIam(iamApiUrl, sanctumToken, debug) {
|
|
1627
|
+
try {
|
|
1628
|
+
const controller = new AbortController();
|
|
1629
|
+
setTimeout(() => controller.abort(), 5e3);
|
|
1630
|
+
const appAccessTokenRef = typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE.APP_ACCESS_TOKEN_REF) : null;
|
|
1631
|
+
const payload = { sanctum_token: sanctumToken };
|
|
1632
|
+
if (appAccessTokenRef) {
|
|
1633
|
+
payload.app_access_token_ref = appAccessTokenRef;
|
|
1634
|
+
}
|
|
1635
|
+
if (debug) {
|
|
1636
|
+
console.log("🔄 [HealthCheck] Revocation IAM:", { hasRef: !!appAccessTokenRef });
|
|
1637
|
+
}
|
|
1638
|
+
fetch(`${iamApiUrl}/iam/disconnect`, {
|
|
1639
|
+
method: "POST",
|
|
1640
|
+
headers: {
|
|
1641
|
+
"Content-Type": "application/json",
|
|
1642
|
+
"Accept": "application/json"
|
|
1643
|
+
},
|
|
1644
|
+
body: JSON.stringify(payload),
|
|
1645
|
+
signal: controller.signal
|
|
1646
|
+
}).catch(() => {
|
|
1647
|
+
if (debug) console.log("🔄 [HealthCheck] Échec revocation IAM (non-bloquant)");
|
|
1648
|
+
});
|
|
1649
|
+
} catch {
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1559
1652
|
function useTokenHealthCheck(options) {
|
|
1560
|
-
const { enabled, saasApiUrl, onTokenInvalid, onUserUpdated, debug = false } = options;
|
|
1653
|
+
const { enabled, saasApiUrl, iamApiUrl, onTokenInvalid, onUserUpdated, debug = false } = options;
|
|
1561
1654
|
const timerRef = react.useRef(null);
|
|
1562
1655
|
const intervalRef = react.useRef(null);
|
|
1563
1656
|
const enabledRef = react.useRef(enabled);
|
|
@@ -1574,15 +1667,19 @@ function useTokenHealthCheck(options) {
|
|
|
1574
1667
|
try {
|
|
1575
1668
|
const result = await checkTokenValidity(saasApiUrl, token, debug);
|
|
1576
1669
|
if (!result.valid) {
|
|
1670
|
+
if (iamApiUrl) {
|
|
1671
|
+
if (debug) console.log("🔄 [HealthCheck] Revocation IAM avec sanctum_token...");
|
|
1672
|
+
revokeOnIam(iamApiUrl, token, debug);
|
|
1673
|
+
}
|
|
1577
1674
|
callbacksRef.current.onTokenInvalid();
|
|
1578
1675
|
return;
|
|
1579
1676
|
}
|
|
1580
|
-
if (result.
|
|
1581
|
-
callbacksRef.current.onUserUpdated(result.
|
|
1677
|
+
if (result.user && callbacksRef.current.onUserUpdated) {
|
|
1678
|
+
callbacksRef.current.onUserUpdated(result.user);
|
|
1582
1679
|
}
|
|
1583
1680
|
} catch {
|
|
1584
1681
|
}
|
|
1585
|
-
}, [saasApiUrl, debug]);
|
|
1682
|
+
}, [saasApiUrl, iamApiUrl, debug]);
|
|
1586
1683
|
react.useEffect(() => {
|
|
1587
1684
|
if (timerRef.current) {
|
|
1588
1685
|
clearTimeout(timerRef.current);
|
|
@@ -1593,7 +1690,7 @@ function useTokenHealthCheck(options) {
|
|
|
1593
1690
|
intervalRef.current = null;
|
|
1594
1691
|
}
|
|
1595
1692
|
if (!enabled || !saasApiUrl) return;
|
|
1596
|
-
if (debug) console.log("🔄 [HealthCheck] Activé — premier check dans 2 min");
|
|
1693
|
+
if (debug) console.log("🔄 [HealthCheck] Activé — premier check dans 60s, puis toutes les 2 min");
|
|
1597
1694
|
timerRef.current = setTimeout(() => {
|
|
1598
1695
|
performCheck();
|
|
1599
1696
|
intervalRef.current = setInterval(performCheck, INTERVAL_DELAY);
|
|
@@ -1620,6 +1717,9 @@ function saveSession(exchangeResult, accountType) {
|
|
|
1620
1717
|
if (aliasRef) {
|
|
1621
1718
|
localStorage.setItem(STORAGE.ALIAS_REFERENCE, aliasRef);
|
|
1622
1719
|
}
|
|
1720
|
+
if (exchangeResult.app_access_token_ref) {
|
|
1721
|
+
localStorage.setItem(STORAGE.APP_ACCESS_TOKEN_REF, exchangeResult.app_access_token_ref);
|
|
1722
|
+
}
|
|
1623
1723
|
const acctType = typeof accountType === "string" ? accountType : "user";
|
|
1624
1724
|
localStorage.setItem(STORAGE.USER, JSON.stringify(userToStore));
|
|
1625
1725
|
localStorage.setItem(STORAGE.ACCOUNT_TYPE, acctType);
|
|
@@ -1631,6 +1731,7 @@ function clearSession() {
|
|
|
1631
1731
|
localStorage.removeItem(STORAGE.USER);
|
|
1632
1732
|
localStorage.removeItem(STORAGE.ACCOUNT_TYPE);
|
|
1633
1733
|
localStorage.removeItem(STORAGE.ALIAS_REFERENCE);
|
|
1734
|
+
localStorage.removeItem(STORAGE.APP_ACCESS_TOKEN_REF);
|
|
1634
1735
|
}
|
|
1635
1736
|
function getErrorMessage$1(err, context) {
|
|
1636
1737
|
if (err instanceof Error) {
|
|
@@ -1704,6 +1805,7 @@ function useNativeAuth(options) {
|
|
|
1704
1805
|
useTokenHealthCheck({
|
|
1705
1806
|
enabled: state.status === "completed" && state.user !== null,
|
|
1706
1807
|
saasApiUrl,
|
|
1808
|
+
iamApiUrl,
|
|
1707
1809
|
onTokenInvalid: handleTokenInvalid,
|
|
1708
1810
|
onUserUpdated: handleUserUpdated,
|
|
1709
1811
|
debug: isDebug
|
|
@@ -1873,7 +1975,7 @@ function useNativeAuth(options) {
|
|
|
1873
1975
|
await nativeAuthService.loadCredentials();
|
|
1874
1976
|
}
|
|
1875
1977
|
const response = await nativeAuthService.loginAccessOtp(otpCode);
|
|
1876
|
-
if (response.
|
|
1978
|
+
if ((response.needs_access || response.status === "needs_access") && response.process_token) {
|
|
1877
1979
|
setState((prev) => ({
|
|
1878
1980
|
...prev,
|
|
1879
1981
|
processToken: response.process_token,
|
|
@@ -2180,7 +2282,7 @@ function useNativeAuth(options) {
|
|
|
2180
2282
|
processToken: null
|
|
2181
2283
|
}));
|
|
2182
2284
|
}, [defaultAccountType]);
|
|
2183
|
-
const
|
|
2285
|
+
const logout2 = react.useCallback(async () => {
|
|
2184
2286
|
const token = localStorage.getItem(STORAGE.AUTH_TOKEN) || localStorage.getItem(STORAGE.TOKEN);
|
|
2185
2287
|
try {
|
|
2186
2288
|
if (token) {
|
|
@@ -2252,7 +2354,7 @@ function useNativeAuth(options) {
|
|
|
2252
2354
|
grantAccess,
|
|
2253
2355
|
resendOtp,
|
|
2254
2356
|
setSession,
|
|
2255
|
-
logout,
|
|
2357
|
+
logout: logout2,
|
|
2256
2358
|
reset,
|
|
2257
2359
|
clearError,
|
|
2258
2360
|
register,
|
|
@@ -2341,7 +2443,8 @@ function LoginModal({
|
|
|
2341
2443
|
iamApiUrl,
|
|
2342
2444
|
loading,
|
|
2343
2445
|
showSwitchToSignup = true,
|
|
2344
|
-
defaultAccountType
|
|
2446
|
+
defaultAccountType,
|
|
2447
|
+
initialPhone
|
|
2345
2448
|
}) {
|
|
2346
2449
|
const {
|
|
2347
2450
|
status,
|
|
@@ -2420,6 +2523,12 @@ function LoginModal({
|
|
|
2420
2523
|
react.useEffect(() => {
|
|
2421
2524
|
if (!open) resetState();
|
|
2422
2525
|
}, [open]);
|
|
2526
|
+
react.useEffect(() => {
|
|
2527
|
+
if (open && initialPhone) {
|
|
2528
|
+
setStep("phone-input");
|
|
2529
|
+
setPhone(initialPhone);
|
|
2530
|
+
}
|
|
2531
|
+
}, [open, initialPhone]);
|
|
2423
2532
|
const exchangeCallbackToken = async (callbackToken) => {
|
|
2424
2533
|
try {
|
|
2425
2534
|
const response = await nativeAuthService.exchange(callbackToken);
|
|
@@ -2576,23 +2685,25 @@ function LoginModal({
|
|
|
2576
2685
|
"."
|
|
2577
2686
|
] })
|
|
2578
2687
|
] }),
|
|
2579
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2580
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "1rem", backgroundColor: C$2.gray100, borderRadius: "0.5rem",
|
|
2688
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogBody, { children: [
|
|
2689
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "1rem", backgroundColor: C$2.gray100, borderRadius: "0.5rem", fontSize: "0.875rem", color: C$2.gray500 }, children: [
|
|
2581
2690
|
"Votre compte ",
|
|
2582
2691
|
/* @__PURE__ */ jsxRuntime.jsx("strong", { style: { color: C$2.primary }, children: "iam.ollaid.com" }),
|
|
2583
2692
|
" existe déjà. Cliquez sur Confirmer pour créer votre accès à ",
|
|
2584
2693
|
/* @__PURE__ */ jsxRuntime.jsx("strong", { style: { color: C$2.gray900 }, children: application.name }),
|
|
2585
2694
|
"."
|
|
2586
2695
|
] }),
|
|
2587
|
-
renderError()
|
|
2588
|
-
|
|
2696
|
+
renderError()
|
|
2697
|
+
] }),
|
|
2698
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogFooter, { children: [
|
|
2699
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: handleGrantAccess, disabled: isSubmitting, style: { width: "100%" }, children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
2589
2700
|
/* @__PURE__ */ jsxRuntime.jsx(IconLoader2, { style: { width: "1rem", height: "1rem" } }),
|
|
2590
2701
|
"Création en cours..."
|
|
2591
2702
|
] }) : "Confirmer la création de mon compte" }),
|
|
2592
2703
|
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "outline", onClick: () => {
|
|
2593
2704
|
resetAuth();
|
|
2594
2705
|
setStep("choice");
|
|
2595
|
-
}, disabled: isSubmitting, style: { width: "100%"
|
|
2706
|
+
}, disabled: isSubmitting, style: { width: "100%" }, children: "Annuler" })
|
|
2596
2707
|
] })
|
|
2597
2708
|
] }) : alternativeMethod ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2598
2709
|
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { style: { textAlign: "center" }, children: [
|
|
@@ -2600,21 +2711,21 @@ function LoginModal({
|
|
|
2600
2711
|
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Moyen de connexion désactivé" }),
|
|
2601
2712
|
/* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: "Vos identifiants sont corrects, mais vous avez désactivé ce moyen de connexion depuis votre compte IAM." })
|
|
2602
2713
|
] }),
|
|
2603
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2714
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogBody, { children: alternativeMethod.value && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "1rem", backgroundColor: C$2.gray100, borderRadius: "0.5rem" }, children: [
|
|
2715
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.875rem", color: C$2.gray500, marginBottom: "0.75rem" }, children: "Vous pouvez vous connecter avec :" }),
|
|
2716
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem", fontSize: "0.875rem", fontWeight: 500, color: C$2.gray900 }, children: [
|
|
2717
|
+
alternativeMethod.type === "phone" ? /* @__PURE__ */ jsxRuntime.jsx(IconPhone, { style: { width: "1rem", height: "1rem", color: C$2.primary } }) : /* @__PURE__ */ jsxRuntime.jsx(IconMail, { style: { width: "1rem", height: "1rem", color: C$2.primary } }),
|
|
2718
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: alternativeMethod.value })
|
|
2719
|
+
] })
|
|
2720
|
+
] }) }),
|
|
2721
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogFooter, { children: [
|
|
2611
2722
|
/* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => {
|
|
2612
2723
|
if (alternativeMethod.type === "phone") setStep("phone-input");
|
|
2613
2724
|
else setStep("email-check");
|
|
2614
2725
|
resetAuth();
|
|
2615
2726
|
}, style: { width: "100%" }, children: alternativeMethod.type === "phone" ? "Se connecter par téléphone" : "Se connecter par email" }),
|
|
2616
|
-
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "outline", onClick: () => window.open("https://iam.ollaid.com", "_blank"), style: { width: "100%"
|
|
2617
|
-
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", onClick: () => onOpenChange(false), style: { width: "100%"
|
|
2727
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "outline", onClick: () => window.open("https://iam.ollaid.com", "_blank"), style: { width: "100%" }, children: "Réactiver depuis iam.ollaid.com" }),
|
|
2728
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", onClick: () => onOpenChange(false), style: { width: "100%" }, children: "Annuler" })
|
|
2618
2729
|
] })
|
|
2619
2730
|
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2620
2731
|
step !== "choice" && renderBackBtn(),
|
|
@@ -2624,7 +2735,7 @@ function LoginModal({
|
|
|
2624
2735
|
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Connexion" }),
|
|
2625
2736
|
/* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: "Choisissez votre méthode de connexion" })
|
|
2626
2737
|
] }),
|
|
2627
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
|
|
2738
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogBody, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
|
|
2628
2739
|
renderError(),
|
|
2629
2740
|
/* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "outline", onClick: () => setStep("email-check"), style: methodBtnStyle, children: [
|
|
2630
2741
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: methodIconStyle(C$2.accent), children: /* @__PURE__ */ jsxRuntime.jsx(IconMail, { style: { width: "1.25rem", height: "1.25rem", color: C$2.white } }) }),
|
|
@@ -2659,7 +2770,7 @@ function LoginModal({
|
|
|
2659
2770
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C$2.gray500 }, children: "Pas encore de compte ? " }),
|
|
2660
2771
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: linkStyle$1, onClick: onSwitchToSignup, children: "Inscrivez-vous" })
|
|
2661
2772
|
] })
|
|
2662
|
-
] })
|
|
2773
|
+
] }) })
|
|
2663
2774
|
] }),
|
|
2664
2775
|
step === "email-check" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2665
2776
|
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { style: { textAlign: "center" }, children: [
|
|
@@ -2667,7 +2778,7 @@ function LoginModal({
|
|
|
2667
2778
|
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Connexion par email" }),
|
|
2668
2779
|
/* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: "Entrez votre adresse email" })
|
|
2669
2780
|
] }),
|
|
2670
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
|
|
2781
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogBody, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "1rem" }, children: [
|
|
2671
2782
|
renderError(),
|
|
2672
2783
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.25rem" }, children: [
|
|
2673
2784
|
/* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "email", children: "Adresse email" }),
|
|
@@ -2689,7 +2800,9 @@ function LoginModal({
|
|
|
2689
2800
|
}
|
|
2690
2801
|
)
|
|
2691
2802
|
] }),
|
|
2692
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "right" }, children: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: { ...linkStyle$1, fontSize: "0.75rem" }, onClick: () => setShowPasswordRecovery(true), children: "Mot de passe oublié ?" }) })
|
|
2803
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "right" }, children: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: { ...linkStyle$1, fontSize: "0.75rem" }, onClick: () => setShowPasswordRecovery(true), children: "Mot de passe oublié ?" }) })
|
|
2804
|
+
] }) }),
|
|
2805
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogFooter, { children: [
|
|
2693
2806
|
renderLoaderBtn("Continuer", "Vérification...", handleEmailCheck, !email.trim()),
|
|
2694
2807
|
showSwitchToSignup && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center", fontSize: "0.875rem" }, children: [
|
|
2695
2808
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C$2.gray500 }, children: "Pas encore de compte ? " }),
|
|
@@ -2707,41 +2820,43 @@ function LoginModal({
|
|
|
2707
2820
|
] }),
|
|
2708
2821
|
/* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: email })
|
|
2709
2822
|
] }),
|
|
2710
|
-
/* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleEmailPasswordSubmit, style: {
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex",
|
|
2714
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2823
|
+
/* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleEmailPasswordSubmit, style: { display: "flex", flexDirection: "column", flex: 1, minHeight: 0 }, children: [
|
|
2824
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogBody, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "1rem" }, children: [
|
|
2825
|
+
renderError(),
|
|
2826
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.25rem" }, children: [
|
|
2827
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
|
|
2828
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "password", children: "Mot de passe" }),
|
|
2829
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: { ...linkStyle$1, fontSize: "0.75rem" }, onClick: () => setShowPasswordRecovery(true), children: "Mot de passe oublié ?" })
|
|
2830
|
+
] }),
|
|
2831
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative" }, children: [
|
|
2832
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2833
|
+
Input,
|
|
2834
|
+
{
|
|
2835
|
+
id: "password",
|
|
2836
|
+
type: showPassword ? "text" : "password",
|
|
2837
|
+
placeholder: "••••••••",
|
|
2838
|
+
value: password,
|
|
2839
|
+
onChange: (e) => setPassword(e.target.value),
|
|
2840
|
+
disabled: isSubmitting,
|
|
2841
|
+
style: { paddingRight: "2.5rem" }
|
|
2842
|
+
}
|
|
2843
|
+
),
|
|
2844
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2845
|
+
"button",
|
|
2846
|
+
{
|
|
2847
|
+
type: "button",
|
|
2848
|
+
onClick: () => setShowPassword(!showPassword),
|
|
2849
|
+
style: { position: "absolute", right: 0, top: 0, height: "100%", padding: "0 0.75rem", background: "none", border: "none", cursor: "pointer" },
|
|
2850
|
+
children: showPassword ? /* @__PURE__ */ jsxRuntime.jsx(IconEyeOff, { style: { width: "1rem", height: "1rem", color: C$2.gray500 } }) : /* @__PURE__ */ jsxRuntime.jsx(IconEye, { style: { width: "1rem", height: "1rem", color: C$2.gray500 } })
|
|
2851
|
+
}
|
|
2852
|
+
)
|
|
2853
|
+
] })
|
|
2739
2854
|
] })
|
|
2740
|
-
] }),
|
|
2741
|
-
/* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", disabled: isSubmitting || !password, style: { width: "100%" }, children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
2855
|
+
] }) }),
|
|
2856
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogFooter, { children: /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", disabled: isSubmitting || !password, style: { width: "100%" }, children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
2742
2857
|
/* @__PURE__ */ jsxRuntime.jsx(IconLoader2, { style: { width: "1rem", height: "1rem" } }),
|
|
2743
2858
|
"Connexion..."
|
|
2744
|
-
] }) : "Se connecter" })
|
|
2859
|
+
] }) : "Se connecter" }) })
|
|
2745
2860
|
] })
|
|
2746
2861
|
] }),
|
|
2747
2862
|
step === "email-otp" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -2754,12 +2869,12 @@ function LoginModal({
|
|
|
2754
2869
|
/* @__PURE__ */ jsxRuntime.jsx("strong", { style: { color: C$2.gray900 }, children: email })
|
|
2755
2870
|
] })
|
|
2756
2871
|
] }),
|
|
2757
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
|
|
2872
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogBody, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "1rem" }, children: [
|
|
2758
2873
|
renderError(),
|
|
2759
2874
|
/* @__PURE__ */ jsxRuntime.jsx(OTPInput, { value: emailOtpCode, onChange: setEmailOtpCode, disabled: isSubmitting }),
|
|
2760
|
-
renderResendLink()
|
|
2761
|
-
|
|
2762
|
-
|
|
2875
|
+
renderResendLink()
|
|
2876
|
+
] }) }),
|
|
2877
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogFooter, { children: renderLoaderBtn("Vérifier", "Vérification...", handleEmailOtpVerify, emailOtpCode.length !== 6) })
|
|
2763
2878
|
] }),
|
|
2764
2879
|
step === "phone-input" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2765
2880
|
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { style: { textAlign: "center" }, children: [
|
|
@@ -2767,7 +2882,7 @@ function LoginModal({
|
|
|
2767
2882
|
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Connexion par téléphone" }),
|
|
2768
2883
|
/* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: "Entrez votre numéro pour recevoir un code SMS" })
|
|
2769
2884
|
] }),
|
|
2770
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
|
|
2885
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogBody, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "1rem" }, children: [
|
|
2771
2886
|
renderError(),
|
|
2772
2887
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.25rem" }, children: [
|
|
2773
2888
|
/* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Indicatif" }),
|
|
@@ -2804,7 +2919,9 @@ function LoginModal({
|
|
|
2804
2919
|
phone.replace(/\D/g, "").length,
|
|
2805
2920
|
"/9)"
|
|
2806
2921
|
] })
|
|
2807
|
-
] })
|
|
2922
|
+
] })
|
|
2923
|
+
] }) }),
|
|
2924
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogFooter, { children: [
|
|
2808
2925
|
renderLoaderBtn("Recevoir le code SMS", "Envoi en cours...", handlePhoneInit, phone.replace(/\D/g, "").length !== 9),
|
|
2809
2926
|
showSwitchToSignup && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center", fontSize: "0.875rem" }, children: [
|
|
2810
2927
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C$2.gray500 }, children: "Pas encore de compte ? " }),
|
|
@@ -2827,12 +2944,12 @@ function LoginModal({
|
|
|
2827
2944
|
] })
|
|
2828
2945
|
] })
|
|
2829
2946
|
] }),
|
|
2830
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
|
|
2947
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogBody, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "1rem" }, children: [
|
|
2831
2948
|
renderError(),
|
|
2832
2949
|
/* @__PURE__ */ jsxRuntime.jsx(OTPInput, { value: phoneOtpCode, onChange: setPhoneOtpCode, disabled: isSubmitting }),
|
|
2833
|
-
renderResendLink()
|
|
2834
|
-
|
|
2835
|
-
|
|
2950
|
+
renderResendLink()
|
|
2951
|
+
] }) }),
|
|
2952
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogFooter, { children: renderLoaderBtn("Se connecter", "Vérification...", handlePhoneVerify, phoneOtpCode.length !== 6) })
|
|
2836
2953
|
] }),
|
|
2837
2954
|
step === "access-otp" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2838
2955
|
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { style: { textAlign: "center" }, children: [
|
|
@@ -2840,7 +2957,7 @@ function LoginModal({
|
|
|
2840
2957
|
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Code d'accès" }),
|
|
2841
2958
|
/* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: "Entrez le code d'accès à 8 chiffres" })
|
|
2842
2959
|
] }),
|
|
2843
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
|
|
2960
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogBody, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "1rem" }, children: [
|
|
2844
2961
|
renderError(),
|
|
2845
2962
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.25rem" }, children: [
|
|
2846
2963
|
/* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Code d'accès (8 chiffres)" }),
|
|
@@ -2857,9 +2974,9 @@ function LoginModal({
|
|
|
2857
2974
|
maxLength: 8
|
|
2858
2975
|
}
|
|
2859
2976
|
)
|
|
2860
|
-
] })
|
|
2861
|
-
|
|
2862
|
-
|
|
2977
|
+
] })
|
|
2978
|
+
] }) }),
|
|
2979
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogFooter, { children: renderLoaderBtn("Se connecter", "Vérification...", handleAccessOtpSubmit, accessOtpCode.length !== 8) })
|
|
2863
2980
|
] })
|
|
2864
2981
|
] }) }) }),
|
|
2865
2982
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3056,6 +3173,7 @@ const COUNTRIES = [
|
|
|
3056
3173
|
];
|
|
3057
3174
|
const DEFAULT_COUNTRY_CODE = "SN";
|
|
3058
3175
|
const DEFAULT_DIAL_CODE = "+221";
|
|
3176
|
+
const COUNTRIES_SORTED_BY_CODE = [...COUNTRIES].sort((a, b) => a.code.localeCompare(b.code));
|
|
3059
3177
|
const getCountryByCode = (code) => COUNTRIES.find((c) => c.code.toLowerCase() === code.toLowerCase());
|
|
3060
3178
|
const getCountryByDialCode = (dialCode) => COUNTRIES.find((c) => c.dialCode === dialCode);
|
|
3061
3179
|
const getDefaultCountry = () => COUNTRIES.find((c) => c.code === DEFAULT_COUNTRY_CODE);
|
|
@@ -3076,7 +3194,17 @@ function PhoneInput({
|
|
|
3076
3194
|
placeholder = "77 123 45 67",
|
|
3077
3195
|
lockCcphone = false
|
|
3078
3196
|
}) {
|
|
3079
|
-
const selectedCountry = getCountryByDialCode(ccphone) ||
|
|
3197
|
+
const selectedCountry = getCountryByDialCode(ccphone) || COUNTRIES_SORTED_BY_CODE[0];
|
|
3198
|
+
const [dropdownOpen, setDropdownOpen] = react.useState(false);
|
|
3199
|
+
const dropdownRef = react.useRef(null);
|
|
3200
|
+
react.useEffect(() => {
|
|
3201
|
+
if (!dropdownOpen) return;
|
|
3202
|
+
const handler = (e) => {
|
|
3203
|
+
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) setDropdownOpen(false);
|
|
3204
|
+
};
|
|
3205
|
+
document.addEventListener("mousedown", handler);
|
|
3206
|
+
return () => document.removeEventListener("mousedown", handler);
|
|
3207
|
+
}, [dropdownOpen]);
|
|
3080
3208
|
const handleChange = (e) => {
|
|
3081
3209
|
const cleaned = e.target.value.replace(/\D/g, "");
|
|
3082
3210
|
onChange(cleaned.slice(0, selectedCountry.digits));
|
|
@@ -3087,33 +3215,96 @@ function PhoneInput({
|
|
|
3087
3215
|
if (phone.length <= 7) return `${phone.slice(0, 2)} ${phone.slice(2, 5)} ${phone.slice(5)}`;
|
|
3088
3216
|
return `${phone.slice(0, 2)} ${phone.slice(2, 5)} ${phone.slice(5, 7)} ${phone.slice(7)}`;
|
|
3089
3217
|
};
|
|
3218
|
+
const handleSelect = (dialCode) => {
|
|
3219
|
+
if (onCcphoneChange) onCcphoneChange(dialCode);
|
|
3220
|
+
setDropdownOpen(false);
|
|
3221
|
+
};
|
|
3090
3222
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3091
3223
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
|
|
3092
3224
|
display: "flex",
|
|
3093
3225
|
alignItems: "center",
|
|
3094
3226
|
border: `2px solid ${error ? "#ef4444" : "#d1d5db"}`,
|
|
3095
3227
|
borderRadius: "0.5rem",
|
|
3096
|
-
overflow: "
|
|
3228
|
+
overflow: "visible",
|
|
3097
3229
|
opacity: disabled ? 0.5 : 1,
|
|
3098
|
-
backgroundColor: disabled ? "#f3f4f6" : "white"
|
|
3230
|
+
backgroundColor: disabled ? "#f3f4f6" : "white",
|
|
3231
|
+
position: "relative"
|
|
3099
3232
|
}, children: [
|
|
3100
|
-
onCcphoneChange && !lockCcphone ? /* @__PURE__ */ jsxRuntime.
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3233
|
+
onCcphoneChange && !lockCcphone ? /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: dropdownRef, style: { position: "relative" }, children: [
|
|
3234
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3235
|
+
"button",
|
|
3236
|
+
{
|
|
3237
|
+
type: "button",
|
|
3238
|
+
onClick: () => !disabled && setDropdownOpen(!dropdownOpen),
|
|
3239
|
+
disabled,
|
|
3240
|
+
style: {
|
|
3241
|
+
display: "flex",
|
|
3242
|
+
alignItems: "center",
|
|
3243
|
+
gap: "0.375rem",
|
|
3244
|
+
padding: "0.75rem",
|
|
3245
|
+
backgroundColor: "#f9fafb",
|
|
3246
|
+
borderRight: "1px solid #e5e7eb",
|
|
3247
|
+
border: "none",
|
|
3248
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
3249
|
+
fontWeight: 500,
|
|
3250
|
+
color: "#374151",
|
|
3251
|
+
fontSize: "0.9375rem",
|
|
3252
|
+
whiteSpace: "nowrap"
|
|
3253
|
+
},
|
|
3254
|
+
children: [
|
|
3255
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "1.125rem" }, children: selectedCountry.flag }),
|
|
3256
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: selectedCountry.dialCode }),
|
|
3257
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.625rem", marginLeft: "0.125rem" }, children: "▼" })
|
|
3258
|
+
]
|
|
3259
|
+
}
|
|
3260
|
+
),
|
|
3261
|
+
dropdownOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
|
|
3262
|
+
position: "absolute",
|
|
3263
|
+
top: "100%",
|
|
3264
|
+
left: 0,
|
|
3265
|
+
zIndex: 50,
|
|
3266
|
+
backgroundColor: "white",
|
|
3267
|
+
border: "1px solid #d1d5db",
|
|
3268
|
+
borderRadius: "0.375rem",
|
|
3269
|
+
boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
|
|
3270
|
+
maxHeight: "15rem",
|
|
3271
|
+
overflowY: "auto",
|
|
3272
|
+
minWidth: "12rem",
|
|
3273
|
+
marginTop: "0.25rem"
|
|
3274
|
+
}, children: COUNTRIES_SORTED_BY_CODE.map((c) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3275
|
+
"button",
|
|
3276
|
+
{
|
|
3277
|
+
type: "button",
|
|
3278
|
+
onClick: () => handleSelect(c.dialCode),
|
|
3279
|
+
style: {
|
|
3280
|
+
display: "flex",
|
|
3281
|
+
alignItems: "center",
|
|
3282
|
+
gap: "0.5rem",
|
|
3283
|
+
width: "100%",
|
|
3284
|
+
padding: "0.5rem 0.75rem",
|
|
3285
|
+
border: "none",
|
|
3286
|
+
cursor: "pointer",
|
|
3287
|
+
fontSize: "0.875rem",
|
|
3288
|
+
backgroundColor: c.dialCode === ccphone ? "#f3f4f6" : "transparent",
|
|
3289
|
+
textAlign: "left"
|
|
3290
|
+
},
|
|
3291
|
+
onMouseEnter: (e) => e.currentTarget.style.backgroundColor = "#f3f4f6",
|
|
3292
|
+
onMouseLeave: (e) => e.currentTarget.style.backgroundColor = c.dialCode === ccphone ? "#f3f4f6" : "transparent",
|
|
3293
|
+
children: [
|
|
3294
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 600, color: "#374151", minWidth: "1.75rem" }, children: c.code }),
|
|
3295
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: c.flag }),
|
|
3296
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#6b7280" }, children: c.dialCode })
|
|
3297
|
+
]
|
|
3298
|
+
},
|
|
3299
|
+
`${c.code}-${c.dialCode}`
|
|
3300
|
+
)) })
|
|
3301
|
+
] }) : (
|
|
3302
|
+
/* Locked view: only flag + dialCode */
|
|
3303
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.375rem", padding: "0.75rem", backgroundColor: "#f9fafb", borderRight: "1px solid #e5e7eb" }, children: [
|
|
3304
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "1.125rem" }, children: selectedCountry.flag }),
|
|
3305
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 500, color: "#374151" }, children: selectedCountry.dialCode })
|
|
3306
|
+
] })
|
|
3307
|
+
),
|
|
3117
3308
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3118
3309
|
"input",
|
|
3119
3310
|
{
|
|
@@ -3416,6 +3607,18 @@ function useMobileRegistration(options) {
|
|
|
3416
3607
|
}));
|
|
3417
3608
|
return { success: false, error_type: response.error_type };
|
|
3418
3609
|
} catch (err) {
|
|
3610
|
+
if (err instanceof ApiError && err.statusCode === 409 && err.response) {
|
|
3611
|
+
const resp = err.response;
|
|
3612
|
+
if (resp.conflict) {
|
|
3613
|
+
setState((prev) => ({
|
|
3614
|
+
...prev,
|
|
3615
|
+
loading: false,
|
|
3616
|
+
error: resp.message || "Ce compte existe déjà",
|
|
3617
|
+
conflict: resp.conflict
|
|
3618
|
+
}));
|
|
3619
|
+
return { success: false, error_type: resp.error_type };
|
|
3620
|
+
}
|
|
3621
|
+
}
|
|
3419
3622
|
const message = getErrorMessage(err, "l'inscription");
|
|
3420
3623
|
setState((prev) => ({ ...prev, loading: false, error: message, conflict: null }));
|
|
3421
3624
|
return { success: false };
|
|
@@ -3561,6 +3764,7 @@ const C$1 = {
|
|
|
3561
3764
|
gray900: "#111827",
|
|
3562
3765
|
red: "#dc2626",
|
|
3563
3766
|
redBg: "#fef2f2",
|
|
3767
|
+
amber: "#f59e0b",
|
|
3564
3768
|
amberBg: "#fef3c7",
|
|
3565
3769
|
white: "#ffffff"
|
|
3566
3770
|
};
|
|
@@ -3653,12 +3857,14 @@ function SuccessOrbit() {
|
|
|
3653
3857
|
})
|
|
3654
3858
|
] });
|
|
3655
3859
|
}
|
|
3656
|
-
function SignupModal({ open, onOpenChange, onSwitchToLogin, onSignupSuccess, saasApiUrl, iamApiUrl, defaultAccountType }) {
|
|
3860
|
+
function SignupModal({ open, onOpenChange, onSwitchToLogin, onSignupSuccess, saasApiUrl, iamApiUrl, defaultAccountType, onSwitchToLoginWithPhone }) {
|
|
3861
|
+
var _a, _b, _c, _d, _e, _f;
|
|
3657
3862
|
const {
|
|
3658
3863
|
status,
|
|
3659
3864
|
formData,
|
|
3660
3865
|
loading: regLoading,
|
|
3661
3866
|
error: regError,
|
|
3867
|
+
conflict,
|
|
3662
3868
|
accountType,
|
|
3663
3869
|
setAccountType,
|
|
3664
3870
|
isPhoneOnly,
|
|
@@ -3670,6 +3876,7 @@ function SignupModal({ open, onOpenChange, onSwitchToLogin, onSignupSuccess, saa
|
|
|
3670
3876
|
reset: resetReg,
|
|
3671
3877
|
clearError
|
|
3672
3878
|
} = useMobileRegistration({ saasApiUrl, iamApiUrl });
|
|
3879
|
+
const [showPasswordRecovery, setShowPasswordRecovery] = react.useState(false);
|
|
3673
3880
|
const [step, setStep] = react.useState("intro");
|
|
3674
3881
|
const [otpCode, setOtpCode] = react.useState("");
|
|
3675
3882
|
const [password, setPassword] = react.useState("");
|
|
@@ -3722,31 +3929,35 @@ function SignupModal({ open, onOpenChange, onSwitchToLogin, onSignupSuccess, saa
|
|
|
3722
3929
|
}
|
|
3723
3930
|
};
|
|
3724
3931
|
const handleInfoSubmit = async (e) => {
|
|
3725
|
-
var
|
|
3932
|
+
var _a2, _b2, _c2, _d2, _e2, _f2, _g;
|
|
3726
3933
|
e.preventDefault();
|
|
3727
3934
|
setLocalError(null);
|
|
3728
3935
|
clearError();
|
|
3729
|
-
if (!((
|
|
3936
|
+
if (!((_a2 = formData.name) == null ? void 0 : _a2.trim())) {
|
|
3730
3937
|
setLocalError("Le nom est requis");
|
|
3731
3938
|
return;
|
|
3732
3939
|
}
|
|
3733
|
-
if (!isPhoneOnly && !((
|
|
3940
|
+
if (!isPhoneOnly && !((_b2 = formData.email) == null ? void 0 : _b2.trim())) {
|
|
3734
3941
|
setLocalError("L'adresse email est requise");
|
|
3735
3942
|
return;
|
|
3736
3943
|
}
|
|
3737
|
-
if (!((
|
|
3944
|
+
if (!((_c2 = formData.phone) == null ? void 0 : _c2.trim()) || (((_d2 = formData.phone) == null ? void 0 : _d2.length) || 0) < 6) {
|
|
3738
3945
|
setLocalError("Numéro de téléphone invalide");
|
|
3739
3946
|
return;
|
|
3740
3947
|
}
|
|
3948
|
+
if (formData.ccphone === "+221" && ((_e2 = formData.phone) == null ? void 0 : _e2.length) !== 9) {
|
|
3949
|
+
setLocalError("Le numéro sénégalais doit contenir exactement 9 chiffres");
|
|
3950
|
+
return;
|
|
3951
|
+
}
|
|
3741
3952
|
if (isPhoneOnly && formData.ccphone !== "+221") {
|
|
3742
3953
|
setLocalError("L'inscription par téléphone est réservée aux numéros sénégalais (+221)");
|
|
3743
3954
|
return;
|
|
3744
3955
|
}
|
|
3745
|
-
if (!((
|
|
3956
|
+
if (!((_f2 = formData.town) == null ? void 0 : _f2.trim())) {
|
|
3746
3957
|
setLocalError("La ville est requise");
|
|
3747
3958
|
return;
|
|
3748
3959
|
}
|
|
3749
|
-
if (!((
|
|
3960
|
+
if (!((_g = formData.country) == null ? void 0 : _g.trim())) {
|
|
3750
3961
|
setLocalError("Le pays est requis");
|
|
3751
3962
|
return;
|
|
3752
3963
|
}
|
|
@@ -3798,197 +4009,281 @@ function SignupModal({ open, onOpenChange, onSwitchToLogin, onSignupSuccess, saa
|
|
|
3798
4009
|
goToStep("info");
|
|
3799
4010
|
};
|
|
3800
4011
|
const renderError = () => error ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "0.75rem", borderRadius: "0.375rem", backgroundColor: C$1.redBg, color: C$1.red, fontSize: "0.875rem" }, children: error }) : null;
|
|
3801
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
3802
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "0.5rem", fontSize: "0.875rem", color: C$1.gray500, marginTop: "1rem" }, children: [
|
|
3810
|
-
/* @__PURE__ */ jsxRuntime.jsx(IconLoader2, { style: { width: "1rem", height: "1rem" } }),
|
|
3811
|
-
"Connexion automatique en cours..."
|
|
3812
|
-
] })
|
|
3813
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3814
|
-
step === "intro" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3815
|
-
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { style: { textAlign: "center" }, children: [
|
|
3816
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: iconCircle(C$1.accent + "1a", "4rem"), children: /* @__PURE__ */ jsxRuntime.jsx(IconShieldCheck, { style: { width: "2rem", height: "2rem", color: C$1.accent } }) }),
|
|
3817
|
-
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Ouvrez un compte Ollaid" }),
|
|
3818
|
-
/* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: "Un compte unique qui vous donne accès à toutes les applications" })
|
|
4012
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4013
|
+
/* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsx(DialogContent, { children: signupSuccess && signupData ? /* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { style: { textAlign: "center" }, children: [
|
|
4014
|
+
/* @__PURE__ */ jsxRuntime.jsx(SuccessOrbit, {}),
|
|
4015
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Félicitations !" }),
|
|
4016
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogDescription, { children: [
|
|
4017
|
+
"Votre compte a été créé avec succès. Bienvenue ",
|
|
4018
|
+
formData.name,
|
|
4019
|
+
" !"
|
|
3819
4020
|
] }),
|
|
3820
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
text
|
|
3824
|
-
] }, text)) }),
|
|
3825
|
-
/* @__PURE__ */ jsxRuntime.jsx(StepIndicator, { current: 1 }),
|
|
3826
|
-
/* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => goToStep("account-type"), style: { width: "100%", marginTop: "1rem" }, children: "Suivant →" }),
|
|
3827
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center", fontSize: "0.875rem", marginTop: "1rem" }, children: [
|
|
3828
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C$1.gray500 }, children: "Déjà un compte ? " }),
|
|
3829
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: linkStyle, onClick: onSwitchToLogin, children: "Connectez-vous" })
|
|
4021
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "0.5rem", fontSize: "0.875rem", color: C$1.gray500, marginTop: "1rem" }, children: [
|
|
4022
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconLoader2, { style: { width: "1rem", height: "1rem" } }),
|
|
4023
|
+
"Connexion automatique en cours..."
|
|
3830
4024
|
] })
|
|
3831
|
-
] }),
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
] }),
|
|
3838
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem", marginTop: "1rem" }, children: [
|
|
3839
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3840
|
-
"button",
|
|
3841
|
-
{
|
|
3842
|
-
type: "button",
|
|
3843
|
-
onClick: () => handleAccountTypeSelect("email"),
|
|
3844
|
-
style: { width: "100%", padding: "1rem", border: `2px solid ${C$1.gray200}`, borderRadius: "0.5rem", textAlign: "left", cursor: "pointer", background: C$1.white, display: "flex", alignItems: "center", gap: "0.75rem" },
|
|
3845
|
-
children: [
|
|
3846
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "2.5rem", height: "2.5rem", backgroundColor: C$1.accent, borderRadius: "0.5rem", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }, children: /* @__PURE__ */ jsxRuntime.jsx(IconMail, { style: { width: "1.25rem", height: "1.25rem", color: C$1.white } }) }),
|
|
3847
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3848
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontWeight: 600, color: C$1.gray900 }, children: "Email + Téléphone" }),
|
|
3849
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "0.875rem", color: C$1.gray500 }, children: "Compte complet" })
|
|
3850
|
-
] })
|
|
3851
|
-
]
|
|
3852
|
-
}
|
|
3853
|
-
),
|
|
3854
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3855
|
-
"button",
|
|
3856
|
-
{
|
|
3857
|
-
type: "button",
|
|
3858
|
-
onClick: () => handleAccountTypeSelect("phone-only"),
|
|
3859
|
-
style: { width: "100%", padding: "1rem", border: `2px solid ${C$1.gray200}`, borderRadius: "0.5rem", textAlign: "left", cursor: "pointer", background: C$1.white, display: "flex", alignItems: "center", gap: "0.75rem" },
|
|
3860
|
-
children: [
|
|
3861
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "2.5rem", height: "2.5rem", backgroundColor: C$1.accent, borderRadius: "0.5rem", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }, children: /* @__PURE__ */ jsxRuntime.jsx(IconSmartphone, { style: { width: "1.25rem", height: "1.25rem", color: C$1.white } }) }),
|
|
3862
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3863
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontWeight: 600, color: C$1.gray900 }, children: "Téléphone uniquement" }),
|
|
3864
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "0.875rem", color: C$1.gray500 }, children: "🇸🇳 Sénégal uniquement" })
|
|
3865
|
-
] })
|
|
3866
|
-
]
|
|
3867
|
-
}
|
|
3868
|
-
)
|
|
3869
|
-
] }),
|
|
3870
|
-
/* @__PURE__ */ jsxRuntime.jsx(StepIndicator, { current: 2 })
|
|
3871
|
-
] }),
|
|
3872
|
-
step === "info" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3873
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => goToStep("account-type"), style: backBtnStyle, type: "button", children: /* @__PURE__ */ jsxRuntime.jsx(IconArrowLeft, { style: { width: "1rem", height: "1rem" } }) }),
|
|
3874
|
-
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { style: { textAlign: "center" }, children: [
|
|
3875
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: iconCircle(C$1.primary + "1a"), children: /* @__PURE__ */ jsxRuntime.jsx(IconShieldCheck, { style: { width: "1.5rem", height: "1.5rem", color: C$1.primary } }) }),
|
|
3876
|
-
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Créer votre compte" })
|
|
3877
|
-
] }),
|
|
3878
|
-
isPhoneOnly && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "0.75rem", borderRadius: "0.375rem", backgroundColor: C$1.accent + "1a", color: C$1.accent, fontSize: "0.8125rem", marginTop: "0.5rem", textAlign: "center" }, children: "📱 Inscription par téléphone — 🇸🇳 Sénégal uniquement" }),
|
|
3879
|
-
!isPhoneOnly && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "0.75rem", borderRadius: "0.375rem", backgroundColor: C$1.amberBg, color: "#92400e", fontSize: "0.8125rem", marginTop: "0.5rem", textAlign: "center" }, children: "⚠️ Un code OTP sera envoyé par email pour vérification" }),
|
|
3880
|
-
/* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleInfoSubmit, style: { display: "flex", flexDirection: "column", gap: "0.75rem", marginTop: "0.75rem" }, children: [
|
|
3881
|
-
renderError(),
|
|
3882
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3883
|
-
/* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Nom complet" }),
|
|
3884
|
-
/* @__PURE__ */ jsxRuntime.jsx(Input, { placeholder: "Jean Dupont", value: formData.name || "", onChange: (e) => updateFormData({ name: e.target.value }), disabled: regLoading })
|
|
4025
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4026
|
+
step === "intro" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4027
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { style: { textAlign: "center" }, children: [
|
|
4028
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: iconCircle(C$1.accent + "1a", "4rem"), children: /* @__PURE__ */ jsxRuntime.jsx(IconShieldCheck, { style: { width: "2rem", height: "2rem", color: C$1.accent } }) }),
|
|
4029
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Ouvrez un compte Ollaid" }),
|
|
4030
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: "Un compte unique qui vous donne accès à toutes les applications" })
|
|
3885
4031
|
] }),
|
|
3886
|
-
|
|
3887
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3888
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4032
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogBody, { children: [
|
|
4033
|
+
/* @__PURE__ */ jsxRuntime.jsx(AppsLogoSlider, { iamApiUrl }),
|
|
4034
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem", fontSize: "0.875rem", color: C$1.gray500, margin: "0.75rem 0" }, children: ["Un seul compte pour toutes les applications", "Plus besoin de multiples mots de passe", "Connexion simplifiée et sécurisée"].map((text) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.75rem" }, children: [
|
|
4035
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconCheckCircle2, { style: { width: "1.25rem", height: "1.25rem", color: C$1.green, flexShrink: 0 } }),
|
|
4036
|
+
text
|
|
4037
|
+
] }, text)) }),
|
|
4038
|
+
/* @__PURE__ */ jsxRuntime.jsx(StepIndicator, { current: 1 })
|
|
3889
4039
|
] }),
|
|
3890
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3891
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3892
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4040
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogFooter, { children: [
|
|
4041
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => goToStep("account-type"), style: { width: "100%" }, children: "Suivant →" }),
|
|
4042
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center", fontSize: "0.875rem" }, children: [
|
|
4043
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C$1.gray500 }, children: "Déjà un compte ? " }),
|
|
4044
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: linkStyle, onClick: onSwitchToLogin, children: "Connectez-vous" })
|
|
4045
|
+
] })
|
|
4046
|
+
] })
|
|
4047
|
+
] }),
|
|
4048
|
+
step === "account-type" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4049
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => goToStep("intro"), style: backBtnStyle, type: "button", children: /* @__PURE__ */ jsxRuntime.jsx(IconArrowLeft, { style: { width: "1rem", height: "1rem" } }) }),
|
|
4050
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { style: { textAlign: "center" }, children: [
|
|
4051
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: iconCircle(C$1.gray100), children: /* @__PURE__ */ jsxRuntime.jsx(IconShieldCheck, { style: { width: "1.5rem", height: "1.5rem", color: C$1.primary } }) }),
|
|
4052
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Choisissez votre type de compte" })
|
|
3893
4053
|
] }),
|
|
3894
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3895
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3896
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3897
|
-
|
|
4054
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogBody, { children: [
|
|
4055
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
|
|
4056
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4057
|
+
"button",
|
|
4058
|
+
{
|
|
4059
|
+
type: "button",
|
|
4060
|
+
onClick: () => handleAccountTypeSelect("email"),
|
|
4061
|
+
style: { width: "100%", padding: "1rem", border: `2px solid ${C$1.gray200}`, borderRadius: "0.5rem", textAlign: "left", cursor: "pointer", background: C$1.white, display: "flex", alignItems: "center", gap: "0.75rem" },
|
|
4062
|
+
children: [
|
|
4063
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "2.5rem", height: "2.5rem", backgroundColor: C$1.accent, borderRadius: "0.5rem", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }, children: /* @__PURE__ */ jsxRuntime.jsx(IconMail, { style: { width: "1.25rem", height: "1.25rem", color: C$1.white } }) }),
|
|
4064
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4065
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontWeight: 600, color: C$1.gray900 }, children: "Email + Téléphone" }),
|
|
4066
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "0.875rem", color: C$1.gray500 }, children: "Compte complet" })
|
|
4067
|
+
] })
|
|
4068
|
+
]
|
|
4069
|
+
}
|
|
4070
|
+
),
|
|
4071
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4072
|
+
"button",
|
|
4073
|
+
{
|
|
4074
|
+
type: "button",
|
|
4075
|
+
onClick: () => handleAccountTypeSelect("phone-only"),
|
|
4076
|
+
style: { width: "100%", padding: "1rem", border: `2px solid ${C$1.gray200}`, borderRadius: "0.5rem", textAlign: "left", cursor: "pointer", background: C$1.white, display: "flex", alignItems: "center", gap: "0.75rem" },
|
|
4077
|
+
children: [
|
|
4078
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "2.5rem", height: "2.5rem", backgroundColor: C$1.accent, borderRadius: "0.5rem", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }, children: /* @__PURE__ */ jsxRuntime.jsx(IconSmartphone, { style: { width: "1.25rem", height: "1.25rem", color: C$1.white } }) }),
|
|
4079
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4080
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontWeight: 600, color: C$1.gray900 }, children: "Téléphone uniquement" }),
|
|
4081
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "0.875rem", color: C$1.gray500 }, children: "🇸🇳 Sénégal uniquement" })
|
|
4082
|
+
] })
|
|
4083
|
+
]
|
|
4084
|
+
}
|
|
4085
|
+
)
|
|
3898
4086
|
] }),
|
|
3899
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
4087
|
+
/* @__PURE__ */ jsxRuntime.jsx(StepIndicator, { current: 2 })
|
|
4088
|
+
] })
|
|
4089
|
+
] }),
|
|
4090
|
+
step === "info" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4091
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => goToStep("account-type"), style: backBtnStyle, type: "button", children: /* @__PURE__ */ jsxRuntime.jsx(IconArrowLeft, { style: { width: "1rem", height: "1rem" } }) }),
|
|
4092
|
+
conflict ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4093
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { style: { textAlign: "center" }, children: [
|
|
4094
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: iconCircle(C$1.amberBg), children: /* @__PURE__ */ jsxRuntime.jsx(IconShieldCheck, { style: { width: "1.5rem", height: "1.5rem", color: C$1.amber } }) }),
|
|
4095
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: conflict.type === "phone" ? "Numéro déjà utilisé" : "Email déjà utilisé" }),
|
|
4096
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogDescription, { children: [
|
|
4097
|
+
conflict.type === "phone" ? `Le numéro ${formData.ccphone || ""} ${formData.phone || ""} est déjà associé à un compte.` : `L'adresse ${formData.email || ""} est déjà associée à un compte.`,
|
|
4098
|
+
" ",
|
|
4099
|
+
"S'il s'agit du vôtre, connectez-vous."
|
|
4100
|
+
] })
|
|
4101
|
+
] }),
|
|
4102
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogFooter, { style: { borderTop: "none" }, children: [
|
|
4103
|
+
conflict.type === "phone" && formData.ccphone === "+221" && ((_a = conflict.options) == null ? void 0 : _a.can_login) && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4104
|
+
Button,
|
|
3903
4105
|
{
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
4106
|
+
onClick: () => {
|
|
4107
|
+
const fullPhone = formData.phone || "";
|
|
4108
|
+
if (onSwitchToLoginWithPhone) onSwitchToLoginWithPhone(fullPhone);
|
|
4109
|
+
else onSwitchToLogin();
|
|
3908
4110
|
},
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
c.name
|
|
3915
|
-
] }, c.code))
|
|
4111
|
+
style: { width: "100%" },
|
|
4112
|
+
children: [
|
|
4113
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconSmartphone, { style: { width: "1rem", height: "1rem" } }),
|
|
4114
|
+
"Se connecter par téléphone"
|
|
4115
|
+
]
|
|
3916
4116
|
}
|
|
3917
|
-
)
|
|
4117
|
+
),
|
|
4118
|
+
(conflict.type === "email" || conflict.type === "phone" && formData.ccphone !== "+221") && ((_b = conflict.options) == null ? void 0 : _b.can_login) && /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: onSwitchToLogin, style: { width: "100%" }, children: "Se connecter" }),
|
|
4119
|
+
!isPhoneOnly && (((_c = conflict.options) == null ? void 0 : _c.can_recover_by_email) || ((_d = conflict.options) == null ? void 0 : _d.can_recover_by_sms)) && /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "outline", onClick: () => setShowPasswordRecovery(true), style: { width: "100%" }, children: "Récupérer mon compte" }),
|
|
4120
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "outline", onClick: () => clearError(), style: { width: "100%" }, children: conflict.type === "phone" ? "Changer le numéro" : "Changer l'email" }),
|
|
4121
|
+
((_e = conflict.options) == null ? void 0 : _e.masked_email) && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "0.75rem", backgroundColor: C$1.gray100, borderRadius: "0.375rem", fontSize: "0.8125rem", color: C$1.gray500, textAlign: "center" }, children: [
|
|
4122
|
+
"Email lié : ",
|
|
4123
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { style: { color: C$1.gray900 }, children: conflict.options.masked_email })
|
|
4124
|
+
] }),
|
|
4125
|
+
((_f = conflict.options) == null ? void 0 : _f.masked_phone) && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "0.75rem", backgroundColor: C$1.gray100, borderRadius: "0.375rem", fontSize: "0.8125rem", color: C$1.gray500, textAlign: "center" }, children: [
|
|
4126
|
+
"Téléphone lié : ",
|
|
4127
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { style: { color: C$1.gray900 }, children: conflict.options.masked_phone })
|
|
4128
|
+
] })
|
|
3918
4129
|
] })
|
|
3919
|
-
] })
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
4130
|
+
] }) : (
|
|
4131
|
+
/* ---- NORMAL INFO FORM ---- */
|
|
4132
|
+
/* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4133
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { style: { textAlign: "center" }, children: [
|
|
4134
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: iconCircle(C$1.primary + "1a"), children: /* @__PURE__ */ jsxRuntime.jsx(IconShieldCheck, { style: { width: "1.5rem", height: "1.5rem", color: C$1.primary } }) }),
|
|
4135
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Créer votre compte" })
|
|
4136
|
+
] }),
|
|
4137
|
+
/* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleInfoSubmit, style: { display: "flex", flexDirection: "column", flex: 1, minHeight: 0 }, children: [
|
|
4138
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogBody, { children: [
|
|
4139
|
+
isPhoneOnly && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "0.75rem", borderRadius: "0.375rem", backgroundColor: C$1.accent + "1a", color: C$1.accent, fontSize: "0.8125rem", marginBottom: "0.5rem", textAlign: "center" }, children: "📱 Inscription par téléphone — 🇸🇳 Sénégal uniquement" }),
|
|
4140
|
+
!isPhoneOnly && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "0.75rem", borderRadius: "0.375rem", backgroundColor: C$1.amberBg, color: "#92400e", fontSize: "0.8125rem", marginBottom: "0.5rem", textAlign: "center" }, children: "⚠️ Un code OTP sera envoyé par email pour vérification" }),
|
|
4141
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
|
|
4142
|
+
renderError(),
|
|
4143
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4144
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Label, { children: [
|
|
4145
|
+
"Nom complet ",
|
|
4146
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C$1.red }, children: "*" })
|
|
4147
|
+
] }),
|
|
4148
|
+
/* @__PURE__ */ jsxRuntime.jsx(Input, { placeholder: "Jean Dupont", value: formData.name || "", onChange: (e) => updateFormData({ name: e.target.value }), disabled: regLoading })
|
|
4149
|
+
] }),
|
|
4150
|
+
!isPhoneOnly && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4151
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Label, { children: [
|
|
4152
|
+
"Adresse email ",
|
|
4153
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C$1.red }, children: "*" })
|
|
4154
|
+
] }),
|
|
4155
|
+
/* @__PURE__ */ jsxRuntime.jsx(Input, { type: "email", placeholder: "vous@exemple.com", value: formData.email || "", onChange: (e) => updateFormData({ email: e.target.value }), disabled: regLoading })
|
|
4156
|
+
] }),
|
|
4157
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4158
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Label, { children: [
|
|
4159
|
+
"Numéro de téléphone ",
|
|
4160
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C$1.red }, children: "*" })
|
|
4161
|
+
] }),
|
|
4162
|
+
/* @__PURE__ */ jsxRuntime.jsx(PhoneInput, { value: formData.phone || "", onChange: (p) => updateFormData({ phone: p }), ccphone: formData.ccphone || "+221", onCcphoneChange: (c) => updateFormData({ ccphone: c }), disabled: regLoading, lockCcphone: isPhoneOnly })
|
|
4163
|
+
] }),
|
|
4164
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "0.75rem" }, children: [
|
|
4165
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4166
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Label, { children: [
|
|
4167
|
+
"Ville ",
|
|
4168
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C$1.red }, children: "*" })
|
|
4169
|
+
] }),
|
|
4170
|
+
/* @__PURE__ */ jsxRuntime.jsx(Input, { placeholder: "Dakar", value: formData.town || "", onChange: (e) => updateFormData({ town: e.target.value }), disabled: regLoading })
|
|
4171
|
+
] }),
|
|
4172
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4173
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Label, { children: [
|
|
4174
|
+
"Pays ",
|
|
4175
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C$1.red }, children: "*" })
|
|
4176
|
+
] }),
|
|
4177
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4178
|
+
"select",
|
|
4179
|
+
{
|
|
4180
|
+
value: formData.country || DEFAULT_COUNTRY_CODE,
|
|
4181
|
+
onChange: (e) => {
|
|
4182
|
+
const country = getCountryByCode(e.target.value);
|
|
4183
|
+
updateFormData({ country: e.target.value, ccphone: (country == null ? void 0 : country.dialCode) || "+221" });
|
|
4184
|
+
},
|
|
4185
|
+
disabled: regLoading || isPhoneOnly,
|
|
4186
|
+
style: { width: "100%", padding: "0.5rem", borderRadius: "0.375rem", border: "1px solid #d1d5db", backgroundColor: regLoading || isPhoneOnly ? "#f3f4f6" : "white", fontSize: "0.875rem" },
|
|
4187
|
+
children: COUNTRIES_SORTED_BY_CODE.map((c) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: c.code, children: [
|
|
4188
|
+
c.code,
|
|
4189
|
+
" ",
|
|
4190
|
+
c.flag,
|
|
4191
|
+
" ",
|
|
4192
|
+
c.name
|
|
4193
|
+
] }, c.code))
|
|
4194
|
+
}
|
|
4195
|
+
)
|
|
4196
|
+
] })
|
|
4197
|
+
] }),
|
|
4198
|
+
/* @__PURE__ */ jsxRuntime.jsx(StepIndicator, { current: 3 })
|
|
4199
|
+
] })
|
|
4200
|
+
] }),
|
|
4201
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogFooter, { children: /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", disabled: regLoading, style: { width: "100%" }, children: regLoading ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
4202
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconLoader2, { style: { width: "1rem", height: "1rem" } }),
|
|
4203
|
+
" Vérification..."
|
|
4204
|
+
] }) : "Continuer" }) })
|
|
4205
|
+
] })
|
|
4206
|
+
] })
|
|
4207
|
+
)
|
|
3936
4208
|
] }),
|
|
3937
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3938
|
-
|
|
3939
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
4209
|
+
step === "otp" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4210
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => goToStep("info"), style: backBtnStyle, type: "button", children: /* @__PURE__ */ jsxRuntime.jsx(IconArrowLeft, { style: { width: "1rem", height: "1rem" } }) }),
|
|
4211
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { style: { textAlign: "center" }, children: [
|
|
4212
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: iconCircle(C$1.accent), children: /* @__PURE__ */ jsxRuntime.jsx(IconKeyRound, { style: { width: "1.5rem", height: "1.5rem", color: C$1.white } }) }),
|
|
4213
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Vérification" }),
|
|
4214
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogDescription, { children: [
|
|
4215
|
+
"Entrez le code envoyé ",
|
|
4216
|
+
isPhoneOnly ? `au ${formData.ccphone} ${formData.phone}` : `à ${formData.email}`
|
|
4217
|
+
] })
|
|
4218
|
+
] }),
|
|
4219
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogBody, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "1rem" }, children: [
|
|
4220
|
+
renderError(),
|
|
4221
|
+
/* @__PURE__ */ jsxRuntime.jsx(OTPInput, { value: otpCode, onChange: setOtpCode, disabled: regLoading }),
|
|
4222
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", fontSize: "0.875rem" }, children: resendCooldown > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: C$1.gray500 }, children: [
|
|
4223
|
+
"Renvoyer dans ",
|
|
4224
|
+
resendCooldown,
|
|
4225
|
+
"s"
|
|
4226
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: handleResendOTP, style: linkStyle, children: "Code non reçu ? Renvoyer" }) }),
|
|
4227
|
+
/* @__PURE__ */ jsxRuntime.jsx(StepIndicator, { current: 4 })
|
|
4228
|
+
] }) }),
|
|
4229
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogFooter, { children: /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: handleOTPSubmit, disabled: regLoading || otpCode.length !== 6, style: { width: "100%" }, children: regLoading ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
3947
4230
|
/* @__PURE__ */ jsxRuntime.jsx(IconLoader2, { style: { width: "1rem", height: "1rem" } }),
|
|
3948
4231
|
" Vérification..."
|
|
3949
|
-
] }) : "Vérifier" })
|
|
3950
|
-
] })
|
|
3951
|
-
] }),
|
|
3952
|
-
step === "password" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3953
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => goToStep("otp"), style: backBtnStyle, type: "button", children: /* @__PURE__ */ jsxRuntime.jsx(IconArrowLeft, { style: { width: "1rem", height: "1rem" } }) }),
|
|
3954
|
-
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { style: { textAlign: "center" }, children: [
|
|
3955
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: iconCircle(C$1.accent), children: /* @__PURE__ */ jsxRuntime.jsx(IconLock, { style: { width: "1.5rem", height: "1.5rem", color: C$1.white } }) }),
|
|
3956
|
-
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Créer un mot de passe" })
|
|
4232
|
+
] }) : "Vérifier" }) })
|
|
3957
4233
|
] }),
|
|
3958
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3959
|
-
|
|
3960
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
3961
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3962
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3963
|
-
] }),
|
|
3964
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3965
|
-
/* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Confirmer le mot de passe" }),
|
|
3966
|
-
/* @__PURE__ */ jsxRuntime.jsx(Input, { type: "password", placeholder: "••••••••", value: passwordConfirm, onChange: (e) => setPasswordConfirm(e.target.value), disabled: regLoading })
|
|
4234
|
+
step === "password" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4235
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => goToStep("otp"), style: backBtnStyle, type: "button", children: /* @__PURE__ */ jsxRuntime.jsx(IconArrowLeft, { style: { width: "1rem", height: "1rem" } }) }),
|
|
4236
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { style: { textAlign: "center" }, children: [
|
|
4237
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: iconCircle(C$1.accent), children: /* @__PURE__ */ jsxRuntime.jsx(IconLock, { style: { width: "1.5rem", height: "1.5rem", color: C$1.white } }) }),
|
|
4238
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Créer un mot de passe" })
|
|
3967
4239
|
] }),
|
|
3968
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
4240
|
+
/* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handlePasswordSubmit, style: { display: "flex", flexDirection: "column", flex: 1, minHeight: 0 }, children: [
|
|
4241
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogBody, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
|
|
4242
|
+
renderError(),
|
|
4243
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4244
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Mot de passe" }),
|
|
4245
|
+
/* @__PURE__ */ jsxRuntime.jsx(Input, { type: "password", placeholder: "Minimum 8 caractères", value: password, onChange: (e) => setPassword(e.target.value), disabled: regLoading })
|
|
4246
|
+
] }),
|
|
4247
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4248
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Confirmer le mot de passe" }),
|
|
4249
|
+
/* @__PURE__ */ jsxRuntime.jsx(Input, { type: "password", placeholder: "••••••••", value: passwordConfirm, onChange: (e) => setPasswordConfirm(e.target.value), disabled: regLoading })
|
|
4250
|
+
] }),
|
|
4251
|
+
/* @__PURE__ */ jsxRuntime.jsx(StepIndicator, { current: 5 })
|
|
4252
|
+
] }) }),
|
|
4253
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogFooter, { children: /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", disabled: regLoading, style: { width: "100%" }, children: "Continuer" }) })
|
|
4254
|
+
] })
|
|
3977
4255
|
] }),
|
|
3978
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3979
|
-
|
|
3980
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3981
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
3982
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3983
|
-
] }
|
|
3984
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3985
|
-
|
|
4256
|
+
step === "confirm" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4257
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => goToStep("password"), style: backBtnStyle, type: "button", children: /* @__PURE__ */ jsxRuntime.jsx(IconArrowLeft, { style: { width: "1rem", height: "1rem" } }) }),
|
|
4258
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { style: { textAlign: "center" }, children: [
|
|
4259
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: iconCircle(C$1.primary + "1a"), children: /* @__PURE__ */ jsxRuntime.jsx(IconShieldCheck, { style: { width: "1.5rem", height: "1.5rem", color: C$1.primary } }) }),
|
|
4260
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Confirmer votre inscription" })
|
|
4261
|
+
] }),
|
|
4262
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogBody, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
|
|
4263
|
+
renderError(),
|
|
4264
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { backgroundColor: C$1.gray100, borderRadius: "0.5rem", padding: "1rem" }, children: [["Nom", formData.name], ...!isPhoneOnly ? [["Email", formData.email]] : [], ["Téléphone", `${formData.ccphone} ${formData.phone}`], ["Ville", formData.town], ["Pays", formData.country]].map(([label, value]) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", padding: "0.375rem 0" }, children: [
|
|
4265
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.875rem", color: C$1.gray500 }, children: label }),
|
|
4266
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.875rem", fontWeight: 500 }, children: value })
|
|
4267
|
+
] }, label)) }),
|
|
4268
|
+
/* @__PURE__ */ jsxRuntime.jsx(StepIndicator, { current: 6 })
|
|
4269
|
+
] }) }),
|
|
4270
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogFooter, { children: /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: handleConfirm, disabled: regLoading, style: { width: "100%" }, children: regLoading ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
3986
4271
|
/* @__PURE__ */ jsxRuntime.jsx(IconLoader2, { style: { width: "1rem", height: "1rem" } }),
|
|
3987
4272
|
" Création du compte..."
|
|
3988
|
-
] }) : "Créer mon compte" })
|
|
4273
|
+
] }) : "Créer mon compte" }) })
|
|
3989
4274
|
] })
|
|
3990
|
-
] })
|
|
3991
|
-
|
|
4275
|
+
] }) }) }),
|
|
4276
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4277
|
+
PasswordRecoveryModal,
|
|
4278
|
+
{
|
|
4279
|
+
open: showPasswordRecovery,
|
|
4280
|
+
onOpenChange: setShowPasswordRecovery,
|
|
4281
|
+
onSuccess: () => setShowPasswordRecovery(false),
|
|
4282
|
+
saasApiUrl,
|
|
4283
|
+
iamApiUrl
|
|
4284
|
+
}
|
|
4285
|
+
)
|
|
4286
|
+
] });
|
|
3992
4287
|
}
|
|
3993
4288
|
const C = {
|
|
3994
4289
|
primary: "#002147",
|
|
@@ -4055,7 +4350,7 @@ function OnboardingModal({ open, onOpenChange, user, onComplete, onSkip }) {
|
|
|
4055
4350
|
] }),
|
|
4056
4351
|
/* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: "Ajoutez les informations manquantes pour finaliser votre compte." })
|
|
4057
4352
|
] }),
|
|
4058
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "1.25rem", marginTop: "
|
|
4353
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogBody, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "1.25rem", marginTop: "0.75rem" }, children: [
|
|
4059
4354
|
needsPhoto && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4060
4355
|
/* @__PURE__ */ jsxRuntime.jsx(Label, { style: { display: "block", marginBottom: "0.5rem", color: C.gray700, fontWeight: 500 }, children: "Photo de profil" }),
|
|
4061
4356
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "1rem" }, children: [
|
|
@@ -4087,15 +4382,7 @@ function OnboardingModal({ open, onOpenChange, user, onComplete, onSkip }) {
|
|
|
4087
4382
|
fontWeight: 500
|
|
4088
4383
|
}, children: [
|
|
4089
4384
|
"Choisir une photo",
|
|
4090
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4091
|
-
"input",
|
|
4092
|
-
{
|
|
4093
|
-
type: "file",
|
|
4094
|
-
accept: "image/*",
|
|
4095
|
-
onChange: handleFileChange,
|
|
4096
|
-
style: { display: "none" }
|
|
4097
|
-
}
|
|
4098
|
-
)
|
|
4385
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "file", accept: "image/*", onChange: handleFileChange, style: { display: "none" } })
|
|
4099
4386
|
] }),
|
|
4100
4387
|
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.75rem", color: fileError ? "#dc2626" : C.gray500, marginTop: "0.25rem" }, children: fileError || "JPG, PNG. Max 2 Mo." })
|
|
4101
4388
|
] })
|
|
@@ -4103,15 +4390,7 @@ function OnboardingModal({ open, onOpenChange, user, onComplete, onSkip }) {
|
|
|
4103
4390
|
] }),
|
|
4104
4391
|
needsPhone && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4105
4392
|
/* @__PURE__ */ jsxRuntime.jsx(Label, { style: { display: "block", marginBottom: "0.5rem", color: C.gray700, fontWeight: 500 }, children: "Numéro de téléphone" }),
|
|
4106
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4107
|
-
PhoneInput,
|
|
4108
|
-
{
|
|
4109
|
-
value: phone,
|
|
4110
|
-
onChange: setPhone,
|
|
4111
|
-
ccphone,
|
|
4112
|
-
onCcphoneChange: setCcphone
|
|
4113
|
-
}
|
|
4114
|
-
)
|
|
4393
|
+
/* @__PURE__ */ jsxRuntime.jsx(PhoneInput, { value: phone, onChange: setPhone, ccphone, onCcphoneChange: setCcphone })
|
|
4115
4394
|
] }),
|
|
4116
4395
|
needsEmail && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4117
4396
|
/* @__PURE__ */ jsxRuntime.jsxs(Label, { style: { display: "block", marginBottom: "0.5rem", color: C.gray700, fontWeight: 500 }, children: [
|
|
@@ -4153,38 +4432,32 @@ function OnboardingModal({ open, onOpenChange, user, onComplete, onSkip }) {
|
|
|
4153
4432
|
type: "checkbox",
|
|
4154
4433
|
checked: confirmed,
|
|
4155
4434
|
onChange: (e) => setConfirmed(e.target.checked),
|
|
4156
|
-
style: {
|
|
4157
|
-
width: "1rem",
|
|
4158
|
-
height: "1rem",
|
|
4159
|
-
marginTop: "0.125rem",
|
|
4160
|
-
accentColor: C.primary,
|
|
4161
|
-
cursor: "pointer"
|
|
4162
|
-
}
|
|
4435
|
+
style: { width: "1rem", height: "1rem", marginTop: "0.125rem", accentColor: C.primary, cursor: "pointer" }
|
|
4163
4436
|
}
|
|
4164
4437
|
),
|
|
4165
4438
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Je confirme que ces informations sont exactes" })
|
|
4166
|
-
] }),
|
|
4167
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
4168
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4169
|
-
Button,
|
|
4170
|
-
{
|
|
4171
|
-
onClick: handleSubmit,
|
|
4172
|
-
disabled: !canSubmit || submitting,
|
|
4173
|
-
style: { width: "100%", height: "2.75rem", opacity: canSubmit && !submitting ? 1 : 0.5 },
|
|
4174
|
-
children: submitting ? "Enregistrement..." : "Valider"
|
|
4175
|
-
}
|
|
4176
|
-
),
|
|
4177
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4178
|
-
Button,
|
|
4179
|
-
{
|
|
4180
|
-
variant: "outline",
|
|
4181
|
-
onClick: onSkip,
|
|
4182
|
-
disabled: submitting,
|
|
4183
|
-
style: { width: "100%", height: "2.75rem" },
|
|
4184
|
-
children: "Passer pour l'instant"
|
|
4185
|
-
}
|
|
4186
|
-
)
|
|
4187
4439
|
] })
|
|
4440
|
+
] }) }),
|
|
4441
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogFooter, { children: [
|
|
4442
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4443
|
+
Button,
|
|
4444
|
+
{
|
|
4445
|
+
onClick: handleSubmit,
|
|
4446
|
+
disabled: !canSubmit || submitting,
|
|
4447
|
+
style: { width: "100%", height: "2.75rem", opacity: canSubmit && !submitting ? 1 : 0.5 },
|
|
4448
|
+
children: submitting ? "Enregistrement..." : "Valider"
|
|
4449
|
+
}
|
|
4450
|
+
),
|
|
4451
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4452
|
+
Button,
|
|
4453
|
+
{
|
|
4454
|
+
variant: "outline",
|
|
4455
|
+
onClick: onSkip,
|
|
4456
|
+
disabled: submitting,
|
|
4457
|
+
style: { width: "100%", height: "2.75rem" },
|
|
4458
|
+
children: "Passer pour l'instant"
|
|
4459
|
+
}
|
|
4460
|
+
)
|
|
4188
4461
|
] })
|
|
4189
4462
|
] }) });
|
|
4190
4463
|
}
|
|
@@ -4435,6 +4708,7 @@ function NativeSSOPage({
|
|
|
4435
4708
|
redirectAfterLogout
|
|
4436
4709
|
}) {
|
|
4437
4710
|
const [modal, setModal] = react.useState("none");
|
|
4711
|
+
const [loginInitialPhone, setLoginInitialPhone] = react.useState();
|
|
4438
4712
|
const [showOnboarding, setShowOnboarding] = react.useState(false);
|
|
4439
4713
|
const [pendingSession, setPendingSession] = react.useState(null);
|
|
4440
4714
|
const [session, setSession] = react.useState(() => {
|
|
@@ -4476,13 +4750,23 @@ function NativeSSOPage({
|
|
|
4476
4750
|
}, []);
|
|
4477
4751
|
const openLogin = react.useCallback(() => setModal("login"), []);
|
|
4478
4752
|
const openSignup = react.useCallback(() => setModal("signup"), []);
|
|
4479
|
-
const closeModal = react.useCallback(() =>
|
|
4753
|
+
const closeModal = react.useCallback(() => {
|
|
4754
|
+
setModal("none");
|
|
4755
|
+
setLoginInitialPhone(void 0);
|
|
4756
|
+
}, []);
|
|
4480
4757
|
const switchToSignup = react.useCallback(() => {
|
|
4481
4758
|
setModal("none");
|
|
4759
|
+
setLoginInitialPhone(void 0);
|
|
4482
4760
|
setTimeout(() => setModal("signup"), 150);
|
|
4483
4761
|
}, []);
|
|
4484
4762
|
const switchToLogin = react.useCallback(() => {
|
|
4485
4763
|
setModal("none");
|
|
4764
|
+
setLoginInitialPhone(void 0);
|
|
4765
|
+
setTimeout(() => setModal("login"), 150);
|
|
4766
|
+
}, []);
|
|
4767
|
+
const switchToLoginWithPhone = react.useCallback((phone) => {
|
|
4768
|
+
setModal("none");
|
|
4769
|
+
setLoginInitialPhone(phone);
|
|
4486
4770
|
setTimeout(() => setModal("login"), 150);
|
|
4487
4771
|
}, []);
|
|
4488
4772
|
const handleLoginSuccess = react.useCallback((token, user) => {
|
|
@@ -4524,12 +4808,8 @@ function NativeSSOPage({
|
|
|
4524
4808
|
onLoginSuccess == null ? void 0 : onLoginSuccess(pendingSession.token, pendingSession.user);
|
|
4525
4809
|
if (redirectAfterLogin) window.location.href = redirectAfterLogin;
|
|
4526
4810
|
}, [pendingSession, onLoginSuccess, redirectAfterLogin]);
|
|
4527
|
-
const handleLogout = react.useCallback(() => {
|
|
4528
|
-
|
|
4529
|
-
localStorage.removeItem(STORAGE.TOKEN);
|
|
4530
|
-
localStorage.removeItem(STORAGE.USER);
|
|
4531
|
-
localStorage.removeItem(STORAGE.ACCOUNT_TYPE);
|
|
4532
|
-
localStorage.removeItem(STORAGE.ALIAS_REFERENCE);
|
|
4811
|
+
const handleLogout = react.useCallback(async () => {
|
|
4812
|
+
await logout();
|
|
4533
4813
|
setSession(null);
|
|
4534
4814
|
onLogout == null ? void 0 : onLogout();
|
|
4535
4815
|
if (redirectAfterLogout) window.location.href = redirectAfterLogout;
|
|
@@ -4633,7 +4913,8 @@ function NativeSSOPage({
|
|
|
4633
4913
|
onLoginSuccess: handleLoginSuccess,
|
|
4634
4914
|
saasApiUrl,
|
|
4635
4915
|
iamApiUrl,
|
|
4636
|
-
defaultAccountType: accountType
|
|
4916
|
+
defaultAccountType: accountType,
|
|
4917
|
+
initialPhone: loginInitialPhone
|
|
4637
4918
|
}
|
|
4638
4919
|
),
|
|
4639
4920
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -4644,6 +4925,7 @@ function NativeSSOPage({
|
|
|
4644
4925
|
if (!open) closeModal();
|
|
4645
4926
|
},
|
|
4646
4927
|
onSwitchToLogin: switchToLogin,
|
|
4928
|
+
onSwitchToLoginWithPhone: switchToLoginWithPhone,
|
|
4647
4929
|
onSignupSuccess: handleLoginSuccess,
|
|
4648
4930
|
saasApiUrl,
|
|
4649
4931
|
iamApiUrl,
|
|
@@ -4683,6 +4965,26 @@ function useNativeSSOConfig() {
|
|
|
4683
4965
|
}
|
|
4684
4966
|
return ctx;
|
|
4685
4967
|
}
|
|
4968
|
+
const useLogout = (options) => {
|
|
4969
|
+
const [loading, setLoading] = react.useState(false);
|
|
4970
|
+
const [error, setError] = react.useState(null);
|
|
4971
|
+
const handleLogout = react.useCallback(async () => {
|
|
4972
|
+
var _a, _b;
|
|
4973
|
+
setLoading(true);
|
|
4974
|
+
setError(null);
|
|
4975
|
+
try {
|
|
4976
|
+
await logout();
|
|
4977
|
+
(_a = options == null ? void 0 : options.onSuccess) == null ? void 0 : _a.call(options);
|
|
4978
|
+
} catch (err) {
|
|
4979
|
+
const message = err instanceof Error ? err.message : "Erreur de déconnexion";
|
|
4980
|
+
setError(message);
|
|
4981
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, err instanceof Error ? err : new Error(message));
|
|
4982
|
+
} finally {
|
|
4983
|
+
setLoading(false);
|
|
4984
|
+
}
|
|
4985
|
+
}, [options]);
|
|
4986
|
+
return { logout: handleLogout, loading, error };
|
|
4987
|
+
};
|
|
4686
4988
|
function getCredentialsOrThrow(params) {
|
|
4687
4989
|
const app_key = params.app_key;
|
|
4688
4990
|
const secret_key = params.secret_key;
|
|
@@ -4852,10 +5154,12 @@ exports.getCountryByDialCode = getCountryByDialCode;
|
|
|
4852
5154
|
exports.getDefaultCountry = getDefaultCountry;
|
|
4853
5155
|
exports.getNativeAuthConfig = getNativeAuthConfig;
|
|
4854
5156
|
exports.iamAccountService = iamAccountService;
|
|
5157
|
+
exports.logout = logout;
|
|
4855
5158
|
exports.mobilePasswordService = mobilePasswordService;
|
|
4856
5159
|
exports.nativeAuthService = nativeAuthService;
|
|
4857
5160
|
exports.searchCountries = searchCountries;
|
|
4858
5161
|
exports.setNativeAuthConfig = setNativeAuthConfig;
|
|
5162
|
+
exports.useLogout = useLogout;
|
|
4859
5163
|
exports.useMobilePassword = useMobilePassword;
|
|
4860
5164
|
exports.useMobileRegistration = useMobileRegistration;
|
|
4861
5165
|
exports.useNativeAuth = useNativeAuth;
|