129 lines
5.0 KiB
TypeScript
129 lines
5.0 KiB
TypeScript
import { useState, useRef, useEffect } from "react";
|
|
import {
|
|
Menu,
|
|
Home,
|
|
History,
|
|
Settings,
|
|
Users,
|
|
BarChart2,
|
|
MapPin,
|
|
UserCircle,
|
|
ChevronRight,
|
|
} from "lucide-react";
|
|
import { useNavigate } from "react-router-dom";
|
|
import { motion, AnimatePresence } from "framer-motion";
|
|
import { Button } from "./ui/button";
|
|
import { Avatar } from "./ui/avatar";
|
|
import { useProfileStore } from "../stores/profileStore";
|
|
|
|
export function NavigationMenu() {
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
const navigate = useNavigate();
|
|
const menuRef = useRef<HTMLDivElement>(null);
|
|
const activeProfile = useProfileStore((s) => s.activeProfile);
|
|
|
|
useEffect(() => {
|
|
const handleClickOutside = (event: MouseEvent) => {
|
|
if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
|
|
setIsOpen(false);
|
|
}
|
|
};
|
|
document.addEventListener("mousedown", handleClickOutside);
|
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
}, []);
|
|
|
|
const nav = (path: string) => {
|
|
setIsOpen(false);
|
|
navigate(path);
|
|
};
|
|
|
|
return (
|
|
<div ref={menuRef} className="relative z-50">
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
onClick={() => setIsOpen(!isOpen)}
|
|
className="rounded-full hover:bg-black/10 dark:hover:bg-white/10"
|
|
>
|
|
<Menu className="w-6 h-6" />
|
|
</Button>
|
|
<AnimatePresence>
|
|
{isOpen && (
|
|
<motion.div
|
|
initial={{ opacity: 0, scale: 0.95, transformOrigin: "top left" }}
|
|
animate={{ opacity: 1, scale: 1 }}
|
|
exit={{ opacity: 0, scale: 0.95 }}
|
|
transition={{ duration: 0.15 }}
|
|
className="absolute top-full left-0 mt-2 w-60 bg-card border shadow-xl rounded-2xl overflow-hidden"
|
|
>
|
|
<div className="flex flex-col">
|
|
<button
|
|
onClick={() => nav("/profiles")}
|
|
className="flex items-center w-full p-4 hover:bg-secondary text-left transition-colors bg-primary/5"
|
|
>
|
|
<Avatar
|
|
src={activeProfile?.avatar}
|
|
name={activeProfile?.name || "?"}
|
|
size="md"
|
|
className="mr-3"
|
|
/>
|
|
<div className="flex-1 min-w-0">
|
|
<div className="text-[10px] font-bold uppercase tracking-wider text-muted-foreground">
|
|
Profil actif
|
|
</div>
|
|
<div className="font-black truncate">
|
|
{activeProfile?.name || "—"}
|
|
</div>
|
|
</div>
|
|
<ChevronRight className="w-4 h-4 text-muted-foreground shrink-0" />
|
|
</button>
|
|
<button
|
|
onClick={() => nav("/")}
|
|
className="flex items-center w-full p-4 hover:bg-secondary text-left font-medium transition-colors border-t border-border/50"
|
|
>
|
|
<Home className="w-5 h-5 mr-3 text-primary" /> Accueil
|
|
</button>
|
|
<button
|
|
onClick={() => nav("/history")}
|
|
className="flex items-center w-full p-4 hover:bg-secondary text-left font-medium transition-colors border-t border-border/50"
|
|
>
|
|
<History className="w-5 h-5 mr-3 text-primary" /> Historique
|
|
</button>
|
|
<button
|
|
onClick={() => nav("/players")}
|
|
className="flex items-center w-full p-4 hover:bg-secondary text-left font-medium transition-colors border-t border-border/50"
|
|
>
|
|
<Users className="w-5 h-5 mr-3 text-primary" /> Joueurs
|
|
</button>
|
|
<button
|
|
onClick={() => nav("/locations")}
|
|
className="flex items-center w-full p-4 hover:bg-secondary text-left font-medium transition-colors border-t border-border/50"
|
|
>
|
|
<MapPin className="w-5 h-5 mr-3 text-primary" /> Emplacements
|
|
</button>
|
|
<button
|
|
onClick={() => nav("/stats")}
|
|
className="flex items-center w-full p-4 hover:bg-secondary text-left font-medium transition-colors border-t border-border/50"
|
|
>
|
|
<BarChart2 className="w-5 h-5 mr-3 text-primary" /> Statistiques
|
|
</button>
|
|
<button
|
|
onClick={() => nav("/profiles")}
|
|
className="flex items-center w-full p-4 hover:bg-secondary text-left font-medium transition-colors border-t border-border/50"
|
|
>
|
|
<UserCircle className="w-5 h-5 mr-3 text-primary" /> Profils
|
|
</button>
|
|
<button
|
|
onClick={() => nav("/settings")}
|
|
className="flex items-center w-full p-4 hover:bg-secondary text-left font-medium transition-colors border-t border-border/50"
|
|
>
|
|
<Settings className="w-5 h-5 mr-3 text-primary" /> Paramètres
|
|
</button>
|
|
</div>
|
|
</motion.div>
|
|
)}
|
|
</AnimatePresence>
|
|
</div>
|
|
);
|
|
}
|