feat: Enhance application structure with new Prueba_appshell page and responsive navbar; update dependencies
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
import { useDisclosure } from '@mantine/hooks';
|
||||
import { AppShell, Burger, Group, Skeleton } from '@mantine/core';
|
||||
|
||||
|
||||
export function CollapseDesktop() {
|
||||
const [mobileOpened, { toggle: toggleMobile }] = useDisclosure();
|
||||
const [desktopOpened, { toggle: toggleDesktop }] = useDisclosure(true);
|
||||
|
||||
return (
|
||||
<AppShell
|
||||
header={{ height: 60 }}
|
||||
navbar={{
|
||||
width: 300,
|
||||
breakpoint: 'sm',
|
||||
collapsed: { mobile: !mobileOpened, desktop: !desktopOpened },
|
||||
}}
|
||||
padding="md"
|
||||
>
|
||||
<AppShell.Header>
|
||||
<Group h="100%" px="md">
|
||||
<Burger opened={mobileOpened} onClick={toggleMobile} hiddenFrom="sm" size="sm" />
|
||||
<Burger opened={desktopOpened} onClick={toggleDesktop} visibleFrom="sm" size="sm" />
|
||||
<img
|
||||
src="/src/favicon.svg"
|
||||
alt="Logo"
|
||||
style={{ width: 30, height: 30 }}
|
||||
/>
|
||||
</Group>
|
||||
</AppShell.Header>
|
||||
<AppShell.Navbar p="md">
|
||||
Navbar
|
||||
{Array(15)
|
||||
.fill(0)
|
||||
.map((_, index) => (
|
||||
<Skeleton key={index} h={28} mt="sm" animate={false} />
|
||||
))}
|
||||
</AppShell.Navbar>
|
||||
<AppShell.Main>Main</AppShell.Main>
|
||||
</AppShell>
|
||||
);
|
||||
}
|
||||
@@ -15,8 +15,9 @@ import {
|
||||
UnstyledButton,
|
||||
ActionIcon,
|
||||
} from '@mantine/core';
|
||||
import { useDisclosure, useMediaQuery } from '@mantine/hooks';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import classes from './DoubleNavbar.module.css';
|
||||
|
||||
const mainLinksdata = [
|
||||
@@ -33,6 +34,7 @@ const submenuLinks: Record<string, { label: string; to: string }[]> = {
|
||||
Home: [
|
||||
{ label: 'Inicio', to: '/' },
|
||||
{ label: 'Consulta Api', to: '/Consulta_API' },
|
||||
{ label: 'Prueba_appshell', to: '/prueba_appshell' },
|
||||
],
|
||||
Dashboard: [
|
||||
{ label: 'Resumen', to: '/dashboard/resumen' },
|
||||
@@ -64,10 +66,15 @@ const submenuLinks: Record<string, { label: string; to: string }[]> = {
|
||||
|
||||
export function DoubleNavbar() {
|
||||
const location = useLocation();
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
const isMobile = useMediaQuery('(max-width: 768px)');
|
||||
|
||||
const [mobileOpened, { toggle: toggleMobile, close: closeMobile }] = useDisclosure(false);
|
||||
const [desktopOpened, { toggle: toggleDesktop, open: openDesktop }] = useDisclosure(true);
|
||||
|
||||
const isCollapsed = useMemo(() => (isMobile ? !mobileOpened : !desktopOpened), [isMobile, mobileOpened, desktopOpened]);
|
||||
|
||||
const [manualActiveTab, setManualActiveTab] = useState<string | null>(null);
|
||||
|
||||
// Detectar cuál pestaña es activa por la ruta actual
|
||||
const matchedMain = Object.entries(submenuLinks).find(([mainKey, items]) =>
|
||||
items.some((item) => location.pathname.startsWith(item.to))
|
||||
);
|
||||
@@ -87,7 +94,10 @@ export function DoubleNavbar() {
|
||||
key={link.label}
|
||||
>
|
||||
<UnstyledButton
|
||||
onClick={() => setManualActiveTab(link.label)}
|
||||
onClick={() => {
|
||||
setManualActiveTab(link.label);
|
||||
if (isMobile) closeMobile();
|
||||
}}
|
||||
className={classes.mainLink}
|
||||
data-active={link.label === active || undefined}
|
||||
>
|
||||
@@ -102,22 +112,29 @@ export function DoubleNavbar() {
|
||||
data-active={activeLink === item.label || undefined}
|
||||
to={item.to}
|
||||
key={item.label}
|
||||
style={{ display: collapsed ? 'none' : 'block' }}
|
||||
style={{ display: isCollapsed ? 'none' : 'block' }}
|
||||
onClick={() => {
|
||||
if (isMobile) closeMobile();
|
||||
}}
|
||||
>
|
||||
{item.label}
|
||||
</Link>
|
||||
));
|
||||
|
||||
// Resetea pestaña seleccionada si la ruta cambia (opcional)
|
||||
// Restaurar pestaña al cambiar ruta (opcional pero útil)
|
||||
useEffect(() => {
|
||||
setManualActiveTab(null);
|
||||
}, [location.pathname]);
|
||||
|
||||
// Abrir navbar de escritorio si cambia a pantalla grande
|
||||
useEffect(() => {
|
||||
if (!isMobile) openDesktop();
|
||||
}, [isMobile, openDesktop]);
|
||||
|
||||
return (
|
||||
<nav className={`${classes.navbar} ${collapsed ? classes.collapsed : ''}`}>
|
||||
<nav className={`${classes.navbar} ${isCollapsed ? classes.collapsed : ''}`}>
|
||||
<div className={classes.wrapper}>
|
||||
<div className={classes.aside}>
|
||||
{/* Sección superior: logo + mainLinks */}
|
||||
<div className={classes.topSection}>
|
||||
<div className={classes.logo}>
|
||||
<img
|
||||
@@ -126,23 +143,21 @@ export function DoubleNavbar() {
|
||||
style={{ width: 30, height: 30 }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{mainLinks}
|
||||
</div>
|
||||
|
||||
{/* Botón de colapsar separado abajo */}
|
||||
<ActionIcon
|
||||
variant="subtle"
|
||||
onClick={() => setCollapsed((c) => !c)}
|
||||
onClick={() => (isMobile ? toggleMobile() : toggleDesktop())}
|
||||
className={classes.collapseButton}
|
||||
size="lg"
|
||||
>
|
||||
{collapsed ? <IconArrowBarRight size={20} /> : <IconArrowBarLeft size={20} />}
|
||||
{isCollapsed ? <IconArrowBarRight size={20} /> : <IconArrowBarLeft size={20} />}
|
||||
</ActionIcon>
|
||||
</div>
|
||||
|
||||
<div className={classes.main}>
|
||||
{!collapsed && (
|
||||
{!isCollapsed && (
|
||||
<Title order={4} className={classes.title}>
|
||||
{active}
|
||||
</Title>
|
||||
@@ -152,4 +167,4 @@ export function DoubleNavbar() {
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ extend({ HoloShaderMaterial });
|
||||
|
||||
// 🎥 Plano con el shader
|
||||
function HoloPlane({ color }: { color: [number, number, number] }) {
|
||||
const mat = useRef<any>();
|
||||
const mat = useRef<any>(null);
|
||||
const { size } = useThree();
|
||||
|
||||
useFrame(({ clock }) => {
|
||||
|
||||
Reference in New Issue
Block a user