100 lines
4.7 KiB
TypeScript
100 lines
4.7 KiB
TypeScript
import { Outlet, Link } from '@tanstack/react-router';
|
|
import { useAuthStore } from '../../hooks/use-auth';
|
|
import { useThemeStore } from '../../hooks/use-theme';
|
|
import { motion } from 'framer-motion';
|
|
import { LayoutDashboard, FolderKanban, FileSignature, Users, LogOut, Sun, Moon } from 'lucide-react';
|
|
|
|
export const MainLayout = () => {
|
|
const { isAuthenticated, logout, user } = useAuthStore();
|
|
const { theme, toggleTheme } = useThemeStore();
|
|
|
|
if (!isAuthenticated) {
|
|
return <Outlet />;
|
|
}
|
|
|
|
const NAV_ITEMS = [
|
|
{ name: 'Dashboard', path: '/', icon: LayoutDashboard },
|
|
{ name: 'Asset Library', path: '/assets', icon: FolderKanban },
|
|
{ name: 'Legal Documents', path: '/legal', icon: FileSignature },
|
|
{ name: 'Directory', path: '/directory', icon: Users },
|
|
];
|
|
|
|
return (
|
|
<div className="flex h-screen bg-ink-50 text-ink-900 overflow-hidden font-sans transition-colors duration-500">
|
|
{/* Sidebar */}
|
|
<motion.aside
|
|
initial={{ x: -300 }}
|
|
animate={{ x: 0 }}
|
|
className="w-72 bg-ink-0 border-r border-ink-200 flex flex-col relative z-20"
|
|
>
|
|
<div className="h-24 flex items-center px-8 border-b border-ink-200">
|
|
<div className="flex items-center gap-4">
|
|
<div className="relative flex items-center justify-center w-11 h-11 rounded-2xl bg-ink-0 border border-ink-200 shadow-sm p-1">
|
|
<img src="/logo.png" alt="Tech4Biz" className="w-full h-full object-contain" />
|
|
</div>
|
|
<span className="font-extrabold text-xl tracking-tight text-ink-900">Tech4Biz</span>
|
|
</div>
|
|
</div>
|
|
|
|
<nav className="flex-1 px-4 py-8 space-y-2 overflow-y-auto">
|
|
{NAV_ITEMS.map((item) => (
|
|
<Link
|
|
key={item.path}
|
|
to={item.path}
|
|
className="flex items-center gap-4 px-4 py-3.5 rounded-xl transition-all duration-300 text-ink-500 hover:text-ink-900 hover:bg-ink-100 group"
|
|
activeProps={{ className: 'bg-ink-100 text-ink-900 border border-ink-300 shadow-sm' }}
|
|
activeOptions={{ exact: item.path === '/' }}
|
|
>
|
|
<item.icon className="w-5 h-5 transition-transform group-hover:scale-110" />
|
|
<span className="font-semibold tracking-wide text-sm">{item.name}</span>
|
|
</Link>
|
|
))}
|
|
</nav>
|
|
|
|
<div className="p-5 border-t border-ink-200 bg-ink-50">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<p className="text-[10px] font-bold text-ink-400 uppercase tracking-widest">Theme Preference</p>
|
|
<button
|
|
onClick={toggleTheme}
|
|
className="p-2 rounded-lg bg-ink-0 border border-ink-200 text-ink-500 hover:text-ink-900 hover:shadow-sm transition-all group"
|
|
>
|
|
{theme === 'dark' ? <Sun className="w-4 h-4 group-hover:rotate-90 transition-transform" /> : <Moon className="w-4 h-4 group-hover:-rotate-12 transition-transform" />}
|
|
</button>
|
|
</div>
|
|
<div className="flex items-center gap-4 p-3.5 rounded-2xl bg-ink-0 border border-ink-200 mb-4 shadow-sm">
|
|
<div className="w-10 h-10 rounded-full bg-gradient-to-br from-ink-900 to-ink-800 flex items-center justify-center text-ink-0 text-sm font-bold shadow-lg">
|
|
{user?.email?.charAt(0).toUpperCase()}
|
|
</div>
|
|
<div className="flex-1 min-w-0">
|
|
<p className="text-sm font-bold text-ink-900 truncate">{user?.email}</p>
|
|
<p className="text-xs text-ink-500 font-medium truncate tracking-wide">{user?.role}</p>
|
|
</div>
|
|
</div>
|
|
<button
|
|
onClick={() => {
|
|
logout();
|
|
window.location.href = '/login';
|
|
}}
|
|
className="w-full flex items-center justify-center gap-2.5 px-4 py-3 rounded-xl text-sm font-bold tracking-wide text-red-600 hover:bg-red-500/10 transition-colors border border-transparent hover:border-red-200"
|
|
>
|
|
<LogOut className="w-4 h-4" />
|
|
SECURE LOGOUT
|
|
</button>
|
|
</div>
|
|
</motion.aside>
|
|
|
|
{/* Main Content */}
|
|
<main className="flex-1 flex flex-col relative overflow-hidden bg-ink-50 transition-colors duration-500">
|
|
{/* Soft Monochromatic Accent Glows */}
|
|
<div className="absolute top-0 right-0 w-[500px] h-[500px] bg-ink-900/5 rounded-full blur-[150px] pointer-events-none" />
|
|
<div className="absolute bottom-0 left-1/4 w-[400px] h-[400px] bg-ink-900/5 rounded-full blur-[120px] pointer-events-none" />
|
|
|
|
<div className="flex-1 overflow-y-auto p-10 relative z-10">
|
|
<Outlet />
|
|
</div>
|
|
</main>
|
|
</div>
|
|
);
|
|
};
|
|
export default MainLayout;
|