Checkpoint: Menu latéral moderne avec couleurs pastel (version douce et élégante) + correction du bug 'Cannot convert undefined or null to object' sur la page émargement formateur
This commit is contained in:
@@ -27,16 +27,41 @@ import { useLocation } from "wouter";
|
||||
import { DashboardLayoutSkeleton } from './DashboardLayoutSkeleton';
|
||||
import { Button } from "./ui/button";
|
||||
|
||||
// Couleurs par catégorie de menu
|
||||
// Couleurs et styles par catégorie de menu
|
||||
const getCategoryColor = (sectionTitle: string) => {
|
||||
const colors: Record<string, string> = {
|
||||
"Tableau de bord": "text-blue-600",
|
||||
"Gestion": "text-green-600",
|
||||
"Configuration": "text-orange-600",
|
||||
"Traçabilité": "text-purple-600",
|
||||
"Analyses": "text-pink-600",
|
||||
"Tableau de bord": "text-blue-500",
|
||||
"Gestion": "text-green-500",
|
||||
"Configuration": "text-orange-500",
|
||||
"Traçabilité": "text-purple-500",
|
||||
"Analyses": "text-pink-500",
|
||||
"Gestion technique": "text-red-500",
|
||||
};
|
||||
return colors[sectionTitle] || "";
|
||||
return colors[sectionTitle] || "text-gray-500";
|
||||
};
|
||||
|
||||
const getCategoryGradient = (sectionTitle: string) => {
|
||||
const gradients: Record<string, string> = {
|
||||
"Tableau de bord": "from-blue-300 to-blue-400",
|
||||
"Gestion": "from-green-300 to-emerald-400",
|
||||
"Configuration": "from-orange-300 to-orange-400",
|
||||
"Traçabilité": "from-purple-300 to-purple-400",
|
||||
"Analyses": "from-pink-300 to-pink-400",
|
||||
"Gestion technique": "from-red-300 to-red-400",
|
||||
};
|
||||
return gradients[sectionTitle] || "from-gray-300 to-gray-400";
|
||||
};
|
||||
|
||||
const getCategoryBgColor = (sectionTitle: string) => {
|
||||
const bgColors: Record<string, string> = {
|
||||
"Tableau de bord": "bg-blue-50/80 hover:bg-blue-100/90",
|
||||
"Gestion": "bg-green-50/80 hover:bg-green-100/90",
|
||||
"Configuration": "bg-orange-50/80 hover:bg-orange-100/90",
|
||||
"Traçabilité": "bg-purple-50/80 hover:bg-purple-100/90",
|
||||
"Analyses": "bg-pink-50/80 hover:bg-pink-100/90",
|
||||
"Gestion technique": "bg-red-50/80 hover:bg-red-100/90",
|
||||
};
|
||||
return bgColors[sectionTitle] || "bg-gray-50/80 hover:bg-gray-100/90";
|
||||
};
|
||||
|
||||
const menuSections = [
|
||||
@@ -369,19 +394,29 @@ function DashboardLayoutContent({
|
||||
)}
|
||||
<button
|
||||
onClick={() => toggleSection(section.title)}
|
||||
className="w-full px-4 py-2 flex items-center justify-between hover:bg-accent/50 transition-colors rounded-md mx-2 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
||||
className={`w-full px-3 py-3 flex items-center justify-between ${getCategoryBgColor(section.title)} transition-all duration-300 rounded-lg mx-2 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring border-l-4 ${isOpen ? 'border-l-' + section.title.toLowerCase().replace(/ /g, '-') : 'border-l-transparent'} shadow-sm hover:shadow-md hover:translate-x-1`}
|
||||
style={{
|
||||
borderLeftColor: isOpen ? `var(--${section.title.toLowerCase().replace(/ /g, '-')}-color, currentColor)` : 'transparent'
|
||||
}}
|
||||
>
|
||||
<h3 className={`text-xs font-semibold uppercase tracking-wider ${getCategoryColor(section.title)}`}>
|
||||
{section.title}
|
||||
</h3>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className={`p-1.5 rounded-lg bg-gradient-to-br ${getCategoryGradient(section.title)} shadow-md transition-transform duration-300 ${isOpen ? 'scale-110 rotate-6' : ''}`}>
|
||||
<div className="w-3 h-3 bg-white/30 rounded-sm" />
|
||||
</div>
|
||||
<h3 className={`text-xs font-bold uppercase tracking-wider ${getCategoryColor(section.title)}`}>
|
||||
{section.title}
|
||||
</h3>
|
||||
</div>
|
||||
<ChevronDown
|
||||
className={`h-3 w-3 transition-transform duration-200 ${getCategoryColor(section.title)} ${
|
||||
isOpen ? 'rotate-180' : ''
|
||||
className={`h-4 w-4 transition-all duration-300 ${getCategoryColor(section.title)} ${
|
||||
isOpen ? 'rotate-180 scale-110' : ''
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
{isOpen && (
|
||||
<SidebarMenu className="px-2 py-1">
|
||||
<div className={`overflow-hidden transition-all duration-300 ease-in-out ${
|
||||
isOpen ? 'max-h-[2000px] opacity-100' : 'max-h-0 opacity-0'
|
||||
}`}>
|
||||
<SidebarMenu className="px-2 py-1 animate-in slide-in-from-top-2">
|
||||
{section.items.map(item => {
|
||||
const isActive = location === item.path;
|
||||
const hasSubItems = 'subItems' in item && item.subItems && Array.isArray(item.subItems) && item.subItems.length > 0;
|
||||
@@ -393,11 +428,21 @@ function DashboardLayoutContent({
|
||||
isActive={isActive || Boolean(isSubItemActive)}
|
||||
onClick={() => setLocation(item.path)}
|
||||
tooltip={item.label}
|
||||
className={`h-10 transition-all font-normal`}
|
||||
className={`h-11 transition-all duration-300 font-normal hover:translate-x-2 hover:shadow-md ${
|
||||
isActive || isSubItemActive
|
||||
? `bg-gradient-to-r ${getCategoryGradient(section.title)} text-white shadow-lg scale-105 border-l-4 border-white/30`
|
||||
: 'hover:bg-accent/70'
|
||||
}`}
|
||||
>
|
||||
<item.icon
|
||||
className={`h-4 w-4 ${isActive || isSubItemActive ? "text-primary" : getCategoryColor(section.title)}`}
|
||||
/>
|
||||
<div className={`p-1.5 rounded-md transition-all duration-300 ${
|
||||
isActive || isSubItemActive
|
||||
? 'bg-white/20 scale-110'
|
||||
: `bg-gradient-to-br ${getCategoryGradient(section.title)}`
|
||||
}`}>
|
||||
<item.icon
|
||||
className={`h-4 w-4 ${isActive || isSubItemActive ? "text-white" : "text-white"}`}
|
||||
/>
|
||||
</div>
|
||||
<span>{item.label}</span>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
@@ -424,7 +469,7 @@ function DashboardLayoutContent({
|
||||
);
|
||||
})}
|
||||
</SidebarMenu>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
Reference in New Issue
Block a user