kandimat/redaktions-app/src/components/SignIn.tsx
Christoph Lienhard b6358c357b
#11 Refactor queries and mutations
* Use more apollo naming convention
* Take care of possible null/undefined fields in responses
2020-12-28 21:22:32 +01:00

160 lines
4.7 KiB
TypeScript

import React, {useState} from 'react';
import Avatar from '@material-ui/core/Avatar';
import CssBaseline from '@material-ui/core/CssBaseline';
import TextField from '@material-ui/core/TextField';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Checkbox from '@material-ui/core/Checkbox';
import Grid from '@material-ui/core/Grid';
import Box from '@material-ui/core/Box';
import {Alert} from '@material-ui/lab';
import LockOutlinedIcon from '@material-ui/icons/LockOutlined';
import {Link, useHistory, useLocation} from 'react-router-dom';
import Typography from '@material-ui/core/Typography';
import {makeStyles} from '@material-ui/core/styles';
import Container from '@material-ui/core/Container';
import {useMutation} from "@apollo/client";
import ButtonWithSpinner from "./ButtonWithSpinner";
import {Copyright} from "./Copyright";
import {LOGIN, LoginResponse, LoginVariables} from "../backend/mutations/login";
const useStyles = makeStyles((theme) => ({
paper: {
marginTop: theme.spacing(8),
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
},
avatar: {
margin: theme.spacing(1),
backgroundColor: theme.palette.secondary.main,
},
form: {
width: '100%', // Fix IE 11 issue.
marginTop: theme.spacing(1),
},
submit: {
margin: theme.spacing(3, 0, 2),
},
alert: {
margin: theme.spacing(1)
}
}));
export default function SignIn() {
const history = useHistory();
const queryParams = new URLSearchParams(useLocation().search);
const classes = useStyles();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const [login, {loading}] = useMutation<LoginResponse, LoginVariables>(
LOGIN,
{
onCompleted(data) {
if (data.authenticate.jwtToken) {
localStorage.setItem("token", data.authenticate.jwtToken)
history.replace("/")
} else {
setError("Wrong username or password.")
}
},
onError(e) {
setError(`Error while trying to log in: ${e.message}`)
}
}
);
return (
<Container component="main" maxWidth="xs">
<CssBaseline/>
<div className={classes.paper}>
<Avatar className={classes.avatar}>
<LockOutlinedIcon/>
</Avatar>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<form
className={classes.form}
noValidate
onSubmit={event => {
event.preventDefault();
login({variables: {email: email, password: password}}).catch(error => console.log(error))
}}
>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="email"
label="Email Address"
name="email"
autoComplete="email"
autoFocus
value={email}
onChange={(e) => {
setEmail(e.target.value);
setError("");
}}
/>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
value={password}
autoComplete="current-password"
onChange={(e) => {
setPassword(e.target.value);
setError("");
}}
/>
<FormControlLabel
disabled={true}
control={<Checkbox value="remember" color="primary"/>}
label="Remember me"
/>
<ButtonWithSpinner
loading={loading}
type="submit"
fullWidth
>Sign In</ButtonWithSpinner>
<Grid container>
<Grid item xs>
{/* todo: see issue #17*/}
{/*<Link to="/restore-password" aria-disabled={true}>*/}
{/* Forgot password?*/}
{/*</Link>*/}
</Grid>
<Grid item>
<Link to="/signup">
{"Don't have an account? Sign Up"}
</Link>
</Grid>
</Grid>
{queryParams.get("recent-sign-up-success")
? <Alert className={classes.alert} severity="success" onClose={() => history.push("/login")}>
Sign-Up was successful. Log in to continue
</Alert>
: null}
{error ? <Alert className={classes.alert} severity="error" onClose={() => setError("")}>{error}</Alert> : null}
</form>
</div>
<Box mt={8}>
<Copyright/>
</Box>
</Container>
);
}