diff --git a/components/navigation.tsx b/components/navigation.tsx index 66f253bdd..af4edb4d8 100644 --- a/components/navigation.tsx +++ b/components/navigation.tsx @@ -1,52 +1,132 @@ "use client" -import { useState, useEffect } from "react" +import { useCallback, useEffect, useState } from "react" +import type { MouseEvent } from "react" import Link from "next/link" -import { Button } from "@/components/ui/button" +import { usePathname, useRouter } from "next/navigation" import { Menu, X } from "lucide-react" +import { Button } from "@/components/ui/button" +import { + NavigationMenu, + NavigationMenuItem, + NavigationMenuLink, + NavigationMenuList, +} from "@/components/ui/navigation-menu" +import { cn } from "@/lib/utils" + +type NavItem = { + href: string + label: string + id: string + isButton?: boolean +} + +const navItems: NavItem[] = [ + { href: "#home", label: "Home", id: "home" }, + { href: "#artists", label: "Artists", id: "artists" }, + { href: "#services", label: "Services", id: "services" }, + { href: "#contact", label: "Contact", id: "contact" }, + { href: "/book", label: "Book Now", id: "book", isButton: true }, +] + +const scrollTrackedIds = navItems.filter((item) => !item.isButton).map((item) => item.id) + export function Navigation() { + const pathname = usePathname() + const router = useRouter() const [isOpen, setIsOpen] = useState(false) const [isScrolled, setIsScrolled] = useState(false) - const [activeSection, setActiveSection] = useState("home") + const [activeSection, setActiveSection] = useState(scrollTrackedIds[0] ?? "") + + const scrollToSection = useCallback( + (targetId: string, options?: { href?: string; updateHistory?: boolean }) => { + const target = document.getElementById(targetId) + if (!target) { + return + } + + const offset = target.getBoundingClientRect().top + window.scrollY - 80 + window.scrollTo({ top: offset, behavior: "smooth" }) + + if (options?.href && options.updateHistory !== false) { + window.history.replaceState(null, "", options.href) + } + + setActiveSection(targetId) + }, + [], + ) useEffect(() => { const handleScroll = () => { setIsScrolled(window.scrollY > 50) - const sections = ["home", "artists", "services", "contact"] const scrollPosition = window.scrollY + 100 - for (const section of sections) { + for (const section of scrollTrackedIds) { const element = document.getElementById(section) - if (element) { - const { offsetTop, offsetHeight } = element - if (scrollPosition >= offsetTop && scrollPosition < offsetTop + offsetHeight) { - setActiveSection(section) - break - } + if (!element) { + continue + } + + const { offsetTop, offsetHeight } = element + if (scrollPosition >= offsetTop && scrollPosition < offsetTop + offsetHeight) { + setActiveSection(section) + return } } } + handleScroll() window.addEventListener("scroll", handleScroll) return () => window.removeEventListener("scroll", handleScroll) - }, []) + }, [scrollTrackedIds]) - const navItems = [ - { href: "#home", label: "Home", id: "home" }, - { href: "#artists", label: "Artists", id: "artists" }, - { href: "#services", label: "Services", id: "services" }, - { href: "#contact", label: "Contact", id: "contact" }, - ] + useEffect(() => { + if (pathname !== "/") { + return + } + + const hash = window.location.hash.slice(1) + if (!hash) { + return + } + + const frame = window.requestAnimationFrame(() => { + scrollToSection(hash, { updateHistory: false }) + }) + + return () => window.cancelAnimationFrame(frame) + }, [pathname, scrollToSection]) + + const handleNavClick = (event: MouseEvent, item: NavItem) => { + if (item.isButton || !item.href.startsWith("/#")) { + return + } + + if (pathname === "/") { + event.preventDefault() + const targetId = item.href.slice(2) + scrollToSection(targetId, { href: item.href }) + return + } + + event.preventDefault() + router.push(item.href) + } + + const handleToggleMenu = () => setIsOpen((previous) => !previous) + const handleCloseMenu = () => setIsOpen(false) return (