diff --git a/frontend/src/components/ClasicoLayout.tsx b/frontend/src/components/ClasicoLayout.tsx index a6ac59a..cb39aee 100644 --- a/frontend/src/components/ClasicoLayout.tsx +++ b/frontend/src/components/ClasicoLayout.tsx @@ -1,5 +1,5 @@ -import type { FC, ReactNode } from 'react'; -import { useEffect, useMemo, useState } from 'react'; +import type { FC, MutableRefObject, ReactNode } from 'react'; +import { useEffect, useMemo, useRef, useState } from 'react'; import { Link, useLocation, useNavigate } from 'react-router-dom'; import { LayoutDashboard, @@ -256,13 +256,47 @@ export const ClasicoLayout: FC = ({ children, title: _title, subtit const toggleGroup = (label: string) => setOpenGroups((prev) => (prev.includes(label) ? prev.filter((l) => l !== label) : [...prev, label])); - const SidebarContent = () => ( + // El menú se renderiza como función (no como componente) a propósito: como + // componente definido dentro del layout, cada render crea un tipo nuevo y + // React remonta el subárbol entero, perdiendo la posición de scroll (los + // últimos items, p. ej. Leads WACRM, quedaban inalcanzables). + const navDesktopRef = useRef(null); + const navMobileRef = useRef(null); + + // 1) El grupo que contiene la ruta activa siempre queda abierto + useEffect(() => { + const current = `${location.pathname}${location.search}`; + const abiertos = menuTree + .filter((e) => e.children?.some((c) => { + const base = c.href.split('?')[0]; + return current === c.href || (current.startsWith(base) && (!c.href.includes('?') || current.includes(c.href.split('?')[1]))); + })) + .map((e) => e.label); + if (!abiertos.length) return; + setOpenGroups((prev) => { + const faltan = abiertos.filter((l) => !prev.includes(l)); + return faltan.length ? [...prev, ...faltan] : prev; + }); + }, [location.pathname, location.search]); + + // 2) Con el grupo ya abierto (re-render), deja visible el item activo. + // Va en un efecto aparte a propósito: en el mismo tick el item todavía no + // está en el DOM y no habría nada que desplazar. + useEffect(() => { + for (const nav of [navDesktopRef.current, navMobileRef.current]) { + if (!nav || nav.scrollHeight <= nav.clientHeight) continue; + const el = nav.querySelector('[data-active="1"]'); + if (el) el.scrollIntoView({ block: 'nearest' }); + } + }, [location.pathname, location.search, openGroups, visibleLeaves]); + + const renderSidebar = ({ navRef = null }: { navRef?: MutableRefObject | null } = {}) => ( <> {/* Sucursal, como en el sistema legacy */}

Rosarito

-