| | import React, { useState, useEffect } from 'react';
|
| | import { useLocation, Link } from 'react-router-dom';
|
| | import {
|
| | LayoutDashboard,
|
| | TrendingUp,
|
| | BarChart3,
|
| | Bot,
|
| | Smile,
|
| | Activity,
|
| | DollarSign,
|
| | Newspaper,
|
| | Radio,
|
| | Monitor,
|
| | Settings,
|
| | HelpCircle,
|
| | ChevronLeft,
|
| | ChevronRight
|
| | } from 'lucide-react';
|
| |
|
| | interface NavItem {
|
| | path: string;
|
| | label: string;
|
| | icon: React.ReactNode;
|
| | badge?: string;
|
| | section?: string;
|
| | }
|
| |
|
| | const navItems: NavItem[] = [
|
| |
|
| | { path: '/', label: 'Dashboard', icon: <LayoutDashboard size={20} />, section: 'Main' },
|
| | { path: '/market', label: 'Market', icon: <TrendingUp size={20} /> },
|
| | { path: '/charts', label: 'Charts', icon: <BarChart3 size={20} /> },
|
| |
|
| |
|
| | { path: '/ai-models', label: 'AI Models', icon: <Bot size={20} />, section: 'AI & Analysis' },
|
| | { path: '/sentiment', label: 'Sentiment', icon: <Smile size={20} /> },
|
| | { path: '/ai-analyst', label: 'AI Analyst', icon: <Activity size={20} /> },
|
| | { path: '/technical-analysis', label: 'Technical', icon: <BarChart3 size={20} /> },
|
| |
|
| |
|
| | { path: '/trading-assistant', label: 'Trading Assistant', icon: <DollarSign size={20} />, section: 'Trading' },
|
| | { path: '/news', label: 'News', icon: <Newspaper size={20} /> },
|
| |
|
| |
|
| | { path: '/providers', label: 'Providers', icon: <Radio size={20} />, section: 'System' },
|
| | { path: '/system-monitor', label: 'System Monitor', icon: <Monitor size={20} />, badge: 'LIVE' },
|
| | { path: '/settings', label: 'Settings', icon: <Settings size={20} /> },
|
| | { path: '/help', label: 'Help', icon: <HelpCircle size={20} /> },
|
| | ];
|
| |
|
| | export const Sidebar: React.FC = () => {
|
| | const [collapsed, setCollapsed] = useState(false);
|
| | const location = useLocation();
|
| |
|
| | useEffect(() => {
|
| | const savedState = localStorage.getItem('sidebar-collapsed');
|
| | if (savedState === 'true') {
|
| | setCollapsed(true);
|
| | }
|
| | }, []);
|
| |
|
| | const toggleCollapse = () => {
|
| | const newState = !collapsed;
|
| | setCollapsed(newState);
|
| | localStorage.setItem('sidebar-collapsed', String(newState));
|
| | };
|
| |
|
| | const isActive = (path: string) => {
|
| | if (path === '/' && location.pathname === '/') return true;
|
| | if (path !== '/' && location.pathname.startsWith(path)) return true;
|
| | return false;
|
| | };
|
| |
|
| | let currentSection = '';
|
| |
|
| | return (
|
| | <aside className={`sidebar ${collapsed ? 'collapsed' : ''}`} role="navigation" aria-label="Main navigation">
|
| | {/* Sidebar Header */}
|
| | <div className="sidebar-header">
|
| | <div className="sidebar-logo">
|
| | <span>C</span>
|
| | </div>
|
| | <div className="sidebar-brand">Crypto Monitor</div>
|
| | </div>
|
| |
|
| | {/* Sidebar Navigation */}
|
| | <nav className="sidebar-nav">
|
| | {navItems.map((item) => {
|
| | const showSection = item.section && item.section !== currentSection;
|
| | if (item.section) currentSection = item.section;
|
| |
|
| | return (
|
| | <React.Fragment key={item.path}>
|
| | {showSection && (
|
| | <div className="nav-section-header">{item.section}</div>
|
| | )}
|
| | <Link
|
| | to={item.path}
|
| | className={`nav-item ${isActive(item.path) ? 'active' : ''}`}
|
| | >
|
| | <span className="nav-item-icon">{item.icon}</span>
|
| | <span className="nav-item-label">{item.label}</span>
|
| | {item.badge && (
|
| | <span className="nav-item-badge">{item.badge}</span>
|
| | )}
|
| | </Link>
|
| | </React.Fragment>
|
| | );
|
| | })}
|
| | </nav>
|
| |
|
| | {/* Sidebar Footer */}
|
| | <div className="sidebar-footer">
|
| | <button
|
| | className="sidebar-toggle"
|
| | onClick={toggleCollapse}
|
| | aria-label="Toggle sidebar"
|
| | >
|
| | <span className="sidebar-toggle-icon">
|
| | {collapsed ? <ChevronRight size={20} /> : <ChevronLeft size={20} />}
|
| | </span>
|
| | <span className="nav-item-label">Collapse</span>
|
| | </button>
|
| | </div>
|
| | </aside>
|
| | );
|
| | };
|
| |
|
| | export default Sidebar;
|
| |
|