From cc0933c514ad0dfb1ca7503d868d8662eced1de3 Mon Sep 17 00:00:00 2001 From: "soroush.asadi" Date: Thu, 4 Jun 2026 05:56:11 +0330 Subject: [PATCH] fix(auth): don't log out fullscreen routes (POS/queue) on refresh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The (fullscreen) layout redirected to /login whenever user.accessToken was falsy — but on a page refresh that fires before Zustand finishes rehydrating the persisted auth from localStorage, so an authenticated user was bounced to login on every refresh. Gate the redirect on _hasHydrated (and show a loader while rehydrating), matching RouteGuard. Tokens themselves are already long (30d access / 365d refresh), so sessions now survive refreshes as expected. Co-Authored-By: Claude Opus 4.8 --- .../src/app/[locale]/(fullscreen)/layout.tsx | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/web/dashboard/src/app/[locale]/(fullscreen)/layout.tsx b/web/dashboard/src/app/[locale]/(fullscreen)/layout.tsx index e6373ea..359a336 100644 --- a/web/dashboard/src/app/[locale]/(fullscreen)/layout.tsx +++ b/web/dashboard/src/app/[locale]/(fullscreen)/layout.tsx @@ -2,24 +2,39 @@ import { useEffect } from "react"; import { useLocale } from "next-intl"; +import { Loader2 } from "lucide-react"; import { useRouter } from "@/i18n/routing"; import { useAuthStore } from "@/lib/stores/auth.store"; import { RouteGuard } from "@/components/auth/route-guard"; -/** Full-viewport routes (queue TV display) — auth only, no dashboard chrome. */ +/** Full-viewport routes (POS, queue TV display) — auth only, no dashboard chrome. */ export default function FullscreenLayout({ children }: { children: React.ReactNode }) { const locale = useLocale(); const router = useRouter(); const user = useAuthStore((s) => s.user); + const hasHydrated = useAuthStore((s) => s._hasHydrated); + const dir = locale === "en" ? "ltr" : "rtl"; useEffect(() => { - if (!user?.accessToken) { + // Only redirect AFTER the persisted auth has rehydrated from localStorage — + // otherwise a page refresh sees the empty initial state and bounces an + // already-authenticated user to /login before their session loads back in. + if (hasHydrated && !user?.accessToken) { router.replace("/login"); } - }, [user, router]); + }, [hasHydrated, user, router]); + + // While rehydrating, show a loader instead of redirecting or flashing content. + if (!hasHydrated) { + return ( +
+ +
+ ); + } return ( -
+
{children}
);