Se mejoro estetica y estandarizaron estilos
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Link, useLocation, useNavigate } from 'react-router-dom';
|
||||
import { useUser } from '../context/UserContext';
|
||||
|
||||
export default function Sidebar() {
|
||||
export default function Sidebar({ isMobileOpen, onMobileClose }) {
|
||||
// Leer si el usuario es importador desde localStorage
|
||||
const isImportador = typeof window !== 'undefined' && localStorage.getItem('user_is_importador') === 'true';
|
||||
// Leer grupos del usuario desde localStorage
|
||||
@@ -18,7 +18,15 @@ export default function Sidebar() {
|
||||
const isGroup35 = Array.isArray(userGroups) && userGroups.length === 2 && userGroups.includes(3) && userGroups.includes(5);
|
||||
// Leer DEBUG_MODE desde variables de entorno
|
||||
const isDebugMode = import.meta.env.VITE_DEBUG_MODE === 'true';
|
||||
|
||||
// Estados para responsividad
|
||||
const [isCollapsed, setIsCollapsed] = useState(false);
|
||||
const [internalMobileOpen, setInternalMobileOpen] = useState(false);
|
||||
|
||||
// Usar estado interno si no se pasan props
|
||||
const mobileOpen = isMobileOpen !== undefined ? isMobileOpen : internalMobileOpen;
|
||||
const handleMobileClose = onMobileClose || (() => setInternalMobileOpen(false));
|
||||
const handleMobileOpen = () => setInternalMobileOpen(true);
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const { user: currentUser, loading } = useUser();
|
||||
@@ -30,6 +38,23 @@ export default function Sidebar() {
|
||||
navigate('/login');
|
||||
};
|
||||
|
||||
// Cerrar menú móvil cuando se navega o cuando la pantalla es grande
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
if (window.innerWidth >= 1024) { // lg breakpoint
|
||||
handleMobileClose();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('resize', handleResize);
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
}, []);
|
||||
|
||||
// Cerrar menú móvil cuando cambia la ubicación
|
||||
useEffect(() => {
|
||||
handleMobileClose();
|
||||
}, [location.pathname]);
|
||||
|
||||
// El usuario y loading ahora vienen del contexto global
|
||||
|
||||
// Definir todas las secciones
|
||||
@@ -196,35 +221,79 @@ export default function Sidebar() {
|
||||
.filter(Boolean);
|
||||
|
||||
return (
|
||||
<div className={`bg-slate-900 text-white transition-all duration-300 ${isCollapsed ? 'w-16' : 'w-64'} h-screen flex flex-col shadow-xl`}>
|
||||
{/* Header - Logo y colapsar */}
|
||||
<div className="p-4 border-b border-slate-700 flex-shrink-0">
|
||||
<div className="flex items-center justify-between">
|
||||
{!isCollapsed && (
|
||||
<div className="flex items-center">
|
||||
{/* Logo de la organización */}
|
||||
<div className="w-8 h-8 bg-gradient-to-br from-blue-500 to-blue-600 rounded-lg flex items-center justify-center mr-3 shadow-lg">
|
||||
<svg className="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
|
||||
</svg>
|
||||
<>
|
||||
{/* Botón flotante para abrir menú en móvil - solo cuando se usa standalone */}
|
||||
{!mobileOpen && isMobileOpen === undefined && (
|
||||
<button
|
||||
onClick={handleMobileOpen}
|
||||
className="lg:hidden fixed top-4 left-4 z-30 p-2.5 bg-slate-900/95 backdrop-blur-sm text-white rounded-xl shadow-lg hover:bg-slate-800/95 transition-all duration-200 border border-slate-700/50"
|
||||
aria-label="Abrir menú"
|
||||
>
|
||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||
</svg>
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* Overlay para móviles */}
|
||||
{mobileOpen && (
|
||||
<div
|
||||
className="fixed inset-0 bg-black bg-opacity-50 z-40 lg:hidden"
|
||||
onClick={handleMobileClose}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Sidebar */}
|
||||
<div className={`
|
||||
bg-slate-900 text-white transition-all duration-300 flex flex-col shadow-xl
|
||||
${isCollapsed ? 'w-16' : 'w-64'}
|
||||
fixed lg:relative inset-y-0 left-0 z-50
|
||||
${mobileOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'}
|
||||
h-screen
|
||||
`}>
|
||||
{/* Header - Logo y colapsar */}
|
||||
<div className="p-4 border-b border-slate-700 flex-shrink-0">
|
||||
<div className="flex items-center justify-between">
|
||||
{!isCollapsed && (
|
||||
<div className="flex items-center">
|
||||
{/* Logo de la organización */}
|
||||
<div className="w-8 h-8 bg-gradient-to-br from-blue-500 to-blue-600 rounded-lg flex items-center justify-center mr-3 shadow-lg">
|
||||
<svg className="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
|
||||
</svg>
|
||||
</div>
|
||||
<h1 className="text-lg font-bold text-white">EFC Dashboard</h1>
|
||||
</div>
|
||||
<h1 className="text-lg font-bold text-white">EFC Dashboard</h1>
|
||||
)}
|
||||
|
||||
{/* Botones de control */}
|
||||
<div className="flex items-center space-x-2">
|
||||
{/* Botón cerrar en móvil */}
|
||||
<button
|
||||
onClick={handleMobileClose}
|
||||
className="lg:hidden p-1.5 rounded-lg hover:bg-slate-700 transition-all duration-200"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
{/* Botón colapsar en desktop */}
|
||||
<button
|
||||
onClick={() => setIsCollapsed(!isCollapsed)}
|
||||
className="hidden lg:block p-1.5 rounded-lg hover:bg-slate-700 transition-all duration-200 hover:shadow-md"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
{isCollapsed ? (
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13 5l7 7-7 7M5 5l7 7-7 7" />
|
||||
) : (
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M11 19l-7-7 7-7m8 14l-7-7 7-7" />
|
||||
)}
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
<button
|
||||
onClick={() => setIsCollapsed(!isCollapsed)}
|
||||
className="p-1.5 rounded-lg hover:bg-slate-700 transition-all duration-200 hover:shadow-md"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
{isCollapsed ? (
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13 5l7 7-7 7M5 5l7 7-7 7" />
|
||||
) : (
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M11 19l-7-7 7-7m8 14l-7-7 7-7" />
|
||||
)}
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Navigation */}
|
||||
<nav className="flex-1 p-3 space-y-4 overflow-y-auto overflow-x-hidden">
|
||||
@@ -404,6 +473,32 @@ export default function Sidebar() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// Hook personalizado para manejar el menú móvil desde otros componentes
|
||||
export function useMobileSidebar() {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const toggle = () => setIsOpen(prev => !prev);
|
||||
const close = () => setIsOpen(false);
|
||||
|
||||
return { isOpen, toggle, close };
|
||||
}
|
||||
|
||||
// Componente botón para abrir menú móvil
|
||||
export function MobileMenuButton({ onClick }) {
|
||||
return (
|
||||
<button
|
||||
onClick={onClick}
|
||||
className="lg:hidden p-2 rounded-lg text-gray-600 hover:text-gray-900 hover:bg-gray-100 transition-colors duration-200"
|
||||
aria-label="Abrir menú"
|
||||
>
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||
</svg>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user