feat(ADM-018): completed feature

This commit is contained in:
chattie
2026-08-17 22:23:10 +02:00
parent cf1c69fc8b
commit d595b4871f
871 changed files with 47411 additions and 281 deletions

View File

@@ -0,0 +1,122 @@
'use client';
import { useEffect, useState } from 'react';
import { useRouter, usePathname } from 'next/navigation';
import Link from 'next/link';
import { AuthProvider, useAuth } from '@/features/auth/components/AuthProvider';
import { visibleNavItems, type NavItem } from '@/lib/permissions';
import type { Role } from '@/types';
function Sidebar({
navItems,
user,
onLogout,
}: {
navItems: NavItem[];
user: { email: string; role: Role };
onLogout: () => void;
}) {
const pathname = usePathname();
return (
<div className="w-60 bg-white border-r border-gray-200 flex flex-col h-screen sticky top-0">
{/* Logo */}
<div className="px-4 py-5 border-b border-gray-100">
<img
src="/images/logo-main.png"
alt="MercadoDeVida"
className="h-9 w-auto object-contain mx-auto"
/>
</div>
{/* Nav */}
<nav className="flex-1 px-3 py-4 space-y-0.5 overflow-y-auto">
{navItems.map((item) => {
const active =
item.href === '/'
? pathname === '/'
: pathname.startsWith(item.href);
return (
<Link
key={item.href}
href={item.href}
className={`
flex items-center gap-3 px-3 py-2 rounded-lg text-sm font-medium transition-all
${
active
? 'bg-[#2D6A4F]/10 text-[#2D6A4F] border-l-[3px] border-[#2D6A4F]'
: 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'
}
`}
>
<span className="text-base">{item.icon}</span>
<span className="truncate">{item.label}</span>
{item.badge != null && item.badge > 0 && (
<span className="ml-auto bg-[#E76F51] text-white text-xs font-bold rounded-full px-1.5 py-0.5 min-w-[18px] text-center">
{item.badge}
</span>
)}
</Link>
);
})}
</nav>
{/* User footer */}
<div className="px-3 py-4 border-t border-gray-100">
<div className="px-3 py-2 mb-2">
<p className="text-xs text-gray-400 truncate">{user.email}</p>
<p className="text-xs text-gray-500 capitalize">{user.role}</p>
</div>
<button
onClick={onLogout}
className="w-full text-left px-3 py-2 text-sm text-gray-500 hover:text-gray-700 hover:bg-gray-50 rounded-lg transition-colors"
>
Cerrar sesión
</button>
</div>
</div>
);
}
function DashboardShell({ children }: { children: React.ReactNode }) {
const { user, loading, logout } = useAuth();
const router = useRouter();
useEffect(() => {
if (!loading && !user) {
router.push('/login');
}
}, [user, loading, router]);
if (loading) {
return (
<div className="min-h-screen flex items-center justify-center bg-gray-50">
<div className="text-gray-500">Cargando...</div>
</div>
);
}
if (!user) return null;
const navItems = visibleNavItems(user.role);
return (
<div className="flex min-h-screen bg-gray-50">
<Sidebar navItems={navItems} user={user} onLogout={logout} />
<main className="flex-1 min-w-0">
{children}
</main>
</div>
);
}
export default function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<AuthProvider>
<DashboardShell>{children}</DashboardShell>
</AuthProvider>
);
}