feat: complete premium NEET/JEE platform with admin, student dashboards, and upgraded branding
This commit is contained in:
123
src/app/dashboard/layout.tsx
Normal file
123
src/app/dashboard/layout.tsx
Normal file
@@ -0,0 +1,123 @@
|
||||
"use client"
|
||||
|
||||
import { ReactNode, useState, useEffect, useRef } from "react"
|
||||
import { BookOpen, LayoutDashboard, Settings, FileText, Activity, LineChart, Trophy, LogOut, User, ChevronUp } from "lucide-react"
|
||||
import Link from "next/link"
|
||||
import Image from "next/image"
|
||||
import { usePathname } from "next/navigation"
|
||||
|
||||
export default function DashboardLayout({ children }: { children: ReactNode }) {
|
||||
const pathname = usePathname()
|
||||
const [dropdownOpen, setDropdownOpen] = useState(false)
|
||||
const dropdownRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
// Close dropdown when clicking outside
|
||||
useEffect(() => {
|
||||
function handleClickOutside(event: MouseEvent) {
|
||||
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
|
||||
setDropdownOpen(false)
|
||||
}
|
||||
}
|
||||
document.addEventListener("mousedown", handleClickOutside)
|
||||
return () => document.removeEventListener("mousedown", handleClickOutside)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="flex h-screen bg-background overflow-hidden text-foreground selection:bg-primary/20">
|
||||
{/* Sidebar */}
|
||||
<aside className="w-64 border-r border-border bg-background flex flex-col hidden md:flex">
|
||||
<div className="p-6">
|
||||
<Link href="/dashboard" className="block relative h-16 w-full hover:opacity-90 transition-opacity">
|
||||
<Image
|
||||
src="/PragatiVeer_Logo/SVG_Logos/Rectangular_light_background.svg"
|
||||
alt="PragatiVeer"
|
||||
fill
|
||||
className="object-contain object-left scale-135 origin-left dark:hidden"
|
||||
priority
|
||||
/>
|
||||
<Image
|
||||
src="/PragatiVeer_Logo/SVG_Logos/Rectangular_dark_background.svg"
|
||||
alt="PragatiVeer"
|
||||
fill
|
||||
className="object-contain object-left scale-135 origin-left hidden dark:block"
|
||||
priority
|
||||
/>
|
||||
</Link>
|
||||
</div>
|
||||
<nav className="flex-1 px-4 space-y-1.5 mt-4 overflow-y-auto">
|
||||
<NavItem href="/dashboard" icon={<LayoutDashboard size={18} />} label="Overview" active={pathname === "/dashboard"} />
|
||||
<NavItem href="/dashboard/cbt" icon={<Activity size={18} />} label="Exams (CBT)" active={pathname.startsWith("/dashboard/cbt")} />
|
||||
<NavItem href="/dashboard/dpp" icon={<FileText size={18} />} label="Daily Practice" active={pathname.startsWith("/dashboard/dpp")} />
|
||||
<NavItem href="/dashboard/materials" icon={<BookOpen size={18} />} label="Study Materials" active={pathname.startsWith("/dashboard/materials")} />
|
||||
|
||||
<div className="pt-4 pb-2">
|
||||
<p className="px-3 text-xs font-bold uppercase tracking-widest text-muted-foreground">AI Intelligence</p>
|
||||
</div>
|
||||
<NavItem href="/dashboard/analytics" icon={<LineChart size={18} />} label="Performance Analytics" active={pathname.startsWith("/dashboard/analytics")} />
|
||||
<NavItem href="/dashboard/rank-predictor" icon={<Trophy size={18} />} label="Rank Predictor" active={pathname.startsWith("/dashboard/rank-predictor")} />
|
||||
</nav>
|
||||
|
||||
<div className="p-4 border-t border-border space-y-2">
|
||||
<NavItem href="/dashboard/settings" icon={<Settings size={18} />} label="Settings" active={pathname.startsWith("/dashboard/settings")} />
|
||||
|
||||
{/* Functional User Dropdown */}
|
||||
<div className="relative mt-2" ref={dropdownRef}>
|
||||
{dropdownOpen && (
|
||||
<div className="absolute bottom-full left-0 w-full mb-2 bg-background border border-border rounded-xl shadow-lg shadow-black/10 overflow-hidden animate-in fade-in slide-in-from-bottom-2 duration-200 z-50">
|
||||
<div className="px-4 py-3 border-b border-border">
|
||||
<p className="text-sm font-bold text-foreground">Demo Student</p>
|
||||
<p className="text-xs text-muted-foreground truncate">demo@pragativeer.com</p>
|
||||
</div>
|
||||
<div className="p-1">
|
||||
<Link href="/dashboard/settings" className="flex items-center gap-2 px-3 py-2 text-sm text-foreground hover:bg-secondary rounded-lg transition-colors">
|
||||
<User size={16} /> Edit Profile
|
||||
</Link>
|
||||
<Link href="/" className="flex items-center gap-2 px-3 py-2 text-sm text-red-500 hover:bg-red-500/10 rounded-lg transition-colors font-medium mt-1">
|
||||
<LogOut size={16} /> Log out
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<button
|
||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
||||
className="w-full flex items-center justify-between p-2 rounded-xl hover:bg-secondary/50 transition-colors border border-transparent hover:border-border"
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="h-8 w-8 rounded-full bg-[#00F0FF]/20 text-[#00F0FF] flex items-center justify-center font-bold text-sm shadow-[0_0_10px_-2px_#00F0FF]">
|
||||
DS
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<p className="text-sm font-bold leading-none">Demo Student</p>
|
||||
<p className="text-xs text-[#00F0FF] font-medium mt-1">AI Pro Plan</p>
|
||||
</div>
|
||||
</div>
|
||||
<ChevronUp size={16} className={`text-muted-foreground transition-transform ${dropdownOpen ? "rotate-180" : ""}`} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
{/* Main Content */}
|
||||
<main className="flex-1 overflow-y-auto">
|
||||
{children}
|
||||
</main>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function NavItem({ href, icon, label, active }: { href: string, icon: React.ReactNode, label: string, active?: boolean }) {
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
className={`flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-300 ${
|
||||
active
|
||||
? "bg-secondary text-foreground font-medium border border-border"
|
||||
: "text-muted-foreground hover:bg-secondary/50 hover:text-foreground border border-transparent"
|
||||
}`}
|
||||
>
|
||||
{icon}
|
||||
<span className="text-sm">{label}</span>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user