Organize navigation menu into logical sections for better user experience

Refactor the Sidebar component in client/src/components/Sidebar.tsx to group navigation links into sections like "GESTION PRINCIPALE", "LOGISTIQUE", and "ANALYSES" for improved UI organization.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 1e4433b5-47ab-464c-b663-fea2e53367dd
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: 1ca378ce-ae32-4181-ba52-5042a0f06d7a
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/1e4433b5-47ab-464c-b663-fea2e53367dd/oKSi9br
This commit is contained in:
michaelschal committed 2025-11-04 13:15:05 +00:00
1 parent 14b6e7c995
commit b1c1e2989e
1 file changed
+84 -42
+84 -42
View File
@@ -228,7 +228,10 @@ export default function Sidebar() {
return false; return false;
}; };
const menuItems = [ const menuSections = [
{
title: "GESTION PRINCIPALE",
items: [
{ {
path: "/dashboard", path: "/dashboard",
label: "Tableau de bord", label: "Tableau de bord",
@@ -241,6 +244,11 @@ export default function Sidebar() {
icon: Calendar, icon: Calendar,
roles: ["admin", "directeur", "manager", "employee"] roles: ["admin", "directeur", "manager", "employee"]
}, },
]
},
{
title: "LOGISTIQUE",
items: [
{ {
path: "/orders", path: "/orders",
label: "Commandes", label: "Commandes",
@@ -265,6 +273,17 @@ export default function Sidebar() {
icon: CreditCard, icon: CreditCard,
roles: ["admin", "directeur"] roles: ["admin", "directeur"]
}, },
{
path: "/avoirs",
label: "Avoirs",
icon: Receipt,
roles: ["admin", "directeur", "manager"]
},
]
},
{
title: "ANALYSES",
items: [
{ {
path: "/analytics", path: "/analytics",
label: "Statistiques", label: "Statistiques",
@@ -277,12 +296,11 @@ export default function Sidebar() {
icon: TrendingUp, icon: TrendingUp,
roles: ["admin", "directeur"] roles: ["admin", "directeur"]
}, },
{ ]
path: "/avoirs",
label: "Avoirs",
icon: Receipt,
roles: ["admin", "directeur", "manager"]
}, },
{
title: "OPÉRATIONS",
items: [
{ {
path: "/publicities", path: "/publicities",
label: "Publicités", label: "Publicités",
@@ -313,6 +331,8 @@ export default function Sidebar() {
icon: Wrench, icon: Wrench,
roles: ["admin", "directeur", "manager", "employee"] roles: ["admin", "directeur", "manager", "employee"]
}, },
]
},
]; ];
const adminItems = [ const adminItems = [
@@ -558,15 +578,31 @@ export default function Sidebar() {
</div> </div>
{/* Navigation */} {/* Navigation */}
<nav className="flex-1 py-4 px-3"> <nav className="flex-1 py-5 px-3 overflow-y-auto">
<div className="space-y-1"> <div className="space-y-7">
{menuItems.map((item) => { {menuSections.map((section, sectionIndex) => {
// Vérifier si au moins un item de la section est accessible
const hasAccessibleItems = section.items.some(item => hasPermission(item.roles));
if (!hasAccessibleItems) return null;
return (
<div key={section.title} className="space-y-3">
{/* Titre de section - caché en mode collapsed */}
{!sidebarCollapsed && (
<h3 className="px-3 mb-3 text-[11px] font-bold text-gray-500 uppercase tracking-widest">
{section.title}
</h3>
)}
{/* Séparateur visuel en mode collapsed */}
{sidebarCollapsed && sectionIndex > 0 && (
<div className="border-t border-gray-200 my-4"></div>
)}
{/* Items du menu */}
<div className="space-y-1.5">
{section.items.map((item) => {
const hasRolePermission = hasPermission(item.roles); const hasRolePermission = hasPermission(item.roles);
// console.log(`🔍 Menu item ${item.path} (${item.label}):`, {
// roles: item.roles,
// hasPermission: hasRolePermission,
// userRole: user?.role
// });
if (!hasRolePermission) return null; if (!hasRolePermission) return null;
@@ -576,16 +612,16 @@ export default function Sidebar() {
return ( return (
<Link key={item.path} href={item.path}> <Link key={item.path} href={item.path}>
<div <div
className={`flex items-center transition-colors hover:bg-gray-100 ${ className={`flex items-center transition-colors hover:bg-gray-100 rounded-md ${
// Espacement adaptatif selon l'écran et l'état // Espacement adaptatif selon l'écran et l'état
sidebarCollapsed && !isMobile sidebarCollapsed && !isMobile
? 'px-3 py-3 justify-center min-h-[44px]' ? 'px-3 py-3 justify-center min-h-11'
: isMobileOrTablet : isMobileOrTablet
? 'px-4 py-3 min-h-[48px]' ? 'px-4 py-3.5 min-h-12'
: 'px-3 py-2 min-h-[40px]' : 'px-3 py-3 min-h-11'
} text-sm font-medium ${ } ${
active active
? 'bg-gray-100 text-gray-900 border-r-2 border-blue-600' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-600'
: 'text-gray-700' : 'text-gray-700'
}`} }`}
title={sidebarCollapsed && !isMobile ? item.label : undefined} title={sidebarCollapsed && !isMobile ? item.label : undefined}
@@ -596,9 +632,11 @@ export default function Sidebar() {
isMobile ? 'h-5 w-5' : isMobile ? 'h-5 w-5' :
isTablet ? 'h-6 w-6' : isTablet ? 'h-6 w-6' :
'h-5 w-5' 'h-5 w-5'
} ${
active ? 'text-blue-700' : 'text-gray-600'
} ${sidebarCollapsed && !isMobile ? '' : 'mr-3'}`} /> } ${sidebarCollapsed && !isMobile ? '' : 'mr-3'}`} />
{(!sidebarCollapsed || isMobile) && ( {(!sidebarCollapsed || isMobile) && (
<span className={`${isMobileOrTablet ? 'text-base' : 'text-sm'} font-medium`}> <span className={`${isMobileOrTablet ? 'text-base' : 'text-[15px]'} font-medium`}>
{item.label} {item.label}
</span> </span>
)} )}
@@ -607,21 +645,23 @@ export default function Sidebar() {
); );
})} })}
</div> </div>
</div>
);
})}
</div>
</nav> </nav>
{/* Administration Section */} {/* Administration Section */}
{adminItems.some(item => hasPermission(item.roles)) && ( {adminItems.some(item => hasPermission(item.roles)) && (
<div className="border-t border-gray-200 py-4 px-3"> <div className="border-t border-gray-200 py-5 px-3">
{!sidebarCollapsed && ( {!sidebarCollapsed && (
<div className="mb-2"> <div className="mb-3">
<h3 className="px-3 text-xs font-medium text-gray-500 uppercase tracking-wider"> <h3 className="px-3 text-[11px] font-bold text-gray-500 uppercase tracking-widest">
Administration Administration
</h3> </h3>
</div> </div>
)} )}
<div className="space-y-1"> <div className="space-y-1.5">
{adminItems.map((item) => { {adminItems.map((item) => {
if (!hasPermission(item.roles)) return null; if (!hasPermission(item.roles)) return null;
@@ -632,13 +672,13 @@ export default function Sidebar() {
return ( return (
<div key={item.path}> <div key={item.path}>
<div <div
className={`flex items-center cursor-pointer transition-colors hover:bg-gray-100 text-gray-700 ${ className={`flex items-center cursor-pointer transition-colors hover:bg-gray-100 rounded-md ${
sidebarCollapsed && !isMobile sidebarCollapsed && !isMobile
? 'px-3 py-3 justify-center min-h-[44px]' ? 'px-3 py-3 justify-center min-h-11'
: isMobileOrTablet : isMobileOrTablet
? 'px-4 py-3 min-h-[48px]' ? 'px-4 py-3.5 min-h-12'
: 'px-3 py-2 min-h-[40px]' : 'px-3 py-3 min-h-11'
} text-sm font-medium`} } text-gray-700`}
title={sidebarCollapsed && !isMobile ? item.label : undefined} title={sidebarCollapsed && !isMobile ? item.label : undefined}
onClick={() => { onClick={() => {
setShowBapModal(true); setShowBapModal(true);
@@ -649,9 +689,9 @@ export default function Sidebar() {
isMobile ? 'h-5 w-5' : isMobile ? 'h-5 w-5' :
isTablet ? 'h-6 w-6' : isTablet ? 'h-6 w-6' :
'h-5 w-5' 'h-5 w-5'
} ${sidebarCollapsed && !isMobile ? '' : 'mr-3'}`} /> } text-gray-600 ${sidebarCollapsed && !isMobile ? '' : 'mr-3'}`} />
{(!sidebarCollapsed || isMobile) && ( {(!sidebarCollapsed || isMobile) && (
<span className={`${isMobileOrTablet ? 'text-base' : 'text-sm'} font-medium`}> <span className={`${isMobileOrTablet ? 'text-base' : 'text-[15px]'} font-medium`}>
{item.label} {item.label}
</span> </span>
)} )}
@@ -663,27 +703,29 @@ export default function Sidebar() {
return ( return (
<Link key={item.path} href={item.path}> <Link key={item.path} href={item.path}>
<div <div
className={`flex items-center transition-colors hover:bg-gray-100 ${ className={`flex items-center transition-colors hover:bg-gray-100 rounded-md ${
sidebarCollapsed && !isMobile sidebarCollapsed && !isMobile
? 'px-3 py-3 justify-center min-h-[44px]' ? 'px-3 py-3 justify-center min-h-11'
: isMobileOrTablet : isMobileOrTablet
? 'px-4 py-3 min-h-[48px]' ? 'px-4 py-3.5 min-h-12'
: 'px-3 py-2 min-h-[40px]' : 'px-3 py-3 min-h-11'
} text-sm font-medium ${ } ${
active active
? 'bg-gray-100 text-gray-900 border-r-2 border-blue-600' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-600'
: 'text-gray-700' : 'text-gray-700'
}`} }`}
title={sidebarCollapsed && !isMobile ? item.label : undefined} title={sidebarCollapsed && !isMobile ? item.label : undefined}
onClick={() => console.log(`Navigating to admin: ${item.path}`)} onClick={handleMenuClick}
> >
<Icon className={`${ <Icon className={`${
isMobile ? 'h-5 w-5' : isMobile ? 'h-5 w-5' :
isTablet ? 'h-6 w-6' : isTablet ? 'h-6 w-6' :
'h-5 w-5' 'h-5 w-5'
} ${
active ? 'text-blue-700' : 'text-gray-600'
} ${sidebarCollapsed && !isMobile ? '' : 'mr-3'}`} /> } ${sidebarCollapsed && !isMobile ? '' : 'mr-3'}`} />
{(!sidebarCollapsed || isMobile) && ( {(!sidebarCollapsed || isMobile) && (
<span className={`${isMobileOrTablet ? 'text-base' : 'text-sm'} font-medium`}> <span className={`${isMobileOrTablet ? 'text-base' : 'text-[15px]'} font-medium`}>
{item.label} {item.label}
</span> </span>
)} )}