177 lines
8.6 KiB
TypeScript
177 lines
8.6 KiB
TypeScript
|
|
|
||
|
|
import React, { useState } from 'react';
|
||
|
|
import { Menu, Palette, Zap, ChevronDown, LogOut, Settings, User, ShoppingCart } from 'lucide-react';
|
||
|
|
import { Button } from '../ui/button';
|
||
|
|
import { useTheme } from '../../context/ThemeContext';
|
||
|
|
import { SearchInput } from '../ui/input';
|
||
|
|
import { Notification } from '../../types';
|
||
|
|
import { useCart } from '../../context/CartContext';
|
||
|
|
import { NotificationBell } from '../notifications/NotificationBell';
|
||
|
|
|
||
|
|
interface NavbarProps {
|
||
|
|
onNavigate: (viewId: string) => void;
|
||
|
|
onLogout: () => void;
|
||
|
|
}
|
||
|
|
|
||
|
|
const mockNotifications: Notification[] = [
|
||
|
|
{ id: '1', type: 'system', text: 'System Update v2.0 Live', time: '2m', read: false },
|
||
|
|
{ id: '2', type: 'like', text: 'Neon_Dev liked your track', time: '15m', read: false, actionUrl: '/track/1' },
|
||
|
|
{ id: '3', type: 'follow', text: 'Skrillex started following you', time: '1h', read: true, actionUrl: '/u/skrillex' },
|
||
|
|
];
|
||
|
|
|
||
|
|
export const Navbar: React.FC<NavbarProps> = ({ onNavigate, onLogout }) => {
|
||
|
|
const { toggleTheme, theme } = useTheme();
|
||
|
|
const { itemCount } = useCart();
|
||
|
|
const [showUserMenu, setShowUserMenu] = useState(false);
|
||
|
|
const [notifications, setNotifications] = useState<Notification[]>(mockNotifications);
|
||
|
|
|
||
|
|
const handleMarkAllRead = () => {
|
||
|
|
setNotifications(prev => prev.map(n => ({ ...n, read: true })));
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleRead = (id: string) => {
|
||
|
|
setNotifications(prev => prev.map(n => n.id === id ? { ...n, read: true } : n));
|
||
|
|
};
|
||
|
|
|
||
|
|
return (
|
||
|
|
<>
|
||
|
|
{/* Backdrop for closing menus - Lower z-index than Navbar (z-40) but higher than content */}
|
||
|
|
{showUserMenu && (
|
||
|
|
<div
|
||
|
|
className="fixed inset-0 z-[35] bg-transparent cursor-default"
|
||
|
|
onClick={() => setShowUserMenu(false)}
|
||
|
|
/>
|
||
|
|
)}
|
||
|
|
|
||
|
|
<nav className="fixed top-0 left-0 right-0 h-16 bg-kodo-void/80 backdrop-blur-md border-b border-kodo-steel/40 z-40 flex items-center justify-between px-6 lg:px-8">
|
||
|
|
|
||
|
|
{/* Brand & Mobile Menu */}
|
||
|
|
<div className="flex items-center gap-4">
|
||
|
|
<Button variant="ghost" size="sm" className="lg:hidden p-1">
|
||
|
|
<Menu className="w-5 h-5" />
|
||
|
|
</Button>
|
||
|
|
<div className="flex items-center gap-3 cursor-pointer" onClick={() => onNavigate('dashboard')}>
|
||
|
|
<div className="w-8 h-8 rounded-full bg-gradient-to-br from-kodo-cyan-dim to-kodo-cyan flex items-center justify-center shadow-lg shadow-kodo-cyan/20">
|
||
|
|
<span className="font-display font-bold text-kodo-void text-lg">V</span>
|
||
|
|
</div>
|
||
|
|
<div className="hidden sm:flex flex-col justify-center">
|
||
|
|
<span className="font-display font-bold text-base tracking-wide text-kodo-primary leading-none">
|
||
|
|
VEZA
|
||
|
|
</span>
|
||
|
|
<span className="text-[10px] text-kodo-secondary font-medium tracking-widest uppercase leading-none mt-1">
|
||
|
|
Spectre Astral
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Center Search (Hidden on Mobile) */}
|
||
|
|
<div className="hidden md:flex flex-1 max-w-md mx-8 relative">
|
||
|
|
<SearchInput placeholder="Search platform..." />
|
||
|
|
<div className="absolute right-0 top-1/2 -translate-y-1/2 pr-3 flex gap-2">
|
||
|
|
<span className="px-1.5 py-0.5 bg-kodo-steel/50 rounded text-[10px] text-kodo-secondary font-mono border border-white/5">CMD+K</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Right Actions */}
|
||
|
|
<div className="flex items-center gap-3 md:gap-6">
|
||
|
|
{/* Pro Badge */}
|
||
|
|
<div className="hidden xl:flex items-center gap-3 border-r border-kodo-steel/50 pr-6">
|
||
|
|
<div className="text-right">
|
||
|
|
<div className="text-xs text-kodo-primary font-medium">Pro Plan</div>
|
||
|
|
<div className="text-[10px] text-kodo-secondary">Valid until Dec 31</div>
|
||
|
|
</div>
|
||
|
|
<div className="w-8 h-8 rounded-full bg-kodo-slate flex items-center justify-center">
|
||
|
|
<Zap className="w-4 h-4 text-kodo-gold fill-current" />
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<Button
|
||
|
|
variant="ghost"
|
||
|
|
size="sm"
|
||
|
|
onClick={toggleTheme}
|
||
|
|
title={`Theme: ${theme}`}
|
||
|
|
className="text-kodo-secondary hover:text-kodo-primary hidden sm:flex"
|
||
|
|
>
|
||
|
|
<Palette className="w-5 h-5" />
|
||
|
|
</Button>
|
||
|
|
|
||
|
|
{/* Cart Trigger */}
|
||
|
|
<Button
|
||
|
|
variant="ghost"
|
||
|
|
size="sm"
|
||
|
|
className="relative text-kodo-secondary hover:text-kodo-primary hidden sm:flex"
|
||
|
|
onClick={() => onNavigate('cart')}
|
||
|
|
>
|
||
|
|
<ShoppingCart className="w-5 h-5" />
|
||
|
|
{itemCount > 0 && <span className="absolute top-1.5 right-1.5 w-2 h-2 bg-kodo-cyan rounded-full border border-kodo-void"></span>}
|
||
|
|
</Button>
|
||
|
|
|
||
|
|
{/* Notification Center */}
|
||
|
|
<NotificationBell
|
||
|
|
notifications={notifications}
|
||
|
|
onMarkAllRead={handleMarkAllRead}
|
||
|
|
onRead={handleRead}
|
||
|
|
onViewAll={() => onNavigate('notifications')}
|
||
|
|
/>
|
||
|
|
|
||
|
|
{/* User Menu */}
|
||
|
|
<div className="relative z-50">
|
||
|
|
<div
|
||
|
|
className="flex items-center gap-2 cursor-pointer group select-none"
|
||
|
|
onClick={() => setShowUserMenu(!showUserMenu)}
|
||
|
|
>
|
||
|
|
<div className="w-9 h-9 rounded-full bg-gradient-to-tr from-gray-700 to-gray-600 p-[1px] hover:ring-2 hover:ring-kodo-cyan transition-all">
|
||
|
|
<div className="w-full h-full rounded-full overflow-hidden">
|
||
|
|
<img src="https://picsum.photos/100/100" alt="Avatar" className="w-full h-full object-cover" />
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<ChevronDown className={`w-4 h-4 text-kodo-secondary group-hover:text-kodo-primary transition-transform duration-200 ${showUserMenu ? 'rotate-180' : ''}`} />
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{showUserMenu && (
|
||
|
|
<div className="absolute top-full right-0 mt-4 w-56 bg-kodo-graphite border border-kodo-steel rounded-xl shadow-2xl overflow-hidden animate-fadeIn origin-top-right ring-1 ring-white/5 flex flex-col">
|
||
|
|
<div className="px-4 py-3 border-b border-kodo-steel/30 mb-1 bg-kodo-ink/50">
|
||
|
|
<p className="text-sm font-bold text-white">Cyber_Producer</p>
|
||
|
|
<p className="text-xs text-gray-500">Pro Plan</p>
|
||
|
|
</div>
|
||
|
|
<button
|
||
|
|
onClick={() => { onNavigate('profile'); setShowUserMenu(false); }}
|
||
|
|
className="w-full text-left px-4 py-2.5 text-sm text-gray-300 hover:bg-white/5 hover:text-white flex items-center gap-3 transition-colors"
|
||
|
|
>
|
||
|
|
<User className="w-4 h-4" /> My Profile
|
||
|
|
</button>
|
||
|
|
<button
|
||
|
|
onClick={() => { onNavigate('studio/go-live'); setShowUserMenu(false); }}
|
||
|
|
className="w-full text-left px-4 py-2.5 text-sm text-gray-300 hover:bg-white/5 hover:text-white flex items-center gap-3 transition-colors"
|
||
|
|
>
|
||
|
|
<Zap className="w-4 h-4 text-kodo-red" /> Go Live
|
||
|
|
</button>
|
||
|
|
<button
|
||
|
|
onClick={() => { onNavigate('purchases'); setShowUserMenu(false); }}
|
||
|
|
className="w-full text-left px-4 py-2.5 text-sm text-gray-300 hover:bg-white/5 hover:text-white flex items-center gap-3 transition-colors"
|
||
|
|
>
|
||
|
|
<ShoppingCart className="w-4 h-4" /> Purchases
|
||
|
|
</button>
|
||
|
|
<button
|
||
|
|
onClick={() => { onNavigate('settings'); setShowUserMenu(false); }}
|
||
|
|
className="w-full text-left px-4 py-2.5 text-sm text-gray-300 hover:bg-white/5 hover:text-white flex items-center gap-3 transition-colors"
|
||
|
|
>
|
||
|
|
<Settings className="w-4 h-4" /> Settings
|
||
|
|
</button>
|
||
|
|
<div className="h-px bg-kodo-steel/30 my-1 mx-2"></div>
|
||
|
|
<button
|
||
|
|
onClick={() => { onLogout(); setShowUserMenu(false); }}
|
||
|
|
className="w-full text-left px-4 py-2.5 text-sm text-kodo-red hover:bg-kodo-red/10 rounded-lg flex items-center gap-3 transition-colors"
|
||
|
|
>
|
||
|
|
<LogOut className="w-4 h-4" /> Sign Out
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</nav>
|
||
|
|
</>
|
||
|
|
);
|
||
|
|
};
|