diff --git a/src/admin/layout/AdminLayout.jsx b/src/admin/layout/AdminLayout.jsx index 1cbe569..5f02ac5 100644 --- a/src/admin/layout/AdminLayout.jsx +++ b/src/admin/layout/AdminLayout.jsx @@ -1,8 +1,9 @@ import { useState, useEffect } from 'react'; import { Outlet, useLocation } from 'react-router-dom'; -import { Plus } from 'lucide-react'; +import { Plus, Menu } from 'lucide-react'; import Sidebar from './Sidebar'; import { supabase } from '../../lib/supabase'; +import { useIsMobile } from '../../hooks/useIsMobile'; const PAGE_TITLES = { '/admin/kanban': 'Канбан', @@ -15,6 +16,8 @@ const AdminLayout = () => { const title = PAGE_TITLES[location.pathname] || 'Панель управления'; const [showNewOrder, setShowNewOrder] = useState(false); const [newCount, setNewCount] = useState(0); + const [sidebarOpen, setSidebarOpen] = useState(false); + const isMobile = useIsMobile(); useEffect(() => { const refreshBadge = () => { @@ -33,10 +36,31 @@ const AdminLayout = () => { return () => supabase.removeChannel(channel); }, []); + useEffect(() => { + setSidebarOpen(false); + }, [location.pathname]); + return (
- -
+ {isMobile && sidebarOpen && ( +
setSidebarOpen(false)} + style={{ + position: 'fixed', inset: 0, + background: 'rgba(0,0,0,0.4)', + zIndex: 99, + }} + /> + )} + setSidebarOpen(false)} + isMobile={isMobile} + /> +
{/* Header */}
{ position: 'sticky', top: 0, zIndex: 50, }}>
+ {isMobile && ( + + )}

{title}

diff --git a/src/admin/layout/Sidebar.jsx b/src/admin/layout/Sidebar.jsx index a4e54cc..2785715 100644 --- a/src/admin/layout/Sidebar.jsx +++ b/src/admin/layout/Sidebar.jsx @@ -1,5 +1,5 @@ import { NavLink, useNavigate } from 'react-router-dom'; -import { LayoutDashboard, BarChart2, CheckSquare, Shield, LogOut, Users, Settings, BookUser } from 'lucide-react'; +import { LayoutDashboard, BarChart2, CheckSquare, Shield, LogOut, Users, Settings, BookUser, X } from 'lucide-react'; import { useAuth } from '../auth/useAuth'; const NAV_ITEMS = [ @@ -11,7 +11,7 @@ const NAV_ITEMS = [ { to: '/admin/settings', icon: Settings, label: 'Настройки' }, ]; -const Sidebar = () => { +const Sidebar = ({ isOpen, onClose, isMobile }) => { const { session, logout } = useAuth(); const navigate = useNavigate(); @@ -28,9 +28,11 @@ const Sidebar = () => { position: 'fixed', top: 0, left: 0, zIndex: 100, borderRight: '1px solid #E9ECEF', + transform: isMobile && !isOpen ? 'translateX(-100%)' : 'translateX(0)', + transition: 'transform 0.25s ease', }}> {/* Logo */} -
+
@@ -40,6 +42,23 @@ const Sidebar = () => {

Панель управления

+ {isMobile && ( + + )}
{/* Navigation */} diff --git a/src/hooks/useIsMobile.js b/src/hooks/useIsMobile.js new file mode 100644 index 0000000..5e0e48c --- /dev/null +++ b/src/hooks/useIsMobile.js @@ -0,0 +1,12 @@ +import { useState, useEffect } from 'react'; + +export function useIsMobile(breakpoint = 768) { + const [isMobile, setIsMobile] = useState(() => window.innerWidth < breakpoint); + useEffect(() => { + const mq = window.matchMedia(`(max-width: ${breakpoint - 1}px)`); + const handler = (e) => setIsMobile(e.matches); + mq.addEventListener('change', handler); + return () => mq.removeEventListener('change', handler); + }, [breakpoint]); + return isMobile; +}