102 lines
4.7 KiB
TypeScript
102 lines
4.7 KiB
TypeScript
|
|
import React from 'react';
|
|
import Link from 'next/link';
|
|
import { Layers, Plus, Search, Hexagon } from 'lucide-react';
|
|
import { UserDTO } from '../types';
|
|
|
|
interface NavbarProps {
|
|
user: UserDTO | null;
|
|
onOpenCreate: () => void;
|
|
onProfileClick: () => void;
|
|
searchQuery?: string;
|
|
onSearch?: (q: string) => void;
|
|
}
|
|
|
|
export const Navbar: React.FC<NavbarProps> = ({ user, onOpenCreate, onProfileClick, searchQuery, onSearch }) => {
|
|
const siteIconSvg = encodeURIComponent(
|
|
`<svg xmlns='http://www.w3.org/2000/svg' width='64' height='64'>`+
|
|
`<rect width='100%' height='100%' fill='#0b0b0b'/>`+
|
|
`<circle cx='32' cy='32' r='28' fill='#111' stroke='#39ff14'/>`+
|
|
`<text x='50%' y='56%' dominant-baseline='middle' text-anchor='middle' fill='#39ff14' font-size='18' font-family='monospace'>NM</text>`+
|
|
`</svg>`
|
|
);
|
|
const avatarSrc = user && user.avatarUrl && user.avatarUrl.trim()
|
|
? user.avatarUrl
|
|
: `data:image/svg+xml;utf8,${siteIconSvg}`;
|
|
return (
|
|
<nav className="sticky top-0 z-50 w-full backdrop-blur-md bg-cyber-black/80 border-b border-cyber-glass">
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div className="flex items-center justify-between h-16">
|
|
|
|
{/* Logo Area */}
|
|
<div className="flex items-center gap-2 group cursor-pointer" onClick={() => window.location.hash = ''}>
|
|
<Hexagon className="text-cyber-neon w-8 h-8 group-hover:rotate-180 transition-transform duration-700" />
|
|
<span className="text-2xl font-mono font-bold tracking-tighter text-white">
|
|
NEXUS_MAT<span className="text-cyber-neon">.OS</span>
|
|
</span>
|
|
</div>
|
|
|
|
{/* Search Bar */}
|
|
<div className="hidden md:flex flex-1 max-w-lg mx-8">
|
|
<div className="relative w-full">
|
|
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
|
<Search className="h-4 w-4 text-gray-500" />
|
|
</div>
|
|
<input
|
|
type="text"
|
|
className="block w-full pl-10 pr-3 py-2 border border-cyber-panel rounded-sm leading-5 bg-cyber-dark text-gray-300 placeholder-gray-600 focus:outline-none focus:border-cyber-neon focus:ring-1 focus:ring-cyber-neon sm:text-sm font-mono transition-all"
|
|
placeholder="SEARCH_PROTOCOL..."
|
|
value={searchQuery ?? ''}
|
|
onChange={(e) => onSearch?.(e.target.value)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Actions */}
|
|
<div className="flex items-center gap-4">
|
|
{user ? (
|
|
<>
|
|
<button
|
|
onClick={onOpenCreate}
|
|
className="flex items-center gap-2 px-4 py-2 bg-cyber-neon/10 border border-cyber-neon text-cyber-neon hover:bg-cyber-neon hover:text-black transition-all duration-300 font-mono text-sm uppercase tracking-wide group"
|
|
>
|
|
<Plus className="w-4 h-4 group-hover:rotate-90 transition-transform" />
|
|
<span className="hidden sm:inline">Upload_Data</span>
|
|
</button>
|
|
|
|
<div
|
|
onClick={onProfileClick}
|
|
className="relative cursor-pointer group"
|
|
>
|
|
<div className="w-10 h-10 rounded-full border border-cyber-panel overflow-hidden bg-cyber-panel group-hover:border-cyber-pink group-hover:shadow-[0_0_15px_rgba(255,0,85,0.4)] transition-all duration-300">
|
|
<img src={avatarSrc} alt="User" width={40} height={40} className="w-full h-full object-cover" />
|
|
</div>
|
|
<div className="absolute bottom-0 right-0 w-3 h-3 bg-cyber-neon rounded-full border-2 border-black"></div>
|
|
</div>
|
|
</>
|
|
) : (
|
|
<>
|
|
<Link
|
|
href="/auth/login"
|
|
className="flex items-center gap-2 px-4 py-2 bg-cyber-neon/10 border border-cyber-neon text-cyber-neon hover:bg-cyber-neon hover:text-black transition-all duration-300 font-mono text-sm uppercase tracking-wide"
|
|
>
|
|
<span>Login</span>
|
|
</Link>
|
|
<Link
|
|
href="/auth/register"
|
|
className="flex items-center gap-2 px-4 py-2 bg-cyber-pink text-white hover:bg-white hover:text-black transition-all duration-300 font-mono text-sm uppercase tracking-wide"
|
|
>
|
|
<span>Register</span>
|
|
</Link>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Decorative Line */}
|
|
<div className="h-[1px] w-full bg-gradient-to-r from-transparent via-cyber-neon/50 to-transparent"></div>
|
|
</nav>
|
|
);
|
|
};
|