Docker/Voltaserve/ui/src/pages/sign-up-page.tsx
2024-04-17 20:22:30 +02:00

234 lines
7.4 KiB
TypeScript

import { useCallback, useState } from 'react'
import { Link } from 'react-router-dom'
import {
Button,
FormControl,
FormErrorMessage,
Input,
Link as ChakraLink,
Heading,
} from '@chakra-ui/react'
import {
Field,
FieldAttributes,
FieldProps,
Form,
Formik,
FormikHelpers,
} from 'formik'
import * as Yup from 'yup'
import cx from 'classnames'
import { Helmet } from 'react-helmet-async'
import AccountAPI from '@/client/idp/account'
import Logo from '@/components/common/logo'
import LayoutFull from '@/components/layout/layout-full'
type FormValues = {
fullName: string
email: string
password: string
passwordConfirmation: string
}
const SignUpPage = () => {
const [isConfirmationVisible, setIsConfirmationVisible] = useState(false)
const formSchema = Yup.object().shape({
fullName: Yup.string().required('Name is required'),
email: Yup.string()
.email('Email is not valid')
.required('Email is required'),
password: Yup.string().required('Password is required'),
passwordConfirmation: Yup.string()
.oneOf([Yup.ref('password'), undefined], 'Passwords must match')
.required('Confirm your password'),
})
const handleSubmit = useCallback(
async (
{ fullName, email, password }: FormValues,
{ setSubmitting }: FormikHelpers<FormValues>,
) => {
try {
await AccountAPI.create({
fullName,
email,
password,
})
setIsConfirmationVisible(true)
} finally {
setSubmitting(false)
}
},
[],
)
return (
<LayoutFull>
<>
<Helmet>
<title>Sign Up to Voltaserve</title>
</Helmet>
{isConfirmationVisible && (
<div
className={cx(
'flex',
'flex-col',
'items-center',
'gap-2.5',
'w-full',
)}
>
<div className={cx('flex', 'flex-col', 'items-center', 'gap-1.5')}>
<div className={cx('w-[64px]')}>
<Logo isGlossy={true} />
</div>
<Heading className={cx('text-heading')}>
Thanks! We just sent you a confirmation email
</Heading>
<span className={cx('text-center')}>
Just open your inbox, find the email, and click on the
confirmation link.
</span>
</div>
</div>
)}
{!isConfirmationVisible && (
<div
className={cx(
'flex',
'flex-col',
'items-center',
'gap-2.5',
'w-full',
)}
>
<div className={cx('w-[64px]')}>
<Logo isGlossy={true} />
</div>
<Heading className={cx('text-heading')}>
Sign Up to Voltaserve
</Heading>
<Formik
initialValues={{
fullName: '',
email: '',
password: '',
passwordConfirmation: '',
}}
validationSchema={formSchema}
validateOnBlur={false}
onSubmit={handleSubmit}
>
{({ errors, touched, isSubmitting }) => (
<Form className={cx('w-full')}>
<div
className={cx(
'flex',
'flex-col',
'items-center',
'gap-1.5',
)}
>
<Field name="fullName">
{({ field }: FieldAttributes<FieldProps>) => (
<FormControl
isInvalid={
errors.fullName && touched.fullName ? true : false
}
>
<Input
{...field}
id="fullName"
placeholder="Full name"
disabled={isSubmitting}
/>
<FormErrorMessage>{errors.fullName}</FormErrorMessage>
</FormControl>
)}
</Field>
<Field name="email">
{({ field }: FieldAttributes<FieldProps>) => (
<FormControl
isInvalid={
errors.email && touched.email ? true : false
}
>
<Input
{...field}
id="email"
placeholder="Email"
disabled={isSubmitting}
/>
<FormErrorMessage>{errors.email}</FormErrorMessage>
</FormControl>
)}
</Field>
<Field name="password">
{({ field }: FieldAttributes<FieldProps>) => (
<FormControl
isInvalid={
errors.password && touched.password ? true : false
}
>
<Input
{...field}
id="password"
placeholder="Password"
type="password"
disabled={isSubmitting}
/>
<FormErrorMessage>{errors.password}</FormErrorMessage>
</FormControl>
)}
</Field>
<Field name="passwordConfirmation">
{({ field }: FieldAttributes<FieldProps>) => (
<FormControl
isInvalid={
errors.passwordConfirmation &&
touched.passwordConfirmation
? true
: false
}
>
<Input
{...field}
id="passwordConfirmation"
placeholder="Confirm password"
type="password"
disabled={isSubmitting}
/>
<FormErrorMessage>
{errors.passwordConfirmation}
</FormErrorMessage>
</FormControl>
)}
</Field>
<Button
className={cx('w-full')}
variant="solid"
colorScheme="blue"
type="submit"
isLoading={isSubmitting}
>
Sign Up
</Button>
</div>
</Form>
)}
</Formik>
<div className={cx('flex', 'flex-row', 'items-center', 'gap-0.5')}>
<span>Already a member?</span>
<ChakraLink as={Link} to="/sign-in">
Sign In
</ChakraLink>
</div>
</div>
)}
</>
</LayoutFull>
)
}
export default SignUpPage