@ollaid/native-sso 2.7.6 → 2.7.8

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.
@@ -2,7 +2,7 @@
2
2
  * Login Modal for @ollaid/native-sso
3
3
  * Complete login flow aligned with Native SSO design
4
4
  *
5
- * @version 2.7.0
5
+ * @version 2.7.8
6
6
  */
7
7
  import type { UserInfos } from '../types/native';
8
8
  export interface LoginModalProps {
@@ -2,7 +2,7 @@
2
2
  * NativeSSOPage — Page autonome complète pour @ollaid/native-sso
3
3
  * Design aligné sur le parcours Native SSO (fond primary, card blanche, ShieldCheck branding)
4
4
  *
5
- * @version 2.7.0
5
+ * @version 2.7.8
6
6
  */
7
7
  import type { UserInfos } from '../types/native';
8
8
  import type { NativeStorageAdapter } from '../services/api';
@@ -3,7 +3,7 @@
3
3
  * Mode `missing` : champs absents uniquement
4
4
  * Mode `edit` : édition complète du profil depuis le SaaS
5
5
  *
6
- * @version 2.7.0
6
+ * @version 2.7.8
7
7
  */
8
8
  import type { NativeUser, UserInfos } from '../types/native';
9
9
  export interface OnboardingModalProps {
@@ -13,6 +13,11 @@ export interface OnboardingModalProps {
13
13
  user: NativeUser;
14
14
  variant?: 'missing' | 'edit';
15
15
  profileHydrating?: boolean;
16
+ hydrateProfile?: boolean;
17
+ onUserInfosSync?: (payload: {
18
+ source: 'hydration' | 'update' | 'avatar' | 'contact';
19
+ user_infos: UserInfos;
20
+ }) => void;
16
21
  onComplete: (data: {
17
22
  name?: string;
18
23
  image_url?: string;
@@ -26,5 +31,5 @@ export interface OnboardingModalProps {
26
31
  }) => void;
27
32
  onSkip: () => void;
28
33
  }
29
- export declare function OnboardingModal({ open, onOpenChange, onDismiss, user, variant, profileHydrating, onComplete, onSkip }: OnboardingModalProps): import("react/jsx-runtime").JSX.Element;
34
+ export declare function OnboardingModal({ open, onOpenChange, onDismiss, user, variant, profileHydrating, hydrateProfile, onUserInfosSync, onComplete, onSkip, }: OnboardingModalProps): import("react/jsx-runtime").JSX.Element;
30
35
  export default OnboardingModal;
@@ -2,7 +2,7 @@
2
2
  * Signup Modal for @ollaid/native-sso — Design aligned with web SSO
3
3
  * Full signup flow: intro → account-type → info → OTP → password → confirm → success
4
4
  *
5
- * @version 2.7.0
5
+ * @version 2.7.8
6
6
  */
7
7
  import type { UserInfos } from '../types/native';
8
8
  export interface SignupModalProps {
package/dist/index.cjs CHANGED
@@ -12146,26 +12146,41 @@ const C = {
12146
12146
  gray700: "#374151",
12147
12147
  white: "#ffffff"
12148
12148
  };
12149
- function OnboardingModal({ open, onOpenChange, onDismiss, user, variant = "missing", profileHydrating = false, onComplete, onSkip }) {
12149
+ function OnboardingModal({
12150
+ open,
12151
+ onOpenChange,
12152
+ onDismiss,
12153
+ user,
12154
+ variant = "missing",
12155
+ profileHydrating = false,
12156
+ hydrateProfile = true,
12157
+ onUserInfosSync,
12158
+ onComplete,
12159
+ onSkip
12160
+ }) {
12150
12161
  var _a;
12151
12162
  const isEditMode = variant === "edit";
12152
- const hasCurrentPhone = Boolean(user.phone);
12153
- const hasCurrentEmail = Boolean(user.email);
12163
+ const [hydratedUser, setHydratedUser] = react.useState(null);
12164
+ const [internalHydrating, setInternalHydrating] = react.useState(false);
12165
+ const hydrationKeyRef = react.useRef(null);
12166
+ const profileUser = hydratedUser ?? user;
12167
+ const hasCurrentPhone = Boolean(profileUser.phone);
12168
+ const hasCurrentEmail = Boolean(profileUser.email);
12154
12169
  const directPhoneEdit = !isEditMode || !hasCurrentPhone;
12155
12170
  const directEmailEdit = !isEditMode || !hasCurrentEmail;
12156
- !isEditMode ? !((_a = user.name) == null ? void 0 : _a.trim()) : true;
12157
- const [name, setName] = react.useState(user.name || "");
12171
+ !isEditMode ? !((_a = profileUser.name) == null ? void 0 : _a.trim()) : true;
12172
+ const [name, setName] = react.useState(profileUser.name || "");
12158
12173
  const [photoPreview, setPhotoPreview] = react.useState("");
12159
12174
  const [avatarPickerOpen, setAvatarPickerOpen] = react.useState(false);
12160
12175
  const [pendingAvatarSrc, setPendingAvatarSrc] = react.useState(null);
12161
12176
  const [avatarUploading, setAvatarUploading] = react.useState(false);
12162
12177
  const avatarFileInputRef = react.useRef(null);
12163
- const [ccphone, setCcphone] = react.useState(user.ccphone || "+221");
12164
- const [phone, setPhone] = react.useState(user.phone || "");
12165
- const [email, setEmail] = react.useState(user.email || "");
12166
- const [address, setAddress] = react.useState(user.address || "");
12167
- const [town, setTown] = react.useState(user.town || "");
12168
- const [country, setCountry] = react.useState(user.country || DEFAULT_COUNTRY_CODE);
12178
+ const [ccphone, setCcphone] = react.useState(profileUser.ccphone || "+221");
12179
+ const [phone, setPhone] = react.useState(profileUser.phone || "");
12180
+ const [email, setEmail] = react.useState(profileUser.email || "");
12181
+ const [address, setAddress] = react.useState(profileUser.address || "");
12182
+ const [town, setTown] = react.useState(profileUser.town || "");
12183
+ const [country, setCountry] = react.useState(profileUser.country || DEFAULT_COUNTRY_CODE);
12169
12184
  const [submitting, setSubmitting] = react.useState(false);
12170
12185
  const [fileError, setFileError] = react.useState("");
12171
12186
  const [contactFlow, setContactFlow] = react.useState(null);
@@ -12175,34 +12190,54 @@ function OnboardingModal({ open, onOpenChange, onDismiss, user, variant = "missi
12175
12190
  const [confirmAction, setConfirmAction] = react.useState(null);
12176
12191
  const [nowTick, setNowTick] = react.useState(Date.now());
12177
12192
  const userHydrationKey = [
12178
- user.reference || "",
12179
- user.name || "",
12180
- user.email || "",
12181
- user.ccphone || "",
12182
- user.phone || "",
12183
- user.address || "",
12184
- user.town || "",
12185
- user.country || "",
12186
- user.image_url || "",
12187
- user.auth_2fa ? "1" : "0"
12193
+ profileUser.reference || "",
12194
+ profileUser.name || "",
12195
+ profileUser.email || "",
12196
+ profileUser.ccphone || "",
12197
+ profileUser.phone || "",
12198
+ profileUser.address || "",
12199
+ profileUser.town || "",
12200
+ profileUser.country || "",
12201
+ profileUser.image_url || "",
12202
+ profileUser.auth_2fa ? "1" : "0"
12188
12203
  ].join("|");
12189
- const currentDialCode = (user.ccphone || ccphone || "+221").trim();
12204
+ const currentDialCode = (profileUser.ccphone || ccphone || "+221").trim();
12190
12205
  const baseSmsAllowed = currentDialCode === "+221";
12191
12206
  const contactSmsAllowed = contactFlow ? contactFlow.kind === "phone" ? contactFlow.newCcphone.trim() === "+221" : baseSmsAllowed : baseSmsAllowed;
12192
12207
  const lockModalClose = profileHydrating || submitting || submitState === "success" || avatarUploading || Boolean(contactFlow == null ? void 0 : contactFlow.loading);
12208
+ const syncFormFromUser = react.useCallback((nextUser) => {
12209
+ setName(nextUser.name || "");
12210
+ setPhotoPreview(isEditMode ? nextUser.image_url || "" : "");
12211
+ setCcphone(nextUser.ccphone || "+221");
12212
+ setPhone(nextUser.phone || "");
12213
+ setEmail(nextUser.email || "");
12214
+ setAddress(nextUser.address || "");
12215
+ setTown(nextUser.town || "");
12216
+ setCountry(nextUser.country || DEFAULT_COUNTRY_CODE);
12217
+ }, [isEditMode]);
12218
+ const toUserInfos = react.useCallback((nextUser) => ({
12219
+ reference: nextUser.reference,
12220
+ name: nextUser.name,
12221
+ email: nextUser.email || null,
12222
+ ccphone: nextUser.ccphone,
12223
+ phone: nextUser.phone,
12224
+ address: nextUser.address,
12225
+ town: nextUser.town,
12226
+ country: nextUser.country,
12227
+ image_url: nextUser.image_url,
12228
+ auth_2fa: nextUser.auth_2fa,
12229
+ alias_reference: nextUser.alias_reference,
12230
+ iam_reference: nextUser.iam_reference
12231
+ }), []);
12193
12232
  react.useEffect(() => {
12194
- if (!open) return;
12195
- setName(user.name || "");
12196
- setPhotoPreview(isEditMode ? user.image_url || "" : "");
12233
+ if (!open) {
12234
+ setHydratedUser(null);
12235
+ hydrationKeyRef.current = null;
12236
+ return;
12237
+ }
12197
12238
  setPendingAvatarSrc(null);
12198
12239
  setAvatarPickerOpen(false);
12199
12240
  setAvatarUploading(false);
12200
- setCcphone(user.ccphone || "+221");
12201
- setPhone(user.phone || "");
12202
- setEmail(user.email || "");
12203
- setAddress(user.address || "");
12204
- setTown(user.town || "");
12205
- setCountry(user.country || DEFAULT_COUNTRY_CODE);
12206
12241
  setSubmitting(false);
12207
12242
  setFileError("");
12208
12243
  setContactFlow(null);
@@ -12210,7 +12245,54 @@ function OnboardingModal({ open, onOpenChange, onDismiss, user, variant = "missi
12210
12245
  setSubmitMessage("");
12211
12246
  setSubmitError("");
12212
12247
  setConfirmAction(null);
12213
- }, [open, isEditMode, userHydrationKey, user.name, user.image_url, user.ccphone, user.phone, user.email, user.address, user.town, user.country]);
12248
+ syncFormFromUser(profileUser);
12249
+ }, [open, userHydrationKey, profileUser, syncFormFromUser]);
12250
+ react.useEffect(() => {
12251
+ if (!open || !hydratedUser) return;
12252
+ if (contactFlow || submitting || submitState !== "idle") return;
12253
+ syncFormFromUser(hydratedUser);
12254
+ }, [open, hydratedUser, contactFlow, submitting, submitState, syncFormFromUser]);
12255
+ react.useEffect(() => {
12256
+ if (!open || !hydrateProfile || profileHydrating || internalHydrating || hydratedUser) return;
12257
+ const key = userHydrationKey;
12258
+ if (hydrationKeyRef.current === key) return;
12259
+ hydrationKeyRef.current = key;
12260
+ let cancelled = false;
12261
+ setInternalHydrating(true);
12262
+ (async () => {
12263
+ try {
12264
+ const response = await profileService.getProfile();
12265
+ const payload = response.user_infos || response.user || {};
12266
+ const nextUser = {
12267
+ ...profileUser,
12268
+ name: payload.name || profileUser.name,
12269
+ email: payload.email ?? profileUser.email ?? null,
12270
+ ccphone: payload.ccphone || profileUser.ccphone,
12271
+ phone: payload.phone || profileUser.phone,
12272
+ address: payload.address || profileUser.address,
12273
+ town: payload.town || profileUser.town,
12274
+ country: payload.country || profileUser.country,
12275
+ image_url: payload.image_url || profileUser.image_url,
12276
+ auth_2fa: payload.auth_2fa ?? profileUser.auth_2fa,
12277
+ alias_reference: payload.alias_reference || profileUser.alias_reference,
12278
+ iam_reference: payload.iam_reference || profileUser.iam_reference
12279
+ };
12280
+ if (cancelled) return;
12281
+ setHydratedUser(nextUser);
12282
+ syncFormFromUser(nextUser);
12283
+ onUserInfosSync == null ? void 0 : onUserInfosSync({ source: "hydration", user_infos: toUserInfos(nextUser) });
12284
+ } catch {
12285
+ if (cancelled) return;
12286
+ } finally {
12287
+ if (!cancelled) {
12288
+ setInternalHydrating(false);
12289
+ }
12290
+ }
12291
+ })();
12292
+ return () => {
12293
+ cancelled = true;
12294
+ };
12295
+ }, [open, hydrateProfile, profileHydrating, internalHydrating, userHydrationKey, profileUser, onUserInfosSync, syncFormFromUser, toUserInfos]);
12214
12296
  react.useEffect(() => {
12215
12297
  if (!(contactFlow == null ? void 0 : contactFlow.resendAvailableAt)) return;
12216
12298
  const timer = window.setInterval(() => {
@@ -12246,9 +12328,9 @@ function OnboardingModal({ open, onOpenChange, onDismiss, user, variant = "missi
12246
12328
  setSubmitError("");
12247
12329
  const data = {
12248
12330
  name: name.trim(),
12249
- ccphone: directPhoneEdit ? ccphone : user.ccphone || void 0,
12250
- phone: directPhoneEdit ? phone : user.phone || void 0,
12251
- email: directEmailEdit ? email.trim() : user.email || void 0,
12331
+ ccphone: directPhoneEdit ? ccphone : profileUser.ccphone || void 0,
12332
+ phone: directPhoneEdit ? phone : profileUser.phone || void 0,
12333
+ email: directEmailEdit ? email.trim() : profileUser.email || void 0,
12252
12334
  ...address.trim() ? { address: address.trim() } : {},
12253
12335
  ...town.trim() ? { town: town.trim() } : {},
12254
12336
  ...country ? { country } : {}
@@ -12257,19 +12339,21 @@ function OnboardingModal({ open, onOpenChange, onDismiss, user, variant = "missi
12257
12339
  const response = await profileService.updateProfile(data);
12258
12340
  const payload = response.user_infos || response.user || {};
12259
12341
  const updatedUser = {
12260
- ...user,
12261
- name: payload.name || data.name || user.name,
12262
- email: payload.email ?? data.email ?? user.email,
12263
- ccphone: payload.ccphone || data.ccphone || user.ccphone,
12264
- phone: payload.phone || data.phone || user.phone,
12265
- address: payload.address || data.address || user.address,
12266
- town: payload.town || data.town || user.town,
12267
- country: payload.country || data.country || user.country,
12268
- image_url: payload.image_url || user.image_url,
12269
- auth_2fa: payload.auth_2fa ?? user.auth_2fa,
12270
- alias_reference: payload.alias_reference || user.alias_reference,
12271
- iam_reference: payload.iam_reference || user.iam_reference
12342
+ ...profileUser,
12343
+ name: payload.name || data.name || profileUser.name,
12344
+ email: payload.email ?? data.email ?? profileUser.email,
12345
+ ccphone: payload.ccphone || data.ccphone || profileUser.ccphone,
12346
+ phone: payload.phone || data.phone || profileUser.phone,
12347
+ address: payload.address || data.address || profileUser.address,
12348
+ town: payload.town || data.town || profileUser.town,
12349
+ country: payload.country || data.country || profileUser.country,
12350
+ image_url: payload.image_url || profileUser.image_url,
12351
+ auth_2fa: payload.auth_2fa ?? profileUser.auth_2fa,
12352
+ alias_reference: payload.alias_reference || profileUser.alias_reference,
12353
+ iam_reference: payload.iam_reference || profileUser.iam_reference
12272
12354
  };
12355
+ setHydratedUser(updatedUser);
12356
+ onUserInfosSync == null ? void 0 : onUserInfosSync({ source: "update", user_infos: toUserInfos(updatedUser) });
12273
12357
  onComplete({
12274
12358
  name: updatedUser.name,
12275
12359
  image_url: updatedUser.image_url,
@@ -12300,7 +12384,7 @@ function OnboardingModal({ open, onOpenChange, onDismiss, user, variant = "missi
12300
12384
  setSubmitState("error");
12301
12385
  setSubmitError(error instanceof Error ? error.message : "Erreur lors de l’enregistrement");
12302
12386
  }
12303
- }, [canSubmit, user, name, directPhoneEdit, directEmailEdit, ccphone, phone, email, address, town, country, onComplete, markSuccess]);
12387
+ }, [canSubmit, profileUser, name, directPhoneEdit, directEmailEdit, ccphone, phone, email, address, town, country, onComplete, onUserInfosSync, toUserInfos, markSuccess]);
12304
12388
  const openAvatarPicker = react.useCallback(() => {
12305
12389
  var _a2;
12306
12390
  (_a2 = avatarFileInputRef.current) == null ? void 0 : _a2.click();
@@ -12330,6 +12414,23 @@ function OnboardingModal({ open, onOpenChange, onDismiss, user, variant = "missi
12330
12414
  setPhotoPreview(URL.createObjectURL(blob));
12331
12415
  }
12332
12416
  if (Object.keys(payload).length > 0) {
12417
+ const updatedUser = {
12418
+ ...profileUser,
12419
+ reference: payload.reference || profileUser.reference,
12420
+ name: payload.name || profileUser.name,
12421
+ email: payload.email ?? profileUser.email ?? null,
12422
+ ccphone: payload.ccphone || profileUser.ccphone,
12423
+ phone: payload.phone || profileUser.phone,
12424
+ address: payload.address || profileUser.address,
12425
+ town: payload.town || profileUser.town,
12426
+ country: payload.country || profileUser.country,
12427
+ image_url: nextImage || profileUser.image_url,
12428
+ auth_2fa: payload.auth_2fa ?? profileUser.auth_2fa,
12429
+ alias_reference: payload.alias_reference || profileUser.alias_reference,
12430
+ iam_reference: payload.iam_reference || profileUser.iam_reference
12431
+ };
12432
+ setHydratedUser(updatedUser);
12433
+ onUserInfosSync == null ? void 0 : onUserInfosSync({ source: "avatar", user_infos: toUserInfos(updatedUser) });
12333
12434
  onComplete({
12334
12435
  name: payload.name,
12335
12436
  image_url: nextImage || void 0,
@@ -12340,18 +12441,18 @@ function OnboardingModal({ open, onOpenChange, onDismiss, user, variant = "missi
12340
12441
  town: payload.town || void 0,
12341
12442
  country: payload.country || void 0,
12342
12443
  user_infos: {
12343
- reference: payload.reference || user.reference,
12344
- name: payload.name || user.name,
12345
- email: payload.email ?? user.email ?? null,
12346
- ccphone: payload.ccphone || user.ccphone,
12347
- phone: payload.phone || user.phone,
12348
- address: payload.address || user.address,
12349
- town: payload.town || user.town,
12350
- country: payload.country || user.country,
12351
- image_url: nextImage || user.image_url,
12352
- auth_2fa: payload.auth_2fa ?? user.auth_2fa,
12353
- alias_reference: payload.alias_reference || user.alias_reference,
12354
- iam_reference: payload.iam_reference || user.iam_reference
12444
+ reference: payload.reference || profileUser.reference,
12445
+ name: payload.name || profileUser.name,
12446
+ email: payload.email ?? profileUser.email ?? null,
12447
+ ccphone: payload.ccphone || profileUser.ccphone,
12448
+ phone: payload.phone || profileUser.phone,
12449
+ address: payload.address || profileUser.address,
12450
+ town: payload.town || profileUser.town,
12451
+ country: payload.country || profileUser.country,
12452
+ image_url: nextImage || profileUser.image_url,
12453
+ auth_2fa: payload.auth_2fa ?? profileUser.auth_2fa,
12454
+ alias_reference: payload.alias_reference || profileUser.alias_reference,
12455
+ iam_reference: payload.iam_reference || profileUser.iam_reference
12355
12456
  }
12356
12457
  });
12357
12458
  }
@@ -12361,7 +12462,7 @@ function OnboardingModal({ open, onOpenChange, onDismiss, user, variant = "missi
12361
12462
  } finally {
12362
12463
  setAvatarUploading(false);
12363
12464
  }
12364
- }, [onComplete, markSuccess, user.reference, user.name, user.email, user.ccphone, user.phone, user.address, user.town, user.country, user.image_url, user.auth_2fa, user.alias_reference, user.iam_reference]);
12465
+ }, [onComplete, onUserInfosSync, toUserInfos, markSuccess, profileUser.reference, profileUser.name, profileUser.email, profileUser.ccphone, profileUser.phone, profileUser.address, profileUser.town, profileUser.country, profileUser.image_url, profileUser.auth_2fa, profileUser.alias_reference, profileUser.iam_reference]);
12365
12466
  const openContactFlow = react.useCallback((kind) => {
12366
12467
  setContactFlow({
12367
12468
  kind,
@@ -12369,7 +12470,7 @@ function OnboardingModal({ open, onOpenChange, onDismiss, user, variant = "missi
12369
12470
  requestId: null,
12370
12471
  method: kind === "email" ? "email" : currentDialCode === "+221" ? "phone" : "email",
12371
12472
  newEmail: "",
12372
- newCcphone: kind === "phone" ? user.ccphone || "+221" : "+221",
12473
+ newCcphone: kind === "phone" ? profileUser.ccphone || "+221" : "+221",
12373
12474
  newPhone: "",
12374
12475
  oldOtp: "",
12375
12476
  newOtp: "",
@@ -12377,18 +12478,18 @@ function OnboardingModal({ open, onOpenChange, onDismiss, user, variant = "missi
12377
12478
  error: "",
12378
12479
  resendAvailableAt: null
12379
12480
  });
12380
- }, [currentDialCode, user.ccphone]);
12481
+ }, [currentDialCode, profileUser.ccphone]);
12381
12482
  const closeContactFlow = react.useCallback(() => {
12382
12483
  setContactFlow(null);
12383
12484
  }, []);
12384
12485
  const updateFlow = react.useCallback((patch) => {
12385
12486
  setContactFlow((prev) => prev ? { ...prev, ...patch } : prev);
12386
12487
  }, []);
12387
- const currentPhoneDialDisplay = user.ccphone || ccphone || "+221";
12388
- const currentPhoneNumberDisplay = user.phone || phone || "";
12389
- const currentEmailLabel = user.email || email || "";
12488
+ const currentPhoneDialDisplay = profileUser.ccphone || ccphone || "+221";
12489
+ const currentPhoneNumberDisplay = profileUser.phone || phone || "";
12490
+ const currentEmailLabel = profileUser.email || email || "";
12390
12491
  const currentPhoneDialCode = currentPhoneDialDisplay.trim() || "+221";
12391
- const currentPhoneDigits = (user.phone || phone || "").replace(/\D/g, "");
12492
+ const currentPhoneDigits = (profileUser.phone || phone || "").replace(/\D/g, "");
12392
12493
  const formatPhoneDisplay = react.useCallback((dial, digits) => {
12393
12494
  const cleanDial = (dial || "+221").trim() || "+221";
12394
12495
  const cleanDigits = (digits || "").replace(/\D/g, "");
@@ -12444,13 +12545,15 @@ function OnboardingModal({ open, onOpenChange, onDismiss, user, variant = "missi
12444
12545
  const response = await profileChangeService.verifyNewOTP(contactFlow.requestId, contactFlow.newOtp);
12445
12546
  if (!response.success) throw new Error(response.message || "Code OTP incorrect");
12446
12547
  const updatedUser = {
12447
- ...user,
12548
+ ...profileUser,
12448
12549
  ...contactFlow.kind === "email" ? { email: contactFlow.newEmail.trim() } : { ccphone: contactFlow.newCcphone, phone: contactFlow.newPhone.trim() }
12449
12550
  };
12450
12551
  if (response.user && typeof response.user === "object") {
12451
12552
  Object.assign(updatedUser, response.user);
12452
12553
  }
12554
+ setHydratedUser(updatedUser);
12453
12555
  setContactFlow(null);
12556
+ onUserInfosSync == null ? void 0 : onUserInfosSync({ source: "contact", user_infos: toUserInfos(updatedUser) });
12454
12557
  onComplete({
12455
12558
  name: updatedUser.name,
12456
12559
  image_url: updatedUser.image_url,
@@ -12476,7 +12579,7 @@ function OnboardingModal({ open, onOpenChange, onDismiss, user, variant = "missi
12476
12579
  } catch (error) {
12477
12580
  updateFlow({ loading: false, error: error instanceof Error ? error.message : "Code OTP incorrect" });
12478
12581
  }
12479
- }, [contactFlow, onComplete, updateFlow, user, markSuccess]);
12582
+ }, [contactFlow, onComplete, onUserInfosSync, updateFlow, profileUser, toUserInfos, markSuccess]);
12480
12583
  const resendFlowOtp = react.useCallback(async () => {
12481
12584
  if (!(contactFlow == null ? void 0 : contactFlow.requestId) || contactFlow.loading) return;
12482
12585
  updateFlow({ loading: true, error: "" });
@@ -12629,7 +12732,7 @@ function OnboardingModal({ open, onOpenChange, onDismiss, user, variant = "missi
12629
12732
  cursor: avatarUploading ? "not-allowed" : "pointer"
12630
12733
  },
12631
12734
  children: [
12632
- photoPreview || user.image_url ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: photoPreview || user.image_url, alt: "Photo de profil", style: { width: "100%", height: "100%", objectFit: "cover" } }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "100%", height: "100%", display: "flex", alignItems: "center", justifyContent: "center", color: C.gray500 }, children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round", children: [
12735
+ photoPreview || profileUser.image_url ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: photoPreview || profileUser.image_url, alt: "Photo de profil", style: { width: "100%", height: "100%", objectFit: "cover" } }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "100%", height: "100%", display: "flex", alignItems: "center", justifyContent: "center", color: C.gray500 }, children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round", children: [
12633
12736
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "8", r: "4" }),
12634
12737
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5.5 21a8.38 8.38 0 0 1 13 0" })
12635
12738
  ] }) }),
@@ -13806,6 +13909,28 @@ function NativeSSOPage({
13806
13909
  }
13807
13910
  void refreshSessionProfile(true);
13808
13911
  }, [pendingSession, debugOnboardingState, onOnboardingComplete, persistSessionUser, refreshSessionProfile]);
13912
+ const handleOnboardingUserInfosSync = react.useCallback((payload) => {
13913
+ const activeSession = debugOnboardingState || pendingSession;
13914
+ if (!activeSession) return;
13915
+ const syncedUser = {
13916
+ ...activeSession.sourceUser,
13917
+ ...payload.user_infos
13918
+ };
13919
+ persistSessionUser(activeSession.token, syncedUser);
13920
+ if (debugOnboardingState) {
13921
+ setDebugOnboardingState((prev) => prev ? {
13922
+ ...prev,
13923
+ user: syncedUser,
13924
+ sourceUser: syncedUser
13925
+ } : prev);
13926
+ } else {
13927
+ setPendingSession((prev) => prev ? {
13928
+ ...prev,
13929
+ user: syncedUser,
13930
+ sourceUser: syncedUser
13931
+ } : prev);
13932
+ }
13933
+ }, [debugOnboardingState, pendingSession, persistSessionUser]);
13809
13934
  const handleOnboardingSkip = react.useCallback(() => {
13810
13935
  const activeSession = debugOnboardingState || pendingSession;
13811
13936
  if (!activeSession) return;
@@ -14013,6 +14138,8 @@ function NativeSSOPage({
14013
14138
  user: (debugOnboardingState || pendingSession).user,
14014
14139
  variant: debugOnboardingState ? "edit" : "missing",
14015
14140
  profileHydrating,
14141
+ hydrateProfile: false,
14142
+ onUserInfosSync: handleOnboardingUserInfosSync,
14016
14143
  onComplete: handleOnboardingComplete,
14017
14144
  onSkip: handleOnboardingSkip
14018
14145
  }
@@ -14092,6 +14219,8 @@ function NativeSSOPage({
14092
14219
  user: (debugOnboardingState || pendingSession).user,
14093
14220
  variant: debugOnboardingState ? "edit" : "missing",
14094
14221
  profileHydrating,
14222
+ hydrateProfile: false,
14223
+ onUserInfosSync: handleOnboardingUserInfosSync,
14095
14224
  onComplete: handleOnboardingComplete,
14096
14225
  onSkip: handleOnboardingSkip
14097
14226
  }