Make main menu responsive
This commit is contained in:
parent
2a9c6cf6a1
commit
c3a3d2345f
5 changed files with 157 additions and 93 deletions
13
src/App.js
13
src/App.js
|
@ -1,5 +1,4 @@
|
||||||
import { lazy, Suspense } from 'react';
|
import { lazy, Suspense } from 'react';
|
||||||
import { Container } from '@mui/material';
|
|
||||||
import { useAuthState } from './context/auth';
|
import { useAuthState } from './context/auth';
|
||||||
|
|
||||||
import LoadingIndicator from './components/LoadingIndicator';
|
import LoadingIndicator from './components/LoadingIndicator';
|
||||||
|
@ -12,21 +11,9 @@ function App() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Suspense fallback={<LoadingIndicator isLoading />}>
|
<Suspense fallback={<LoadingIndicator isLoading />}>
|
||||||
<Container maxWidth="false" sx={container}>
|
|
||||||
{isAuthenticated ? <AuthenticatedApp /> : <UnauthenticatedApp />}
|
{isAuthenticated ? <AuthenticatedApp /> : <UnauthenticatedApp />}
|
||||||
</Container>
|
|
||||||
</Suspense>
|
</Suspense>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const container = {
|
|
||||||
height: '100vh',
|
|
||||||
margin: 0,
|
|
||||||
padding: 0,
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
backgroundColor: 'primary.mainBackground',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|
|
@ -7,35 +7,59 @@ import {
|
||||||
Info,
|
Info,
|
||||||
InfoOutlined,
|
InfoOutlined,
|
||||||
} from '@mui/icons-material';
|
} from '@mui/icons-material';
|
||||||
import MainDrawer from './components/MainDrawer';
|
import MainMenu from './components/MainMenu';
|
||||||
import Home from './screens/Home';
|
import Home from './screens/Home';
|
||||||
import Information from './screens/Information';
|
import Information from './screens/Information';
|
||||||
import Calendar from './screens/Calendar';
|
import Calendar from './screens/Calendar';
|
||||||
|
import { Container } from '@mui/system';
|
||||||
|
import useLayoutType from './hooks/useLayoutType';
|
||||||
|
|
||||||
function AuthenticatedApp() {
|
function AuthenticatedApp() {
|
||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
|
const layoutType = useLayoutType();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Container
|
||||||
<MainDrawer options={menuOptions(pathname)} />
|
maxWidth="false"
|
||||||
|
sx={layoutType === 'desktop' ? container : mobileContainer}
|
||||||
|
>
|
||||||
|
<MainMenu options={menuOptions(pathname)} layoutType={layoutType} />
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/home" element={<Home />} />
|
<Route path="/home" element={<Home />} />
|
||||||
<Route path="/info" element={<Information />} />
|
<Route path="/info" element={<Information />} />
|
||||||
<Route path="/calendar" element={<Calendar />} />
|
<Route path="/calendar" element={<Calendar />} />
|
||||||
<Route path="/login" element={<Navigate to="/home" />} />
|
<Route path="/login" element={<Navigate to="/home" />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const container = {
|
||||||
|
height: '100vh',
|
||||||
|
margin: 0,
|
||||||
|
padding: 0,
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: 'primary.mainBackground',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileContainer = {
|
||||||
|
...container,
|
||||||
|
flexDirection: 'column-reverse',
|
||||||
|
};
|
||||||
|
|
||||||
const menuOptions = activePath => [
|
const menuOptions = activePath => [
|
||||||
{
|
{
|
||||||
|
id: 0,
|
||||||
text: 'Página Inicial',
|
text: 'Página Inicial',
|
||||||
selectedIcon: <HomeIcon />,
|
selectedIcon: <HomeIcon />,
|
||||||
unselectedIcon: <HomeOutlined />,
|
unselectedIcon: <HomeOutlined />,
|
||||||
pathname: '/home',
|
pathname: '/home',
|
||||||
isActive: activePath === '/home',
|
isActive: activePath === '/home' || activePath === '/login',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: 1,
|
||||||
text: 'Informações',
|
text: 'Informações',
|
||||||
selectedIcon: <Info />,
|
selectedIcon: <Info />,
|
||||||
unselectedIcon: <InfoOutlined />,
|
unselectedIcon: <InfoOutlined />,
|
||||||
|
@ -43,6 +67,7 @@ const menuOptions = activePath => [
|
||||||
isActive: activePath === '/info',
|
isActive: activePath === '/info',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: 2,
|
||||||
text: 'Calendário',
|
text: 'Calendário',
|
||||||
selectedIcon: <CalendarMonth />,
|
selectedIcon: <CalendarMonth />,
|
||||||
unselectedIcon: <CalendarMonthOutlined />,
|
unselectedIcon: <CalendarMonthOutlined />,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Fragment } from 'react';
|
import { Container } from '@mui/material';
|
||||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||||
|
|
||||||
import Login from './screens/Login';
|
import Login from './screens/Login';
|
||||||
|
@ -6,14 +6,24 @@ import UnauthenticatedHome from './screens/UnauthenticatedHome';
|
||||||
|
|
||||||
function UnauthenticatedApp() {
|
function UnauthenticatedApp() {
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Container maxWidth="false" sx={container}>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<UnauthenticatedHome />} />
|
<Route path="/" element={<UnauthenticatedHome />} />
|
||||||
<Route path="/login" element={<Login />} />
|
<Route path="/login" element={<Login />} />
|
||||||
<Route path="*" element={<Navigate to="/" />} />
|
<Route path="*" element={<Navigate to="/" />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</Fragment>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const container = {
|
||||||
|
height: '100vh',
|
||||||
|
margin: 0,
|
||||||
|
padding: 0,
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: 'primary.mainBackground',
|
||||||
|
};
|
||||||
|
|
||||||
export default UnauthenticatedApp;
|
export default UnauthenticatedApp;
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
import {
|
|
||||||
Drawer,
|
|
||||||
List,
|
|
||||||
ListItem,
|
|
||||||
ListItemButton,
|
|
||||||
ListItemIcon,
|
|
||||||
ListItemText,
|
|
||||||
Toolbar,
|
|
||||||
} from '@mui/material';
|
|
||||||
import { NavLink } from 'react-router-dom';
|
|
||||||
import logoImage from '../assets/if-salas-logo.svg';
|
|
||||||
|
|
||||||
function MainDrawer({ options }) {
|
|
||||||
return (
|
|
||||||
<Drawer sx={drawer} variant="permanent" anchor="left">
|
|
||||||
<Toolbar disableGutters sx={toolbar}>
|
|
||||||
<img src={logoImage} width="70" alt="Logotipo" />
|
|
||||||
</Toolbar>
|
|
||||||
<List>
|
|
||||||
{options.map(option => (
|
|
||||||
<ListItem key={option.text} sx={listItem} disablePadding>
|
|
||||||
<NavLink to={option.pathname}>
|
|
||||||
<ListItemButton selected={option.isActive}>
|
|
||||||
<ListItemIcon sx={listItemIcon}>
|
|
||||||
{option.unselectedIcon}
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText primary={option.text} />
|
|
||||||
</ListItemButton>
|
|
||||||
</NavLink>
|
|
||||||
</ListItem>
|
|
||||||
))}
|
|
||||||
</List>
|
|
||||||
</Drawer>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const drawerWidth = 230;
|
|
||||||
const drawer = {
|
|
||||||
width: drawerWidth,
|
|
||||||
flexShrink: 0,
|
|
||||||
'& .MuiDrawer-paper': {
|
|
||||||
width: drawerWidth,
|
|
||||||
boxSizing: 'border-box',
|
|
||||||
backgroundColor: 'secondary.main',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const toolbar = {
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'center',
|
|
||||||
padding: '20px 0',
|
|
||||||
};
|
|
||||||
|
|
||||||
const listItem = {
|
|
||||||
'> a': {
|
|
||||||
width: drawerWidth,
|
|
||||||
textDecoration: 'none',
|
|
||||||
color: 'white',
|
|
||||||
height: 'inherit',
|
|
||||||
},
|
|
||||||
'.Mui-selected': {
|
|
||||||
backgroundColor: '#003708',
|
|
||||||
borderLeft: '4px solid #ffffff',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const listItemIcon = {
|
|
||||||
color: 'white',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MainDrawer;
|
|
113
src/components/MainMenu.js
Normal file
113
src/components/MainMenu.js
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
import {
|
||||||
|
BottomNavigation,
|
||||||
|
BottomNavigationAction,
|
||||||
|
Box,
|
||||||
|
Drawer,
|
||||||
|
List,
|
||||||
|
ListItem,
|
||||||
|
ListItemButton,
|
||||||
|
ListItemIcon,
|
||||||
|
ListItemText,
|
||||||
|
Toolbar,
|
||||||
|
} from '@mui/material';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { NavLink, useNavigate } from 'react-router-dom';
|
||||||
|
import logoImage from '../assets/if-salas-logo.svg';
|
||||||
|
|
||||||
|
function MainMenu({ options, layoutType }) {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [selectedOption, setSelectedOption] = useState(
|
||||||
|
options.find(option => option.isActive)
|
||||||
|
);
|
||||||
|
|
||||||
|
switch (layoutType) {
|
||||||
|
case 'desktop':
|
||||||
|
return (
|
||||||
|
<Drawer sx={drawer} variant="permanent" anchor="left">
|
||||||
|
<Toolbar disableGutters sx={toolbar}>
|
||||||
|
<img src={logoImage} width="70" alt="Logotipo" />
|
||||||
|
</Toolbar>
|
||||||
|
<List>
|
||||||
|
{options.map(option => (
|
||||||
|
<ListItem key={option.text} sx={listItem} disablePadding>
|
||||||
|
<NavLink to={option.pathname}>
|
||||||
|
<ListItemButton selected={option.isActive}>
|
||||||
|
<ListItemIcon sx={listItemIcon}>
|
||||||
|
{option.unselectedIcon}
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText primary={option.text} />
|
||||||
|
</ListItemButton>
|
||||||
|
</NavLink>
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</Drawer>
|
||||||
|
);
|
||||||
|
|
||||||
|
case 'mobile':
|
||||||
|
return (
|
||||||
|
<Box sx={{ width: '100%', position: 'fixed', bottom: 0 }}>
|
||||||
|
<BottomNavigation
|
||||||
|
onChange={(_, newValue) => {
|
||||||
|
const newOption = options.find(option => option.id === newValue);
|
||||||
|
setSelectedOption(newOption);
|
||||||
|
navigate(newOption.pathname, { replace: true });
|
||||||
|
}}
|
||||||
|
showLabels
|
||||||
|
value={selectedOption.id}
|
||||||
|
>
|
||||||
|
{options.map(option => (
|
||||||
|
<BottomNavigationAction
|
||||||
|
key={option.text}
|
||||||
|
label={option.text}
|
||||||
|
icon={
|
||||||
|
option.id === selectedOption.id
|
||||||
|
? option.selectedIcon
|
||||||
|
: option.unselectedIcon
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</BottomNavigation>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const drawerWidth = 230;
|
||||||
|
const drawer = {
|
||||||
|
width: drawerWidth,
|
||||||
|
flexShrink: 0,
|
||||||
|
'& .MuiDrawer-paper': {
|
||||||
|
width: drawerWidth,
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
backgroundColor: 'secondary.main',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const toolbar = {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
padding: '20px 0',
|
||||||
|
};
|
||||||
|
|
||||||
|
const listItem = {
|
||||||
|
'> a': {
|
||||||
|
width: drawerWidth,
|
||||||
|
textDecoration: 'none',
|
||||||
|
color: 'white',
|
||||||
|
height: 'inherit',
|
||||||
|
},
|
||||||
|
'.Mui-selected': {
|
||||||
|
backgroundColor: '#003708',
|
||||||
|
borderLeft: '4px solid #ffffff',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const listItemIcon = {
|
||||||
|
color: 'white',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MainMenu;
|
Loading…
Reference in a new issue