Refactor Login and add responsive layout
This commit is contained in:
parent
d9bb329cf7
commit
c1bde64266
6 changed files with 212 additions and 122 deletions
17
src/hooks/useLayoutType.js
Normal file
17
src/hooks/useLayoutType.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { useMediaQuery } from '@mui/material';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export default function useLayoutType() {
|
||||
const [layoutType, setLayoutType] = useState('desktop');
|
||||
const isMediaQueryRuleActive = useMediaQuery('(max-width:800px)');
|
||||
|
||||
useEffect(() => {
|
||||
if (isMediaQueryRuleActive) {
|
||||
setLayoutType('mobile');
|
||||
} else {
|
||||
setLayoutType('desktop');
|
||||
}
|
||||
}, [isMediaQueryRuleActive]);
|
||||
|
||||
return layoutType;
|
||||
}
|
|
@ -3,6 +3,7 @@ body {
|
|||
font-family: 'Fira Code', monospace;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
code {
|
||||
|
|
|
@ -1,122 +0,0 @@
|
|||
import { Fragment, useState } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Container,
|
||||
Link,
|
||||
Paper,
|
||||
Stack,
|
||||
TextField,
|
||||
} from '@mui/material';
|
||||
import { useAuthState } from '../context/auth';
|
||||
|
||||
import LoadingIndicator from '../components/LoadingIndicator';
|
||||
import SnackbarIndicator from '../components/SnackbarIndicator';
|
||||
|
||||
import logoImage from '../assets/if-salas-logo.svg';
|
||||
|
||||
function Login() {
|
||||
const { login, isPending, isError, error } = useAuthState();
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
|
||||
const isSubmitable = email.length !== 0 && password.length !== 0;
|
||||
|
||||
const onTryLogin = () => {
|
||||
isSubmitable && login(email, password);
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Paper sx={paper} elevation={4} variant="elevation">
|
||||
<Box sx={boxLogo}>
|
||||
<Container>
|
||||
<img src={logoImage} width="100" alt="Logotipo" />
|
||||
<p>A plataforma de ensino de código aberto.</p>
|
||||
</Container>
|
||||
</Box>
|
||||
<Box sx={boxForm}>
|
||||
<h1>Login</h1>
|
||||
<p>Bem-vindo de volta. Faça o login digitando os dados abaixo.</p>
|
||||
<Stack spacing={4} sx={stack} component="form">
|
||||
<TextField
|
||||
id="email"
|
||||
label="E-mail"
|
||||
variant="standard"
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={e => setEmail(e.target.value)}
|
||||
/>
|
||||
<TextField
|
||||
id="password"
|
||||
label="Senha"
|
||||
variant="standard"
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={e => setPassword(e.target.value)}
|
||||
/>
|
||||
<Button
|
||||
disabled={!isSubmitable}
|
||||
onClick={onTryLogin}
|
||||
variant="contained"
|
||||
>
|
||||
Entrar
|
||||
</Button>
|
||||
<Link href="#">Esqueci minha senha</Link>
|
||||
<Link href="#">Cadastre-se</Link>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Paper>
|
||||
<LoadingIndicator isLoading={isPending} />
|
||||
<SnackbarIndicator
|
||||
isOpen={isError}
|
||||
severity="error"
|
||||
message={error && error.message}
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
const paper = {
|
||||
width: '950px',
|
||||
height: '500px',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
color: 'white',
|
||||
textAlign: 'center',
|
||||
};
|
||||
|
||||
const baseBox = {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'column',
|
||||
};
|
||||
|
||||
const boxLogo = {
|
||||
...baseBox,
|
||||
backgroundColor: 'secondary.main',
|
||||
};
|
||||
|
||||
const boxForm = {
|
||||
...baseBox,
|
||||
'> h1, p ': {
|
||||
paddingLeft: '70px',
|
||||
paddingRight: '70px',
|
||||
textAlign: 'initial',
|
||||
},
|
||||
'> h1': {
|
||||
color: 'primary.black',
|
||||
margin: 0,
|
||||
},
|
||||
'> p': {
|
||||
color: 'primary.lightGray',
|
||||
},
|
||||
};
|
||||
|
||||
const stack = {
|
||||
padding: '0 70px',
|
||||
};
|
||||
|
||||
export default Login;
|
88
src/screens/Login/View.js
Normal file
88
src/screens/Login/View.js
Normal file
|
@ -0,0 +1,88 @@
|
|||
import { Fragment } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Container,
|
||||
Link,
|
||||
Paper,
|
||||
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';
|
||||
|
||||
function View({
|
||||
email,
|
||||
password,
|
||||
onChangeEmail,
|
||||
onChangePassword,
|
||||
isSubmitable,
|
||||
onTryLogin,
|
||||
isPending,
|
||||
isError,
|
||||
error,
|
||||
layoutType,
|
||||
}) {
|
||||
const { paper, boxLogo, boxForm } = styles[layoutType];
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Paper sx={paper} elevation={4} variant="elevation">
|
||||
<Box sx={boxLogo}>
|
||||
<Container>
|
||||
<img
|
||||
src={logoImage}
|
||||
width={layoutType === 'desktop' ? '100' : '70'}
|
||||
alt="Logotipo"
|
||||
/>
|
||||
<p>A plataforma de ensino de código aberto.</p>
|
||||
</Container>
|
||||
</Box>
|
||||
<Box sx={boxForm}>
|
||||
<h1>Login</h1>
|
||||
<p>Bem-vindo de volta. Faça o login digitando os dados abaixo.</p>
|
||||
<Stack spacing={4} component="form">
|
||||
<TextField
|
||||
id="email"
|
||||
label="E-mail"
|
||||
variant="standard"
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={e => onChangeEmail(e.target.value)}
|
||||
/>
|
||||
<TextField
|
||||
id="password"
|
||||
label="Senha"
|
||||
variant="standard"
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={e => onChangePassword(e.target.value)}
|
||||
/>
|
||||
<Button
|
||||
disabled={!isSubmitable}
|
||||
onClick={onTryLogin}
|
||||
variant="contained"
|
||||
>
|
||||
Entrar
|
||||
</Button>
|
||||
<Link href="#">Esqueci minha senha</Link>
|
||||
<Link href="#">Cadastre-se</Link>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Paper>
|
||||
<LoadingIndicator isLoading={isPending} />
|
||||
<SnackbarIndicator
|
||||
isOpen={isError}
|
||||
severity="error"
|
||||
message={error && error.message}
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
export default View;
|
35
src/screens/Login/index.js
Normal file
35
src/screens/Login/index.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
import { useState } from 'react';
|
||||
import { useAuthState } from '../../context/auth';
|
||||
import useLayoutType from '../../hooks/useLayoutType';
|
||||
|
||||
import View from './View';
|
||||
|
||||
function Login() {
|
||||
const { login, isPending, isError, error } = useAuthState();
|
||||
const layoutType = useLayoutType();
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
|
||||
const isSubmitable = email.length !== 0 && password.length !== 0;
|
||||
|
||||
const onTryLogin = () => {
|
||||
isSubmitable && login(email, password);
|
||||
};
|
||||
|
||||
return (
|
||||
<View
|
||||
email={email}
|
||||
password={password}
|
||||
onChangeEmail={setEmail}
|
||||
onChangePassword={setPassword}
|
||||
isSubmitable={isSubmitable}
|
||||
onTryLogin={onTryLogin}
|
||||
isPending={isPending}
|
||||
isError={isError}
|
||||
error={error}
|
||||
layoutType={layoutType}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default Login;
|
71
src/screens/Login/styles.js
Normal file
71
src/screens/Login/styles.js
Normal file
|
@ -0,0 +1,71 @@
|
|||
const desktopPaper = {
|
||||
width: '950px',
|
||||
height: '500px',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
color: 'white',
|
||||
textAlign: 'center',
|
||||
};
|
||||
|
||||
const mobilePaper = {
|
||||
...desktopPaper,
|
||||
flexDirection: 'column',
|
||||
height: '700px',
|
||||
marginLeft: '10px',
|
||||
marginRight: '10px',
|
||||
};
|
||||
|
||||
const baseBox = {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'column',
|
||||
padding: '0 70px',
|
||||
};
|
||||
|
||||
const desktopBoxLogo = {
|
||||
...baseBox,
|
||||
backgroundColor: 'secondary.main',
|
||||
};
|
||||
|
||||
const mobileBoxLogo = {
|
||||
...desktopBoxLogo,
|
||||
height: '45%',
|
||||
padding: '0',
|
||||
};
|
||||
|
||||
const desktopBoxForm = {
|
||||
...baseBox,
|
||||
'> h1, p ': {
|
||||
textAlign: 'initial',
|
||||
},
|
||||
'> h1': {
|
||||
color: 'primary.black',
|
||||
margin: 0,
|
||||
},
|
||||
'> p': {
|
||||
color: 'primary.lightGray',
|
||||
},
|
||||
};
|
||||
|
||||
const mobileBoxForm = {
|
||||
...desktopBoxForm,
|
||||
padding: '0 15px',
|
||||
width: 'fit-content',
|
||||
};
|
||||
|
||||
const desktop = {
|
||||
paper: desktopPaper,
|
||||
boxLogo: desktopBoxLogo,
|
||||
boxForm: desktopBoxForm,
|
||||
};
|
||||
|
||||
const mobile = {
|
||||
paper: mobilePaper,
|
||||
boxLogo: mobileBoxLogo,
|
||||
boxForm: mobileBoxForm,
|
||||
};
|
||||
|
||||
const styles = { desktop, mobile };
|
||||
export default styles;
|
Loading…
Reference in a new issue