Compare commits
3 Commits
7714a6c704
...
e4c8ed534d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4c8ed534d | ||
|
|
6300421693 | ||
|
|
4ac86a9097 |
BIN
public/Expand.png
Normal file
BIN
public/Expand.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 290 B |
BIN
public/MiniLogo.png
Normal file
BIN
public/MiniLogo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
@@ -1,9 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
import fendiLogo from '/favicon.png'
|
||||
import { AppBar, Toolbar, Typography, IconButton, Box, Avatar } from '@mui/material';
|
||||
|
||||
import MenuDrawer from './MenuDrawer';
|
||||
import MenuIcon from '@mui/icons-material/Menu';
|
||||
import { useAuth } from '../context/AuthContext';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
@@ -15,7 +13,7 @@ export default function AppHeader({ zone = 'public', onSelectMenuItem }) {
|
||||
private: '#40120EFF',
|
||||
};
|
||||
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
const [drawerExpanded, setDrawerExpanded] = useState(true);
|
||||
const { user, logout } = useAuth();
|
||||
|
||||
const isPrivate = zone === 'private';
|
||||
@@ -33,11 +31,6 @@ export default function AppHeader({ zone = 'public', onSelectMenuItem }) {
|
||||
fontSize: { xs: '0.75rem', md: '1rem' },
|
||||
}} >
|
||||
<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 */}
|
||||
{isPublic && !user && (
|
||||
@@ -60,8 +53,8 @@ export default function AppHeader({ zone = 'public', onSelectMenuItem }) {
|
||||
{/* Rendering the Drawer */}
|
||||
<MenuDrawer
|
||||
zone="private"
|
||||
open={menuOpen}
|
||||
onClose={() => setMenuOpen(false)}
|
||||
open={drawerExpanded}
|
||||
onClose={() => setDrawerExpanded(false)}
|
||||
onSelect={onSelectMenuItem} // pass handler from App
|
||||
/>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Box, Typography } from '@mui/material';
|
||||
import fendiLogo from '/logo.png'
|
||||
import fendiLogo from '/Logo.png'
|
||||
|
||||
export default function Footer({ zone = 'public' }) {
|
||||
const bgColor = {
|
||||
|
||||
@@ -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 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 = {
|
||||
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 /> },
|
||||
],
|
||||
restricted: [],
|
||||
@@ -24,72 +42,282 @@ const menuOptions = {
|
||||
],
|
||||
};
|
||||
|
||||
export default function MenuDrawer({ zone = 'public', open, onClose, onSelect }) {
|
||||
const isMobile = useMediaQuery('(max-width:900px)');
|
||||
const items = menuOptions[zone];
|
||||
// Mini‑variant sizes
|
||||
const OPEN_WIDTH = 300;
|
||||
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();
|
||||
|
||||
// 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 (
|
||||
<Drawer anchor="left" open={open} onClose={onClose} slotProps={{
|
||||
paper: {
|
||||
sx: {
|
||||
<Drawer
|
||||
anchor="left"
|
||||
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',
|
||||
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}>
|
||||
<img
|
||||
src="/logo.png"
|
||||
alt="Dream Views"
|
||||
style={{ margin: 'auto', marginBottom: 8 }}
|
||||
/>
|
||||
}}
|
||||
>
|
||||
{/* 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
|
||||
src="Logo.png"
|
||||
alt="Dream Views"
|
||||
/>
|
||||
|
||||
<Box sx={{ position: 'relative', display: { xs: 'none', md: 'flex' } }}>
|
||||
<InputBase
|
||||
placeholder="Filter options..."
|
||||
sx={{
|
||||
pl: 4,
|
||||
pr: 2,
|
||||
py: 0.5,
|
||||
borderRadius: 2,
|
||||
border: '1px solid #40120EFF', // Borde visible
|
||||
color: '#40120EFF',
|
||||
width: { md: '300px', lg: '400px' }
|
||||
}}
|
||||
/>
|
||||
</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') {
|
||||
logout(); // cerrar sesión y redirigir
|
||||
} else {
|
||||
onSelect?.(text); // navegar al resto de vistas
|
||||
}
|
||||
}}>
|
||||
|
||||
<ListItemIcon sx={{ color: '#40120EFF' }}>{icon}</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={text}
|
||||
slotProps={{
|
||||
primary: {
|
||||
sx: {
|
||||
color: '#40120EFF',
|
||||
fontWeight: 'medium',
|
||||
},
|
||||
},
|
||||
<InputBase
|
||||
placeholder="Filter options..."
|
||||
sx={{
|
||||
pl: 1.5,
|
||||
pr: 1.5,
|
||||
py: 0.75,
|
||||
borderRadius: 2,
|
||||
border: '1px solid #40120EFF',
|
||||
color: '#40120EFF',
|
||||
width: '100%',
|
||||
}}
|
||||
/>
|
||||
</ListItem>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* Collapsed */}
|
||||
{collapsed && (
|
||||
<Box textAlign="center" p={3} minHeight={112} justifyContent="center" display="flex"
|
||||
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';
|
||||
|
||||
// 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
|
||||
primary={text}
|
||||
slotProps={{
|
||||
primary: {
|
||||
sx: {
|
||||
color: '#40120EFF',
|
||||
fontWeight: 'medium',
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
{openCatalog ? <ExpandLess /> : <ExpandMore />}
|
||||
</>
|
||||
)}
|
||||
</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>
|
||||
</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>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user