From bc5ede096b65e3cee84eda38efb769f2f13f5558 Mon Sep 17 00:00:00 2001 From: Cascade Bot Date: Mon, 23 Feb 2026 13:02:40 +0000 Subject: [PATCH] fix(dashboard): fix auth routing - reactive state, beforeLoad guard, post-login nav --- web/src/routes/__root.tsx | 41 ++++++++++++++++++++++++--------------- web/src/routes/login.tsx | 4 ++-- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/web/src/routes/__root.tsx b/web/src/routes/__root.tsx index 930c107d..b9f2b1b7 100644 --- a/web/src/routes/__root.tsx +++ b/web/src/routes/__root.tsx @@ -1,22 +1,15 @@ import { Header } from '@/components/layout/header.js'; import { Sidebar } from '@/components/layout/sidebar.js'; import { OrgProvider } from '@/lib/org-context.js'; +import { queryClient } from '@/lib/query-client.js'; import { trpc } from '@/lib/trpc.js'; import { useQuery } from '@tanstack/react-query'; -import { Outlet, createRootRoute, useNavigate } from '@tanstack/react-router'; -import { useEffect } from 'react'; +import { Outlet, createRootRoute, redirect, useRouterState } from '@tanstack/react-router'; function RootLayout() { - const navigate = useNavigate(); - const meQuery = useQuery(trpc.auth.me.queryOptions()); - - const isLoginPage = window.location.pathname === '/login'; - - useEffect(() => { - if (meQuery.isError && !isLoginPage) { - navigate({ to: '/login' }); - } - }, [meQuery.isError, isLoginPage, navigate]); + const routerState = useRouterState(); + const isLoginPage = routerState.location.pathname === '/login'; + const meQuery = useQuery({ ...trpc.auth.me.queryOptions(), retry: false }); if (isLoginPage) { return ; @@ -30,10 +23,6 @@ function RootLayout() { ); } - if (meQuery.isError) { - return null; - } - return (
@@ -49,6 +38,26 @@ function RootLayout() { ); } +function PendingComponent() { + return ( +
+
Loading...
+
+ ); +} + export const rootRoute = createRootRoute({ component: RootLayout, + pendingComponent: PendingComponent, + beforeLoad: async ({ location }) => { + if (location.pathname === '/login') return; + try { + await queryClient.ensureQueryData({ + ...trpc.auth.me.queryOptions(), + retry: false, + }); + } catch { + throw redirect({ to: '/login' }); + } + }, }); diff --git a/web/src/routes/login.tsx b/web/src/routes/login.tsx index 261ff7cd..45ee9d5b 100644 --- a/web/src/routes/login.tsx +++ b/web/src/routes/login.tsx @@ -32,8 +32,8 @@ function LoginPage() { return; } - await queryClient.refetchQueries({ queryKey: trpc.auth.me.queryOptions().queryKey }); - navigate({ to: '/' }); + await queryClient.invalidateQueries({ queryKey: trpc.auth.me.queryOptions().queryKey }); + navigate({ to: '/', replace: true }); } catch { setError('Network error'); } finally {