import React, { useRef, useState, useEffect } from 'react';
import { Outlet, NavLink, useNavigate, useLocation } from 'react-router-dom';
import { useAuth } from '../context/AuthContext';
import { useTheme } from '../context/ThemeContext';
import {
LayoutDashboard, Map, Calendar, LogOut, User, Home, MessageSquare,
ChevronLeft, ChevronRight, Sun, Moon, Trophy, Users, Briefcase,
FileText, Menu, X, Calculator, PlusCircle, ClipboardList, Zap
} from 'lucide-react';
import PageTransition from './PageTransition';
import Chatbot from './Chatbot';
import Logo from '../assets/images/LynkedUp_Icon.png';
const SidebarItem = ({ to, icon: Icon, label, isCollapsed, onClick }) => {
return (
`
group relative flex items-center px-3 py-3 rounded-xl mb-1
transition-all duration-200 outline-none
${isCollapsed ? 'justify-center' : 'space-x-3'}
${isActive
? 'text-zinc-900 dark:text-white font-semibold'
: 'text-zinc-500 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-white'
}
`
}
>
{({ isActive }) => (
<>
{/* Glow/Border Effect Container */}
{/* Sharp Border */}
{/* Masking Background (Creates the border look) */}
{/* Content */}
{label}
{'S'}{'.'}{'y'}{'.'}{'s'}{'.'}{'t'}{'.'}{'e'}{'.'}{'m'}{'.'}
{/* Collapsed Tooltip */}
{isCollapsed && (
{label}
)}
>
)}
);
};
const Layout = () => {
const { user, logout } = useAuth();
const { theme, toggleTheme } = useTheme();
const navigate = useNavigate();
const location = useLocation();
// -- State --
// Desktop: User controls collapse manually. Default open.
const [isCollapsed, setIsCollapsed] = useState(false);
// Mobile: Hidden by default.
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const handleLogout = () => {
logout();
navigate('/login');
};
// Close mobile menu on route change
useEffect(() => {
setIsMobileMenuOpen(false);
}, [location.pathname]);
// Body scroll lock when mobile menu is open
useEffect(() => {
document.body.style.overflow = isMobileMenuOpen ? 'hidden' : '';
return () => { document.body.style.overflow = ''; };
}, [isMobileMenuOpen]);
// Keyboard Accessibility: Close mobile menu on ESC
useEffect(() => {
const handleEsc = (e) => {
if (e.key === 'Escape') {
setIsMobileMenuOpen(false);
}
};
window.addEventListener('keydown', handleEsc);
return () => window.removeEventListener('keydown', handleEsc);
}, []);
// Determine standard layout vs full screen for Public pages
const isPublic = ['/', '/login'].includes(location.pathname);
if (isPublic) {
return (
);
}
// Role-specific Navigation Items
const getNavItems = () => {
if (!user) return [];
const commonItems = [
{ to: "/chat-assistant", icon: MessageSquare, label: "AI Assistant" },
];
const homeItem = { to: "/", icon: Home, label: "Home" };
switch (user.role) {
case 'OWNER':
return [
{ to: "/owner/snapshot", icon: LayoutDashboard, label: "Owners Box" },
{ to: "/admin/dashboard", icon: LayoutDashboard, label: "Dashboard" },
{ to: "/owner/projects", icon: Briefcase, label: "Projects" },
{ to: "/emp/fa/leads", icon: ClipboardList, label: "Leads" },
{ to: "/admin/dispatch", icon: Zap, label: "LynkDispatch" },
{ to: "/owner/maps", icon: Map, label: "Territory Map" },
{
to: "/owner/pro-canvas",
icon: LayoutDashboard,
label: ProCanvas
},
{ to: "/owner/estimates", icon: Calculator, label: "Estimates" },
{ to: "/admin/schedule", icon: Calendar, label: "Team Schedule" },
{ to: "/admin/leaderboard", icon: Trophy, label: "Leaderboard" },
...commonItems,
];
case 'ADMIN':
return [
{ to: "/admin/dashboard", icon: LayoutDashboard, label: "Dashboard" },
{ to: "/admin/schedule", icon: Calendar, label: "Schedule" },
{ to: "/admin/leaderboard", icon: Trophy, label: "Leaderboard" },
{ to: "/emp/fa/leads", icon: ClipboardList, label: "Leads" },
{ to: "/admin/dispatch", icon: Zap, label: "LynkDispatch" },
{ to: "/admin/maps", icon: Map, label: "Territory Map" },
{
to: "/admin/pro-canvas",
icon: LayoutDashboard,
label: ProCanvas
},
{ to: "/admin/estimates", icon: Calculator, label: "Estimates" },
...commonItems,
];
case 'CONTRACTOR':
case 'SUBCONTRACTOR':
return [
{ to: user.role === 'CONTRACTOR' ? "/contractor/dashboard" : "/subcontractor/dashboard", icon: LayoutDashboard, label: "Dashboard" },
{ to: user.role === 'CONTRACTOR' ? "/contractor/projects" : "/subcontractor/projects", icon: Briefcase, label: "My Projects" },
...commonItems,
];
case 'VENDOR':
return [
{ to: "/vendor/dashboard", icon: LayoutDashboard, label: "Dashboard" },
{ to: "/vendor/orders", icon: Briefcase, label: "Orders" },
...commonItems,
];
case 'FIELD_AGENT':
return [
{ to: "/emp/fa/dashboard", icon: LayoutDashboard, label: "Dashboard" },
{ to: "/emp/fa/maps", icon: Map, label: "My Map" },
{ to: "/emp/fa/leads", icon: ClipboardList, label: "Leads" },
{
to: "/emp/fa/pro-canvas",
icon: LayoutDashboard,
label: ProCanvas
},
{ to: "/emp/fa/estimates", icon: Calculator, label: "Estimates" },
...commonItems,
];
default: // Customer or Fallback
return [
{ to: "/customer/profile", icon: LayoutDashboard, label: "Dashboard" },
...commonItems,
];
}
};
const navItems = getNavItems();
return (
{/* --- Mobile Header --- */}
LynkedUp Pro
{/* --- Mobile Backdrop --- */}
{isMobileMenuOpen && (
setIsMobileMenuOpen(false)}
aria-hidden="true"
/>
)}
{/* --- Sidebar --- */}
{/* --- Main Content --- */}
);
};
export default Layout;