|
|
@@ -1,12 +1,12 @@
|
|
|
"use client"
|
|
|
|
|
|
-import { useState } from "react"
|
|
|
+import { useState, useEffect, Fragment } from "react"
|
|
|
import { Menu, ChevronLeft, ChevronRight } from "lucide-react"
|
|
|
+import { Dialog, Transition } from "@headlessui/react"
|
|
|
import SidebarHeader from "@/components/sidebar/SidebarHeader"
|
|
|
import SidebarUserInfo from "@/components/sidebar/SidebarUserInfo"
|
|
|
import SidebarNavigation from "@/components/sidebar/SidebarNavigation"
|
|
|
import SidebarFooter from "@/components/sidebar/SidebarFooter"
|
|
|
-import MobileSidebar from "@/components/sidebar/MobileSidebar"
|
|
|
|
|
|
interface SidebarProps {
|
|
|
isCollapsed?: boolean
|
|
|
@@ -16,62 +16,128 @@ interface SidebarProps {
|
|
|
export default function Sidebar({ isCollapsed: externalIsCollapsed, onToggleCollapse }: SidebarProps) {
|
|
|
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false)
|
|
|
const [internalIsCollapsed, setInternalIsCollapsed] = useState(false)
|
|
|
+ const [isDesktop, setIsDesktop] = useState(false)
|
|
|
|
|
|
const isCollapsed = externalIsCollapsed !== undefined ? externalIsCollapsed : internalIsCollapsed
|
|
|
const toggleCollapse = onToggleCollapse || (() => setInternalIsCollapsed(!internalIsCollapsed))
|
|
|
|
|
|
+ useEffect(() => {
|
|
|
+ const checkDesktop = () => setIsDesktop(window.innerWidth >= 1024)
|
|
|
+ checkDesktop()
|
|
|
+ window.addEventListener('resize', checkDesktop)
|
|
|
+ return () => window.removeEventListener('resize', checkDesktop)
|
|
|
+ }, [])
|
|
|
|
|
|
+ const handleButtonClick = () => {
|
|
|
+ if (isDesktop) {
|
|
|
+ toggleCollapse()
|
|
|
+ } else {
|
|
|
+ setIsMobileMenuOpen(true)
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
return (
|
|
|
<>
|
|
|
- {/* Botón del menú móvil */}
|
|
|
+ {/* Botón flotante unificado */}
|
|
|
<button
|
|
|
type="button"
|
|
|
- className="lg:hidden fixed top-4 left-4 z-50 p-2 rounded-md shadow-lg border border-gray-200 bg-white"
|
|
|
- onClick={() => setIsMobileMenuOpen(true)}
|
|
|
+ className="fixed top-4 left-4 z-50 p-2 rounded-md shadow-lg border border-gray-200 bg-white"
|
|
|
+ onClick={handleButtonClick}
|
|
|
>
|
|
|
- <Menu className="h-6 w-6 text-gray-600" />
|
|
|
+ {isDesktop ? (
|
|
|
+ isCollapsed ? (
|
|
|
+ <ChevronRight className="h-6 w-6 text-gray-600" />
|
|
|
+ ) : (
|
|
|
+ <ChevronLeft className="h-6 w-6 text-gray-600" />
|
|
|
+ )
|
|
|
+ ) : (
|
|
|
+ <Menu className="h-6 w-6 text-gray-600" />
|
|
|
+ )}
|
|
|
</button>
|
|
|
|
|
|
- {/* Sidebar móvil */}
|
|
|
- <MobileSidebar
|
|
|
- isOpen={isMobileMenuOpen}
|
|
|
- onClose={() => setIsMobileMenuOpen(false)}
|
|
|
- />
|
|
|
-
|
|
|
{/* Sidebar de escritorio */}
|
|
|
- <div
|
|
|
- className="hidden lg:fixed lg:inset-y-0 lg:z-50 lg:flex lg:flex-col transition-all duration-300"
|
|
|
- style={{ width: isCollapsed ? '4rem' : '18rem' }}
|
|
|
- >
|
|
|
+ {isDesktop && (
|
|
|
<div
|
|
|
- className="flex grow flex-col overflow-y-auto border-r border-gray-200 bg-white shadow-sm"
|
|
|
+ className="fixed inset-y-0 left-0 z-50 flex flex-col transition-all duration-300"
|
|
|
+ style={{ width: isCollapsed ? '4rem' : '18rem' }}
|
|
|
>
|
|
|
- {/* Botón de toggle */}
|
|
|
- <div className={`flex ${isCollapsed ? 'justify-center' : 'justify-end'} p-4 border-b border-gray-200`}>
|
|
|
- <button
|
|
|
- onClick={toggleCollapse}
|
|
|
- className="p-1.5 rounded-md hover:bg-gray-100 transition-colors"
|
|
|
- title={isCollapsed ? 'Expandir sidebar' : 'Colapsar sidebar'}
|
|
|
- >
|
|
|
- {isCollapsed ? (
|
|
|
- <ChevronRight className="h-4 w-4 text-gray-600" />
|
|
|
- ) : (
|
|
|
- <ChevronLeft className="h-4 w-4 text-gray-600" />
|
|
|
- )}
|
|
|
- </button>
|
|
|
+ <div
|
|
|
+ className="flex grow flex-col overflow-y-auto border-r border-gray-200 bg-white shadow-sm"
|
|
|
+ >
|
|
|
+ {/* Botón de toggle removido, ahora flotante */}
|
|
|
+
|
|
|
+ <SidebarHeader isCollapsed={isCollapsed} />
|
|
|
+ <SidebarNavigation isCollapsed={isCollapsed} />
|
|
|
+
|
|
|
+ {/* User info y footer al final */}
|
|
|
+ <div className="mt-auto">
|
|
|
+ <SidebarUserInfo isCollapsed={isCollapsed} />
|
|
|
+ <SidebarFooter isCollapsed={isCollapsed} />
|
|
|
+ </div>
|
|
|
</div>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
|
|
|
- <SidebarHeader isCollapsed={isCollapsed} />
|
|
|
- <SidebarNavigation isCollapsed={isCollapsed} />
|
|
|
-
|
|
|
- {/* User info y footer al final */}
|
|
|
- <div className="mt-auto">
|
|
|
- <SidebarUserInfo isCollapsed={isCollapsed} />
|
|
|
- <SidebarFooter isCollapsed={isCollapsed} />
|
|
|
+ {/* Sidebar móvil */}
|
|
|
+ <Transition.Root show={!isDesktop && isMobileMenuOpen} as={Fragment}>
|
|
|
+ <Dialog as="div" className="relative z-50 lg:hidden" onClose={() => setIsMobileMenuOpen(false)}>
|
|
|
+ <Transition.Child
|
|
|
+ as={Fragment}
|
|
|
+ enter="transition-opacity ease-linear duration-300"
|
|
|
+ enterFrom="opacity-0"
|
|
|
+ enterTo="opacity-100"
|
|
|
+ leave="transition-opacity ease-linear duration-300"
|
|
|
+ leaveFrom="opacity-100"
|
|
|
+ leaveTo="opacity-0"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ className="fixed inset-0"
|
|
|
+ style={{ backgroundColor: 'rgba(0, 0, 0, 0.5)' }}
|
|
|
+ />
|
|
|
+ </Transition.Child>
|
|
|
+
|
|
|
+ <div className="fixed inset-0 flex">
|
|
|
+ <Transition.Child
|
|
|
+ as={Fragment}
|
|
|
+ enter="transition ease-in-out duration-300 transform"
|
|
|
+ enterFrom="-translate-x-full"
|
|
|
+ enterTo="translate-x-0"
|
|
|
+ leave="transition ease-in-out duration-300 transform"
|
|
|
+ leaveFrom="translate-x-0"
|
|
|
+ leaveTo="-translate-x-full"
|
|
|
+ >
|
|
|
+ <Dialog.Panel className="relative mr-16 flex w-full max-w-xs flex-1">
|
|
|
+ <Transition.Child
|
|
|
+ as={Fragment}
|
|
|
+ enter="ease-in-out duration-300"
|
|
|
+ enterFrom="opacity-0"
|
|
|
+ enterTo="opacity-100"
|
|
|
+ leave="ease-in-out duration-300"
|
|
|
+ leaveFrom="opacity-100"
|
|
|
+ leaveTo="opacity-0"
|
|
|
+ >
|
|
|
+ <div className="absolute left-full top-0 flex w-16 justify-center pt-5">
|
|
|
+ {/* Botón de cerrar removido, ahora en header */}
|
|
|
+ </div>
|
|
|
+ </Transition.Child>
|
|
|
+
|
|
|
+ <div
|
|
|
+ className="flex grow flex-col overflow-y-auto ring-1 ring-white/10"
|
|
|
+ style={{ backgroundColor: 'white' }}
|
|
|
+ >
|
|
|
+ <SidebarHeader isCollapsed={false} onClose={() => setIsMobileMenuOpen(false)} />
|
|
|
+ <SidebarNavigation onItemClick={() => setIsMobileMenuOpen(false)} isCollapsed={false} />
|
|
|
+
|
|
|
+ <div className="mt-auto">
|
|
|
+ <SidebarUserInfo isCollapsed={false} />
|
|
|
+ <SidebarFooter onItemClick={() => setIsMobileMenuOpen(false)} isCollapsed={false} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </Dialog.Panel>
|
|
|
+ </Transition.Child>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ </Dialog>
|
|
|
+ </Transition.Root>
|
|
|
</>
|
|
|
)
|
|
|
}
|