full project: admin panel, backend modules, docs

This commit is contained in:
Lizandro Guarnizo
2026-06-03 22:11:01 -05:00
parent 1635723035
commit afc096d552
94 changed files with 15994 additions and 240 deletions
+95
View File
@@ -0,0 +1,95 @@
'use client';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { useAuth } from '@/lib/auth';
import {
LayoutDashboard,
Users,
Briefcase,
ClipboardList,
MapPin,
Wrench,
Settings,
LogOut,
ChevronLeft,
Menu,
} from 'lucide-react';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
import { useState } from 'react';
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
const menu = [
{ href: '/', label: 'Dashboard', icon: LayoutDashboard },
{ href: '/users', label: 'Usuarios', icon: Users },
{ href: '/professionals', label: 'Profesionales', icon: Briefcase },
{ href: '/services', label: 'Servicios', icon: ClipboardList },
{ href: '/cities', label: 'Ciudades', icon: MapPin },
{ href: '/professions', label: 'Profesiones', icon: Wrench },
{ href: '/settings', label: 'Configuración', icon: Settings },
];
export default function Sidebar({ children }: { children: React.ReactNode }) {
const path = usePathname();
const { user, logout } = useAuth();
const [collapsed, setCollapsed] = useState(false);
if (path === '/login') return <>{children}</>;
return (
<div className="flex h-screen">
<aside
className={cn(
'flex flex-col border-r bg-card transition-all duration-200',
collapsed ? 'w-16' : 'w-56',
)}
>
<div className="flex h-14 items-center justify-between border-b px-3">
{!collapsed && <span className="font-semibold">ProsApp Admin</span>}
<Button variant="ghost" size="icon" onClick={() => setCollapsed(!collapsed)}>
{collapsed ? <Menu size={18} /> : <ChevronLeft size={18} />}
</Button>
</div>
<nav className="flex-1 space-y-1 p-2">
{menu.map((item) => (
<Link key={item.href} href={item.href}>
<Button
variant={path === item.href ? 'secondary' : 'ghost'}
className={cn('w-full justify-start', collapsed ? 'px-2' : 'px-3')}
>
<item.icon size={18} className={collapsed ? 'mx-auto' : 'mr-2'} />
{!collapsed && item.label}
</Button>
</Link>
))}
</nav>
<div className="border-t p-2">
{collapsed ? (
<Button variant="ghost" size="icon" className="w-full" onClick={logout}>
<LogOut size={18} />
</Button>
) : (
<div className="flex items-center gap-2">
<Avatar className="h-8 w-8">
<AvatarFallback>{user?.name?.charAt(0) || 'A'}</AvatarFallback>
</Avatar>
<div className="flex-1 min-w-0">
<p className="text-sm font-medium truncate">{user?.name}</p>
</div>
<Button variant="ghost" size="icon" onClick={logout}>
<LogOut size={16} />
</Button>
</div>
)}
</div>
</aside>
<main className="flex-1 overflow-auto bg-muted/20">
<div className="mx-auto max-w-7xl p-6">{children}</div>
</main>
</div>
);
}