163 lines
5.3 KiB
TypeScript

'use client'
import { useState } from 'react'
import { usePathname, useRouter } from 'next/navigation'
import Link from 'next/link'
import { createClient } from '@/lib/supabase/client'
import {
LayoutDashboard,
BookOpen,
Plus,
BarChart3,
Settings,
LogOut,
Shield,
Menu,
X,
} from 'lucide-react'
import { cn } from '@/lib/utils'
interface SidebarProps {
username: string
email: string
role: string
}
const navLinks = [
{ href: '/dashboard', label: 'Dashboard', icon: LayoutDashboard },
{ href: '/dashboard/quizzes', label: 'Mes Quizzes', icon: BookOpen },
{ href: '/dashboard/sessions/create', label: 'Créer Session', icon: Plus },
{ href: '/dashboard/reports', label: 'Rapports', icon: BarChart3 },
{ href: '/dashboard/settings', label: 'Paramètres', icon: Settings },
]
export default function Sidebar({ username, email, role }: SidebarProps) {
const pathname = usePathname()
const router = useRouter()
const [mobileOpen, setMobileOpen] = useState(false)
const handleLogout = async () => {
const supabase = createClient()
await supabase.auth.signOut()
router.push('/login')
router.refresh()
}
const closeMobile = () => setMobileOpen(false)
const sidebarContent = (
<>
{/* Brand */}
<div className="p-5 border-b border-border">
<div className="flex items-center gap-3">
<div className="w-10 h-10 bg-primary rounded-xl flex items-center justify-center shadow-lg shadow-primary/30 flex-shrink-0">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 14H9V8h2v8zm4 0h-2V8h2v8z" fill="white"/>
</svg>
</div>
<div>
<p className="font-bold text-text-primary leading-tight">SolyQuiz</p>
<p className="text-xs text-text-muted capitalize">{role === 'admin' ? 'Admin Portal' : 'Trainer Portal'}</p>
</div>
</div>
</div>
{/* Navigation */}
<nav className="flex-1 p-4 space-y-1 overflow-y-auto">
{navLinks.map(({ href, label, icon: Icon }) => {
const isActive = pathname === href || (href !== '/dashboard' && pathname.startsWith(href))
return (
<Link
key={href}
href={href}
onClick={closeMobile}
className={cn('sidebar-link', isActive && 'sidebar-link-active')}
>
<Icon size={18} />
<span>{label}</span>
</Link>
)
})}
</nav>
{/* Section admin */}
{role === 'admin' && (
<div className="px-4 pb-2 border-t border-border pt-3 mt-1">
<p className="text-xs font-medium text-text-muted uppercase tracking-wider px-3 mb-1">Administration</p>
<Link
href="/dashboard/admin/users"
onClick={closeMobile}
className={cn('sidebar-link', pathname.startsWith('/dashboard/admin') && 'sidebar-link-active')}
>
<Shield size={18} />
<span>Utilisateurs</span>
</Link>
</div>
)}
{/* User profile + logout */}
<div className="border-t border-border p-4">
<div className="flex items-center gap-3 mb-3">
<div className="w-9 h-9 bg-primary/20 rounded-full flex items-center justify-center text-primary font-semibold text-sm flex-shrink-0">
{username.slice(0, 2).toUpperCase()}
</div>
<div className="min-w-0">
<p className="text-sm font-medium text-text-primary truncate">{username}</p>
<p className="text-xs text-text-muted truncate">{email}</p>
</div>
</div>
<button
onClick={handleLogout}
className="sidebar-link w-full text-red-400 hover:text-red-300 hover:bg-red-500/10"
>
<LogOut size={18} />
<span>Déconnexion</span>
</button>
</div>
</>
)
return (
<>
{/* Bouton hamburger — mobile uniquement */}
<button
onClick={() => setMobileOpen(true)}
className="lg:hidden fixed top-4 left-4 z-40 p-2 bg-background-secondary border border-border rounded-lg shadow-md"
aria-label="Ouvrir le menu"
>
<Menu size={20} className="text-text-primary" />
</button>
{/* Overlay mobile */}
{mobileOpen && (
<div
className="lg:hidden fixed inset-0 z-40 bg-black/60 backdrop-blur-sm"
onClick={closeMobile}
/>
)}
{/* Sidebar desktop (sticky) */}
<aside className="hidden lg:flex w-64 flex-shrink-0 bg-background-secondary border-r border-border flex-col h-screen sticky top-0">
{sidebarContent}
</aside>
{/* Sidebar mobile (drawer) */}
<aside
className={cn(
'lg:hidden fixed top-0 left-0 z-50 w-72 bg-background-secondary border-r border-border flex flex-col h-screen transition-transform duration-300',
mobileOpen ? 'translate-x-0' : '-translate-x-full'
)}
>
{/* Bouton fermer */}
<button
onClick={closeMobile}
className="absolute top-4 right-4 p-1.5 hover:bg-background-elevated rounded-lg text-text-muted hover:text-text-primary transition-colors"
>
<X size={18} />
</button>
{sidebarContent}
</aside>
</>
)
}