import React, { useState, useEffect } from "react"; import { Link, Outlet, useNavigate, useLocation } from "react-router-dom"; import { useAuth } from "@/contexts/AuthContext"; import { Package, ChevronLeft, ChevronRight, User, LogOut, CirclePlay, CircleArrowRight, SquareArrowRight, SquarePlay, SquareDot, CircleDot, SquareAsterisk, KeyRound, Home, } from "lucide-react"; // Color mappings for navigation items — defined outside component for stable reference const colorClasses = { gray: { inactive: "text-gray-300 hover:text-white hover:bg-gray-800", active: "bg-gray-800 text-white", icon: "text-gray-400", }, cyan: { inactive: "text-cyan-300 hover:text-cyan-100 hover:bg-cyan-950/30", active: "bg-cyan-950/50 text-cyan-100 shadow-lg shadow-cyan-900/50", icon: "text-cyan-400", }, blue: { inactive: "text-blue-300 hover:text-blue-100 hover:bg-blue-950/30", active: "bg-blue-950/50 text-blue-100 shadow-lg shadow-blue-900/50", icon: "text-blue-400", }, violet: { inactive: "text-violet-300 hover:text-violet-100 hover:bg-violet-950/30", active: "bg-violet-950/50 text-violet-100 shadow-lg shadow-violet-900/50", icon: "text-violet-400", }, purple: { inactive: "text-purple-300 hover:text-purple-100 hover:bg-purple-950/30", active: "bg-purple-950/50 text-purple-100 shadow-lg shadow-purple-900/50", icon: "text-purple-400", }, fuchsia: { inactive: "text-fuchsia-300 hover:text-fuchsia-100 hover:bg-fuchsia-950/30", active: "bg-fuchsia-950/50 text-fuchsia-100 shadow-lg shadow-fuchsia-900/50", icon: "text-fuchsia-400", }, rose: { inactive: "text-rose-300 hover:text-rose-100 hover:bg-rose-950/30", active: "bg-rose-950/50 text-rose-100 shadow-lg shadow-rose-900/50", icon: "text-rose-400", }, orange: { inactive: "text-orange-300 hover:text-orange-100 hover:bg-orange-950/30", active: "bg-orange-950/50 text-orange-100 shadow-lg shadow-orange-900/50", icon: "text-orange-400", }, }; // Navigation sections with dividers and colors const navSections = [ { items: [{ to: "/", label: "Dashboard", icon: Home, color: "gray" }], }, { // Component Management - Cool colors (cyan -> blue -> violet) items: [ { to: "/actions", label: "Actions", icon: SquarePlay, color: "cyan" }, { to: "/rules", label: "Rules", icon: SquareArrowRight, color: "blue" }, { to: "/triggers", label: "Triggers", icon: SquareDot, color: "violet", }, { to: "/sensors", label: "Sensors", icon: SquareAsterisk, color: "purple", }, ], }, { // Runtime Logs - Warm colors (fuchsia -> rose -> orange) items: [ { to: "/executions", label: "Execution History", icon: CirclePlay, color: "fuchsia", }, { to: "/enforcements", label: "Enforcement History", icon: CircleArrowRight, color: "rose", }, { to: "/events", label: "Event History", icon: CircleDot, color: "orange", }, ], }, { items: [ { to: "/keys", label: "Keys & Secrets", icon: KeyRound, color: "gray" }, { to: "/packs", label: "Pack Management", icon: Package, color: "gray", }, ], }, ]; // NavLink extracted outside MainLayout so React preserves DOM identity across // re-renders, which is required for CSS transitions to work on collapse/expand. function NavLink({ to, label, icon: Icon, color = "gray", isCollapsed, isActive, }: { to: string; label: string; icon: React.ElementType; color?: string; isCollapsed: boolean; isActive: boolean; }) { const colors = colorClasses[color as keyof typeof colorClasses] || colorClasses.gray; return ( {label} ); } export default function MainLayout() { const { user, logout } = useAuth(); const navigate = useNavigate(); const location = useLocation(); const [isCollapsed, setIsCollapsed] = useState(() => { // Initialize from localStorage const saved = localStorage.getItem("sidebar-collapsed"); return saved === "true"; }); const [showUserMenu, setShowUserMenu] = useState(false); // Persist collapsed state to localStorage and close user menu when expanding useEffect(() => { localStorage.setItem("sidebar-collapsed", isCollapsed.toString()); }, [isCollapsed]); const handleToggleCollapse = () => { setIsCollapsed((prev) => { const next = !prev; if (!next) { setShowUserMenu(false); } return next; }); }; const handleLogout = () => { logout(); navigate("/login"); }; return (
{/* Sidebar */}
{/* Header */}
Attune Attune
{/* Navigation */} {/* Toggle Button */}
{/* User Section */}

{user?.login}

{/* User Menu Popup (collapsed mode only) */} {isCollapsed && showUserMenu && ( <>
setShowUserMenu(false)} />

{user?.login}

)}
{/* Main Content */}
); }