Compare commits

...

3 Commits

Author SHA1 Message Date
Rodolfo Ruiz
e4c8ed534d chore: adding collapsable submenu to Catalog 2025-08-14 17:22:45 -06:00
Rodolfo Ruiz
6300421693 feat: show drawer collapsed 2025-08-12 17:31:48 -06:00
Rodolfo Ruiz
4ac86a9097 chore: show icons only when collapsed 2025-08-12 17:13:24 -06:00
5 changed files with 291 additions and 70 deletions

BIN
public/Expand.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

BIN
public/MiniLogo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,9 +1,7 @@
import { useState } from 'react'; import { useState } from 'react';
import fendiLogo from '/favicon.png'
import { AppBar, Toolbar, Typography, IconButton, Box, Avatar } from '@mui/material'; import { AppBar, Toolbar, Typography, IconButton, Box, Avatar } from '@mui/material';
import MenuDrawer from './MenuDrawer'; import MenuDrawer from './MenuDrawer';
import MenuIcon from '@mui/icons-material/Menu';
import { useAuth } from '../context/AuthContext'; import { useAuth } from '../context/AuthContext';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
@@ -15,7 +13,7 @@ export default function AppHeader({ zone = 'public', onSelectMenuItem }) {
private: '#40120EFF', private: '#40120EFF',
}; };
const [menuOpen, setMenuOpen] = useState(false); const [drawerExpanded, setDrawerExpanded] = useState(true);
const { user, logout } = useAuth(); const { user, logout } = useAuth();
const isPrivate = zone === 'private'; const isPrivate = zone === 'private';
@@ -33,11 +31,6 @@ export default function AppHeader({ zone = 'public', onSelectMenuItem }) {
fontSize: { xs: '0.75rem', md: '1rem' }, fontSize: { xs: '0.75rem', md: '1rem' },
}} > }} >
<Toolbar sx={{ justifyContent: 'space-between', flexWrap: 'wrap' }}> <Toolbar sx={{ justifyContent: 'space-between', flexWrap: 'wrap' }}>
<Box display="flex" alignItems="center">
<IconButton edge="start" color="inherit" onClick={() => setMenuOpen(true)}>
<MenuIcon />
</IconButton>
</Box>
{/* Login button only visible for public zone */} {/* Login button only visible for public zone */}
{isPublic && !user && ( {isPublic && !user && (
@@ -60,8 +53,8 @@ export default function AppHeader({ zone = 'public', onSelectMenuItem }) {
{/* Rendering the Drawer */} {/* Rendering the Drawer */}
<MenuDrawer <MenuDrawer
zone="private" zone="private"
open={menuOpen} open={drawerExpanded}
onClose={() => setMenuOpen(false)} onClose={() => setDrawerExpanded(false)}
onSelect={onSelectMenuItem} // pass handler from App onSelect={onSelectMenuItem} // pass handler from App
/> />

View File

@@ -1,5 +1,5 @@
import { Box, Typography } from '@mui/material'; import { Box, Typography } from '@mui/material';
import fendiLogo from '/logo.png' import fendiLogo from '/Logo.png'
export default function Footer({ zone = 'public' }) { export default function Footer({ zone = 'public' }) {
const bgColor = { const bgColor = {

View File

@@ -1,12 +1,30 @@
import { Drawer, List, ListItem, ListItemText, ListItemIcon, Typography, Box, useMediaQuery, InputBase } from '@mui/material'; import {
Drawer,
List,
ListItem,
ListItemText,
ListItemIcon,
IconButton,
Box,
useMediaQuery,
InputBase,
Tooltip,
Divider,
ListItemButton,
Collapse
} from '@mui/material';
import { useTheme } from '@mui/material/styles';
import { useEffect, useMemo, useState } from 'react';
import { useAuth } from '../context/AuthContext'; import { useAuth } from '../context/AuthContext';
import ExitToAppIcon from '@mui/icons-material/ExitToApp'; import ExitToAppIcon from '@mui/icons-material/ExitToApp';
import ExpandLess from '@mui/icons-material/ExpandLess';
import ExpandMore from '@mui/icons-material/ExpandMore';
// ---- Menu options (unchanged) ----
const menuOptions = { const menuOptions = {
public: [ public: [
{ text: 'Dashboard', icon: <img src="/Dashboard.png" alt="Dashboard" width={24} height={24} />}, { text: 'Dashboard', icon: <img src="/Dashboard.png" alt="Dashboard" width={24} height={24} /> },
{ text: 'Logout', icon: <ExitToAppIcon /> }, { text: 'Logout', icon: <ExitToAppIcon /> },
], ],
restricted: [], restricted: [],
@@ -24,58 +42,160 @@ const menuOptions = {
], ],
}; };
export default function MenuDrawer({ zone = 'public', open, onClose, onSelect }) { // Minivariant sizes
const isMobile = useMediaQuery('(max-width:900px)'); const OPEN_WIDTH = 300;
const items = menuOptions[zone]; const MINI_WIDTH = 72;
export default function MenuDrawer({ zone = 'public', open, onClose, onSelect }) {
const theme = useTheme();
const isMobile = useMediaQuery('(max-width:900px)');
const items = useMemo(() => menuOptions[zone] ?? [], [zone]);
const { logout } = useAuth(); const { logout } = useAuth();
// Collapsed state is only meaningful on desktop (permanent drawer)
const [collapsed, setCollapsed] = useState(false);
const catalogChildren = [
'Furniture',
'Lighting',
'Textiles',
'Decorative Accessories',
'Kitchen & Dining',
'Outdoor Living',
];
const [openCatalog, setOpenCatalog] = useState(false);
// Interpret parent "open" prop:
// - Mobile (temporary): open controls visibility
// - Desktop (permanent): open=true => expanded, open=false => collapsed
useEffect(() => {
if (!isMobile) {
setCollapsed(!open);
}
}, [open, isMobile]);
const paperWidth = isMobile ? OPEN_WIDTH : (collapsed ? MINI_WIDTH : OPEN_WIDTH);
return ( return (
<Drawer anchor="left" open={open} onClose={onClose} slotProps={{ <Drawer
paper: { anchor="left"
sx: { variant={isMobile ? 'temporary' : 'permanent'}
open={isMobile ? open : true}
onClose={isMobile ? onClose : undefined}
ModalProps={{ keepMounted: true }}
sx={{
width: paperWidth,
flexShrink: 0,
'& .MuiDrawer-paper': {
width: paperWidth,
boxSizing: 'border-box',
backgroundColor: '#FFFFFFFF', backgroundColor: '#FFFFFFFF',
width: isMobile ? '100vw' : 300, color: '#40120EFF',
color: '#40120EFF' transition: theme.transitions.create('width', {
duration: theme.transitions.duration.standard,
easing: theme.transitions.easing.sharp,
}),
borderRight: '1px solid rgba(0,0,0,0.08)',
}, },
}, }}
}}> >
<Box textAlign="center" p={3}> {/* Header */}
<Box
sx={{
display: 'flex',
alignItems: 'center',
gap: 1,
px: collapsed ? 1 : 2,
py: 1.5,
justifyContent: collapsed ? 'center' : 'space-between',
}}
>
{/* Expanded - default */}
{!collapsed && (
<Box textAlign="center" p={3} alignItems="center" minHeight={72}>
<img <img
src="/logo.png" src="Logo.png"
alt="Dream Views" alt="Dream Views"
style={{ margin: 'auto', marginBottom: 8 }}
/> />
<Box sx={{ position: 'relative', display: { xs: 'none', md: 'flex' } }}>
<InputBase <InputBase
placeholder="Filter options..." placeholder="Filter options..."
sx={{ sx={{
pl: 4, pl: 1.5,
pr: 2, pr: 1.5,
py: 0.5, py: 0.75,
borderRadius: 2, borderRadius: 2,
border: '1px solid #40120EFF', // Borde visible border: '1px solid #40120EFF',
color: '#40120EFF', color: '#40120EFF',
width: { md: '300px', lg: '400px' } width: '100%',
}} }}
/> />
</Box> </Box>
)}
</Box> </Box>
<List sx={{ width: isMobile ? '100vw' : 250, marginTop: 0 }}>
{items.map(({ text, icon }, index) => (
<ListItem key={index} onClick={() => {
onClose(); // Close drawer
onSelect?.(text); // Notify parent of selected item
if (text === 'Logout') { {/* Collapsed */}
logout(); // cerrar sesión y redirigir {collapsed && (
} else { <Box textAlign="center" p={3} minHeight={112} justifyContent="center" display="flex"
onSelect?.(text); // navegar al resto de vistas alignItems="start">
} <img
style={{ marginTop: 5 }}
src="MiniLogo.png"
alt="Dream Views"
/>
</Box>
)}
{/* Items */}
<List sx={{
width: '100%',
py: 0,
display: 'flex',
flexDirection: 'column',
alignItems: 'stretch'
}}> }}>
{items.map(({ text, icon }, index) => {
const isCatalog = text === 'Catalog';
<ListItemIcon sx={{ color: '#40120EFF' }}>{icon}</ListItemIcon> // Special case: Catalog with submenu
if (isCatalog) {
return (
<Box key={`catalog-${index}`}>
<Tooltip
title={collapsed ? text : ''}
placement="right"
disableHoverListener={!collapsed}
>
<ListItem
onClick={() => {
if (collapsed) {
// Expand drawer first so submenu is visible
setCollapsed(false);
setOpenCatalog(true);
} else {
setOpenCatalog((v) => !v);
}
}}
sx={{
px: collapsed ? 0 : 2,
minHeight: collapsed ? 48 : 44,
cursor: 'pointer',
justifyContent: collapsed ? 'center' : 'flex-start',
width: '100%',
}}
>
<ListItemIcon
sx={{
color: '#40120EFF',
minWidth: collapsed ? 'auto' : 40,
mr: collapsed ? 0 : 1.5,
justifyContent: 'center',
}}
>
{icon}
</ListItemIcon>
{!collapsed && (
<>
<ListItemText <ListItemText
primary={text} primary={text}
slotProps={{ slotProps={{
@@ -87,9 +207,117 @@ export default function MenuDrawer({ zone = 'public', open, onClose, onSelect })
}, },
}} }}
/> />
{openCatalog ? <ExpandLess /> : <ExpandMore />}
</>
)}
</ListItem> </ListItem>
</Tooltip>
{/* Submenu list */}
{!collapsed && (
<Collapse in={openCatalog} timeout="auto" unmountOnExit>
<List component="div" disablePadding sx={{ pl: 7 }}>
{catalogChildren.map((child) => (
<ListItemButton
key={child}
sx={{ py: 0.5, borderRadius: 1 }}
onClick={() => {
if (isMobile) onClose?.();
onSelect?.(child);
}}
>
<ListItemText
primary={child}
slotProps={{
primary: {
sx: { color: '#40120EFF', fontWeight: 400 },
},
}}
/>
</ListItemButton>
))} ))}
</List> </List>
</Collapse>
)}
</Box>
);
}
// Default items
return (
<Tooltip
key={`${text}-${index}`}
title={collapsed ? (text || ' ') : ''}
placement="right"
disableHoverListener={!collapsed}
>
<ListItem
onClick={() => {
if (isMobile) onClose?.();
if (text === 'Logout') {
logout();
} else {
onSelect?.(text);
}
}}
sx={{
px: collapsed ? 0 : 2,
minHeight: collapsed ? 48 : 44,
cursor: 'pointer',
justifyContent: collapsed ? 'center' : 'flex-start',
width: '100%',
}}
>
<ListItemIcon
sx={{
color: '#40120EFF',
minWidth: collapsed ? 'auto' : 40,
mr: collapsed ? 0 : 1.5,
justifyContent: 'center',
}}
>
{icon}
</ListItemIcon>
{!collapsed && (
<ListItemText
primary={text}
slotProps={{
primary: {
sx: {
color: '#40120EFF',
fontWeight: 'medium',
},
},
}}
/>
)}
</ListItem>
</Tooltip>
);
})}
</List>
<Tooltip title={collapsed ? 'Expand' : 'Collapse'} placement="right">
<IconButton onClick={() => setCollapsed((c) => !c)} sx={{
backgroundColor: 'transparent',
color: 'transparent',
'&:hover': {
backgroundColor: '#fff4ec',
borderColor: 'transparent'
},
borderRadius: 0,
marginLeft: 2,
width: 40,
height: 40,
}}>
<img
src={collapsed ? '/Expand.png' : '/Contract.png'}
alt={collapsed ? 'Expand' : 'Contract'}
width={24}
height={24}
/>
</IconButton>
</Tooltip>
</Drawer> </Drawer>
); );
} }