134 lines
3.9 KiB
TypeScript
134 lines
3.9 KiB
TypeScript
"use client";
|
|
|
|
import { useSession } from "next-auth/react";
|
|
import { useRouter, usePathname } from "next/navigation";
|
|
import { useEffect } from "react";
|
|
import Image from "next/image";
|
|
import { Footer } from "@/components/layout/Footer";
|
|
import { CommonHeader } from "@/components/layout/CommonHeader";
|
|
import { PresenceProvider } from "@/components/providers/presence-provider";
|
|
|
|
// Pages that don't require authentication
|
|
const publicPaths = [
|
|
"/home",
|
|
"/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),
|
|
);
|
|
};
|
|
|
|
export default function UserLayout({
|
|
children,
|
|
}: {
|
|
children: React.ReactNode;
|
|
}) {
|
|
const { data: session, status } = useSession();
|
|
const router = useRouter();
|
|
const pathname = usePathname();
|
|
// const isDashboard = pathname === "/user/dashboard";
|
|
const isDashboard = pathname === "/user/dashboard" || pathname === "/home";
|
|
const isPublic = isPublicPath(pathname);
|
|
|
|
useEffect(() => {
|
|
if (status === "loading") return;
|
|
|
|
// Allow public pages without authentication.
|
|
// Agents are intentionally allowed to land on /user/dashboard — the logo
|
|
// points there for all roles, so this layout must not bounce them away.
|
|
if (isPublic) {
|
|
return;
|
|
}
|
|
|
|
// Don't redirect to /login here for protected pages — the middleware handles that.
|
|
// Doing it here causes race conditions during logout (layout detects session loss
|
|
// and redirects to /login via client-side navigation, conflicting with server-side
|
|
// logout redirect).
|
|
if (!session) return;
|
|
|
|
// Redirect agents to agent dashboard for protected user pages
|
|
const userRole = (session.user as any)?.role;
|
|
if (userRole === "AGENT") {
|
|
router.replace("/agent/dashboard");
|
|
}
|
|
}, [session, status, router, pathname, isPublic]);
|
|
|
|
const splashLoading = (
|
|
<div
|
|
className="min-h-screen flex flex-col items-center justify-center"
|
|
style={{ background: "linear-gradient(to bottom, #c4d9d4, #f0f5fc)" }}
|
|
>
|
|
<Image
|
|
src="/assets/images/splash-house.png"
|
|
alt=""
|
|
width={150}
|
|
height={108}
|
|
priority
|
|
/>
|
|
<div className="mt-[35px]">
|
|
<Image
|
|
src="/assets/images/splash-logo.png"
|
|
alt="RE-Quest"
|
|
width={264}
|
|
height={55}
|
|
priority
|
|
/>
|
|
</div>
|
|
<div className="mt-8">
|
|
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-[#00293d]" />
|
|
</div>
|
|
</div>
|
|
);
|
|
|
|
// Show loading only for protected pages while checking auth
|
|
if (status === "loading" && !isPublic) {
|
|
return splashLoading;
|
|
}
|
|
|
|
// Redirect protected pages if not logged in
|
|
if (!session && !isPublic) {
|
|
return splashLoading;
|
|
}
|
|
|
|
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 sm:px-6 lg:px-8 pt-3 pb-1 bg-white">
|
|
<div className="max-w-7xl mx-auto">
|
|
<CommonHeader />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Main Content */}
|
|
<main className="flex-1">{children}</main>
|
|
</>
|
|
)}
|
|
|
|
{/* Footer */}
|
|
<Footer />
|
|
</div>
|
|
</PresenceProvider>
|
|
);
|
|
}
|