226 lines
7.2 KiB
JavaScript

"use client";
import Link from "next/link";
import React, { useEffect, useState } from "react";
import { usePathname } from "next/navigation";
export default function Nav({ color = "#fab758" }) {
const [menu, setMenu] = useState([]);
const pathname = usePathname();
useEffect(() => {
fetch("/api/get-menu")
.then((res) => res.json())
.then((data) => setMenu(data.menu || []));
const handleClickOutside = (event) => {
if (window.innerWidth <= 768) {
if (!event.target.closest('.navbar-nav .offcanvas-body .dropdown')) {
document.querySelectorAll('.navbar-nav .offcanvas-body .dropdown-menu').forEach(menu => {
menu.style.display = 'none';
});
}
}
};
const handleDropdownEvents = () => {
document.querySelectorAll('.dropdown-submenu').forEach(submenu => {
submenu.addEventListener('mouseenter', function() {
const dropdownMenu = this.querySelector('.dropdown-menu');
if (dropdownMenu) {
dropdownMenu.style.display = 'block';
}
});
submenu.addEventListener('mouseleave', function() {
const dropdownMenu = this.querySelector('.dropdown-menu');
if (dropdownMenu) {
dropdownMenu.style.display = 'none';
}
});
});
};
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', handleDropdownEvents);
} else {
setTimeout(handleDropdownEvents, 100);
}
document.addEventListener('click', handleClickOutside);
return () => {
document.removeEventListener('click', handleClickOutside);
document.querySelectorAll('.dropdown-submenu').forEach(submenu => {
submenu.removeEventListener('mouseenter', handleDropdownEvents);
submenu.removeEventListener('mouseleave', handleDropdownEvents);
});
};
}, []);
const filterHeaderMenu = (items) => {
return items.filter(item => item.position === 'Header');
};
const renderMenu = (items, level = 0) => {
if (level === 0) items = filterHeaderMenu(items);
return items.map((item) => {
const hasChildren = item.children && item.children.length > 0;
const hasHref = !!item.href && item.href !== "#";
if (hasChildren) {
return (
<li key={item.id} className={`nav-item dropdown${level > 0 ? " dropdown-submenu dropend" : ""}`}>
<div style={{ display: 'flex', alignItems: 'center' }}>
{hasHref && (
<Link
className={`${level > 0 ? "dropdown-item" : "nav-link"} !text-[.7rem] !tracking-[normal] hover:!text-[var(--current-color)] after:!text-[var(--current-color)] ${pathname === item.href ? "!text-[var(--current-color)]" : ""}`}
href={item.href}
style={{ paddingRight: 0 }}
>
{item.label}
</Link>
)}
<a
className={`${hasHref ? "dropdown-toggle" : (level > 0 ? "dropdown-item" : "nav-link")} !text-[.7rem] !tracking-[normal] hover:!text-[var(--current-color)] after:!text-[var(--current-color)] ${!hasHref && pathname === item.href ? "!text-[var(--current-color)]" : ""}`}
href="#"
onClick={(e) => {
if (window.innerWidth <= 768) {
e.preventDefault();
const dropdownMenu = e.target.closest('.dropdown').querySelector('.dropdown-menu');
if (dropdownMenu) {
dropdownMenu.style.display = dropdownMenu.style.display === 'block' ? 'none' : 'block';
}
}
}}
style={hasHref ? { paddingLeft: 8, minWidth: 24 } : {}}
>
{hasHref ? <span className="sr-only">Open</span> : item.label}
</a>
</div>
<ul className={`dropdown-menu${level > 0 ? " submenu" : ""}`}>
{renderMenu(item.children, level + 1)}
</ul>
</li>
);
} else {
return (
<li key={item.id} className="nav-item">
<Link
className={`${level > 0 ? "dropdown-item" : "nav-link"} !text-[.7rem] !tracking-[normal] hover:!text-[var(--current-color)] after:!text-[var(--current-color)] ${pathname === item.href ? "!text-[var(--current-color)]" : ""}`}
href={item.href || "#"}
>
{item.label}
</Link>
</li>
);
}
});
};
return (
<ul className="navbar-nav" style={{ "--current-color": color }}>
{renderMenu(menu)}
<style jsx>{`
.navbar-nav .dropdown-submenu {
position: relative;
}
.navbar-nav .dropdown-submenu .dropdown-menu {
top: 0;
left: 100%;
margin-top: -1px;
position: absolute;
z-index: 1000;
}
.dropdown-submenu.dropend .dropdown-menu {
left: 100%;
top: 0;
}
.dropdown-submenu > .dropdown-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: "";
border-top: 0.3em solid transparent;
border-right: 0;
border-bottom: 0.3em solid transparent;
border-left: 0.3em solid;
}
.dropdown-menu {
display: none;
position: absolute;
z-index: 1000;
min-width: 10rem;
padding: 0.5rem 0;
margin: 0;
font-size: 1rem;
color: #212529;
text-align: left;
list-style: none;
background-color: #fff;
background-clip: padding-box;
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 0.375rem;
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
}
.dropdown-menu.show {
display: block;
}
.dropdown-item {
display: block;
width: 100%;
padding: 0.25rem 1rem;
clear: both;
font-weight: 400;
color: #212529;
text-align: inherit;
text-decoration: none;
white-space: nowrap;
background-color: transparent;
border: 0;
}
.dropdown-item:hover,
.dropdown-item:focus {
color: #1e2125;
background-color: #e9ecef;
}
.nav-link {
color: #6c757d;
text-decoration: none;
padding: 0.5rem 1rem;
}
.nav-link:hover {
color: var(--current-color);
}
.dropdown-submenu .dropdown-submenu .dropdown-menu {
z-index: 1001;
}
.navbar-nav > .dropdown > .dropdown-menu {
top: 100%;
left: 0;
margin-top: 0;
}
.dropdown-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: "";
border-top: 0.3em solid;
border-right: 0.3em solid transparent;
border-bottom: 0;
border-left: 0.3em solid transparent;
}
`}</style>
</ul>
);
}