chore: Make the main container dynamic based on the with of the menudrawer
This commit is contained in:
		
							
								
								
									
										93
									
								
								src/App.jsx
									
									
									
									
									
								
							
							
						
						
									
										93
									
								
								src/App.jsx
									
									
									
									
									
								
							| @@ -1,65 +1,84 @@ | |||||||
| import { useState } from 'react' | import { useState } from 'react'; | ||||||
| import './App.css' | import { Box, useMediaQuery } from '@mui/material'; | ||||||
|  | import { useTheme } from '@mui/material/styles'; | ||||||
| import AppHeader from './components/AppHeader'; | import AppHeader from './components/AppHeader'; | ||||||
|  | import MenuDrawerPrivate, { OPEN_WIDTH, MINI_WIDTH } from './components/MenuDrawerPrivate'; | ||||||
| import Footer from './components/Footer'; | import Footer from './components/Footer'; | ||||||
| import Box from '@mui/material/Box'; |  | ||||||
|  |  | ||||||
| import Clients from './private/clients/Clients'; |  | ||||||
| import Dashboard from './private/dashboard/Dashboard'; | import Dashboard from './private/dashboard/Dashboard'; | ||||||
| import UserManagement from './private/users/UserManagement'; | import UserManagement from './private/users/UserManagement'; | ||||||
|  |  | ||||||
| import LoginPage from './private/LoginPage'; | import LoginPage from './private/LoginPage'; | ||||||
| import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'; | import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'; | ||||||
|  |  | ||||||
| import { useAuth } from './context/AuthContext'; | import { useAuth } from './context/AuthContext'; | ||||||
|  |  | ||||||
|  | const DRAWER_EXPANDED = OPEN_WIDTH; | ||||||
|  | const DRAWER_COLLAPSED = MINI_WIDTH; | ||||||
|  | const APPBAR_HEIGHT = 64; | ||||||
|  |  | ||||||
| function PrivateRoute({ children }) { | function PrivateRoute({ children }) { | ||||||
|   const { user } = useAuth(); |   const { user } = useAuth(); | ||||||
|   return user ? children : <Navigate to="/login" replace />; |   return user ? children : <Navigate to="/login" replace />; | ||||||
| } | } | ||||||
|  |  | ||||||
| function App() { | export default function App() { | ||||||
|  |   const theme = useTheme(); | ||||||
|  |   const isMobile = useMediaQuery('(max-width:900px)'); | ||||||
|   const [zone, setZone] = useState('public'); // public | restricted | private |   const [zone, setZone] = useState('public'); // public | restricted | private | ||||||
|  |  | ||||||
|  |   const [drawerExpanded, setDrawerExpanded] = useState(true); | ||||||
|   const [currentView, setCurrentView] = useState('Dashboard'); |   const [currentView, setCurrentView] = useState('Dashboard'); | ||||||
|  |  | ||||||
|  |   const mainLeft = isMobile ? 0 : (drawerExpanded ? DRAWER_EXPANDED : DRAWER_COLLAPSED); | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <> |     <> | ||||||
|  |       <AppHeader | ||||||
|  |         zone="private" | ||||||
|  |         onSelectMenuItem={setCurrentView} | ||||||
|  |         drawerExpanded={drawerExpanded} | ||||||
|  |       /> | ||||||
|  |  | ||||||
|  |       <MenuDrawerPrivate | ||||||
|  |         onSelect={(value) => { | ||||||
|  |           setCurrentView(value === '/users/UserManagement' ? 'UserManagement' : value); | ||||||
|  |         }} | ||||||
|  |         onExpandedChange={(expanded) => setDrawerExpanded(expanded)} | ||||||
|  |       /> | ||||||
|  |  | ||||||
|       <Box |       <Box | ||||||
|  |         component="main" | ||||||
|         sx={{ |         sx={{ | ||||||
|           display: 'flex', |           ml: { xs: 0, md: `${mainLeft}px` }, | ||||||
|           flexDirection: 'column', |           mt: `${APPBAR_HEIGHT}px`, | ||||||
|           minHeight: '100vh', // full height of the viewport |           p: 2, | ||||||
|  |           transition: theme.transitions.create('margin-left', { | ||||||
|  |             duration: theme.transitions.duration.standard, | ||||||
|  |             easing: theme.transitions.easing.sharp, | ||||||
|  |           }), | ||||||
|         }} |         }} | ||||||
|       > |       > | ||||||
|  |         <Routes> | ||||||
|  |           <Route path="/login" element={<LoginPage />} /> | ||||||
|  |  | ||||||
|         <AppHeader zone={zone} onSelectMenuItem={(view) => setCurrentView(view)} /> |           <Route | ||||||
|         <Box sx={{ height: 64 }} /> |             path="/" | ||||||
|  |             element={ | ||||||
|  |               <PrivateRoute> | ||||||
|  |                 {zone === 'private' && <Clients />} | ||||||
|  |                 {zone === 'restricted' && <Clients />} | ||||||
|  |  | ||||||
|         <Box component="main" sx={{ flex: 1, p: 2 }}> |                 {zone === 'public' && currentView === 'Dashboard' && <Dashboard />} | ||||||
|           <Routes> |  | ||||||
|             <Route path="/login" element={<LoginPage />} /> |  | ||||||
|  |  | ||||||
|             <Route |                 {zone === 'public' && currentView === 'UserManagement' && <UserManagement />} | ||||||
|               path="/" |               </PrivateRoute> | ||||||
|               element={ |             } | ||||||
|                 <PrivateRoute> |           /> | ||||||
|                   {zone === 'private' && <Clients />} |         </Routes> | ||||||
|                   {zone === 'restricted' && <Clients />} |  | ||||||
|  |  | ||||||
|                   {zone === 'public' && currentView === 'Dashboard' && <Dashboard />} |  | ||||||
|  |  | ||||||
|                  {zone === 'public' && currentView === 'UserManagement' && <UserManagement />} |  | ||||||
|                 </PrivateRoute> |  | ||||||
|               } |  | ||||||
|             /> |  | ||||||
|           </Routes> |  | ||||||
|         </Box> |  | ||||||
|  |  | ||||||
|         <Box sx={{ height: 64 }} /> |  | ||||||
|         <Footer zone={zone} /> |  | ||||||
|       </Box> |       </Box> | ||||||
|  |  | ||||||
|     </> |       <Box sx={{ height: 64 }} /> | ||||||
|   ) |       <Footer zone={zone} /> | ||||||
| } |  | ||||||
|  |  | ||||||
| export default App |     </> | ||||||
|  |   ); | ||||||
|  | } | ||||||
| @@ -1,64 +1,45 @@ | |||||||
| import { useState } from 'react'; |  | ||||||
| import { AppBar, Toolbar, Typography, IconButton, Box, Avatar } from '@mui/material'; |  | ||||||
|  |  | ||||||
| import MenuDrawer from './MenuDrawer'; |  | ||||||
| import MenuDrawerPrivate from './MenuDrawerPrivate'; |  | ||||||
| import { useAuth } from '../context/AuthContext'; | import { useAuth } from '../context/AuthContext'; | ||||||
| import { useNavigate } from 'react-router-dom'; | import { AppBar, Toolbar, Typography, IconButton, Box, Avatar, useMediaQuery } from '@mui/material'; | ||||||
|  | import { useTheme } from '@mui/material/styles'; | ||||||
|  | import { OPEN_WIDTH, MINI_WIDTH } from './MenuDrawerPrivate'; | ||||||
|  |  | ||||||
| export default function AppHeader({ zone = 'public', onSelectMenuItem }) { |  | ||||||
|  |  | ||||||
|   const bgColor = { | export default function AppHeader({ drawerExpanded = true, currentPage = 'Dashboard' }) { | ||||||
|     public: 'white', |   const theme = useTheme(); | ||||||
|     restricted: 'white', |   const isMobile = useMediaQuery('(max-width:900px)'); | ||||||
|     private: 'white', |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   const [drawerExpanded, setDrawerExpanded] = useState(true); |  | ||||||
|   const [currentPage, setCurrentPage] = useState('Dashboard'); |  | ||||||
|   const { user } = useAuth(); |   const { user } = useAuth(); | ||||||
|  |  | ||||||
|   const isPrivate = zone === 'private'; |  | ||||||
|   const isRestricted = zone === 'restricted'; |  | ||||||
|   const isPublic = zone === 'public'; |  | ||||||
|  |  | ||||||
|   const navigate = useNavigate(); |   const leftOffset = isMobile ? 0 : (drawerExpanded ? OPEN_WIDTH : MINI_WIDTH); | ||||||
|  |  | ||||||
|   const handleMenuSelect = (page) => { |  | ||||||
|     setCurrentPage(page); |  | ||||||
|     onSelectMenuItem?.(page); |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <AppBar position="fixed" |     <AppBar | ||||||
|  |       position="fixed" | ||||||
|       sx={{ |       sx={{ | ||||||
|         textAlign: 'center', |         background: 'white', | ||||||
|         backgroundColor: bgColor[zone], |         color: '#40120E', | ||||||
|         fontSize: { xs: '0.75rem', md: '1rem' }, |  | ||||||
|         boxShadow: '0px 2px 4px rgba(0,0,0,0.1)', |         boxShadow: '0px 2px 4px rgba(0,0,0,0.1)', | ||||||
|         border: 'none', |       }} | ||||||
|         width: '100%', |     > | ||||||
|         left: 0, |       <Toolbar sx={{ minHeight: 64 }}> | ||||||
|         right: 0, |  | ||||||
|       }} > |  | ||||||
|       <Toolbar disableGutters sx={{ justifyContent: 'flex-start', alignItems: 'center', flexWrap: 'nowrap', pl: 0, pr: 0, minHeight: 64, width: '100%', '&.MuiToolbar-gutters': { pl: 0, pr: 0 }, position: 'relative', }}> |  | ||||||
|         <Box |         <Box | ||||||
|           sx={{ |           sx={{ | ||||||
|  |             ml: `${leftOffset}px`, | ||||||
|  |             transition: theme.transitions.create('margin-left', { | ||||||
|  |               duration: theme.transitions.duration.standard, | ||||||
|  |               easing: theme.transitions.easing.sharp, | ||||||
|  |             }), | ||||||
|             display: 'flex', |             display: 'flex', | ||||||
|             alignItems: 'center', |             alignItems: 'center', | ||||||
|             ml: `${drawerExpanded ? '300px' : '72px'}`, |             flexGrow: 1, | ||||||
|           }} |           }} | ||||||
|         > |         > | ||||||
|           <Typography |           <Typography variant="h6" sx={{ fontWeight: 600 }}> | ||||||
|             variant="h6" |  | ||||||
|             noWrap |  | ||||||
|             sx={{ color: '#40120EFF', fontWeight: 'light', fontSize: '30px' }} |  | ||||||
|           > |  | ||||||
|             {currentPage} |             {currentPage} | ||||||
|           </Typography> |           </Typography> | ||||||
|         </Box> |         </Box> | ||||||
|  |  | ||||||
|         <Box |                 <Box | ||||||
|           sx={{ |           sx={{ | ||||||
|             position: 'absolute', |             position: 'absolute', | ||||||
|             right: 20, |             right: 20, | ||||||
| @@ -87,12 +68,6 @@ export default function AppHeader({ zone = 'public', onSelectMenuItem }) { | |||||||
|           )} |           )} | ||||||
|         </Box> |         </Box> | ||||||
|  |  | ||||||
|         <MenuDrawerPrivate |  | ||||||
|           zone="private" |  | ||||||
|           onSelect={handleMenuSelect} |  | ||||||
|           onExpandedChange={(expanded) => setDrawerExpanded(expanded)} |  | ||||||
|         /> |  | ||||||
|  |  | ||||||
|       </Toolbar> |       </Toolbar> | ||||||
|     </AppBar> |     </AppBar> | ||||||
|   ); |   ); | ||||||
|   | |||||||
| @@ -14,8 +14,8 @@ import SettingsIcon from '@mui/icons-material/Settings'; | |||||||
| import ExpandLess from '@mui/icons-material/ExpandLess'; | import ExpandLess from '@mui/icons-material/ExpandLess'; | ||||||
| import ExpandMore from '@mui/icons-material/ExpandMore'; | import ExpandMore from '@mui/icons-material/ExpandMore'; | ||||||
|  |  | ||||||
| const OPEN_WIDTH = 400; | export const OPEN_WIDTH = 450; | ||||||
| const MINI_WIDTH = 72; | export const MINI_WIDTH = 72; | ||||||
|  |  | ||||||
| const menuData = [ | const menuData = [ | ||||||
|     { |     { | ||||||
| @@ -37,13 +37,15 @@ const menuData = [ | |||||||
|                     { |                     { | ||||||
|                         title: 'Category Dictionary', |                         title: 'Category Dictionary', | ||||||
|                         children: [ |                         children: [ | ||||||
|                             { title: 'Categories' }, |                             { title: 'Categories' } | ||||||
|                             { title: 'Products' }, |  | ||||||
|                             { title: 'All Assets Library' }, |  | ||||||
|                             { title: 'Media Management' }, |  | ||||||
|                             { title: 'Product Collections' }, |  | ||||||
|                         ] |                         ] | ||||||
|                     } |                     }, | ||||||
|  |                     { title: 'Products', | ||||||
|  |                     children: [ | ||||||
|  |                         { title: 'AR  Assets Library Management' }, | ||||||
|  |                         { title: 'Media Management' }, | ||||||
|  |                     ] }, | ||||||
|  |                     { title: 'Product Collections' }, | ||||||
|                 ] |                 ] | ||||||
|             } |             } | ||||||
|         ] |         ] | ||||||
| @@ -52,13 +54,17 @@ const menuData = [ | |||||||
|         title: 'Customers', |         title: 'Customers', | ||||||
|         icon: <PeopleAltIcon />, |         icon: <PeopleAltIcon />, | ||||||
|         children: [ |         children: [ | ||||||
|             { title: 'CRM' }, |             { title: 'CRM', | ||||||
|             { title: 'Customer List' }, |  | ||||||
|             { |  | ||||||
|                 title: 'Projects', |  | ||||||
|                 children: [ |                 children: [ | ||||||
|  |                      { title: 'Customer List' }, | ||||||
|  |                       { title: 'Projects' }, | ||||||
|                     { title: 'Customer Collections' }, |                     { title: 'Customer Collections' }, | ||||||
|                     { title: 'Sales' }, |                 ] | ||||||
|  |              }, | ||||||
|  |             | ||||||
|  |             { | ||||||
|  |                 title: 'Sales', | ||||||
|  |                 children: [ | ||||||
|                     { title: 'Quotes' }, |                     { title: 'Quotes' }, | ||||||
|                     { title: 'Orders' }, |                     { title: 'Orders' }, | ||||||
|                 ] |                 ] | ||||||
| @@ -80,9 +86,12 @@ const menuData = [ | |||||||
|         icon: <AdminPanelSettingsIcon />, |         icon: <AdminPanelSettingsIcon />, | ||||||
|         children: [ |         children: [ | ||||||
|             { title: 'Users Management' }, |             { title: 'Users Management' }, | ||||||
|             { title: 'Access Control' }, |             { title: 'Access Control', | ||||||
|             { title: 'Roles' }, |                 children: [ | ||||||
|             { title: 'Permissions' }, |                     { title: 'Roles' }, | ||||||
|  |                     { title: 'Permissions' }, | ||||||
|  |                 ] | ||||||
|  |              }, | ||||||
|         ] |         ] | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ export default function LoginPage() { | |||||||
|     const navigate = useNavigate(); |     const navigate = useNavigate(); | ||||||
|  |  | ||||||
|     return ( |     return ( | ||||||
|         <Box display="flex" justifyContent="center" alignItems="center" Height="100vh"> |         <Box display="flex" justifyContent="center" alignItems="center" height="100vh"> | ||||||
|             <Paper sx={{ p: 4, borderRadius: 2, boxShadow: 3, textAlign: 'center' }}> |             <Paper sx={{ p: 4, borderRadius: 2, boxShadow: 3, textAlign: 'center' }}> | ||||||
|                 <Typography variant="h5" mb={2}>Login to Dream Views</Typography> |                 <Typography variant="h5" mb={2}>Login to Dream Views</Typography> | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Rodolfo Ruiz
					Rodolfo Ruiz