145 lines
5.1 KiB
TypeScript
145 lines
5.1 KiB
TypeScript
"use client";
|
|
import { useState, useEffect } from "react";
|
|
import Link from "next/link";
|
|
import { usePathname } from "next/navigation";
|
|
import { Button } from "../ui/Button";
|
|
import { motion, AnimatePresence } from "framer-motion";
|
|
import { FiMenu, FiX, FiGlobe } from "react-icons/fi";
|
|
import { useLanguage } from "@/context/LanguageContext";
|
|
|
|
export const Navbar = () => {
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
const pathname = usePathname();
|
|
const { locale, setLocale, t } = useLanguage();
|
|
|
|
const isActive = (path: string) => pathname === path;
|
|
|
|
useEffect(() => {
|
|
setIsOpen(false);
|
|
}, [pathname]);
|
|
|
|
useEffect(() => {
|
|
if (isOpen) {
|
|
document.body.style.overflow = "hidden";
|
|
} else {
|
|
document.body.style.overflow = "unset";
|
|
}
|
|
}, [isOpen]);
|
|
|
|
const navLinks = [
|
|
{ name: t.navbar.consultora, href: "/nosotros" },
|
|
{ name: t.navbar.servicios, href: "/servicios" },
|
|
{ name: t.navbar.participa, href: "/participa" },
|
|
{ name: t.navbar.insights, href: "/insights" },
|
|
];
|
|
|
|
return (
|
|
<nav className="w-full h-[80px] bg-white/80 backdrop-blur-md border-b border-crisp sticky top-0 z-[100]">
|
|
<div className="max-w-7xl mx-auto px-6 lg:px-12 h-full flex justify-between items-center">
|
|
{/* Logo */}
|
|
<Link href="/" className="text-[20px] md:text-[22px] font-extrabold tracking-tight text-navy uppercase">
|
|
Item Opina.
|
|
</Link>
|
|
|
|
{/* Menú Central (Escritorio) */}
|
|
<div className="hidden md:flex space-x-8 lg:space-x-10 text-[13px] lg:text-[14px] font-bold uppercase tracking-wider">
|
|
{navLinks.map((link) => (
|
|
<Link
|
|
key={link.href}
|
|
href={link.href}
|
|
className={`${isActive(link.href) ? "text-ocean" : "text-navy/60"} hover:text-ocean transition-colors`}
|
|
>
|
|
{link.name}
|
|
</Link>
|
|
))}
|
|
</div>
|
|
|
|
{/* Idiomas y Acción (Escritorio) */}
|
|
<div className="hidden md:flex items-center space-x-6">
|
|
{/* Selector de Idiomas */}
|
|
<div className="flex items-center gap-3 pr-6">
|
|
{(["es", "ca", "en"] as const).map((lang) => (
|
|
<button
|
|
key={lang}
|
|
onClick={() => setLocale(lang)}
|
|
className={`text-[11px] font-black uppercase transition-all ${
|
|
locale === lang ? "text-ocean scale-110" : "text-navy/30 hover:text-navy"
|
|
}`}
|
|
>
|
|
{lang}
|
|
</button>
|
|
))}
|
|
</div>
|
|
|
|
<Link href="/contacto">
|
|
<Button
|
|
variant={isActive("/contacto") ? "primary" : "outline"}
|
|
className="!py-2.5 !px-6 text-[12px]"
|
|
>
|
|
{t.navbar.contacto}
|
|
</Button>
|
|
</Link>
|
|
</div>
|
|
|
|
{/* Botón Hamburguesa (Móvil) */}
|
|
<button
|
|
onClick={() => setIsOpen(!isOpen)}
|
|
className="md:hidden text-navy p-2 outline-none focus:outline-none ring-0"
|
|
aria-label="Toggle Menu"
|
|
>
|
|
{isOpen ? <FiX size={28} /> : <FiMenu size={28} />}
|
|
</button>
|
|
</div>
|
|
|
|
{/* Menú Móvil (Overlay) */}
|
|
<AnimatePresence>
|
|
{isOpen && (
|
|
<motion.div
|
|
initial={{ opacity: 0, x: 20 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
exit={{ opacity: 0, x: 20 }}
|
|
transition={{ duration: 0.3 }}
|
|
className="fixed inset-0 top-[80px] w-full h-[calc(100vh-80px)] bg-white z-[90] flex flex-col p-8 md:hidden"
|
|
>
|
|
<div className="flex flex-col space-y-6 mt-6">
|
|
{navLinks.map((link) => (
|
|
<Link
|
|
key={link.href}
|
|
href={link.href}
|
|
className={`text-[32px] font-extrabold uppercase tracking-tighter ${
|
|
isActive(link.href) ? "text-ocean" : "text-navy"
|
|
}`}
|
|
>
|
|
{link.name}
|
|
</Link>
|
|
))}
|
|
|
|
<div className="pt-8 border-t border-crisp flex flex-col gap-8">
|
|
{/* Selector de Idiomas Móvil */}
|
|
<div className="flex gap-6">
|
|
{(["es", "ca", "en"] as const).map((lang) => (
|
|
<button
|
|
key={lang}
|
|
onClick={() => setLocale(lang)}
|
|
className={`text-[16px] font-bold uppercase ${
|
|
locale === lang ? "text-ocean border-b-2 border-ocean" : "text-navy/40"
|
|
}`}
|
|
>
|
|
{lang === "es" ? "Español" : lang === "ca" ? "Català" : "English"}
|
|
</button>
|
|
))}
|
|
</div>
|
|
|
|
<Link href="/contacto">
|
|
<Button variant="primary" className="w-full !py-5 text-[16px] uppercase tracking-widest font-bold">
|
|
{t.navbar.contacto}
|
|
</Button>
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
)}
|
|
</AnimatePresence>
|
|
</nav>
|
|
);
|
|
}; |