| "use client"; | |
| import React, { useState, useEffect, useRef } from "react"; | |
| import Link from "next/link"; | |
| import Image from "next/image"; | |
| import { usePathname } from "next/navigation"; | |
| import "./Sidebar.css"; | |
| import config from "@/lib/config"; | |
| const Sidebar = () => { | |
| const [isOpen, setIsOpen] = useState(false); | |
| const pathname = usePathname(); | |
| const [hoveredLink, setHoveredLink] = useState(null); | |
| const [prevLink, setPrevLink] = useState(null); | |
| const sidebarRef = useRef(null); | |
| useEffect(() => { | |
| const activeLink = document.querySelector( | |
| `.sidebar-link[href="${pathname}"]` | |
| ); | |
| if (activeLink) { | |
| setPrevLink(activeLink); | |
| } | |
| }, [pathname]); | |
| const toggleSidebar = () => { | |
| setIsOpen(!isOpen); | |
| }; | |
| const handleMouseEnter = (e) => { | |
| setPrevLink(document.querySelector(".sidebar-link.active")); | |
| setHoveredLink(e.target); | |
| }; | |
| const handleMouseLeave = () => { | |
| setHoveredLink(null); | |
| }; | |
| const handleClickOutside = (e) => { | |
| if (sidebarRef.current && !sidebarRef.current.contains(e.target)) { | |
| setIsOpen(false); | |
| } | |
| }; | |
| const handleLinkClick = () => { | |
| setIsOpen(false); | |
| }; | |
| useEffect(() => { | |
| if (isOpen) { | |
| document.addEventListener("mousedown", handleClickOutside); | |
| } else { | |
| document.removeEventListener("mousedown", handleClickOutside); | |
| } | |
| return () => { | |
| document.removeEventListener("mousedown", handleClickOutside); | |
| }; | |
| }, [isOpen]); | |
| return ( | |
| <div ref={sidebarRef} className={`sidebar ${isOpen ? "open" : "closed"}`}> | |
| <div className="sidebar-header"> | |
| <button className="sidebar-toggle" onClick={toggleSidebar}> | |
| <span className="material-symbols-outlined">{isOpen ? "menu_open" : "menu"}</span> | |
| </button> | |
| {isOpen && ( | |
| <h1 className="sidebar-title"> | |
| Nexora{" "} | |
| <Image | |
| className="sidebar-logo" | |
| src="/favicon-32x32.png" | |
| width={32} | |
| height={32} | |
| alt="Nexora Logo" | |
| /> | |
| </h1> | |
| )} | |
| </div> | |
| <div className="sidebar-content"> | |
| {isOpen && ( | |
| <div className="sidebar-menu"> | |
| <Link | |
| href="/" | |
| className={`sidebar-link ${pathname === "/" ? "active" : ""}`} | |
| onMouseEnter={handleMouseEnter} | |
| onMouseLeave={handleMouseLeave} | |
| onClick={handleLinkClick} | |
| > | |
| <SidebarItem icon="home" text="Home" /> | |
| </Link> | |
| <Link | |
| href="/movies" | |
| className={`sidebar-link ${pathname === "/movies" || pathname.includes("/movie") ? "active" : ""}`} | |
| onMouseEnter={handleMouseEnter} | |
| onMouseLeave={handleMouseLeave} | |
| onClick={handleLinkClick} | |
| > | |
| <SidebarItem icon="movie" text="Movies" /> | |
| </Link> | |
| <Link | |
| href="/tvshows" | |
| className={`sidebar-link ${pathname === "/tvshows" || pathname.includes("/tvshow") ? "active" : ""}`} | |
| onMouseEnter={handleMouseEnter} | |
| onMouseLeave={handleMouseLeave} | |
| onClick={handleLinkClick} | |
| > | |
| <SidebarItem icon="tv_guide" text="TV Shows" /> | |
| </Link> | |
| <Link | |
| href="/categories" | |
| className={`sidebar-link ${pathname === "/categories" ? "active" : ""}`} | |
| onMouseEnter={handleMouseEnter} | |
| onMouseLeave={handleMouseLeave} | |
| onClick={handleLinkClick} | |
| > | |
| <SidebarItem icon="tile_small" text="Categories" /> | |
| </Link> | |
| </div> | |
| )} | |
| {isOpen && ( | |
| <div className="sidebar-footer"> | |
| <Link | |
| href="/dashboard" | |
| className={`sidebar-link ${pathname.includes("/dashboard")? "active" : ""}`} | |
| onMouseEnter={handleMouseEnter} | |
| onMouseLeave={handleMouseLeave} | |
| onClick={handleLinkClick} | |
| > | |
| <SidebarItem icon="space_dashboard" text="Dashboard" /> | |
| </Link> | |
| <Link | |
| href="/settings" | |
| className={`sidebar-link ${pathname === "/settings" ? "active" : ""}`} | |
| onMouseEnter={handleMouseEnter} | |
| onMouseLeave={handleMouseLeave} | |
| onClick={handleLinkClick} | |
| > | |
| <SidebarItem icon="settings" text="Settings" /> | |
| </Link> | |
| <SidebarItem icon="conversion_path" text={config.version} /> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| ); | |
| }; | |
| const SidebarItem = ({ icon, text }) => { | |
| return ( | |
| <div className="sidebar-item"> | |
| <span className="material-symbols-outlined">{icon}</span> | |
| <p className="sidebar-item-text">{text}</p> | |
| </div> | |
| ); | |
| }; | |
| export default Sidebar; | |