226 lines
7.2 KiB
JavaScript
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>
|
|
);
|
|
}
|