Newer
Older
cortex-hub / ui / client-app / src / components / Navbar.js
import React from 'react';
import { ReactComponent as Logo } from '../logo.svg';

const Navbar = ({ isOpen, onToggle, onNavigate, onLogout, isLoggedIn, user, Icon }) => {
  const navItems = [
    { name: "Home", icon: "M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z", page: "home" },
    { name: "Voice Chat", icon: "M12 1a3 3 0 0 1 3 3v7a3 3 0 1 1-6 0V4a3 3 0 0 1 3-3zm5 10a5 5 0 0 1-10 0H5a7 7 0 0 0 14 0h-2zm-5 11v-4h-2v4h2z", page: "voice-chat" },
    { name: "Coding Assistant", icon: "M9 16l-4-4 4-4M15 16l4-4-4-4", page: "coding-assistant" },
    { name: "History", icon: "M22 12h-4l-3 9L9 3l-3 9H2", page: "history", disabled: true },
    { name: "Favorites", icon: "M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z", page: "favorites", disabled: true },
  ];

  return (
    <aside
      className={`flex flex-col h-screen bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-xl border-r dark:border-gray-700 transition-all duration-300 ${isOpen ? "w-64 p-4" : "w-16 p-2"
        } flex-shrink-0 z-50`}
    >
      {/* Sidebar Header with Toggle Button and Logo */}
      <div
        className={`flex items-center mb-8 ${isOpen ? "justify-between" : "justify-center"
          }`}
      >
        {isOpen && (
          <div className="flex items-center space-x-2">
            <Logo className="h-6 w-6 filter dark:invert" />
            <h1 className="text-xl font-bold transition-opacity duration-300">
              Cortex Hub
            </h1>
          </div>
        )}
        <div
          onClick={onToggle}
          className="p-2 rounded-lg cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors duration-200"
        >
          <Icon path="M3 12h18M3 6h18M3 18h18" />
        </div>
      </div>

      {/* Main Navigation Items */}
      <nav className="flex-grow space-y-4 transition-opacity duration-300">
        {navItems.map((item) => {
          const isDisabled = item.disabled;

          return (
            <div
              key={item.name}
              onClick={() => {
                if (!isDisabled) onNavigate(item.page);
              }}
              className={`flex items-center space-x-4 p-2 rounded-lg transition-colors duration-200 ${isDisabled
                ? "cursor-not-allowed text-gray-400 dark:text-gray-500"
                : "cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-700"
                } ${item.page === 'profile' && !isOpen ? 'hidden' : ''}`}
            >
              <Icon path={item.icon} className="flex-shrink-0 h-5 w-5" />
              {isOpen && (
                <span className={`font-medium ${isDisabled ? "text-gray-400 dark:text-gray-500" : ""}`}>
                  {item.name}
                </span>
              )}
            </div>
          );
        })}
      </nav>

      {/* Bottom Section: User, Settings and Logout */}
      <div className="mt-auto space-y-4 pt-4 border-t border-gray-100 dark:border-gray-700">
        {/* Settings Button - Only shown to Admin */}
        {isLoggedIn && user?.role === "admin" && (
          <div
            onClick={() => onNavigate("settings")}
            className="flex items-center space-x-4 p-2 text-gray-700 dark:text-gray-300 rounded-lg cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors duration-200"
          >
            <Icon path="M12 20v-8M12 4v4M12 14a2 2 0 1 0 0 4 2 2 0 0 0 0-4z" />
            {isOpen && <span className="font-medium">Settings</span>}
          </div>
        )}

        {/* User Profile Summary - Always show avatar, details when expanded */}
        {isLoggedIn && user && (
          <div
            onClick={() => onNavigate("profile")}
            className={`flex items-center p-2 rounded-xl transition-colors cursor-pointer group ${isOpen
              ? 'space-x-3 bg-gray-50 dark:bg-gray-700/50 hover:bg-gray-100 dark:hover:bg-gray-700'
              : 'justify-center hover:bg-gray-200 dark:hover:bg-gray-700'
              }`}
            title={!isOpen ? (user.full_name || user.username || "Profile") : ""}
          >
            <div className={`rounded-full bg-indigo-500 flex items-center justify-center text-white font-bold overflow-hidden flex-shrink-0 ${isOpen ? 'w-10 h-10' : 'w-8 h-8'
              }`}>
              {user.avatar_url ? (
                <img src={user.avatar_url} alt="User" className="w-full h-full object-cover" />
              ) : (
                (user.full_name || user.username || "U")[0].toUpperCase()
              )}
            </div>

            {isOpen && (
              <>
                <div className="flex-1 min-w-0">
                  <p className="text-sm font-bold truncate">
                    {user.full_name || user.username || "User"}
                  </p>
                  <p className="text-[10px] text-gray-500 dark:text-gray-400 uppercase tracking-wider font-semibold">
                    {user.role || 'user'}
                  </p>
                </div>
                <svg className="w-4 h-4 text-gray-400 group-hover:translate-x-1 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
                </svg>
              </>
            )}
          </div>
        )}

        {/* Conditional Login/Logout Button */}
        {isLoggedIn ? (
          <div
            onClick={onLogout}
            className="flex items-center space-x-4 p-2 rounded-lg cursor-pointer bg-red-500/10 text-red-600 hover:bg-red-500 hover:text-white transition-all duration-200"
          >
            <Icon path="M16 10v-3l8 8-8 8v-3h-16v-10h16z" />
            {isOpen && <span className="font-medium">Logout</span>}
          </div>
        ) : (
          <div
            onClick={() => onNavigate("login")}
            className="flex items-center space-x-4 p-2 rounded-lg cursor-pointer bg-blue-500 text-white hover:bg-blue-600 transition-colors duration-200"
          >
            <Icon path="M10 17l5-5-5-5v3H3v4h7v3zm10-11h-8v2h8v10h-8v2h8a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2z" />
            {isOpen && <span className="font-medium">Login</span>}
          </div>
        )}
      </div>
    </aside>
  );
};

export default Navbar;