"use client"; import React, { useEffect, useState } from "react"; import { useRouter, usePathname } from "next/navigation"; import Link from "next/link"; import { LayoutDashboard, Users, Clock, FileSpreadsheet, Settings, Monitor, LogOut, Menu, X, ChevronRight, Scan, History, Sun, Moon } from "lucide-react"; import { getAccessToken, getUserProfile, clearTokens } from "@/app/utils/api"; const navItems = [ { name: "Dashboard", href: "/dashboard", icon: LayoutDashboard }, { name: "Attendance", href: "/attendance", icon: Clock }, { name: "Employees", href: "/employees", icon: Users }, { name: "Reports", href: "/reports", icon: FileSpreadsheet }, { name: "Audit Logs", href: "/audit", icon: History }, { name: "Settings", href: "/settings", icon: Settings }, ]; function NavLink({ item, isActive, isCollapsed, onClick }: { item: typeof navItems[0], isActive: boolean, isCollapsed: boolean, onClick?: () => void }) { const Icon = item.icon; return ( {/* Active indicator */} {isActive && ( )}
{!isCollapsed && (

{item.name}

)} {isActive && !isCollapsed && } ); } export default function SidebarLayout({ children }: { children: React.ReactNode }) { const router = useRouter(); const pathname = usePathname(); const [sidebarOpen, setSidebarOpen] = useState(false); const [isCollapsed, setIsCollapsed] = useState(false); const [user, setUser] = useState(null); const [authorized, setAuthorized] = useState(false); const [theme, setTheme] = useState<"light" | "dark">("light"); // Load theme and sidebar state from localStorage on client side useEffect(() => { const saved = localStorage.getItem("sidebar_collapsed"); if (saved === "true") { setIsCollapsed(true); } const savedTheme = localStorage.getItem("theme"); const systemPrefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches; const initialTheme = (savedTheme as "light" | "dark") || (systemPrefersDark ? "dark" : "light"); setTheme(initialTheme); if (initialTheme === "dark") { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } }, []); const toggleTheme = () => { const nextTheme = theme === "dark" ? "light" : "dark"; setTheme(nextTheme); localStorage.setItem("theme", nextTheme); if (nextTheme === "dark") { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } }; const toggleCollapse = () => { const nextVal = !isCollapsed; setIsCollapsed(nextVal); localStorage.setItem("sidebar_collapsed", String(nextVal)); }; useEffect(() => { const token = getAccessToken(); const profile = getUserProfile(); if (!token || !profile) { clearTokens(); router.push("/"); } else { setUser(profile); setAuthorized(true); } }, [router]); if (!authorized) { return (

Authenticating...

); } const handleLogout = () => { clearTokens(); router.push("/"); }; const initials = user?.email ? user.email[0].toUpperCase() : "A"; return (
{/* Ambient background */}
{/* ─── Desktop Sidebar ─── */} {/* ─── Mobile Top Bar ─── */}
NetraID
{/* Theme Toggle Mobile */}
{/* ─── Mobile Drawer ─── */} {sidebarOpen && (
setSidebarOpen(false)} >
)} {/* ─── Main Content ─── */}
{/* Desktop Top Navbar */}
{children}
); }