Commit 7aa1175a authored by Djordje's avatar Djordje

Add logout and autofocus on forms

parent 3311ef45
...@@ -4,16 +4,15 @@ import { BrowserRouter as Router, Navigate, Route, Routes } from 'react-router-d ...@@ -4,16 +4,15 @@ import { BrowserRouter as Router, Navigate, Route, Routes } from 'react-router-d
import { EntryPage } from './components/entry-page/EntryPage'; 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 { Form } from './components/Form';
import { Application } from './components/Application'; import { Application } from './components/Application';
function App() { function App() {
return ( return (
<Router> <Router>
<Routes> <Routes>
<Route path='register/:buildingId' element={<EntryPage children={<Form children={<RegisterForm />} title="Create Account" />} />} /> <Route path='register/:buildingId' element={<EntryPage children={<RegisterForm />} />} />
<Route path='register/error' element={<EntryPage children={<div>Invalid invitational link - screen to be implemented</div>} />} /> <Route path='register/error' element={<EntryPage children={<div>Invalid invitational link - screen to be implemented</div>} />} />
<Route path='login' element={<EntryPage children={<Form children={<LoginForm />} title="Login" />} />} /> <Route path='login' element={<EntryPage children={<LoginForm />} />} />
<Route path='tenant' element={<Application />} /> <Route path='tenant' element={<Application />} />
<Route path='*' element={<Navigate replace to="login" />} /> <Route path='*' element={<Navigate replace to="login" />} />
</Routes> </Routes>
......
import { Box } from "@mui/material"; import { Box } from "@mui/material";
import { useEffect } from "react" 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";
...@@ -21,20 +21,28 @@ const classes = { ...@@ -21,20 +21,28 @@ const classes = {
export const Application = () => { export const Application = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const [logedIn, setLogedIn] = useState(false);
useEffect(() => { useEffect(() => {
if (!localStorage.getItem(JWT_TENANT)) { if (!!localStorage.getItem(JWT_TENANT)) {
navigate('../login'); setLogedIn(true);
return;
} }
navigate('../login');
}, [navigate]) }, [navigate])
return ( return (
<Box sx={classes.mainWrapper}> <>
<SideMenu /> {logedIn &&
<Box sx={classes.rightSideWrapper}> <Box sx={classes.mainWrapper}>
<NavBar /> <SideMenu />
<ApplicationTab /> <Box sx={classes.rightSideWrapper}>
</Box> <NavBar />
</Box> <ApplicationTab />
</Box>
</Box>
}
</>
) )
} }
\ No newline at end of file
import { Box, Typography } from "@mui/material";
import { ReactNode } from "react";
const classes = {
wrapper: {
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
gap: '20px'
},
title: {
fontFamily: 'Inter',
fontWeight: 'bold',
}
} as const;
export const Form = ({ children, title }: { children?: ReactNode, title: string }) => {
return (
<Box style={classes.wrapper}>
<Typography sx={classes.title} variant='h4'>{title}</Typography>
{children}
</Box>
);
}
\ No newline at end of file
import { Button, TextField } from "@mui/material" import { Box, Button, TextField, Typography } from "@mui/material"
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { LoginInfo } from "../internal-types"; import { LoginInfo } from "../internal-types";
import { postLogin } from "../actions/data-manager"; import { postLogin } from "../actions/data-manager";
...@@ -6,6 +6,17 @@ import { JWT_TENANT } from "../actions/network-manager"; ...@@ -6,6 +6,17 @@ import { JWT_TENANT } from "../actions/network-manager";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
const classes = { const classes = {
wrapper: {
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
gap: '20px'
},
title: {
fontFamily: 'Inter',
fontWeight: 'bold',
},
textField: { textField: {
'& label.Mui-focused': { '& label.Mui-focused': {
color: 'rgb(30, 41, 60)' color: 'rgb(30, 41, 60)'
...@@ -81,9 +92,17 @@ export const LoginForm = () => { ...@@ -81,9 +92,17 @@ export const LoginForm = () => {
navigate('../tenant'); navigate('../tenant');
} }
const handleKeyUp = (event: React.KeyboardEvent<HTMLDivElement>): void => {
if (event.key === 'Enter') {
postLogin(loginInfo.username, loginInfo.password, false, loginCallback);
}
}
return ( return (
<> <Box style={classes.wrapper} onKeyUp={handleKeyUp}>
<Typography sx={classes.title} variant='h4'>Login</Typography>
<TextField <TextField
autoFocus
variant="outlined" variant="outlined"
size='small' size='small'
label="Username" label="Username"
...@@ -116,5 +135,5 @@ export const LoginForm = () => { ...@@ -116,5 +135,5 @@ export const LoginForm = () => {
loginCallback) loginCallback)
}} }}
>Login</Button> >Login</Button>
</>) </Box>)
} }
\ No newline at end of file
.icons-stroke { .icons-stroke {
width: 12%; width: 12%;
stroke: rgb(86, 107, 130); stroke: rgb(86, 107, 130);
}
.logout:hover {
stroke: white;
} }
\ No newline at end of file
import { useNavigate } from 'react-router-dom';
import { JWT_TENANT } from '../../actions/network-manager';
import './Icons.css'; import './Icons.css';
export const LogoutIcon = () => { export const LogoutIcon = () => {
const navigate = useNavigate();
const logout = () => {
localStorage.removeItem(JWT_TENANT);
navigate('../login');
}
return ( return (
<svg xmlns="http://www.w3.org/2000/svg" className="icons-stroke" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}> <svg xmlns="http://www.w3.org/2000/svg" className="icons-stroke logout" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2} onClick={logout}>
<path strokeLinecap="round" strokeLinejoin="round" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" /> <path strokeLinecap="round" strokeLinejoin="round" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
</svg> </svg>
); );
......
import { TextField, Box, Button, Select, FormControl, InputLabel, MenuItem } from "@mui/material"; import { TextField, Box, Button, Select, FormControl, InputLabel, MenuItem, Typography } from "@mui/material";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { getPreRegisterData, registerUser } from "../../actions/data-manager"; import { getPreRegisterData, registerUser } from "../../actions/data-manager";
import { RegistrationInfo } from "../../internal-types"; import { RegistrationInfo } from "../../internal-types";
const classes = { const classes = {
wrapper: {
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
gap: '20px'
},
title: {
fontFamily: 'Inter',
fontWeight: 'bold',
},
nameWrapper: {
display: 'flex',
gap: '20px'
},
textField: { textField: {
flex: 1,
'& label.Mui-focused': { '& label.Mui-focused': {
color: 'rgb(30, 41, 60)' color: 'rgb(30, 41, 60)'
}, },
...@@ -59,6 +73,8 @@ const classes = { ...@@ -59,6 +73,8 @@ const classes = {
export const RegisterForm = (): JSX.Element => { export const RegisterForm = (): JSX.Element => {
// TODO Add proper frontend validation
let navigate = useNavigate(); let navigate = useNavigate();
let { buildingId } = useParams(); let { buildingId } = useParams();
...@@ -92,30 +108,38 @@ export const RegisterForm = (): JSX.Element => { ...@@ -92,30 +108,38 @@ export const RegisterForm = (): JSX.Element => {
}); });
}, [buildingId, navigate]); }, [buildingId, navigate]);
const handleKeyUp = (event: React.KeyboardEvent<HTMLDivElement>): void => {
if (event.key === 'Enter') {
registerUser(buildingId, registerInfo, registerCallBack);
}
}
return ( return (
<> <>
{buildingUnits && {buildingUnits &&
<Box sx={{ display: 'flex', flexDirection: 'column', gap: '20px' }}> <Box style={classes.wrapper} onKeyUp={handleKeyUp}>
<Box sx={{ display: 'flex', gap: '20px' }}> <Typography sx={classes.title} variant='h4'>Create Account</Typography>
<Box sx={classes.nameWrapper}>
<TextField <TextField
hiddenLabel hiddenLabel
variant="outlined" variant="outlined"
size='small' size='small'
label="First name" label="First name"
sx={classes.textField} sx={{...classes.textField, flex: 1}}
value={registerInfo.firstName} value={registerInfo.firstName}
onChange={(e) => { onChange={(e) => {
setRegisterInfo({ ...registerInfo, firstName: e.target.value }) setRegisterInfo({ ...registerInfo, firstName: e.target.value })
}} }}
error={"firstName" === errorField} error={"firstName" === errorField}
helperText={"firstName" === errorField ? errorMessage : null} helperText={"firstName" === errorField ? errorMessage : null}
autoFocus
/> />
<TextField <TextField
hiddenLabel hiddenLabel
variant="outlined" variant="outlined"
size='small' size='small'
label="Last name" label="Last name"
sx={classes.textField} sx={{...classes.textField, flex: 1}}
value={registerInfo.lastName} value={registerInfo.lastName}
onChange={(e) => { onChange={(e) => {
setRegisterInfo({ ...registerInfo, lastName: e.target.value }) setRegisterInfo({ ...registerInfo, lastName: e.target.value })
...@@ -173,7 +197,7 @@ export const RegisterForm = (): JSX.Element => { ...@@ -173,7 +197,7 @@ export const RegisterForm = (): JSX.Element => {
error={"mobile" === errorField} error={"mobile" === errorField}
helperText={"mobile" === errorField ? errorMessage : null} helperText={"mobile" === errorField ? errorMessage : null}
/> />
<FormControl fullWidth size="small"> <FormControl fullWidth size="small" onKeyUp={(e) => {e.stopPropagation();}}>
<InputLabel>Select your units</InputLabel> <InputLabel>Select your units</InputLabel>
<Select <Select
label="Select your units" label="Select your units"
......
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