Files
frontend/src/app/(user)/layout.tsx

129 lines
3.8 KiB
TypeScript
Raw Normal View History

2026-01-11 21:30:57 +05:30
'use client';
import { useSession } from 'next-auth/react';
import { useRouter, usePathname } from 'next/navigation';
import { useEffect, useState } from 'react';
import { Footer } from '@/components/layout/Footer';
import { CommonHeader } from '@/components/layout/CommonHeader';
import { PresenceProvider } from '@/components/providers/presence-provider';
2026-01-11 21:30:57 +05:30
// Pages that don't require authentication
const publicPaths = [
'/user/dashboard',
'/user/profiles',
'/user/profile/', // Agent profile view (includes /user/profile/[id])
];
// Check if current path is public
const isPublicPath = (pathname: string) => {
return publicPaths.some(path => pathname === path || pathname.startsWith(path));
};
2026-01-11 21:21:34 +05:30
export default function UserLayout({
children,
}: {
children: React.ReactNode;
}) {
2026-01-11 21:30:57 +05:30
const { data: session, status } = useSession();
const router = useRouter();
const pathname = usePathname();
const [hasTokens, setHasTokens] = useState(false);
const isDashboard = pathname === '/user/dashboard';
const isPublic = isPublicPath(pathname);
2026-01-11 21:30:57 +05:30
// Fast check for existing tokens on mount
useEffect(() => {
setHasTokens(!!localStorage.getItem('accessToken'));
}, []);
2026-01-11 21:30:57 +05:30
useEffect(() => {
if (status === 'loading') return;
// Allow public pages without authentication
if (isPublic) {
// If logged in as agent, redirect to agent dashboard only from user dashboard
if (session && pathname === '/user/dashboard') {
const userRole = (session.user as any)?.role;
if (userRole === 'AGENT') {
router.replace('/agent/dashboard');
}
}
return;
}
// Protected pages require login
2026-01-11 21:30:57 +05:30
if (!session) {
// Check localStorage - if tokens exist, session might still be resolving
// Don't redirect to /login prematurely (prevents login page flash)
const tokensExist = !!localStorage.getItem('accessToken');
if (!tokensExist) {
router.replace('/login');
}
2026-01-11 21:30:57 +05:30
return;
}
// Redirect agents to agent dashboard for protected user pages
2026-01-11 21:30:57 +05:30
const userRole = (session.user as any)?.role;
if (userRole === 'AGENT') {
router.replace('/agent/dashboard');
}
}, [session, status, router, pathname, isPublic]);
// Show loading only for protected pages while checking auth
if (status === 'loading' && !isPublic) {
return (
<div className="min-h-screen bg-white flex items-center justify-center">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-[#00293d]"></div>
</div>
);
}
2026-01-11 21:30:57 +05:30
// Redirect protected pages if not logged in
if (!session && !isPublic) {
2026-01-11 21:30:57 +05:30
return (
<div className="min-h-screen bg-white flex items-center justify-center">
2026-01-11 21:30:57 +05:30
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-[#00293d]"></div>
</div>
);
}
return (
<PresenceProvider>
<div className="min-h-screen flex flex-col">
{isDashboard ? (
<>
{/* Main Content with Header Overlay for Dashboard */}
<main className="flex-1 relative">
{/* Header overlaying the content */}
<div className="absolute top-0 left-0 right-0 z-50 px-4 py-3">
<div className="max-w-7xl mx-auto">
<CommonHeader />
</div>
</div>
{children}
</main>
</>
) : (
<>
{/* Regular Header for other pages */}
<div className="px-4 py-3 bg-white">
<div className="max-w-7xl mx-auto">
<CommonHeader />
</div>
</div>
{/* Main Content */}
<main className="flex-1">
{children}
</main>
</>
)}
2026-01-11 21:30:57 +05:30
{/* Footer */}
<Footer />
</div>
</PresenceProvider>
2026-01-11 21:30:57 +05:30
);
2026-01-11 21:21:34 +05:30
}