Commit 0f569607 authored by Djordje's avatar Djordje

Implement responsivness

parent 48357c0c
@media only screen and (min-width: 1921px) {
html {
font-size: 24px;
}
}
@media only screen and (max-width: 1920px) {
html {
font-size: 16px;
}
}
@media only screen and (max-width: 1370px) {
html {
font-size: 14px;
}
}
@media only screen and (max-width: 1200px) {
html {
font-size: 12px;
}
}
@media only screen and (max-width: 1020px) {
html {
font-size: 10px;
}
}
@media only screen and (max-width: 800px) {
html {
font-size: 14px;
}
}
\ No newline at end of file
...@@ -5,18 +5,30 @@ import { EntryPage } from './components/entry-page/EntryPage'; ...@@ -5,18 +5,30 @@ import { EntryPage } from './components/entry-page/EntryPage';
import { RegisterForm } from './components/register/RegisterForm'; import { RegisterForm } from './components/register/RegisterForm';
import { LoginForm } from './components/LoginForm'; import { LoginForm } from './components/LoginForm';
import { Application } from './components/Application'; import { Application } from './components/Application';
import { createTheme, ThemeProvider } from '@mui/material';
const theme = createTheme({
typography: {
body1: {
fontSize: '1em',
}
},
});
function App() { function App() {
return ( return (
<Router> <ThemeProvider theme={theme}>
<Routes> <Router>
<Route path='register/:buildingId' element={<EntryPage children={<RegisterForm />} />} /> <Routes>
<Route path='register/error' element={<EntryPage children={<div>Invalid invitational link - screen to be implemented</div>} />} /> <Route path='register/:buildingId' element={<EntryPage children={<RegisterForm />} />} />
<Route path='login' element={<EntryPage children={<LoginForm />} />} /> <Route path='register/error' element={<EntryPage children={<div>Invalid invitational link - screen to be implemented</div>} />} />
<Route path='tenant' element={<Application />} /> <Route path='login' element={<EntryPage children={<LoginForm />} />} />
<Route path='*' element={<Navigate replace to="login" />} /> <Route path='tenant' element={<Application />} />
</Routes> <Route path='*' element={<Navigate replace to="login" />} />
</Router> </Routes>
</Router>
</ThemeProvider>
); );
} }
......
...@@ -3,18 +3,18 @@ import { useEffect, useState } from "react" ...@@ -3,18 +3,18 @@ import { useEffect, useState } from "react"
import { useNavigate } from "react-router-dom" import { useNavigate } from "react-router-dom"
import { JWT_TENANT } from "../actions/network-manager" import { JWT_TENANT } from "../actions/network-manager"
import { ApplicationTab } from "./ApplicationTab"; import { ApplicationTab } from "./ApplicationTab";
import { NavBar } from "./NavBar"; import { NavBar } from "./NavBar/NavBar";
import { SideMenu } from "./SideMenu"; import { SideMenu } from "./SideMenu/SideMenu";
const classes = { const classes = {
mainWrapper: { mainWrapper: {
display: 'flex', display: 'flex',
flexDirection: 'row' flexDirection: 'row',
}, },
rightSideWrapper: { rightSideWrapper: {
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
width: '85%' flex: 1
} }
} as const; } as const;
...@@ -22,6 +22,11 @@ export const Application = () => { ...@@ -22,6 +22,11 @@ export const Application = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const [logedIn, setLogedIn] = useState(false); const [logedIn, setLogedIn] = useState(false);
const [sideMenuOpen, setSideMenuOpen] = useState(false);
const toggleSideMenu = (open: boolean) => {
setSideMenuOpen(open);
}
useEffect(() => { useEffect(() => {
if (!!localStorage.getItem(JWT_TENANT)) { if (!!localStorage.getItem(JWT_TENANT)) {
...@@ -36,10 +41,10 @@ export const Application = () => { ...@@ -36,10 +41,10 @@ export const Application = () => {
<> <>
{logedIn && {logedIn &&
<Box sx={classes.mainWrapper}> <Box sx={classes.mainWrapper}>
<SideMenu /> <SideMenu active={sideMenuOpen} toggleSideMenu={toggleSideMenu}/>
<Box sx={classes.rightSideWrapper}> <Box sx={classes.rightSideWrapper}>
<NavBar /> <NavBar toggleSideMenu={toggleSideMenu}/>
<ApplicationTab /> <ApplicationTab/>
</Box> </Box>
</Box> </Box>
} }
......
...@@ -3,7 +3,9 @@ import { Box } from "@mui/material" ...@@ -3,7 +3,9 @@ import { Box } from "@mui/material"
const classes = { const classes = {
wrapper: { wrapper: {
backgroundColor: 'rgb(241, 245, 249)', backgroundColor: 'rgb(241, 245, 249)',
minHeight: '95vh', width: '100%' minHeight: '95vh',
width: '100%',
flex: 1,
} }
} as const; } as const;
......
import { Box } from "@mui/material";
const classes = {
wrapper: {
height: '5vh',
backgroundColor: 'white',
boxSizing: 'border-box',
border: '2px solid rgb(213, 225, 239)',
position: 'sticky',
top: '0'
},
} as const;
export const NavBar = () => {
return (
<Box sx={classes.wrapper}></Box>
);
}
\ No newline at end of file
.navbar {
height: 5vh;
background-color: white;
box-sizing: border-box;
border: 2px solid rgb(213, 225, 239);
top: 0;
padding: 0.5vh;
}
@media only screen and (max-width: 800px) {
}
@media only screen and (min-width: 801px) {
.hamburger-menu {
display: none;
}
}
\ No newline at end of file
import { Box } from "@mui/material";
import { ActivityIcon } from "../icons/ActivityIcon";
import { HamburgerIcon } from "../icons/HamburgerIcon";
import './NavBar.css';
const classes = {
wrapper: {
height: '5vh',
backgroundColor: 'white',
boxSizing: 'border-box',
border: '2px solid rgb(213, 225, 239)',
top: '0'
},
} as const;
export const NavBar = ({toggleSideMenu} : {toggleSideMenu: (open: boolean) => void}) => {
return (
<div className="navbar">
<HamburgerIcon toggleSideMenu={toggleSideMenu}/>
</div>
);
}
\ No newline at end of file
.side-menu {
height: 100vh;
width: 100%;
position: fixed;
top: 0;
left: -100%;
transition: 860ms;
display: flex;
flex-direction: row;
}
.side-menu.active {
left: 0;
transition: 550ms;
}
.content {
background-color: rgba(19, 34, 50, 1);
width: 70%;
display: flex;
flex-direction: column;
box-sizing: border-box;
padding-inline: 5px;
padding-block: 15px;
gap: 30px;
}
.transparent {
height: 100%;
width: 30%;
}
@media only screen and (max-width: 800px) {
.icons-stroke {
width: 25px;
}
.user-icon {
width: 50px;
}
}
@media only screen and (min-width: 801px) {
.side-menu {
width: 15%;
position: sticky;
}
.transparent {
display: none;
}
.navbar {
display: none;
}
.content {
width: 100%;
height: 100%;
}
}
\ No newline at end of file
import { Box, Typography } from "@mui/material"; import { Box, Typography } from "@mui/material";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { getTenantInfo } from "../actions/data-manager"; import { getTenantInfo } from "../../actions/data-manager";
import { SubMenu } from "../internal-types"; import { LogoutIcon } from "../icons/LogoutIcon";
import { SideMenuItem } from "./SideMenuItem"; import { UserIcon } from "../icons/UserIcon";
import { ActivityIcon } from "./icons/ActivityIcon"; import { SideMenuItem } from "../SideMenuItem";
import { HomeIcon } from "./icons/HomeIcon"; import { subMenu } from "./SideMenuData";
import { NotificationIcon } from "./icons/NotificationIcon"; import "./SideMenu.css";
import { VotingIcon } from "./icons/VotingIcon";
import { InvoicesIcon } from "./icons/InvoicesIcon";
import { BuidlingInvoicesIcon } from "./icons/BuildingInvoicesIcon";
import { DocumentIcon } from "./icons/DocumentIcon";
import { SettingsIcon } from "./icons/SettingsIcon";
import { LanguageIcon } from "./icons/LanguageIcon";
import { LogoutIcon } from "./icons/LogoutIcon";
import { UserIcon } from "./icons/UserIcon";
const subMenu: SubMenu[] = [
{
title: 'Glavni meni',
items: [
{ title: 'Pregled', icon: <HomeIcon /> },
{ title: 'Obaveštenja', icon: <NotificationIcon /> },
{ title: 'Aktivnosti', icon: <ActivityIcon /> },
{ title: 'Glasanje', icon: <VotingIcon /> }
]
},
{
title: 'Računi/Finansije',
items: [
{ title: 'Moj Račun', icon: <InvoicesIcon /> },
{ title: 'Finansije zgrade', icon: <BuidlingInvoicesIcon /> },
{ title: 'Dokumenta', icon: <DocumentIcon /> }]
},
{
title: 'Aplikacija',
items: [
{ title: 'Podešavanja', icon: <SettingsIcon /> },
{ title: 'Language', icon: <LanguageIcon /> }]
}
];
const classes = { const classes = {
wrapper: {
width: '15%',
backgroundColor: 'rgba(19, 34, 50, 1)',
height: '100vh',
position: 'sticky',
top: '0px'
},
content: {
display: 'flex',
flexDirection: 'column',
paddingInline: '3%',
paddingBlock: '7.5%',
gap: '30px'
},
logo: { logo: {
width: '75%', width: '75%',
alignSelf: 'center' alignSelf: 'center'
...@@ -75,37 +26,36 @@ const classes = { ...@@ -75,37 +26,36 @@ const classes = {
boldText: { boldText: {
fontWeight: 'bolder', fontWeight: 'bolder',
}, },
signOut: { signOut: {
display: 'flex', display: 'flex',
flexDirection: 'row', flexDirection: 'row',
width: '100%', width: '100%',
justifyContent: 'center', justifyContent: 'center',
gap: '10px', gap: '10px',
alignItems: 'center' alignItems: 'center'
} }
} as const; } as const;
export const SideMenu = () => { export const SideMenu = ({ active, toggleSideMenu }: { active: boolean, toggleSideMenu: (open: boolean) => void }) => {
const [tenantInfo, setTenantInfo] = useState<any>(); const [tenantInfo, setTenantInfo] = useState<any>();
useEffect(() => { useEffect(() => {
getTenantInfo((err: any, data: any) => { getTenantInfo((err: any, data: any) => {
setTenantInfo(data); setTenantInfo(data);
}) });
}, []); }, []);
return ( return (
<> <>
{ {tenantInfo &&
tenantInfo && <div className={active ? 'side-menu active' : 'side-menu'}>
<Box sx={classes.wrapper}> <div className="content">
<Box sx={classes.content}>
{/* TODO Create component for logo as well. */} {/* TODO Create component for logo as well. */}
<img src={process.env.PUBLIC_URL + '/assets/logo-svg.svg'} alt='logo' style={classes.logo} /> <img src={process.env.PUBLIC_URL + '/assets/logo-svg.svg'} alt='logo' style={classes.logo} />
<Box sx={classes.accountInfo}> <Box sx={classes.accountInfo}>
<UserIcon /> <UserIcon />
<Typography variant="body1" sx={{ ...classes.menuText, ...classes.boldText }}>{tenantInfo.firstName}</Typography> <Typography sx={{ ...classes.menuText, ...classes.boldText }}>{tenantInfo.firstName}</Typography>
<Typography style={classes.menuText}>{tenantInfo.email}</Typography> <Typography style={classes.menuText}>{tenantInfo.email}</Typography>
<Box sx={classes.signOut}> <Box sx={classes.signOut}>
...@@ -116,8 +66,9 @@ export const SideMenu = () => { ...@@ -116,8 +66,9 @@ export const SideMenu = () => {
{subMenu.map((menu, index) => ( {subMenu.map((menu, index) => (
<SideMenuItem key={index} content={menu} /> <SideMenuItem key={index} content={menu} />
))} ))}
</Box> </div>
</Box> <div className="transparent" onClick={() => {toggleSideMenu(false)}}></div>
</div>
} }
</> </>
); );
......
import { SubMenu } from "../../internal-types";
import { ActivityIcon } from "../icons/ActivityIcon";
import { BuidlingInvoicesIcon } from "../icons/BuildingInvoicesIcon";
import { DocumentIcon } from "../icons/DocumentIcon";
import { HomeIcon } from "../icons/HomeIcon";
import { InvoicesIcon } from "../icons/InvoicesIcon";
import { LanguageIcon } from "../icons/LanguageIcon";
import { NotificationIcon } from "../icons/NotificationIcon";
import { SettingsIcon } from "../icons/SettingsIcon";
import { VotingIcon } from "../icons/VotingIcon";
export const subMenu: SubMenu[] = [
{
title: 'Glavni meni',
items: [
{ title: 'Pregled', icon: <HomeIcon /> },
{ title: 'Obaveštenja', icon: <NotificationIcon /> },
{ title: 'Aktivnosti', icon: <ActivityIcon /> },
{ title: 'Glasanje', icon: <VotingIcon /> }
]
},
{
title: 'Računi/Finansije',
items: [
{ title: 'Moj Račun', icon: <InvoicesIcon /> },
{ title: 'Finansije zgrade', icon: <BuidlingInvoicesIcon /> },
{ title: 'Dokumenta', icon: <DocumentIcon /> }]
},
{
title: 'Aplikacija',
items: [
{ title: 'Podešavanja', icon: <SettingsIcon /> },
{ title: 'English', icon: <LanguageIcon /> }]
}
];
\ No newline at end of file
...@@ -6,17 +6,22 @@ const classes = { ...@@ -6,17 +6,22 @@ const classes = {
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
color: 'white', color: 'white',
paddingInline: '10%',
gap: '10px' gap: '10px'
}, },
itemTitle: { itemTitle: {
color: 'rgb(24, 95, 167)' color: 'rgb(24, 95, 167)',
paddingInline: '10%',
}, },
itemsWrapper: { itemsWrapper: {
display: 'flex', display: 'flex',
flexDirection: 'row', flexDirection: 'row',
gap: '10%', gap: '15px',
alignItems: 'center' alignItems: 'center',
paddingInline: '10%',
// boxSizing: 'border-box',
// backgroundColor: 'red',
borderRadius: '5px'
} }
} as const; } as const;
......
import './Icons.css';
export const HamburgerIcon = ({toggleSideMenu}: {toggleSideMenu: (open: boolean) => void}) => {
return (
<svg xmlns="http://www.w3.org/2000/svg" className='hamburger-menu' fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2} width={'25px'} onClick={() => {toggleSideMenu(true)}}>
<path strokeLinecap="round" strokeLinejoin="round" d="M4 6h16M4 12h16M4 18h16" />
</svg>
);
}
...@@ -5,4 +5,12 @@ ...@@ -5,4 +5,12 @@
.logout:hover { .logout:hover {
stroke: white; stroke: white;
}
.hamburger-menu {
stroke: rgba(19, 34, 50, 1);
}
.user-icon {
width: 25%;
} }
\ No newline at end of file
...@@ -2,7 +2,7 @@ import './Icons.css'; ...@@ -2,7 +2,7 @@ import './Icons.css';
export const UserIcon = () => { export const UserIcon = () => {
return ( return (
<svg xmlns="http://www.w3.org/2000/svg" className="icons-stroke" viewBox="0 0 20 20" fill="rgb(86, 107, 130)" style={{width: '30%'}}> <svg xmlns="http://www.w3.org/2000/svg" className="icons-stroke user-icon" viewBox="0 0 20 20" fill="rgb(86, 107, 130)">
<path fillRule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-6-3a2 2 0 11-4 0 2 2 0 014 0zm-2 4a5 5 0 00-4.546 2.916A5.986 5.986 0 0010 16a5.986 5.986 0 004.546-2.084A5 5 0 0010 11z" clipRule="evenodd" /> <path fillRule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-6-3a2 2 0 11-4 0 2 2 0 014 0zm-2 4a5 5 0 00-4.546 2.916A5.986 5.986 0 0010 16a5.986 5.986 0 004.546-2.084A5 5 0 0010 11z" clipRule="evenodd" />
</svg> </svg>
); );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment