62 lines
1.9 KiB
TypeScript
62 lines
1.9 KiB
TypeScript
"use client"
|
|
|
|
import { useEffect, useState } from "react"
|
|
import { useRouter } from "next/navigation"
|
|
import { Sidebar } from "@/components/sidebar"
|
|
import { DashboardHeader } from "@/components/dashboard-header"
|
|
import { getCurrentUser } from "@/lib/auth"
|
|
|
|
export default function DashboardLayout({
|
|
children,
|
|
}: {
|
|
children: React.ReactNode
|
|
}) {
|
|
const router = useRouter()
|
|
const [isAuthorized, setIsAuthorized] = useState(false)
|
|
const [mounted, setMounted] = useState(false)
|
|
|
|
useEffect(() => {
|
|
setMounted(true)
|
|
// Simple auth check for dashboard access
|
|
const user = getCurrentUser()
|
|
if (!user) {
|
|
router.push("/login")
|
|
} else {
|
|
setIsAuthorized(true)
|
|
}
|
|
}, [router])
|
|
|
|
// Prevent hydration mismatch by returning null on first render
|
|
if (!mounted) return null
|
|
|
|
// Optional: Loading state while checking auth
|
|
if (!isAuthorized) {
|
|
return (
|
|
// Simple loading screen to match background
|
|
<div className="min-h-screen bg-background flex items-center justify-center">
|
|
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
// Canonical Layout Structure
|
|
return (
|
|
<div className="flex h-screen overflow-hidden bg-background">
|
|
{/* Sidebar - Fixed Left, Fixed Width */}
|
|
<Sidebar />
|
|
|
|
{/* Main Content Area - Flex Column */}
|
|
<div className="flex-1 flex flex-col h-full w-full overflow-hidden">
|
|
{/* Header - Fixed Top */}
|
|
<div className="h-16 shrink-0 z-50">
|
|
<DashboardHeader />
|
|
</div>
|
|
|
|
{/* Scrollable Main Content */}
|
|
<main className="flex-1 overflow-y-auto p-6 scroll-smooth bg-muted/10">
|
|
{children}
|
|
</main>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|