213 lines
5.7 KiB
TypeScript
213 lines
5.7 KiB
TypeScript
import React, { FC, useState } from 'react'
|
||
import styled from 'styled-components'
|
||
import { Modal, ModalProps } from 'components/Modal'
|
||
import { Title, Paragraph, Link } from 'components/Typography'
|
||
import { Form } from 'antd'
|
||
import { Button } from 'components/Button'
|
||
import { Input, Password, ErrorMessage, LabelWithTooltip, Captcha } from 'components/FormControl'
|
||
import Image from './images/password@2x.png'
|
||
|
||
type Props = Pick<ModalProps, 'open'> & {
|
||
onClose?: () => void
|
||
}
|
||
|
||
const StyledWrapper = styled.div`
|
||
display: flex;
|
||
align-items: center;
|
||
flex-direction: column;
|
||
min-height: 366px;
|
||
|
||
${props => props.theme.breakpoints.up('s')} {
|
||
justify-content: center;
|
||
}
|
||
`
|
||
const StyledMain = styled.div`
|
||
width: 100%;
|
||
|
||
${props => props.theme.breakpoints.up('s')} {
|
||
width: 350px;
|
||
}
|
||
|
||
${props => props.theme.breakpoints.down('s')} {
|
||
padding-top: 37px;
|
||
}
|
||
|
||
.ant-form-item-required {
|
||
width: 100%;
|
||
}
|
||
`
|
||
const StyledTitle = styled(Title)`
|
||
margin-bottom: 2px !important;
|
||
|
||
${props => props.theme.breakpoints.down('s')} {
|
||
margin-bottom: 5px !important;
|
||
}
|
||
`
|
||
const StyledCaptchaHint = styled(Paragraph)`
|
||
margin-top: 30px;
|
||
`
|
||
const TitleCopies = [
|
||
'Forgot Password',
|
||
'Reset Password',
|
||
'Reset Password',
|
||
'Password Reset'
|
||
]
|
||
|
||
const DescriptionCopies = [
|
||
'Enter your email address to reset your password.',
|
||
'A 6-digit code has been sent to John.smith@gmail.com',
|
||
]
|
||
|
||
export const ForgetPasswordModal: FC<Props> = ({ onClose, ...props }) => {
|
||
const [step, setStep] = useState(0)
|
||
const [email, setEmail] = useState('')
|
||
const [captcha, setCaptcha] = useState('')
|
||
const [expiration, setExpiration] = useState('9:45')
|
||
const handleFinishEmail = ({ email }: { email: string }) => {
|
||
setEmail(email)
|
||
setStep(1)
|
||
}
|
||
|
||
const handleFinishCaptcha = ({ captcha }: { captcha: string }) => {
|
||
setCaptcha(captcha)
|
||
setStep(2)
|
||
}
|
||
|
||
const handleSendAgain = () => {
|
||
// TODO: Update expiration
|
||
|
||
}
|
||
|
||
const handleConfirm = (data: { password: string }) => {
|
||
console.log(data)
|
||
setStep(3)
|
||
}
|
||
|
||
const handleClose = () => {
|
||
setStep(0)
|
||
setEmail('')
|
||
setCaptcha('')
|
||
|
||
onClose && onClose()
|
||
}
|
||
|
||
const handleLogin = () => {
|
||
// TODO: login
|
||
}
|
||
return (
|
||
<Modal {...props} width={688} destroyOnClose onCancel={handleClose}>
|
||
<StyledWrapper>
|
||
<StyledMain>
|
||
<StyledTitle level={2}>{TitleCopies[step]}</StyledTitle>
|
||
{step < 2 && <Paragraph>{DescriptionCopies[step]}</Paragraph>}
|
||
{step === 0 ? (
|
||
<Form
|
||
layout="vertical"
|
||
style={{ marginTop: 4 }}
|
||
onFinish={handleFinishEmail}>
|
||
<Form.Item
|
||
name="email"
|
||
rules={[
|
||
{
|
||
required: true, message: <ErrorMessage message="Please input your email" />
|
||
},
|
||
{ type: 'email', message: <ErrorMessage message="Invalid email" /> }
|
||
]}
|
||
>
|
||
<Input placeholder="email@example.com" />
|
||
</Form.Item>
|
||
<Form.Item>
|
||
<Button style={{ marginTop: 20 }} block htmlType="submit">Next</Button>
|
||
</Form.Item>
|
||
</Form>
|
||
) : null}
|
||
{step === 1 ? (
|
||
<Form
|
||
layout="vertical"
|
||
style={{ marginTop: 27 }}
|
||
onFinish={handleFinishCaptcha}>
|
||
<Form.Item
|
||
name="captcha"
|
||
rules={[
|
||
{
|
||
required: true, message: <ErrorMessage message="Please input your code" />
|
||
}, {
|
||
len: 6,
|
||
validateTrigger: 'onSubmit',
|
||
message: <ErrorMessage message="The verification code you entered is invalid." />
|
||
},
|
||
]}
|
||
>
|
||
<Captcha />
|
||
</Form.Item>
|
||
<StyledCaptchaHint>
|
||
The code will expire in {expiration}<br />
|
||
Didn’t receive the code? <Link onClick={handleSendAgain}>Send again</Link>
|
||
</StyledCaptchaHint>
|
||
<Form.Item>
|
||
<Button block htmlType="submit">Verify</Button>
|
||
</Form.Item>
|
||
</Form>
|
||
) : null}
|
||
{step === 2 ? (
|
||
<Form
|
||
layout="vertical"
|
||
onFinish={handleConfirm}
|
||
>
|
||
<Form.Item
|
||
label={
|
||
<LabelWithTooltip
|
||
primary
|
||
title='The minimum password length is 8 characters and must contain at least 1 uppercase letter, 1 lowercase letter, 1 number, and 1 special character (!@#$%^&*).'
|
||
>
|
||
Please enter a new password
|
||
</LabelWithTooltip>
|
||
}
|
||
name="password"
|
||
rules={[
|
||
{ required: true, message: <ErrorMessage message="Please input your password" /> },
|
||
{
|
||
pattern: /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$/,
|
||
message: <ErrorMessage message="Invalid password" />
|
||
}
|
||
]}
|
||
>
|
||
<Password placeholder="********" />
|
||
</Form.Item>
|
||
<Form.Item
|
||
label="Confirm password"
|
||
name="repeatPassword"
|
||
dependencies={['password']}
|
||
rules={[{ required: true, message: <ErrorMessage message="Please confirm your password" /> },
|
||
({ getFieldValue }) => ({
|
||
validator(_, value) {
|
||
if (!value || getFieldValue('password') === value) {
|
||
return Promise.resolve();
|
||
}
|
||
return Promise.reject(new Error('The two passwords that you entered do not match'));
|
||
},
|
||
}),
|
||
]}
|
||
>
|
||
<Password placeholder="********" />
|
||
</Form.Item>
|
||
<Form.Item>
|
||
<Button style={{ marginTop: 17 }} block htmlType="submit">Confirm</Button>
|
||
</Form.Item>
|
||
</Form>
|
||
) : null}
|
||
{step === 3 ? (
|
||
<>
|
||
<Paragraph style={{ marginTop: 20, marginBottom: 16 }}>
|
||
Your password has just been reset, please log in to continue.
|
||
</Paragraph>
|
||
<img src={Image} style={{ width: 232, height: 83, margin: 'auto', display: 'block' }} alt="" />
|
||
<Button block style={{ marginTop: 20 }} onClick={handleLogin}>Log in</Button>
|
||
</>
|
||
) : null}
|
||
</StyledMain>
|
||
</StyledWrapper>
|
||
</Modal>
|
||
)
|
||
}
|