fix(onboarding): prefill verified email in a disabled field; bump SDK 0.2.4

- Onboarding reads the OAuth email (session-storage hint + live Supabase
  session via getUserEmail) so Continue is no longer disabled.
- Replace the empty 'Signed in as' banner with a disabled, prefilled
  email field (email is fixed — Google-verified).
- Stash the verified email at OAuth callback time for onboarding prefill.
- Bump @abe-kap/appshell-sdk to ^0.2.4 (getUserEmail via getSession).
This commit is contained in:
tanweer919
2026-07-13 03:55:05 +05:30
parent 948abf75fd
commit 08ef85869f
5 changed files with 798 additions and 31 deletions
+1
View File
@@ -41,3 +41,4 @@ yarn-error.log*
next-env.d.ts
.vercel
.env*.local
+780 -20
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -9,7 +9,7 @@
"lint": "eslint"
},
"dependencies": {
"@abe-kap/appshell-sdk": "^0.2.3",
"@abe-kap/appshell-sdk": "^0.2.4",
"clsx": "^2.1.1",
"lucide-react": "^1.21.0",
"next": "16.2.9",
+6 -3
View File
@@ -24,7 +24,7 @@ const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
export function LoginFlow() {
const router = useRouter();
const { login, loginWithOAuth, completeOAuthLogin } = useAuth();
const { login, loginWithOAuth, completeOAuthLogin, getUserEmail } = useAuth();
const { ready, sdk } = useAppShell();
const [step, setStep] = useState<Step>("identify");
const [email, setEmail] = useState("");
@@ -86,13 +86,16 @@ export function LoginFlow() {
registered = !!st?.registered;
} catch { registered = false; }
window.history.replaceState({}, "", "/portal/login");
router.replace(registered ? "/dashboard" : "/portal/onboarding");
if (registered) { router.replace("/dashboard"); return; }
// Capture the verified email now (session is fresh) so onboarding prefills it.
try { const em = await getUserEmail(); if (em) sessionStorage.setItem("onboard_email", em); } catch { /* ignore */ }
router.replace("/portal/onboarding");
})
.catch(() => {
setFlash("Google sign-in didn't complete. Please try again.");
replace("identify");
});
}, [ready, completeOAuthLogin, router, sdk]);
}, [ready, completeOAuthLogin, router, sdk, getUserEmail]);
/* ---- auth resolution ---- */
function afterAuth(factor: "password" | "passkey" | "otp" | "totp" | "push" | "social") {
+10 -7
View File
@@ -54,9 +54,11 @@ export function RegisterFlow({ mode = "register" }: { mode?: "register" | "onboa
const [emailVerified, setEmailVerified] = useState(false);
const [phoneVerified, setPhoneVerified] = useState(false);
// Onboarding: prefill the verified email from the Google session (the ACE omits it).
// Onboarding: prefill the verified email from the session-storage hint the login
// page stashed at OAuth time, then confirmed via the live Supabase session.
useEffect(() => {
if (!onboard) return;
try { const cached = sessionStorage.getItem("onboard_email"); if (cached) setEmail(cached); } catch { /* ignore */ }
getUserEmail().then((e) => { if (e) setEmail(e); }).catch(() => { /* ignore */ });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [onboard]);
@@ -205,12 +207,13 @@ function StepAccount(p: {
<h1>Complete your profile</h1>
<p className="sub">Tell us a bit about you to set up your account.</p>
<div style={{ marginTop: 16 }}>
{p.sso ? (
<div className="conn-banner conn-green"><Icon name="check" size={16} /> Connected with {cap(p.sso.provider)} · {p.sso.email}</div>
) : (
<div className="conn-banner conn-blue"><Icon name="mail" size={16} /> {p.onboard ? "Signed in as" : "Creating account for"} {p.email}</div>
)}
<div className="field" style={{ marginTop: 16 }}>
<label className="label">Email address</label>
<div className="input-wrap">
<span className="input-ico"><Icon name="mail" size={17} /></span>
<input className="input" type="email" value={p.email} disabled readOnly aria-label="Email address" />
</div>
<span className="faint" style={{ fontSize: 12 }}>{p.onboard ? "Verified with Google — this can't be changed." : "The email you're registering with."}</span>
</div>
<div className="row gap-3" style={{ marginTop: 18, alignItems: "center" }}>