almeira-web/src/components/Navbar.tsx

170 lines
10 KiB
TypeScript

"use client";
import Link from 'next/link';
import { Radio, Newspaper, Megaphone, Menu, CalendarDays, Tv, X, User } from 'lucide-react';
import { useState, useEffect } from 'react';
import { usePathname } from 'next/navigation';
export const Navbar = ({ entity }: { entity?: any }) => {
const [scrolled, setScrolled] = useState(false);
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
const [user, setUser] = useState<any>(null);
const pathname = usePathname();
const ENDPOINT = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1';
const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c';
let logoUrl = entity?.logotipo || null;
if (logoUrl && !logoUrl.startsWith('http') && !logoUrl.startsWith('/')) {
logoUrl = `${ENDPOINT}/storage/buckets/media/files/${logoUrl}/view?project=${PROJECT_ID}`;
}
useEffect(() => {
const handleScroll = () => setScrolled(window.scrollY > 20);
window.addEventListener('scroll', handleScroll);
fetch('/api/auth/me', { cache: 'no-store' })
.then(res => res.json())
.then(data => { if(data.user) setUser(data.user); })
.catch(e => console.error("No session API"));
return () => window.removeEventListener('scroll', handleScroll);
}, []);
const navItems = [
{ name: 'Noticias', href: '/', icon: Newspaper },
{ name: 'Eventos', href: '/eventos', icon: CalendarDays },
{ name: 'Clasificados', href: '/clasificados', icon: Megaphone },
{ name: 'TV en Vivo', href: '/tv', icon: Tv, highlight: 'pink' },
{ name: 'Radio en Vivo', href: '/radio', icon: Radio, highlight: 'cyan' },
];
return (
<nav className={`fixed top-0 left-0 right-0 z-50 transition-all duration-500 ${
scrolled
? 'py-3 bg-slate-950/80 border-b border-cyan-500/20 shadow-[0_4px_30px_rgba(6,182,212,0.15)] backdrop-blur-xl'
: 'py-5 bg-transparent'
}`}>
<div className="container mx-auto px-4 lg:px-8 flex items-center justify-between">
{/* Brand Logo Holográfico */}
<Link href="/" className="flex items-center gap-3 group">
{logoUrl ? (
<div className="relative flex items-center shrink-0">
<div className="absolute inset-0 bg-transparent blur-md opacity-50 group-hover:opacity-100 transition-opacity rounded-xl"></div>
<img src={logoUrl} alt={entity?.razon_social || "Logo"} className="h-10 md:h-12 w-auto max-w-[180px] md:max-w-[240px] object-contain relative z-10 group-hover:scale-105 transition-transform drop-shadow-lg shrink-0" />
</div>
) : (
<div className="relative">
<div className="absolute inset-0 bg-cyan-400 blur-md opacity-50 group-hover:opacity-100 transition-opacity rounded-xl"></div>
<div className="relative bg-gradient-to-br from-cyan-500 to-blue-600 p-2.5 rounded-xl text-white shadow-lg group-hover:scale-105 transition-transform border border-white/20">
<Radio size={22} className="animate-pulse" />
</div>
</div>
)}
{(!logoUrl || entity?.mostrar_texto_logo) && (
<span className="text-2xl font-black tracking-tight text-white flex gap-1 font-outfit uppercase">
{entity?.razon_social ? (
entity.razon_social.split(' ').map((word: string, i: number, arr: string[]) =>
i === arr.length - 1 ?
<span key={i} className="holographic-text">{word}</span> :
<span key={i}>{word}</span>
)
) : (
<>Almeira<span className="holographic-text">PRO</span></>
)}
</span>
)}
</Link>
{/* Enlaces Futuristas (Desktop) */}
<div className="hidden lg:flex items-center gap-1 bg-slate-900/40 border border-white/10 rounded-full px-2 py-1.5 backdrop-blur-xl shadow-inner">
{navItems.map((item) => {
const Icon = item.icon;
const isActive = pathname === item.href;
const iconColor = item.highlight === 'pink' ? 'text-pink-400' : (item.highlight === 'cyan' ? 'text-cyan-400' : 'text-slate-500');
return (
<Link
key={item.name}
href={item.href}
className={`flex items-center gap-1.5 transition-all duration-300 ${
isActive ? 'futuristic-link active' : 'futuristic-link text-slate-400'
}`}
>
<Icon size={16} className={`${isActive ? 'text-cyan-300' : iconColor} ${item.highlight ? 'animate-pulse' : 'group-hover:text-cyan-400'} transition-colors`} />
<span className="text-[0.8rem] xl:text-sm whitespace-nowrap">{item.name}</span>
</Link>
);
})}
</div>
{/* Auth Actions */}
<div className="hidden lg:flex items-center gap-4">
{user ? (
<Link href="/dashboard/profile" className="group relative flex items-center gap-2 px-5 py-2 rounded-full text-sm font-bold text-white overflow-hidden transition-all hover:scale-105 border border-white/10 hover:border-cyan-500/50 shadow-[0_0_15px_rgba(0,0,0,0)] hover:shadow-[0_0_20px_rgba(6,182,212,0.3)] bg-gradient-to-r from-cyan-600 to-blue-600">
<User size={16} className="text-white" />
<span className="relative z-10 tracking-wider">Mi perfil</span>
</Link>
) : (
<Link href="/login" className="group relative flex items-center gap-2 px-5 py-2 rounded-full text-sm font-bold text-white overflow-hidden transition-all hover:scale-105 border border-white/10 hover:border-cyan-500/50 shadow-[0_0_15px_rgba(0,0,0,0)] hover:shadow-[0_0_20px_rgba(6,182,212,0.3)] bg-slate-800/80">
<User size={16} className="text-cyan-400 group-hover:text-white transition-colors" />
<span className="relative z-10 tracking-wider">Iniciar sesión</span>
</Link>
)}
</div>
{/* Menú Móvil Toggle */}
<button
onClick={(e) => {
e.preventDefault();
console.log("Toggle mobile menu:", !mobileMenuOpen);
setMobileMenuOpen(!mobileMenuOpen);
}}
className="lg:hidden relative z-[60] p-2 text-cyan-400 hover:text-cyan-300 transition-colors bg-slate-800/50 rounded-lg border border-cyan-500/30 active:scale-95"
aria-label="Menu"
>
{mobileMenuOpen ? <X size={26} /> : <Menu size={26} />}
</button>
</div>
{/* Menú Móvil Desplegable (HUD Style) */}
<div className={`fixed inset-0 bg-slate-950/95 backdrop-blur-3xl z-40 transition-all duration-500 flex flex-col items-center justify-center lg:hidden ${mobileMenuOpen ? 'opacity-100 pointer-events-auto translate-y-0' : 'opacity-0 pointer-events-none -translate-y-full'}`}>
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,_var(--tw-gradient-stops))] from-cyan-900/20 via-slate-950 to-slate-950"></div>
<div className="relative z-10 flex flex-col items-center gap-4 w-full px-8 max-w-sm">
{navItems.map((item) => {
const Icon = item.icon;
const isActive = pathname === item.href;
const iconColor = item.highlight === 'pink' ? 'text-pink-400' : (item.highlight === 'cyan' ? 'text-cyan-400' : 'text-slate-500');
return (
<Link
key={item.name}
href={item.href}
onClick={() => setMobileMenuOpen(false)}
className={`flex items-center gap-4 text-xl font-outfit uppercase tracking-widest transition-all w-full p-4 rounded-2xl border ${isActive ? 'bg-cyan-500/10 border-cyan-500/50 text-cyan-300 shadow-[0_0_30px_rgba(6,182,212,0.2)]' : 'border-white/5 text-slate-300 hover:text-white hover:bg-white/5 hover:border-white/10'}`}
>
<Icon size={24} className={isActive ? 'text-cyan-400' : iconColor} />
{item.name}
</Link>
)
})}
<div className="h-px w-full bg-gradient-to-r from-transparent via-cyan-500/30 to-transparent my-6"></div>
{user ? (
<Link href="/dashboard/profile" onClick={() => setMobileMenuOpen(false)} className="flex items-center justify-center gap-3 w-full py-4 rounded-xl bg-gradient-to-r from-cyan-600 to-blue-600 text-white shadow-[0_0_20px_rgba(6,182,212,0.4)] uppercase tracking-widest font-bold font-outfit hover:brightness-110 transition-all">
<User size={20} className="text-white" /> Mi perfil
</Link>
) : (
<Link href="/login" onClick={() => setMobileMenuOpen(false)} className="flex items-center justify-center gap-3 w-full py-4 rounded-xl bg-slate-800 border border-slate-700 text-white uppercase tracking-widest font-bold font-outfit hover:bg-slate-700 transition-colors">
<User size={20} className="text-cyan-400" /> Iniciar sesión
</Link>
)}
</div>
</div>
</nav>
);
};