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 { 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
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -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 = {
|
||||||
|
|||||||
@@ -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 }) {
|
// Mini‑variant 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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user