From 9f6defd25c74f8818b6dd8ff2acd7c77471fcf1f Mon Sep 17 00:00:00 2001 From: nikita Date: Sun, 5 Apr 2026 08:04:42 +0300 Subject: [PATCH] fix: adaptive #2 --- frontend/src/app/providers/layout/layout.tsx | 40 ++++++++++++-- .../layout/navigation/navigation.tsx | 28 +++++++++- .../app/providers/layout/sidebar/sidebar.tsx | 53 ++++++++++--------- 3 files changed, 91 insertions(+), 30 deletions(-) diff --git a/frontend/src/app/providers/layout/layout.tsx b/frontend/src/app/providers/layout/layout.tsx index 4210ac4..8a54aea 100644 --- a/frontend/src/app/providers/layout/layout.tsx +++ b/frontend/src/app/providers/layout/layout.tsx @@ -4,9 +4,34 @@ import { Navigation } from "@/app/providers/layout/navigation/navigation"; import { useAgentStore } from "@/app/providers/layout/store/agent.store"; export const Layout = ({ children }: { children: ReactNode }) => { - const [isOpen, setOpen] = useState(true); + const [mobileOpen, setMobileOpen] = useState(false); + const [isMobile, setIsMobile] = useState(() => + typeof window !== "undefined" ? window.innerWidth < 856 : false, + ); const { fetchAgents } = useAgentStore(); + const sidebarOpen = isMobile ? mobileOpen : true; + + useEffect(() => { + const handleResize = () => { + const mobile = window.innerWidth < 856; + setIsMobile(mobile); + if (!mobile) { + setMobileOpen(false); + } + }; + + window.addEventListener("resize", handleResize); + handleResize(); + return () => window.removeEventListener("resize", handleResize); + }, []); + + const toggleSidebar = () => { + if (isMobile) { + setMobileOpen((prev) => !prev); + } + }; + useEffect(() => { fetchAgents(); }, [fetchAgents]); @@ -20,10 +45,17 @@ export const Layout = ({ children }: { children: ReactNode }) => { }, [fetchAgents]); return ( -
- setOpen(!isOpen)} /> +
+
- +
{children}
diff --git a/frontend/src/app/providers/layout/navigation/navigation.tsx b/frontend/src/app/providers/layout/navigation/navigation.tsx index a081579..289c62c 100644 --- a/frontend/src/app/providers/layout/navigation/navigation.tsx +++ b/frontend/src/app/providers/layout/navigation/navigation.tsx @@ -1,6 +1,6 @@ import { useState, useRef, useEffect } from "react"; import { useNavigate, useLocation } from "react-router-dom"; -import { FaCode, FaChevronDown } from "react-icons/fa"; +import { FaBars, FaCode, FaChevronDown } from "react-icons/fa"; import { FaHome, FaServer, @@ -21,7 +21,15 @@ import { getCurrentTheme, } from "@/modules/theme-changer/utils/apply.theme"; -export const Navigation = () => { +interface NavigationProps { + onToggleSidebar?: () => void; + isMobile?: boolean; +} + +export const Navigation: React.FC = ({ + onToggleSidebar, + isMobile, +}) => { const navigate = useNavigate(); const location = useLocation(); const { user, logout } = useAuthStore(); @@ -75,6 +83,22 @@ export const Navigation = () => { }} >
+ {/* Бургер — только на мобильных */} + {isMobile && ( + + )} + {/* Навигация */}
diff --git a/frontend/src/app/providers/layout/sidebar/sidebar.tsx b/frontend/src/app/providers/layout/sidebar/sidebar.tsx index 763cf74..6064324 100644 --- a/frontend/src/app/providers/layout/sidebar/sidebar.tsx +++ b/frontend/src/app/providers/layout/sidebar/sidebar.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useState } from "react"; +import React, { useMemo, useState, useRef, useEffect } from "react"; import { FaBars, FaMicrochip, @@ -21,11 +21,13 @@ import { adminApi } from "@/modules/admin/api/admin.api"; interface SidebarProps { isOpen?: boolean; onToggle?: () => void; + isMobile?: boolean; } export const Sidebar: React.FC = ({ isOpen = true, onToggle, + isMobile = false, }) => { const navigate = useNavigate(); const { agents, isLoading, error, fetchAgents, removeAgent } = @@ -35,10 +37,26 @@ export const Sidebar: React.FC = ({ const [copied, setCopied] = useState(false); const [showTokenModal, setShowTokenModal] = useState(false); const [showGraphs, setShowGraphs] = useState(false); + const [sidebarWidth, setSidebarWidth] = useState(288); + const sidebarRef = useRef(null); const [expandedAgents, setExpandedAgents] = useState>( new Set(agents.map((a) => a.label)), ); + // Рассчитываем максимальную ширину при переключении на графы + useEffect(() => { + const updateWidth = () => { + const targetWidth = showGraphs ? 500 : 288; + const maxWidth = window.innerWidth - 200; + const finalWidth = Math.min(targetWidth, maxWidth); + setSidebarWidth(Math.max(finalWidth, 250)); + }; + + updateWidth(); + window.addEventListener("resize", updateWidth); + return () => window.removeEventListener("resize", updateWidth); + }, [showGraphs]); + // Token generation state const [tokenLabel, setTokenLabel] = useState(""); const [generatedToken, setGeneratedToken] = useState(null); @@ -132,35 +150,21 @@ export const Sidebar: React.FC = ({ }; if (!isOpen) { - return ( - - ); + return null; } return ( <> - {/* Overlay для мобильных */} -
+ {/* Overlay — только на мобильных (< 856px) */} + {isMobile && ( +
+ )}