All files / frontend/src/components Sidebar.tsx

19.4% Statements 13/67
100% Branches 0/0
0% Functions 0/1
19.4% Lines 13/67

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 971x 1x 1x 1x             1x 1x 1x 1x 1x 1x 1x   1x                                                                                                                                                         1x  
import React from 'react';
import { Link, useLocation } from 'react-router-dom';
import { X, LogOut } from 'lucide-react';
import Button from './Button';
 
interface SidebarProps {
    isOpen: boolean;
    onClose: () => void;
}
 
const navigation = [
    { name: 'Dashboard', path: '/dashboard', icon: '📊' },
    { name: 'Projects', path: '/projects', icon: '📁' },
    { name: 'Analytics', path: '/analytics', icon: '📈' },
    { name: 'Settings', path: '/settings', icon: '⚙️' },
    { name: 'Profile', path: '/profile', icon: '👤' },
];
 
const Sidebar: React.FC<SidebarProps> = ({ isOpen, onClose }) => {
    const location = useLocation();
 
    return (
        <>
            {/* Mobile Overlay */}
            {isOpen && (
                <div
                    className="fixed inset-0 bg-oxford-blue bg-opacity-50 lg:hidden z-30"
                    onClick={onClose}
                    aria-hidden="true"
                />
            )}
 
            {/* Sidebar */}
            <aside
                className={`fixed left-0 top-0 h-full w-64 bg-gradient-to-b from-oxford-blue to-sea-green border-r border-neon-blue border-opacity-20 transform transition-transform duration-300 ease-in-out z-40 lg:translate-x-0 ${isOpen ? 'translate-x-0' : '-translate-x-full'
                    }`}
                aria-label="Main navigation"
            >
                {/* Logo */}
                <div className="p-6 border-b border-neon-blue border-opacity-20">
                    <h1 className="text-2xl font-bold text-transparent bg-clip-text bg-gradient-right">
                        🚀 Heimdall
                    </h1>
                    <p className="text-sm text-french-gray mt-1">Analytics Platform</p>
                </div>
 
                {/* Navigation */}
                <nav className="p-4 flex-1" aria-label="Primary navigation">
                    {navigation.map((item) => {
                        const isActive = location.pathname === item.path;
                        return (
                            <Link
                                key={item.path}
                                to={item.path}
                                className={`flex items-center gap-3 px-4 py-3 rounded-lg mb-2 transition-all duration-200 ${isActive
                                        ? 'bg-neon-blue bg-opacity-20 text-light-green border border-light-green border-opacity-50'
                                        : 'text-french-gray hover:bg-sea-green hover:bg-opacity-10 hover:text-light-green'
                                    }`}
                                aria-current={isActive ? 'page' : undefined}
                            >
                                <span className="text-lg" aria-hidden="true">{item.icon}</span>
                                <span className="font-medium">{item.name}</span>
                            </Link>
                        );
                    })}
                </nav>
 
                {/* Footer */}
                <div className="p-4 border-t border-neon-blue border-opacity-20">
                    <Button
                        variant="danger"
                        size="sm"
                        className="w-full flex items-center justify-center gap-2"
                        aria-label="Logout from application"
                    >
                        <LogOut size={16} aria-hidden="true" />
                        Logout
                    </Button>
                </div>
            </aside>
 
            {/* Close Button for Mobile */}
            {isOpen && (
                <button
                    onClick={onClose}
                    className="fixed top-4 right-4 lg:hidden z-50 p-2 bg-neon-blue rounded-lg"
                    aria-label="Close navigation menu"
                >
                    <X size={24} aria-hidden="true" />
                </button>
            )}
        </>
    );
};
 
export default Sidebar;