Spaces:
Sleeping
Sleeping
| import { useState, useEffect } from 'react'; | |
| import { Outlet, Navigate, NavLink, useNavigate } from 'react-router-dom'; | |
| import { FiHome, FiBox, FiShoppingCart, FiSettings, FiLogOut, FiMenu, FiX } from 'react-icons/fi'; | |
| export default function Layout() { | |
| const [sidebarOpen, setSidebarOpen] = useState(false); | |
| const navigate = useNavigate(); | |
| const isAuthenticated = localStorage.getItem('admin_token') !== null; | |
| if (!isAuthenticated) { | |
| return <Navigate to="/login" replace />; | |
| } | |
| const handleLogout = () => { | |
| localStorage.removeItem('admin_token'); | |
| navigate('/login'); | |
| }; | |
| const links = [ | |
| { path: '/', icon: FiHome, label: 'Dashboard' }, | |
| { path: '/orders', icon: FiShoppingCart, label: 'Buyurtmalar' }, | |
| { path: '/products', icon: FiBox, label: 'Mahsulotlar' }, | |
| { path: '/settings', icon: FiSettings, label: 'Sozlamalar' }, | |
| ]; | |
| return ( | |
| <div className="min-h-screen bg-gray-950 text-gray-100 flex"> | |
| {/* Mobile Header */} | |
| <div className="lg:hidden fixed top-0 left-0 right-0 h-16 bg-gray-900 border-b border-gray-800 flex items-center justify-between px-4 z-20"> | |
| <span className="font-bold text-xl tracking-wider text-white">M-TEXTILE<span className="text-blue-500">.</span></span> | |
| <button | |
| onClick={() => setSidebarOpen(!sidebarOpen)} | |
| className="text-gray-400 hover:text-white p-2" | |
| > | |
| {sidebarOpen ? <FiX size={24} /> : <FiMenu size={24} />} | |
| </button> | |
| </div> | |
| {/* Sidebar */} | |
| <aside className={` | |
| fixed inset-y-0 left-0 z-10 w-64 bg-gray-900 border-r border-gray-800 transform transition-transform duration-300 ease-in-out | |
| lg:translate-x-0 ${sidebarOpen ? 'translate-x-0 pt-16' : '-translate-x-full pt-16'} lg:pt-0 | |
| `}> | |
| <div className="hidden lg:flex h-16 items-center px-6 border-b border-gray-800"> | |
| <span className="font-bold text-xl tracking-wider text-white">M-TEXTILE<span className="text-blue-500">.</span></span> | |
| </div> | |
| <nav className="flex-1 px-4 py-6 space-y-2"> | |
| {links.map((link) => ( | |
| <NavLink | |
| key={link.path} | |
| to={link.path} | |
| onClick={() => setSidebarOpen(false)} | |
| className={({ isActive }) => ` | |
| flex items-center gap-3 px-4 py-3 rounded-lg transition-colors font-medium | |
| ${isActive | |
| ? 'bg-blue-600/10 text-blue-500' | |
| : 'text-gray-400 hover:text-white hover:bg-gray-800'} | |
| `} | |
| > | |
| <link.icon size={20} /> | |
| {link.label} | |
| </NavLink> | |
| ))} | |
| </nav> | |
| <div className="absolute bottom-0 w-full p-4 border-t border-gray-800 bg-gray-900"> | |
| <button | |
| onClick={handleLogout} | |
| className="flex items-center gap-3 px-4 py-3 rounded-lg w-full text-red-400 hover:bg-red-500/10 hover:text-red-500 transition-colors font-medium" | |
| > | |
| <FiLogOut size={20} /> | |
| Chiqish | |
| </button> | |
| </div> | |
| </aside> | |
| {/* Main Content */} | |
| <main className="flex-1 lg:ml-64 pt-16 lg:pt-0 min-h-screen flex flex-col"> | |
| <div className="flex-1 p-4 lg:p-8"> | |
| <Outlet /> | |
| </div> | |
| </main> | |
| {/* Mobile Overlay */} | |
| {sidebarOpen && ( | |
| <div | |
| className="fixed inset-0 bg-black/50 z-0 lg:hidden backdrop-blur-sm" | |
| onClick={() => setSidebarOpen(false)} | |
| /> | |
| )} | |
| </div> | |
| ); | |
| } | |