- Added cursor-pointer to view mode toggles (LibraryPage) - Added cursor-pointer and transition-colors to FeedView buttons - Added cursor-pointer to logout buttons (Sidebar, Header) - Added cursor-pointer to Dashboard time period buttons - Added cursor-pointer to Collapsible trigger button - Button component already has cursor-pointer built-in - Navigation links already have hover states - Updated audit document with progress - High-priority areas complete, remaining elements can be addressed incrementally - Task 8.2.1.3 complete
223 lines
9.1 KiB
TypeScript
223 lines
9.1 KiB
TypeScript
import { useState } from 'react';
|
|
import { Link, useNavigate } from 'react-router-dom';
|
|
import { useAuthStore } from '@/features/auth/store/authStore';
|
|
import { useUser } from '@/features/auth/hooks/useUser';
|
|
import { useUIStore } from '@/stores/ui';
|
|
import { useTranslation } from '@/hooks/useTranslation';
|
|
import { EmailVerificationBadge } from '@/features/auth/components/EmailVerificationBadge';
|
|
import { NotificationMenu } from '@/components/notifications/NotificationMenu';
|
|
import { GlobalSearchBar } from '@/components/search/GlobalSearchBar';
|
|
import { RateLimitIndicator } from '@/components/RateLimitIndicator';
|
|
import { Button } from '@/components/ui/button';
|
|
import { FocusTrap } from '@/components/ui/focus-trap';
|
|
import { Tooltip } from '@/components/ui/tooltip';
|
|
import { cn } from '@/lib/utils';
|
|
import {
|
|
User,
|
|
Settings,
|
|
LogOut,
|
|
Moon,
|
|
Sun,
|
|
Monitor,
|
|
Search,
|
|
Cpu,
|
|
} from 'lucide-react';
|
|
import type { BaseComponentProps } from '../types';
|
|
|
|
/**
|
|
* Props for Header component
|
|
* FE-TYPE-013: Fully typed component props
|
|
*/
|
|
export interface HeaderProps extends BaseComponentProps {
|
|
// No additional props needed - uses global stores
|
|
}
|
|
|
|
export function Header(_props: HeaderProps) {
|
|
const [isUserMenuOpen, setIsUserMenuOpen] = useState(false);
|
|
const { logout } = useAuthStore();
|
|
const { data: user } = useUser();
|
|
const { theme, setTheme } = useUIStore();
|
|
const { t } = useTranslation();
|
|
const navigate = useNavigate();
|
|
|
|
const handleLogout = async () => {
|
|
await logout();
|
|
navigate('/login');
|
|
};
|
|
|
|
const toggleTheme = () => {
|
|
const newTheme =
|
|
theme === 'light' ? 'dark' : theme === 'dark' ? 'system' : 'light';
|
|
setTheme(newTheme);
|
|
};
|
|
|
|
const getThemeIcon = () => {
|
|
switch (theme) {
|
|
case 'light':
|
|
return <Sun className="h-4 w-4" />;
|
|
case 'dark':
|
|
return <Moon className="h-4 w-4" />;
|
|
default:
|
|
return <Monitor className="h-4 w-4" />;
|
|
}
|
|
};
|
|
|
|
return (
|
|
<header
|
|
className="fixed top-0 left-0 right-0 h-16 px-6 mt-4 pointer-events-none"
|
|
style={{ zIndex: 'var(--z-fixed)' }}
|
|
>
|
|
<div className="max-w-[1700px] mx-auto w-full h-full glass-hud rounded-2xl border-white/10 flex items-center justify-between px-6 pointer-events-auto hud-corner shadow-neon-cyan/5 group">
|
|
<div className="flex items-center gap-6">
|
|
<Link
|
|
to="/dashboard"
|
|
className="flex items-center gap-3 active:scale-95 transition-transform"
|
|
>
|
|
<div className="w-10 h-10 bg-kodo-cyan/20 rounded-xl flex items-center justify-center border border-kodo-cyan/30 shadow-neon-cyan/20 animate-scan">
|
|
<Cpu className="w-6 h-6 text-kodo-cyan animate-pulse-glow" />
|
|
</div>
|
|
<div className="hidden sm:block">
|
|
<h1 className="text-3xl font-display font-bold text-white tracking-widest uppercase leading-tight">
|
|
Veza<span className="text-kodo-cyan">OS</span>
|
|
</h1>
|
|
<div className="text-[9px] font-mono text-kodo-cyan/50 tracking-[0.2em] uppercase -mt-0.5">
|
|
Core Network v2.4
|
|
</div>
|
|
</div>
|
|
</Link>
|
|
|
|
{/* HUD System Status */}
|
|
<div className="hidden xl:flex items-center gap-6 border-l border-white/10 pl-8 h-8">
|
|
<div className="flex flex-col">
|
|
<span className="text-hud">Uplink Status</span>
|
|
<div className="flex items-center gap-1.5">
|
|
<span className="w-1.5 h-1.5 rounded-full bg-kodo-lime animate-pulse" />
|
|
<span className="text-[11px] font-mono text-white opacity-90 uppercase tracking-tighter">
|
|
Connected
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div className="flex flex-col">
|
|
<span className="text-hud">Node ID</span>
|
|
<span className="text-[11px] font-mono text-kodo-cyan opacity-90 uppercase truncate max-w-[80px]">
|
|
VZ-{user?.id?.slice(0, 4)}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Global Search integrated */}
|
|
<div className="flex-1 max-w-lg mx-8 relative hidden md:block">
|
|
<GlobalSearchBar className="w-full bg-transparent border-none" />
|
|
<div className="absolute left-3 top-1/2 -translate-y-1/2 flex items-center gap-2 pointer-events-none opacity-50 group-hover:opacity-100 transition-opacity">
|
|
<Search className="w-4 h-4 text-kodo-cyan" />
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex items-center gap-3">
|
|
{/* Quick Stats Overlay - Styled specifically */}
|
|
<div className="hidden lg:flex items-center gap-1 mr-4 bg-kodo-cyan/5 border border-kodo-cyan/10 rounded-full px-3 py-1.5">
|
|
<div className="w-1.5 h-1.5 rounded-full bg-kodo-lime" />
|
|
<span className="text-[10px] font-mono text-kodo-cyan uppercase font-bold tracking-tight">
|
|
Active_Stream_OK
|
|
</span>
|
|
</div>
|
|
|
|
<NotificationMenu />
|
|
|
|
<RateLimitIndicator />
|
|
|
|
<Tooltip content={t('common.changeTheme')}>
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
onClick={toggleTheme}
|
|
className="hover:bg-white/5 hover:text-kodo-cyan transition-all rounded-xl border border-transparent hover:border-white/5"
|
|
>
|
|
{getThemeIcon()}
|
|
</Button>
|
|
</Tooltip>
|
|
|
|
<div className="w-px h-6 bg-white/10 mx-1" />
|
|
|
|
{/* User Profile HUD */}
|
|
<div className="relative">
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
onClick={() => setIsUserMenuOpen(!isUserMenuOpen)}
|
|
className={cn(
|
|
'p-1 pr-3 rounded-xl gap-2 transition-all border border-transparent',
|
|
isUserMenuOpen
|
|
? 'bg-kodo-cyan/10 border-kodo-cyan/30 text-kodo-cyan'
|
|
: 'hover:bg-white/5',
|
|
)}
|
|
>
|
|
<div className="w-8 h-8 rounded-lg bg-kodo-graphite border border-white/10 flex items-center justify-center overflow-hidden">
|
|
<User className="w-5 h-5 text-kodo-secondary" />
|
|
</div>
|
|
<div className="flex flex-col items-start hidden sm:flex">
|
|
<span className="text-xs font-bold text-white leading-none">
|
|
{user?.username}
|
|
</span>
|
|
<span className="text-[9px] font-mono text-kodo-secondary uppercase tracking-tighter">
|
|
Lvl 1 Operative
|
|
</span>
|
|
</div>
|
|
</Button>
|
|
|
|
{isUserMenuOpen && (
|
|
<FocusTrap
|
|
active={isUserMenuOpen}
|
|
onEscape={() => setIsUserMenuOpen(false)}
|
|
>
|
|
<div className="absolute right-0 mt-3 w-56 glass-hud rounded-2xl border-white/10 shadow-2xl z-50 p-2 animate-scaleIn hud-corner">
|
|
<div className="px-4 py-3 border-b border-white/5 mb-2">
|
|
<div className="text-xs font-mono text-kodo-cyan opacity-50 uppercase tracking-widest mb-1">
|
|
User_Registry
|
|
</div>
|
|
<div className="text-sm font-bold text-white truncate">
|
|
{user?.email}
|
|
</div>
|
|
{user && !user.is_verified && (
|
|
<div className="mt-2">
|
|
<EmailVerificationBadge verified={false} />
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="space-y-1">
|
|
<Link
|
|
to="/profile"
|
|
onClick={() => setIsUserMenuOpen(false)}
|
|
className="flex items-center gap-3 px-3 py-2 text-sm text-kodo-secondary hover:text-kodo-cyan hover:bg-kodo-cyan/5 rounded-xl transition-all group"
|
|
>
|
|
<User className="w-4 h-4 group-hover:drop-shadow-[0_0_5px_rgba(102,252,241,0.5)]" />
|
|
<span>System.Profile</span>
|
|
</Link>
|
|
<Link
|
|
to="/settings"
|
|
onClick={() => setIsUserMenuOpen(false)}
|
|
className="flex items-center gap-3 px-3 py-2 text-sm text-kodo-secondary hover:text-kodo-cyan hover:bg-kodo-cyan/5 rounded-xl transition-all group"
|
|
>
|
|
<Settings className="w-4 h-4 group-hover:rotate-45 transition-transform" />
|
|
<span>Global.Settings</span>
|
|
</Link>
|
|
<div className="h-px bg-white/5 my-2 mx-2" />
|
|
<button
|
|
onClick={handleLogout}
|
|
className="flex items-center gap-3 w-full px-3 py-2 text-sm text-red-400/80 hover:text-red-400 hover:bg-red-500/10 rounded-xl transition-all group cursor-pointer"
|
|
>
|
|
<LogOut className="w-4 h-4" />
|
|
<span>Terminate.Session</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</FocusTrap>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
);
|
|
}
|