kandimat/redaktions-app/src/components/SignUp.tsx
2021-01-30 16:12:10 +01:00

208 lines
5.8 KiB
TypeScript

import React, { ChangeEvent, 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 { Link, useHistory } from "react-router-dom";
import Grid from "@material-ui/core/Grid";
import Box from "@material-ui/core/Box";
import LockOutlinedIcon from "@material-ui/icons/LockOutlined";
import Typography from "@material-ui/core/Typography";
import { makeStyles } from "@material-ui/core/styles";
import Container from "@material-ui/core/Container";
import { Copyright } from "./Copyright";
import { useMutation } from "@apollo/client";
import ButtonWithSpinner from "./ButtonWithSpinner";
import { errorHandler, SignUpError } from "./SignUpErrorHandler";
import { Alert } from "@material-ui/lab";
import {
SIGN_UP,
SignUpResponse,
SignUpVariables,
} from "../backend/mutations/signUp";
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(3),
},
submit: {
margin: theme.spacing(3, 0, 2),
},
error: {
color: "red",
},
alert: {
margin: theme.spacing(1),
},
}));
export default function SignUp(): React.ReactElement {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [error, setError] = useState<SignUpError | undefined>(undefined);
const history = useHistory();
const [createAccount, { loading }] = useMutation<
SignUpResponse,
SignUpVariables
>(SIGN_UP, {
onCompleted() {
history.push("/login?recent-sign-up-success=true");
},
onError(e) {
console.error(e);
setPassword("");
setError(errorHandler(e));
},
});
const classes = useStyles();
const onSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
createAccount({ variables: { firstName, lastName, email, password } });
};
const onFirstNameChange = (
e: ChangeEvent<HTMLTextAreaElement | HTMLInputElement>
) => {
setFirstName(e.target.value);
if (error?.firstNameInvalid) {
setError(undefined);
}
};
const onLastNameChange = (
e: ChangeEvent<HTMLTextAreaElement | HTMLInputElement>
) => {
setLastName(e.target.value);
if (error?.lastNameInvalid) {
setError(undefined);
}
};
const onEmailChange = (
e: ChangeEvent<HTMLTextAreaElement | HTMLInputElement>
) => {
setEmail(e.target.value);
if (error?.emailInvalid) {
setError(undefined);
}
};
const onPasswordChange = (
e: ChangeEvent<HTMLTextAreaElement | HTMLInputElement>
) => {
setPassword(e.target.value);
if (error?.passwordInvalid) {
setError(undefined);
}
};
return (
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<Avatar className={classes.avatar}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Sign up
</Typography>
<form className={classes.form} noValidate onSubmit={onSubmit}>
<Grid container spacing={2}>
<Grid item xs={12} sm={6}>
<TextField
autoComplete="fname"
name="firstName"
variant="outlined"
required
fullWidth
id="firstName"
label="First Name"
autoFocus
value={firstName}
onChange={onFirstNameChange}
error={error?.firstNameInvalid}
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
variant="outlined"
required
fullWidth
id="lastName"
label="Last Name"
name="lastName"
autoComplete="lname"
value={lastName}
onChange={onLastNameChange}
error={error?.lastNameInvalid}
/>
</Grid>
<Grid item xs={12}>
<TextField
variant="outlined"
required
fullWidth
id="email"
label="Email Address"
name="email"
autoComplete="email"
value={email}
onChange={onEmailChange}
error={error?.emailInvalid}
/>
</Grid>
<Grid item xs={12}>
<TextField
variant="outlined"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
value={password}
onChange={onPasswordChange}
error={error?.passwordInvalid}
/>
</Grid>
</Grid>
<ButtonWithSpinner loading={loading} type="submit" fullWidth>
Sign Up
</ButtonWithSpinner>
<Grid container justify="flex-end">
<Grid item>
<Link to="/login">Already have an account? Sign in</Link>
</Grid>
</Grid>
{error ? (
<Alert
className={classes.alert}
severity="error"
onClose={() => setError(undefined)}
>
{error.message}
</Alert>
) : null}
</form>
</div>
<Box mt={5}>
<Copyright />
</Box>
</Container>
);
}