kleckrelay/src/routes/VerifyEmailRoute.tsx
2022-11-01 15:57:53 +01:00

101 lines
2.6 KiB
TypeScript

import * as yup from "yup"
import {useLoaderData, useNavigate} from "react-router-dom"
import {useAsync, useLocalStorage} from "react-use"
import {MdCancel} from "react-icons/md"
import {AxiosError} from "axios"
import {useTranslation} from "react-i18next"
import React, {ReactElement, useContext} from "react"
import {Grid, Paper, Typography, useTheme} from "@mui/material"
import {useMutation} from "@tanstack/react-query"
import {AuthenticationDetails, ServerSettings} from "~/server-types"
import {VerifyEmailData, verifyEmail} from "~/apis"
import {useQueryParams} from "~/hooks"
import AuthContext from "~/AuthContext/AuthContext"
const emailSchema = yup.string().email()
export default function VerifyEmailRoute(): ReactElement {
const theme = useTheme()
const navigate = useNavigate()
const {t} = useTranslation()
const {login} = useContext(AuthContext)
const [_, setEmail] = useLocalStorage<string>("signup-form-state-email", "")
const {email, token} = useQueryParams<{
email: string
token: string
}>()
const serverSettings = useLoaderData() as ServerSettings
const tokenSchema = yup
.string()
.length(serverSettings.emailVerificationLength)
.test("token", t("routes.VerifyEmailRoute.errors.code.invalid") as string, token => {
if (!token) {
return false
}
const chars = serverSettings.emailVerificationChars.split("")
return token.split("").every(char => chars.includes(char))
})
const {mutateAsync} = useMutation<AuthenticationDetails, AxiosError, VerifyEmailData>(
verifyEmail,
{
onSuccess: ({user}) => {
setEmail("")
login(user)
navigate("/auth/complete-account")
},
},
)
const {loading} = useAsync(async () => {
await emailSchema.validate(email)
await tokenSchema.validate(token)
await mutateAsync({
email,
token,
})
}, [email, token])
return (
<Paper>
<Grid
container
spacing={4}
padding={4}
alignItems="center"
justifyContent="center"
flexDirection="column"
>
<Grid item>
<Typography variant="h5" component="h1" align="center">
{t("routes.VerifyEmailRoute.title")}
</Typography>
</Grid>
{loading ? (
<Grid item>
<Typography variant="subtitle1" component="p" align="center">
{t("routes.VerifyEmailRoute.isLoading")}
</Typography>
</Grid>
) : (
<>
<Grid item>
<MdCancel size={100} color={theme.palette.error.main} />
</Grid>
<Grid item>
<Typography variant="subtitle1" component="p" align="center">
{t("routes.VerifyEmailRoute.isCodeInvalid")}
</Typography>
</Grid>
</>
)}
</Grid>
</Paper>
)
}