Files
prosapp-migration/admin/src/components/sidebar.tsx
T
Lizandro GuarnizoandClaude Sonnet 4.6 42d41eb199 feat: módulo de sugerencias (backend) + página pública /sugerencias (admin)
- Backend: POST /suggestions (público) + GET /suggestions (JWT admin)
- Admin: página pública /sugerencias con formulario de sugerencias
- schema.prisma: modelo suggestions
- AuthGuard + Sidebar: /sugerencias como ruta pública

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 19:05:58 -05:00

107 lines
3.6 KiB
TypeScript

'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,
MessageSquare,
Star,
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: '/locations', label: 'Ubicaciones', icon: MapPin },
{ href: '/professions', label: 'Profesiones', icon: Wrench },
{ href: '/comments', label: 'Comentarios', icon: Star },
{ href: '/sms', label: 'SMS', icon: MessageSquare },
{ 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' || path === '/sugerencias') 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 && (
<img src="https://prosapp.co/img/logo_prosapp.png" alt="ProsApp" className="h-7 w-auto object-contain" />
)}
{collapsed && (
<div className="flex h-7 w-7 items-center justify-center rounded-lg bg-[#42A4EF] mx-auto">
<span className="text-xs font-black text-white">P</span>
</div>
)}
<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>
);
}