learning_ai_invt_trdg/web/src/components/layout/Sidebar.tsx

123 lines
4.0 KiB
TypeScript

import { NavLink } from 'react-router-dom';
import {
Home, Briefcase, FlaskConical, Target, TrendingUp,
SlidersHorizontal, Star, Bell, Settings,
} from 'lucide-react';
import { useAppContext } from '../../context/AppContext';
import { getPlansRoute } from '../../views/tradePlansRoutes';
const NAV = [
{ to: '/', icon: Home, label: 'Home', end: true },
{ to: '/portfolio', icon: Briefcase, label: 'Portfolio', end: false },
{ to: '/research', icon: FlaskConical, label: 'Research', end: false },
{ to: getPlansRoute(), icon: Target, label: 'Plans', end: false },
{ to: '/markets', icon: TrendingUp, label: 'Markets', end: false },
{ to: '/screener', icon: SlidersHorizontal, label: 'Screener', end: false },
{ to: '/watchlist', icon: Star, label: 'Watchlist', end: false },
{ to: '/alerts', icon: Bell, label: 'Alerts', end: false },
{ to: '/settings', icon: Settings, label: 'Settings', end: false },
];
export function Sidebar() {
const { user, handleSignOut } = useAppContext();
const initials = user?.email
? user.email.slice(0, 2).toUpperCase()
: 'US';
return (
<aside className="trading-sidebar">
{/* Logo */}
<div className="trading-sidebar-logo" style={{
width: 40,
height: 40,
borderRadius: 10,
background: 'linear-gradient(135deg, var(--accent), color-mix(in oklab, var(--accent) 70%, var(--bl-info-strong) 30%))',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
marginBottom: 24,
flexShrink: 0,
boxShadow: '0 2px 8px color-mix(in oklab, var(--accent) 35%, transparent 65%)',
cursor: 'pointer',
fontSize: 20,
}}>
📈
</div>
{/* Nav items */}
<nav className="trading-sidebar-nav">
{NAV.map(({ to, icon: Icon, label, end }) => (
<NavLink
key={to}
to={to}
end={end}
className="trading-sidebar-link"
style={({ isActive }) => ({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
padding: '10px 0 8px',
gap: 3,
borderLeft: isActive ? '3px solid var(--accent)' : '3px solid transparent',
color: isActive ? 'var(--accent)' : 'var(--muted-foreground)',
textDecoration: 'none',
background: isActive ? 'var(--sidebar-active)' : 'transparent',
transition: 'all 0.15s',
})}
>
{({ isActive }) => (
<>
<Icon size={20} strokeWidth={isActive ? 2.2 : 1.8} />
<span style={{
fontSize: 10,
fontWeight: isActive ? 700 : 500,
letterSpacing: '0.01em',
lineHeight: 1,
}}>
{label}
</span>
</>
)}
</NavLink>
))}
</nav>
{/* User avatar */}
<div
className="trading-sidebar-avatar"
title={`${user?.email ?? ''} — click to sign out`}
onClick={handleSignOut}
style={{
width: 36,
height: 36,
borderRadius: '50%',
background: 'var(--accent)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: 'var(--primary-foreground)',
fontSize: 12,
fontWeight: 700,
cursor: 'pointer',
position: 'relative',
userSelect: 'none',
flexShrink: 0,
}}
>
{initials}
<span style={{
position: 'absolute',
bottom: 1,
right: 1,
width: 9,
height: 9,
borderRadius: '50%',
background: 'var(--bl-success)',
border: '2px solid var(--card)',
}} />
</div>
</aside>
);
}