UEA-PRODEM

This commit is contained in:
2026-06-10 11:39:21 -03:00
parent 47b753b5f1
commit d420d33415
10 changed files with 891 additions and 14217 deletions
+146 -115
View File
@@ -1,176 +1,207 @@
import { useState, useEffect } from 'react';
import { useState, useEffect, useRef } from 'react';
import { Link, useLocation } from 'react-router-dom';
import { Menu, X, Phone, ChevronDown } from 'lucide-react';
import { Menu, X, Phone, ChevronDown, ArrowRight } from 'lucide-react';
import { LOGO, NAV_LINKS, CONTACT } from '../config/site';
type NavItem = {
name: string;
href: string;
submenu?: { name: string; href: string }[];
};
const Navigation = () => {
const [isScrolled, setIsScrolled] = useState(false);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const [isServicesOpen, setIsServicesOpen] = useState(false);
const [openSubmenu, setOpenSubmenu] = useState<string | null>(null);
const [mobileOpenSubmenu, setMobileOpenSubmenu] = useState<string | null>(null);
const location = useLocation();
const submenuTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 50);
};
const handleScroll = () => setIsScrolled(window.scrollY > 50);
window.addEventListener('scroll', handleScroll, { passive: true });
return () => window.removeEventListener('scroll', handleScroll);
}, []);
// Fechar menu mobile ao mudar de rota
useEffect(() => {
setIsMobileMenuOpen(false);
setIsServicesOpen(false);
setOpenSubmenu(null);
setMobileOpenSubmenu(null);
}, [location]);
const isActive = (path: string) => {
if (path === '/') {
return location.pathname === '/';
}
if (path === '/') return location.pathname === '/';
return location.pathname.startsWith(path);
};
// Renderiza o logo (SVG inline ou imagem)
const handleSubmenuEnter = (name: string) => {
if (submenuTimeout.current) clearTimeout(submenuTimeout.current);
setOpenSubmenu(name);
};
const handleSubmenuLeave = () => {
submenuTimeout.current = setTimeout(() => setOpenSubmenu(null), 200);
};
const renderLogo = () => {
if (LOGO.imageUrl) {
return <img src={LOGO.imageUrl} alt={LOGO.text} className="h-10 w-auto" />;
}
return (
<div dangerouslySetInnerHTML={{ __html: LOGO.svgInline }} className="flex-shrink-0" />
);
return <div dangerouslySetInnerHTML={{ __html: LOGO.svgInline }} className="flex-shrink-0" />;
};
return (
<nav className={`nav-sticky ${isScrolled ? 'scrolled' : ''}`}>
<div className="container-custom">
<div className="flex items-center justify-between h-20">
{/* Logo - importado de config/site.ts */}
<Link to={LOGO.href} className="flex items-center" aria-label="Avanzato Tecnologia - Pagina inicial">
<nav
className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ${
isScrolled
? 'bg-[#0e0e0e]/95 backdrop-blur-md shadow-lg shadow-black/20 border-b border-[#2a2a2a]/50'
: 'bg-transparent'
}`}
>
<div className="max-w-7xl mx-auto px-4 lg:px-6">
<div className="flex items-center justify-between h-[72px]">
{/* Logo */}
<Link to={LOGO.href} className="flex items-center shrink-0" aria-label="Avanzato Tecnologia">
{renderLogo()}
</Link>
{/* Desktop Navigation - importado de config/site.ts */}
<div className="hidden lg:flex items-center gap-8">
{NAV_LINKS.map((link) => (
<div key={link.name} className="relative">
{link.submenu ? (
<div
className="relative"
onMouseEnter={() => setIsServicesOpen(true)}
onMouseLeave={() => setIsServicesOpen(false)}
>
{/* Desktop Menu */}
<div className="hidden lg:flex items-center gap-1">
{NAV_LINKS.map((item: NavItem) => (
<div
key={item.name}
className="relative"
onMouseEnter={() => item.submenu && handleSubmenuEnter(item.name)}
onMouseLeave={handleSubmenuLeave}
>
{item.submenu ? (
<>
<button
className={`flex items-center gap-1 nav-link text-sm font-medium transition-colors ${
link.submenu.some(s => location.pathname.startsWith(s.href))
? 'text-[#cbf400]'
: 'text-gray-300 hover:text-white'
className={`flex items-center gap-1 px-3 py-2 rounded-lg text-sm font-medium transition-all duration-200 ${
isActive(item.href) || item.submenu.some(s => isActive(s.href))
? 'text-[#cbf400] bg-[#cbf400]/10'
: 'text-gray-300 hover:text-white hover:bg-white/5'
}`}
>
{link.name}
<ChevronDown className={`w-4 h-4 transition-transform ${isServicesOpen ? 'rotate-180' : ''}`} />
{item.name}
<ChevronDown className={`w-3.5 h-3.5 transition-transform duration-200 ${openSubmenu === item.name ? 'rotate-180' : ''}`} />
</button>
{isServicesOpen && (
<div className="absolute top-full left-0 mt-2 w-56 bg-[#1a1a1a] rounded-xl border border-white/10 shadow-xl py-2 z-50">
{link.submenu.map((sub) => (
{/* Submenu Dropdown */}
{openSubmenu === item.name && (
<div className="absolute top-full left-0 mt-1 w-64 bg-[#1a1a1a] rounded-xl border border-[#2a2a2a] shadow-2xl shadow-black/40 overflow-hidden animate-in fade-in slide-in-from-top-2 duration-200">
<div className="p-2">
{item.submenu.map((sub) => (
<Link
key={sub.href}
to={sub.href}
className={`flex items-center justify-between px-3 py-2.5 rounded-lg text-sm transition-all duration-150 ${
isActive(sub.href)
? 'text-[#cbf400] bg-[#cbf400]/10'
: 'text-gray-300 hover:text-white hover:bg-white/5'
}`}
>
{sub.name}
<ArrowRight className="w-3.5 h-3.5 opacity-0 -translate-x-2 group-hover:opacity-100 group-hover:translate-x-0 transition-all" />
</Link>
))}
</div>
</div>
)}
</>
) : (
<Link
to={item.href}
className={`px-3 py-2 rounded-lg text-sm font-medium transition-all duration-200 ${
isActive(item.href)
? 'text-[#cbf400] bg-[#cbf400]/10'
: 'text-gray-300 hover:text-white hover:bg-white/5'
}`}
>
{item.name}
</Link>
)}
</div>
))}
{/* CTA Button */}
<Link
to="/contato"
className="ml-3 bg-[#cbf400] text-[#0e0e0e] px-5 py-2.5 rounded-xl text-sm font-bold hover:bg-[#b8e000] transition-all duration-200 hover:shadow-lg hover:shadow-[#cbf400]/20 flex items-center gap-2"
>
<Phone className="w-4 h-4" />
{CONTACT.phone}
</Link>
</div>
{/* Mobile Toggle */}
<button
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
className="lg:hidden p-2 rounded-lg text-gray-300 hover:text-white hover:bg-white/5 transition-colors"
aria-label="Menu"
>
{isMobileMenuOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
</button>
</div>
</div>
{/* Mobile Menu */}
{isMobileMenuOpen && (
<div className="lg:hidden bg-[#0e0e0e]/98 backdrop-blur-lg border-t border-[#2a2a2a]">
<div className="max-w-7xl mx-auto px-4 py-4 space-y-1">
{NAV_LINKS.map((item: NavItem) => (
<div key={item.name}>
{item.submenu ? (
<>
<button
onClick={() => setMobileOpenSubmenu(mobileOpenSubmenu === item.name ? null : item.name)}
className="w-full flex items-center justify-between px-4 py-3 rounded-xl text-gray-300 hover:text-white hover:bg-white/5 transition-colors"
>
<span className="font-medium">{item.name}</span>
<ChevronDown className={`w-4 h-4 transition-transform ${mobileOpenSubmenu === item.name ? 'rotate-180' : ''}`} />
</button>
{mobileOpenSubmenu === item.name && (
<div className="pl-4 space-y-1 pb-2">
{item.submenu.map((sub) => (
<Link
key={sub.name}
key={sub.href}
to={sub.href}
className="block px-4 py-2.5 text-sm text-gray-300 hover:text-[#cbf400] hover:bg-white/5 transition-colors"
className={`block px-4 py-2.5 rounded-xl text-sm transition-colors ${
isActive(sub.href) ? 'text-[#cbf400] bg-[#cbf400]/10' : 'text-gray-400 hover:text-white hover:bg-white/5'
}`}
>
{sub.name}
</Link>
))}
</div>
)}
</div>
</>
) : (
<Link
to={link.href}
className={`nav-link text-sm font-medium transition-colors ${
isActive(link.href) ? 'text-[#cbf400]' : 'text-gray-300 hover:text-white'
to={item.href}
className={`block px-4 py-3 rounded-xl font-medium transition-colors ${
isActive(item.href) ? 'text-[#cbf400] bg-[#cbf400]/10' : 'text-gray-300 hover:text-white hover:bg-white/5'
}`}
>
{link.name}
{item.name}
</Link>
)}
</div>
))}
</div>
{/* Desktop CTA - importado de config/site.ts */}
<div className="hidden lg:flex items-center gap-4">
{/* Mobile CTA */}
<a
href={`tel:${CONTACT.phoneRaw}`}
className="flex items-center gap-2 text-sm text-gray-400 hover:text-[#cbf400] transition-colors"
href={`https://wa.me/${CONTACT.phoneRaw}`}
target="_blank"
rel="noopener noreferrer"
className="flex items-center justify-center gap-2 bg-[#cbf400] text-[#0e0e0e] px-5 py-3.5 rounded-xl font-bold mt-3"
>
<Phone className="w-4 h-4" />
{CONTACT.phone}
WhatsApp {CONTACT.phone}
</a>
</div>
{/* Mobile Menu Button */}
<button
className="lg:hidden p-2 text-gray-300 hover:text-white"
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
aria-label="Menu"
>
{isMobileMenuOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
</button>
</div>
{/* Mobile Menu - importado de config/site.ts */}
{isMobileMenuOpen && (
<div className="lg:hidden py-4 border-t border-white/10">
<div className="flex flex-col gap-4">
{NAV_LINKS.map((link) => (
<div key={link.name}>
{link.submenu ? (
<div>
<button
onClick={() => setIsServicesOpen(!isServicesOpen)}
className="flex items-center justify-between w-full text-gray-300 hover:text-[#cbf400] transition-colors py-2"
>
<span className="font-medium">{link.name}</span>
<ChevronDown className={`w-4 h-4 transition-transform ${isServicesOpen ? 'rotate-180' : ''}`} />
</button>
{isServicesOpen && (
<div className="pl-4 mt-2 space-y-2">
{link.submenu.map((sub) => (
<Link
key={sub.name}
to={sub.href}
className="block text-sm text-gray-400 hover:text-[#cbf400] py-1"
>
{sub.name}
</Link>
))}
</div>
)}
</div>
) : (
<Link
to={link.href}
className={`block py-2 font-medium transition-colors ${
isActive(link.href) ? 'text-[#cbf400]' : 'text-gray-300 hover:text-[#cbf400]'
}`}
>
{link.name}
</Link>
)}
</div>
))}
<a
href={`tel:${CONTACT.phoneRaw}`}
className="flex items-center gap-2 text-sm text-gray-400 hover:text-[#cbf400] pt-4 border-t border-white/10"
>
<Phone className="w-4 h-4" />
{CONTACT.phone}
</a>
</div>
</div>
)}
</div>
)}
</nav>
);
};