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 ( +