92 lines
3.6 KiB
TypeScript
Executable File
92 lines
3.6 KiB
TypeScript
Executable File
|
||
import React from 'react';
|
||
import { NavItem } from '../types';
|
||
import { NAV_ITEMS } from '../constants';
|
||
|
||
interface SidebarProps {
|
||
activeTab: string;
|
||
setActiveTab: (id: string) => void;
|
||
isMobileOpen: boolean;
|
||
setIsMobileOpen: (open: boolean) => void;
|
||
}
|
||
|
||
export const Sidebar: React.FC<SidebarProps> = ({ activeTab, setActiveTab, isMobileOpen, setIsMobileOpen }) => {
|
||
return (
|
||
<>
|
||
{/* Mobile Overlay */}
|
||
{isMobileOpen && (
|
||
<div
|
||
className="fixed inset-0 bg-black/50 z-40 lg:hidden backdrop-blur-sm"
|
||
onClick={() => setIsMobileOpen(false)}
|
||
/>
|
||
)}
|
||
|
||
{/* Sidebar Container */}
|
||
<aside
|
||
className={`
|
||
fixed top-0 left-0 z-50 h-full w-64 bg-slate-850 text-white transition-transform duration-300 ease-in-out
|
||
lg:translate-x-0 lg:static lg:block shadow-2xl
|
||
${isMobileOpen ? 'translate-x-0' : '-translate-x-full'}
|
||
`}
|
||
>
|
||
<div className="flex flex-col h-full">
|
||
{/* Logo Area */}
|
||
<div className="p-6 border-b border-slate-700">
|
||
<div className="flex items-center gap-3">
|
||
<div className="w-8 h-8 rounded-lg bg-primary-500 flex items-center justify-center">
|
||
<svg className="w-5 h-5 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
|
||
</svg>
|
||
</div>
|
||
<h1 className="text-base font-bold tracking-tight leading-tight">Центр управления<br/>домами</h1>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Navigation Items */}
|
||
<nav className="flex-1 overflow-y-auto py-4">
|
||
<ul className="space-y-1 px-3">
|
||
{NAV_ITEMS.map((item) => {
|
||
const Icon = item.icon;
|
||
const isActive = activeTab === item.id;
|
||
return (
|
||
<li key={item.id}>
|
||
<button
|
||
onClick={() => {
|
||
setActiveTab(item.id);
|
||
setIsMobileOpen(false);
|
||
}}
|
||
className={`
|
||
w-full flex items-center gap-3 px-3 py-3 rounded-lg text-sm font-medium transition-all duration-200
|
||
${isActive
|
||
? 'bg-primary-600 text-white shadow-lg shadow-primary-900/20'
|
||
: 'text-slate-400 hover:bg-slate-800 hover:text-white'}
|
||
`}
|
||
>
|
||
<Icon className={`w-5 h-5 ${isActive ? 'text-white' : 'text-slate-400'}`} />
|
||
{item.label}
|
||
</button>
|
||
</li>
|
||
);
|
||
})}
|
||
</ul>
|
||
</nav>
|
||
|
||
{/* User Profile Snippet */}
|
||
<div className="p-4 border-t border-slate-700">
|
||
<div className="flex items-center gap-3">
|
||
<img
|
||
src="https://picsum.photos/id/1005/64/64"
|
||
alt="Admin"
|
||
className="w-10 h-10 rounded-full border-2 border-slate-600"
|
||
/>
|
||
<div className="overflow-hidden">
|
||
<p className="text-sm font-medium text-white truncate">Алексей Петров</p>
|
||
<p className="text-xs text-slate-400 truncate">Главный инженер</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
</>
|
||
);
|
||
}; |