Add initial desktop register screen

This commit is contained in:
Leonardo Murça 2022-09-05 22:03:53 -03:00
parent 7ef0b98c8e
commit 5085c05623
6 changed files with 354 additions and 3 deletions

View file

@ -2,6 +2,7 @@ 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';
import Register from '../screens/Register';
import UnauthenticatedHome from '../screens/UnauthenticatedHome'; import UnauthenticatedHome from '../screens/UnauthenticatedHome';
function UnauthenticatedApp() { function UnauthenticatedApp() {
@ -10,6 +11,7 @@ function UnauthenticatedApp() {
<Routes> <Routes>
<Route path="/" element={<UnauthenticatedHome />} /> <Route path="/" element={<UnauthenticatedHome />} />
<Route path="/login" element={<Login />} /> <Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
<Route path="*" element={<Navigate to="/" />} /> <Route path="*" element={<Navigate to="/" />} />
</Routes> </Routes>
</Container> </Container>

View file

@ -1,5 +1,5 @@
import { createContext, useContext, useEffect, useState } from 'react'; import { createContext, useContext, useEffect, useState } from 'react';
import { getUser } from '../services/user-service'; import { getUser, registerUser } from '../services/user-service';
const AuthContext = createContext(); const AuthContext = createContext();
@ -20,6 +20,20 @@ function AuthProvider(props) {
bootstrapUser(); bootstrapUser();
}, []); }, []);
const register = data => {
setState({ ...state, status: 'pending' });
let shouldFail =
data.email !== 'leo@gmail.com' && data.password !== '#leo1234';
return registerUser(data, shouldFail).then(data => {
if (shouldFail) {
return setState({ status: 'error', user: null, error: data });
} else {
return setState({ status: 'success', user: data, error: null });
}
});
};
const login = (email, password) => { const login = (email, password) => {
setState({ ...state, status: 'pending' }); setState({ ...state, status: 'pending' });
let shouldFail = email !== 'leo@gmail.com' && password !== '#leo1234'; let shouldFail = email !== 'leo@gmail.com' && password !== '#leo1234';
@ -38,11 +52,16 @@ function AuthProvider(props) {
window.localStorage.clear(); window.localStorage.clear();
}; };
return <AuthContext.Provider value={{ state, login, logout }} {...props} />; return (
<AuthContext.Provider
value={{ state, register, login, logout }}
{...props}
/>
);
} }
function useAuthState() { function useAuthState() {
const { state, login, logout } = useContext(AuthContext); const { state, register, login, logout } = useContext(AuthContext);
const isPending = state.status === 'pending'; const isPending = state.status === 'pending';
const isError = state.status === 'error'; const isError = state.status === 'error';
const isSuccess = state.status === 'success'; const isSuccess = state.status === 'success';
@ -55,6 +74,7 @@ function useAuthState() {
isError, isError,
isSuccess, isSuccess,
isAuthenticated, isAuthenticated,
register,
login, login,
logout, logout,
}; };

View file

@ -0,0 +1,179 @@
import { Fragment } from 'react';
import {
Box,
Button,
Container,
FormControl,
InputLabel,
Link,
MenuItem,
Paper,
Select,
Stack,
TextField,
} from '@mui/material';
import SnackbarIndicator from '../../components/SnackbarIndicator';
import LoadingIndicator from '../../components/LoadingIndicator';
import logoImage from '../../assets/if-salas-logo.svg';
import styles from './styles';
import dayjs from 'dayjs';
function View({
isPending,
isError,
error,
layoutType,
data,
onChangeInput,
onTryRegister,
}) {
const { paper, boxLogo, boxForm, logoContainer } = styles[layoutType];
const currentYear = dayjs().year();
console.log(currentYear);
return (
<Fragment>
<Paper sx={paper} elevation={4} variant="elevation">
<Box sx={boxForm}>
<h1>Criar conta</h1>
<p>Crie sua conta digitando os dados abaixo.</p>
<Stack spacing={4} component="form">
<TextField
id="firstName"
name="firstName"
label="Primeiro nome"
variant="standard"
type="text"
value={data.firstName}
onChange={onChangeInput}
autoFocus
/>
<TextField
id="lastName"
name="lastName"
label="Sobrenome"
variant="standard"
type="text"
value={data.lastName}
onChange={onChangeInput}
/>
<TextField
id="ra"
name="ra"
label="RA (Registro Acadêmico)"
variant="standard"
type="text"
value={data.ra}
onChange={onChangeInput}
/>
<FormControl sx={{ textAlign: 'start' }} fullWidth>
<InputLabel variant="standard" id="course">
Curso
</InputLabel>
<Select
variant="standard"
labelId="course"
id="course"
name="course"
value={data.course}
label="Curso"
onChange={onChangeInput}
>
<MenuItem value={0}>
Bacharelado em Sistemas de Informação
</MenuItem>
<MenuItem value={1}>
Tecnologia em Processos Gerenciais
</MenuItem>
<MenuItem value={2}>Tecnologia em Logística</MenuItem>
<MenuItem value={3}>
Engenharia de Controle e Automação
</MenuItem>
<MenuItem value={4}>Bacharelado em Administração</MenuItem>
</Select>
</FormControl>
<FormControl sx={{ textAlign: 'start' }} fullWidth>
<InputLabel variant="standard" id="course">
Ano da turma
</InputLabel>
<Select
variant="standard"
labelId="year"
id="year"
name="year"
value={data.year}
label="Ano da turma"
onChange={onChangeInput}
>
<MenuItem value={0}>{currentYear}</MenuItem>
<MenuItem value={1}>{currentYear - 1}</MenuItem>
<MenuItem value={2}>{currentYear - 2}</MenuItem>
<MenuItem value={3}>{currentYear - 3}</MenuItem>
<MenuItem value={4}>{currentYear - 4}</MenuItem>
<MenuItem value={5}>{currentYear - 5}</MenuItem>
</Select>
</FormControl>
{/* TODO: Add field mask */}
<TextField
id="phone"
name="phone"
label="Telefone"
variant="standard"
type="phone"
value={data.phone}
onChange={onChangeInput}
/>
<TextField
id="email"
name="email"
label="E-mail"
variant="standard"
type="email"
value={data.email}
onChange={onChangeInput}
/>
<TextField
id="password"
name="password"
label="Senha"
variant="standard"
type="password"
value={data.password}
onChange={onChangeInput}
/>
<Button
// disabled={!isSubmitable}
onClick={onTryRegister}
variant="contained"
>
Entrar
</Button>
<Link href="#">Esqueci minha senha</Link>
<Link href="#">Cadastre-se</Link>
</Stack>
</Box>
<Box sx={boxLogo}>
<Container sx={logoContainer}>
<img
src={logoImage}
width={layoutType === 'desktop' ? '130' : '70'}
alt="Logotipo"
/>
<p>A plataforma de ensino de código aberto.</p>
</Container>
</Box>
</Paper>
<LoadingIndicator isLoading={isPending} />
<SnackbarIndicator
isOpen={isError}
severity="error"
message={error && error.message}
/>
</Fragment>
);
}
export default View;

View file

@ -0,0 +1,49 @@
import { Button } from '@mui/material';
import { useState } from 'react';
import { useAuthState } from '../../context/auth';
import { useDocumentTitle } from '../../hooks/useDocumentTitle';
import useLayoutType from '../../hooks/useLayoutType';
import View from './View';
function Register() {
useDocumentTitle('Entrar');
const { register, isPending, isError, error } = useAuthState();
const layoutType = useLayoutType();
const [data, setData] = useState({
firstName: '',
lastName: '',
ra: '',
course: 0,
year: 0,
phone: '',
email: '',
password: '',
termsAgreed: false,
});
const onTryRegister = () => {
register(data);
};
const onChangeInput = e => {
const name = e.target.name;
const value = e.target.value;
setData(prev => ({ ...prev, [name]: value }));
};
return (
<View
isPending={isPending}
isError={isError}
error={error}
layoutType={layoutType}
data={data}
onChangeInput={onChangeInput}
onTryRegister={onTryRegister}
/>
);
}
export default Register;

View file

@ -0,0 +1,89 @@
// ========== Desktop ==========
const desktopPaper = {
width: '1500px',
height: '70%',
display: 'flex',
justifyContent: 'center',
color: 'white',
textAlign: 'center',
};
const baseBox = {
width: '100%',
height: '100%',
display: 'flex',
justifyContent: 'center',
flexDirection: 'column',
padding: '0 70px',
};
const desktopBoxLogo = {
...baseBox,
backgroundColor: 'secondary.main',
};
const desktopBoxForm = {
...baseBox,
'> h1, p ': {
textAlign: 'initial',
},
'> h1': {
color: 'primary.black',
margin: 0,
},
'> p': {
color: 'primary.lightGray',
},
};
const logoContainerDesktop = {};
const desktop = {
paper: desktopPaper,
boxLogo: desktopBoxLogo,
boxForm: desktopBoxForm,
logoContainer: logoContainerDesktop,
};
// ========== Mobile ==========
const mobilePaper = {
...desktopPaper,
flexDirection: 'column',
height: '700px',
marginLeft: '10px',
marginRight: '10px',
};
const mobileBoxLogo = {
...desktopBoxLogo,
height: '50%',
padding: '0',
};
const mobileBoxForm = {
...desktopBoxForm,
padding: '0 15px',
width: 'fit-content',
};
const logoContainerMobile = {
padding: '20px 16px',
};
const mobile = {
paper: mobilePaper,
boxLogo: mobileBoxLogo,
boxForm: mobileBoxForm,
logoContainer: logoContainerMobile,
};
// ========== Unset ==========
const unset = {
paper: null,
boxLogo: null,
boxForm: null,
logoContainer: null,
};
const styles = { desktop, mobile, unset };
export default styles;

View file

@ -86,6 +86,17 @@ const getUser = shouldFail =>
} }
}); });
const registerUser = (data, shouldFail) =>
sleep(3000).then(() => {
if (shouldFail) {
return authFailure;
} else {
console.log(data);
window.localStorage.setItem('$USER', JSON.stringify(data));
return data;
}
});
export { export {
getClassrooms, getClassrooms,
getClassroomById, getClassroomById,
@ -96,4 +107,5 @@ export {
getPeopleByClassId, getPeopleByClassId,
getFaq, getFaq,
getUser, getUser,
registerUser,
}; };