Ctrl+K
- 1.52 kB initial commit
- 206 Bytes import React, { useState, useEffect } from 'react'; import { navItems } from '../data/sondelaData'; const Sidebar = ({ onToggle }) => { const [activeItem, setActiveItem] = useState('dashboard'); const [collapsed, setCollapsed] = useState(false); const [expandedSection, setExpandedSection] = useState(null); useEffect(() => { if (onToggle) { onToggle(collapsed); } }, [collapsed, onToggle]); const toggleSidebar = () => { setCollapsed(!collapsed); // Reset expanded section when collapsing sidebar if (!collapsed) { setExpandedSection(null); } }; // Group navigation items by section const navSections = navItems.reduce((acc, item) => { if (!acc[item.section]) { acc[item.section] = []; } acc[item.section].push(item); return acc; }, {}); // Toggle section expansion const toggleSection = (section) => { if (collapsed) return; // Don't toggle when sidebar is collapsed setExpandedSection(expandedSection === section ? null : section); }; return ( <div className={`sidebar bg-gradient-to-b from-blue-900 to-blue-800 text-white shadow-xl ${collapsed ? 'collapsed w-20' : 'w-64'} flex flex-col h-screen transition-all duration-300`} > {/* Logo */} <div className="p-4 flex items-center justify-between border-b border-blue-800"> <div className="flex items-center"> <div className="bg-white p-2 rounded-lg"> <i className="fas fa-shield-alt text-blue-800 text-xl"></i> </div> {!collapsed && ( <h1 className="logo-text text-xl font-bold ml-3">Sondela</h1> )} </div> {/* Collapse Button */} <button className="text-blue-200 hover:text-white hover:bg-blue-700 p-1.5 rounded-md transition-colors" onClick={toggleSidebar} aria-label={collapsed ? "Expand sidebar" : "Collapse sidebar"} > <i className={`fas fa-chevron-${collapsed ? 'right' : 'left'}`}></i> </button> </div> {/* User Profile */} <div className="p-4 flex items-center border-b border-blue-800"> <img src="https://randomuser.me/api/portraits/men/32.jpg" alt="User" className={`${collapsed ? 'w-10 h-10 mx-auto' : 'w-10 h-10'} rounded-full border-2 border-white shadow-md`} /> {!collapsed && ( <div className="ml-3"> <p className="font-semibold">Cmdt. Williams</p> <div className="flex items-center"> <span className="inline-block w-2 h-2 bg-green-500 rounded-full mr-1.5"></span> <p className="text-blue-200 text-xs">Online</p> </div> </div> )} </div> {/* Navigation */} <nav className="flex-1 overflow-y-auto custom-scrollbar pt-2"> {Object.keys(navSections).map((section) => ( <div key={section} className="mb-2"> {/* Section Header */} {!collapsed && ( <div className="flex items-center justify-between px-4 py-2 text-blue-300 text-xs uppercase font-semibold cursor-pointer hover:text-white" onClick={() => toggleSection(section)} > <span>{section}</span> {section !== 'Main' && ( <i className={`fas fa-chevron-${expandedSection === section ? 'down' : 'right'} text-xs`}></i> )} </div> )} {/* Section Items */} <ul className={`${ collapsed || section === 'Main' || expandedSection === section ? 'max-h-96' : 'max-h-0' } overflow-hidden transition-all duration-300`}> {navSections[section].map((item) => ( <li key={item.id} className="px-2"> <a href="#" className={`nav-item flex items-center rounded-lg ${ collapsed ? 'justify-center mx-auto py-3 px-1' : 'py-2.5 px-4' } hover:bg-blue-800/50 transition-all duration-200 ${ activeItem === item.id ? 'bg-blue-800 text-white' : 'text-blue-100 hover:text-white' }`} onClick={() => setActiveItem(item.id)} > <div className="relative"> <i className={`fas fa-${item.icon} ${collapsed ? 'text-xl' : ''}`}></i> {item.badge && ( <span className="absolute -right-2 -top-2 bg-red-500 text-white text-xs rounded-full w-4 h-4 flex items-center justify-center"> {item.badge} </span> )} </div> {!collapsed && ( <> <span className="ml-3 flex-grow">{item.name}</span> {item.badge && ( <span className="bg-red-500 text-xs text-white px-2 py-0.5 rounded-full"> {item.badge} </span> )} </> )} </a> </li> ))} </ul> </div> ))} </nav> {/* Footer */} <div className="p-4 border-t border-blue-800"> {collapsed ? ( <div className="text-center"> <button className="text-blue-200 hover:text-white p-2 rounded-full hover:bg-blue-700"> <i className="fas fa-sign-out-alt"></i> </button> </div> ) : ( <div className="flex items-center justify-between"> <div> <p className="text-sm text-blue-200">System Status</p> <p className="text-xs flex items-center"> <span className="w-2 h-2 bg-green-500 rounded-full inline-block mr-1"></span> Online </p> </div> <button className="text-blue-200 hover:text-white p-2 rounded hover:bg-blue-700"> <i className="fas fa-sign-out-alt mr-1"></i> {!collapsed && <span>Logout</span>} </button> </div> )} </div> </div> ); }; export default Sidebar; - Initial Deployment
- 21.4 kB import React, { useState, useEffect } from 'react'; import { navItems } from '../data/sondelaData'; const Sidebar = ({ onToggle }) => { const [activeItem, setActiveItem] = useState('dashboard'); const [collapsed, setCollapsed] = useState(false); const [expandedSection, setExpandedSection] = useState(null); useEffect(() => { if (onToggle) { onToggle(collapsed); } }, [collapsed, onToggle]); const toggleSidebar = () => { setCollapsed(!collapsed); // Reset expanded section when collapsing sidebar if (!collapsed) { setExpandedSection(null); } }; // Group navigation items by section const navSections = navItems.reduce((acc, item) => { if (!acc[item.section]) { acc[item.section] = []; } acc[item.section].push(item); return acc; }, {}); // Toggle section expansion const toggleSection = (section) => { if (collapsed) return; // Don't toggle when sidebar is collapsed setExpandedSection(expandedSection === section ? null : section); }; return ( <div className={`sidebar bg-gradient-to-b from-blue-900 to-blue-800 text-white shadow-xl ${collapsed ? 'collapsed w-20' : 'w-64'} flex flex-col h-screen transition-all duration-300`} > {/* Logo */} <div className="p-4 flex items-center justify-between border-b border-blue-800"> <div className="flex items-center"> <div className="bg-white p-2 rounded-lg"> <i className="fas fa-shield-alt text-blue-800 text-xl"></i> </div> {!collapsed && ( <h1 className="logo-text text-xl font-bold ml-3">Sondela</h1> )} </div> {/* Collapse Button */} <button className="text-blue-200 hover:text-white hover:bg-blue-700 p-1.5 rounded-md transition-colors" onClick={toggleSidebar} aria-label={collapsed ? "Expand sidebar" : "Collapse sidebar"} > <i className={`fas fa-chevron-${collapsed ? 'right' : 'left'}`}></i> </button> </div> {/* User Profile */} <div className="p-4 flex items-center border-b border-blue-800"> <img src="https://randomuser.me/api/portraits/men/32.jpg" alt="User" className={`${collapsed ? 'w-10 h-10 mx-auto' : 'w-10 h-10'} rounded-full border-2 border-white shadow-md`} /> {!collapsed && ( <div className="ml-3"> <p className="font-semibold">Cmdt. Williams</p> <div className="flex items-center"> <span className="inline-block w-2 h-2 bg-green-500 rounded-full mr-1.5"></span> <p className="text-blue-200 text-xs">Online</p> </div> </div> )} </div> {/* Navigation */} <nav className="flex-1 overflow-y-auto custom-scrollbar pt-2"> {Object.keys(navSections).map((section) => ( <div key={section} className="mb-2"> {/* Section Header */} {!collapsed && ( <div className="flex items-center justify-between px-4 py-2 text-blue-300 text-xs uppercase font-semibold cursor-pointer hover:text-white" onClick={() => toggleSection(section)} > <span>{section}</span> {section !== 'Main' && ( <i className={`fas fa-chevron-${expandedSection === section ? 'down' : 'right'} text-xs`}></i> )} </div> )} {/* Section Items */} <ul className={`${ collapsed || section === 'Main' || expandedSection === section ? 'max-h-96' : 'max-h-0' } overflow-hidden transition-all duration-300`}> {navSections[section].map((item) => ( <li key={item.id} className="px-2"> <a href="#" className={`nav-item flex items-center rounded-lg ${ collapsed ? 'justify-center mx-auto py-3 px-1' : 'py-2.5 px-4' } hover:bg-blue-800/50 transition-all duration-200 ${ activeItem === item.id ? 'bg-blue-800 text-white' : 'text-blue-100 hover:text-white' }`} onClick={() => setActiveItem(item.id)} > <div className="relative"> <i className={`fas fa-${item.icon} ${collapsed ? 'text-xl' : ''}`}></i> {item.badge && ( <span className="absolute -right-2 -top-2 bg-red-500 text-white text-xs rounded-full w-4 h-4 flex items-center justify-center"> {item.badge} </span> )} </div> {!collapsed && ( <> <span className="ml-3 flex-grow">{item.name}</span> {item.badge && ( <span className="bg-red-500 text-xs text-white px-2 py-0.5 rounded-full"> {item.badge} </span> )} </> )} </a> </li> ))} </ul> </div> ))} </nav> {/* Footer */} <div className="p-4 border-t border-blue-800"> {collapsed ? ( <div className="text-center"> <button className="text-blue-200 hover:text-white p-2 rounded-full hover:bg-blue-700"> <i className="fas fa-sign-out-alt"></i> </button> </div> ) : ( <div className="flex items-center justify-between"> <div> <p className="text-sm text-blue-200">System Status</p> <p className="text-xs flex items-center"> <span className="w-2 h-2 bg-green-500 rounded-full inline-block mr-1"></span> Online </p> </div> <button className="text-blue-200 hover:text-white p-2 rounded hover:bg-blue-700"> <i className="fas fa-sign-out-alt mr-1"></i> {!collapsed && <span>Logout</span>} </button> </div> )} </div> </div> ); }; export default Sidebar; - Initial Deployment
- 388 Bytes initial commit