From f9f98b1a65c276140727a779d997ab0800fd71ba Mon Sep 17 00:00:00 2001 From: Michael Chihlas Date: Fri, 15 May 2026 00:34:23 -0400 Subject: [PATCH] fix(routing): finish /home migration in WelcomeStep3 + VerifyEmailPage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The original public-landing routing refactor migrated WelcomeRouter, WelcomeStep1, and WelcomeStep2 post-onboarding redirects to /home, but left four sites still pointing at the old / + query-string destinations: - WelcomeStep3 `completeWizardAndExit` (Send invites) - WelcomeStep3 `handleSkipStep` (Skip) - VerifyEmailPage post-verify auto-redirect (`setTimeout`) - VerifyEmailPage success-state "Go to dashboard" Link These all worked by accident because PublicLanding redirects authed users from / to /home — so users still landed on the dashboard, but through an unnecessary mount-and-redirect flicker, and the `?welcome=true` / `?verified=1` query markers got dropped on the way. Drop both query markers — neither is read anywhere in the codebase (grepped frontend/src; the dashboard's onboarding UX is driven by `getOnboardingStatus`, not URL state). Carrying dead URL params just invites future "is this load-bearing?" investigations. Test stubs in WelcomeStep3.test.tsx and VerifyEmailPage.test.tsx moved from `` to `` so the assertions verify the new destination instead of accidentally matching the old one (the previous stubs masked the partial migration). Out of scope: AcceptInvitePage and OAuthCallbackPage still use `?welcome=teammate`, but that one carries an explicit "decoded by the dashboard in Task 41" annotation and may be wired up later, so left untouched. Co-Authored-By: Claude Opus 4.7 (1M context) --- frontend/src/pages/VerifyEmailPage.tsx | 10 ++++------ frontend/src/pages/__tests__/VerifyEmailPage.test.tsx | 6 +++--- frontend/src/pages/welcome/WelcomeStep3.tsx | 6 +++--- .../src/pages/welcome/__tests__/WelcomeStep3.test.tsx | 2 +- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/frontend/src/pages/VerifyEmailPage.tsx b/frontend/src/pages/VerifyEmailPage.tsx index 12fb49b8..0ac355a0 100644 --- a/frontend/src/pages/VerifyEmailPage.tsx +++ b/frontend/src/pages/VerifyEmailPage.tsx @@ -20,8 +20,7 @@ const SUCCESS_REDIRECT_MS = 1200 * "Already verified" state. No API call. * - Else fire `POST /auth/email/verify` exactly once (a `useRef` guard keeps * React 19 strict-mode double-invoke from double-firing the call). On - * success, refresh the auth store and bounce to `/?verified=1` so the - * dashboard surfaces a toast. + * success, refresh the auth store and bounce to `/home`. * - On error, show "Invalid or expired token" + a "Resend" CTA that calls * `POST /auth/email/send-verification`. */ @@ -70,10 +69,9 @@ export function VerifyEmailPage() { if (cancelled) return setStatus('success') toast.success('Email verified') - // Brief success state, then redirect with a query flag so the - // dashboard can re-surface confirmation if it wants to. + // Brief success state, then redirect to the dashboard. window.setTimeout(() => { - navigate('/?verified=1', { replace: true }) + navigate('/home', { replace: true }) }, SUCCESS_REDIRECT_MS) }) .catch((err) => { @@ -126,7 +124,7 @@ export function VerifyEmailPage() { Redirecting you to the dashboard…

} /> - dashboard} /> + dashboard} /> , @@ -130,7 +130,7 @@ describe('VerifyEmailPage', () => { } /> - dashboard} /> + dashboard} /> , @@ -142,7 +142,7 @@ describe('VerifyEmailPage', () => { } /> - dashboard} /> + dashboard} /> , diff --git a/frontend/src/pages/welcome/WelcomeStep3.tsx b/frontend/src/pages/welcome/WelcomeStep3.tsx index b345dfa3..be2f6309 100644 --- a/frontend/src/pages/welcome/WelcomeStep3.tsx +++ b/frontend/src/pages/welcome/WelcomeStep3.tsx @@ -39,7 +39,7 @@ function makeEmptyRow(): InviteRow { * * 1. POST `/accounts/me/invites/bulk` with populated rows. * 2. PATCH `/users/me/onboarding-step` `{step: 3, action: "complete"}`. - * 3. Navigate to `/?welcome=true` and fire a "You're all set" toast. + * 3. Navigate to `/home` and fire a "You're all set" toast. * * Partial-failure UX: rows in `failed[]` keep their input and show an * inline error. The wizard does NOT auto-advance when there are failures — @@ -109,7 +109,7 @@ export function WelcomeStep3() { await onboardingApi.updateStep({ step: 3, action: 'complete' }) await fetchUser() toast.success("You're all set!") - navigate('/?welcome=true') + navigate('/home') } const handleSendInvites = async () => { @@ -177,7 +177,7 @@ export function WelcomeStep3() { await onboardingApi.updateStep({ step: 3, action: 'skip' }) await fetchUser() toast.success("You're all set!") - navigate('/?welcome=true') + navigate('/home') } catch { setError('Could not save. Please try again.') setSubmitting(null) diff --git a/frontend/src/pages/welcome/__tests__/WelcomeStep3.test.tsx b/frontend/src/pages/welcome/__tests__/WelcomeStep3.test.tsx index c90be2dd..b6d0788e 100644 --- a/frontend/src/pages/welcome/__tests__/WelcomeStep3.test.tsx +++ b/frontend/src/pages/welcome/__tests__/WelcomeStep3.test.tsx @@ -88,7 +88,7 @@ function renderPage() { } /> - dashboard} /> + dashboard} /> , )