almeira-web/src/components/Sidebar.tsx

151 lines
7.1 KiB
TypeScript

"use client";
import { useState } from 'react';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { LayoutDashboard, Newspaper, Folders, Building2, MapPin, BadgeDollarSign, FileText, LogOut, ChevronDown, ChevronRight, Image as ImageIcon, Settings, Calendar, RadioTower, Users } from 'lucide-react';
import { logout } from '@/app/actions/auth';
export const Sidebar = ({ user }: { user: any }) => {
const pathname = usePathname();
const [openSections, setOpenSections] = useState<Record<string, boolean>>({
directorio: true,
geografia: false,
comercial: false,
sistema: false
});
const toggleSection = (section: string) => {
setOpenSections(prev => ({ ...prev, [section]: !prev[section] }));
};
const sections = [
{
id: 'directorio',
title: 'Directorio',
items: [
{ name: 'Clientes', href: '/dashboard/clients', icon: Building2 },
{ name: 'Tipos de Cliente', href: '/dashboard/client_types', icon: Building2 },
]
},
{
id: 'geografia',
title: 'Geografía',
items: [
{ name: 'Países', href: '/dashboard/countries', icon: MapPin },
{ name: 'Departamentos', href: '/dashboard/departments', icon: MapPin },
{ name: 'Ciudades', href: '/dashboard/cities', icon: MapPin },
]
},
{
id: 'comercial',
title: 'Comercial',
items: [
{ name: 'Contratos', href: '/dashboard/contracts', icon: FileText },
{ name: 'Formas de Pago', href: '/dashboard/payment_methods', icon: BadgeDollarSign },
{ name: 'Facturación Electrónica', href: '/dashboard/facturacion', icon: BadgeDollarSign },
]
},
{
id: 'archivos',
title: 'Contenido Multimedia',
items: [
{ name: 'Biblioteca de Medios', href: '/dashboard/media', icon: ImageIcon },
]
},
{
id: 'sistema',
title: 'Sistema y Motor',
items: [
{ name: 'Perfil de Entidad', href: '/dashboard/entity', icon: Building2 },
{ name: 'Parrilla Programación', href: '/dashboard/programming', icon: Calendar },
{ name: 'Gestor StreamingTV', href: '/dashboard/streaming', icon: RadioTower },
{ name: 'Configuración Global', href: '/dashboard/settings', icon: Settings },
]
},
{
id: 'administracion',
title: 'Administración',
items: [
{ name: 'Gestión de Usuarios', href: '/dashboard/users', icon: Users },
]
}
];
return (
<aside className="w-64 border-r border-slate-800 bg-slate-900 overflow-y-auto hidden md:flex flex-col h-full shrink-0">
<div className="p-4 border-b border-slate-800 flex justify-between items-center bg-slate-950/50 sticky top-0 z-10">
<div>
<h2 className="text-xl font-black font-outfit uppercase tracking-tighter bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-cyan-400">
Almeira CMS
</h2>
<p className="text-xs font-bold text-slate-400 mt-1 truncate max-w-[140px]" title={user.email}>
{user.name || user.email}
</p>
</div>
<form action={logout}>
<button title="Cerrar sesión" className="text-slate-500 hover:text-red-400 p-2 rounded-lg hover:bg-slate-800 transition-colors border border-transparent hover:border-red-500/30">
<LogOut size={16} />
</button>
</form>
</div>
<nav className="p-4 space-y-2 flex-grow">
{/* Core items (No collapsible) */}
<div className="space-y-1 mb-6">
<Link href="/dashboard" className={`flex items-center gap-3 px-3 py-2.5 text-sm font-medium rounded-lg transition-colors ${pathname === '/dashboard' ? 'bg-cyan-500/10 text-cyan-400 border border-cyan-500/30' : 'text-slate-300 hover:bg-slate-800/80 hover:text-white'}`}>
<LayoutDashboard size={18} />
Inicio Dashboard
</Link>
<Link href="/dashboard/posts" className={`flex items-center gap-3 px-3 py-2.5 text-sm font-medium rounded-lg transition-colors ${pathname.includes('posts') ? 'bg-cyan-500/10 text-cyan-400 border border-cyan-500/30' : 'text-slate-300 hover:bg-slate-800/80 hover:text-white'}`}>
<Newspaper size={18} />
Publicaciones
</Link>
<Link href="/dashboard/categories" className={`flex items-center gap-3 px-3 py-2.5 text-sm font-medium rounded-lg transition-colors ${pathname.includes('categories') ? 'bg-cyan-500/10 text-cyan-400 border border-cyan-500/30' : 'text-slate-300 hover:bg-slate-800/80 hover:text-white'}`}>
<Folders size={18} />
Categorías
</Link>
</div>
{/* Expandable Sections */}
{sections.map((section) => {
const isOpen = openSections[section.id];
// Check if any child is active
const hasActiveChild = section.items.some(item => pathname.includes(item.href));
return (
<div key={section.id} className="pt-2">
<button
onClick={() => toggleSection(section.id)}
className={`flex items-center justify-between w-full px-3 py-2 text-xs font-black uppercase tracking-widest rounded-lg transition-colors ${hasActiveChild && !isOpen ? 'text-cyan-400 bg-cyan-500/5' : 'text-slate-500 hover:text-slate-300 hover:bg-slate-800/50'}`}
>
{section.title}
{isOpen ? <ChevronDown size={14} /> : <ChevronRight size={14} />}
</button>
<div className={`mt-1 space-y-1 overflow-hidden transition-all duration-300 ease-in-out ${isOpen ? 'max-h-64 opacity-100' : 'max-h-0 opacity-0'}`}>
{section.items.map(item => {
const isActive = pathname.includes(item.href);
return (
<Link
key={item.href}
href={item.href}
className={`flex items-center gap-3 pl-8 pr-3 py-2.5 text-sm font-medium rounded-lg transition-colors ${isActive ? 'bg-cyan-500/10 text-cyan-400 border border-cyan-500/30' : 'text-slate-400 hover:bg-slate-800/80 hover:text-white'}`}
>
<item.icon size={16} className={isActive ? 'text-cyan-400' : 'opacity-70'} />
{item.name}
</Link>
);
})}
</div>
</div>
)
})}
</nav>
<div className="p-4 border-t border-slate-800 text-center text-xs font-bold text-slate-600 uppercase tracking-widest pb-6">
Almeira CMS 1.0
</div>
</aside>
);
};