Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pterodactyl
GitHub Repository: pterodactyl/panel
Path: blob/1.0-develop/resources/scripts/components/auth/ResetPasswordContainer.tsx
7461 views
1
import React, { useState } from 'react';
2
import { RouteComponentProps } from 'react-router';
3
import { Link } from 'react-router-dom';
4
import performPasswordReset from '@/api/auth/performPasswordReset';
5
import { httpErrorToHuman } from '@/api/http';
6
import LoginFormContainer from '@/components/auth/LoginFormContainer';
7
import { Actions, useStoreActions } from 'easy-peasy';
8
import { ApplicationStore } from '@/state';
9
import { Formik, FormikHelpers } from 'formik';
10
import { object, ref, string } from 'yup';
11
import Field from '@/components/elements/Field';
12
import Input from '@/components/elements/Input';
13
import tw from 'twin.macro';
14
import Button from '@/components/elements/Button';
15
16
interface Values {
17
password: string;
18
passwordConfirmation: string;
19
}
20
21
export default ({ match, location }: RouteComponentProps<{ token: string }>) => {
22
const [email, setEmail] = useState('');
23
24
const { clearFlashes, addFlash } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes);
25
26
const parsed = new URLSearchParams(location.search);
27
if (email.length === 0 && parsed.get('email')) {
28
setEmail(parsed.get('email') || '');
29
}
30
31
const submit = ({ password, passwordConfirmation }: Values, { setSubmitting }: FormikHelpers<Values>) => {
32
clearFlashes();
33
performPasswordReset(email, { token: match.params.token, password, passwordConfirmation })
34
.then(() => {
35
// @ts-expect-error this is valid
36
window.location = '/';
37
})
38
.catch((error) => {
39
console.error(error);
40
41
setSubmitting(false);
42
addFlash({ type: 'error', title: 'Error', message: httpErrorToHuman(error) });
43
});
44
};
45
46
return (
47
<Formik
48
onSubmit={submit}
49
initialValues={{
50
password: '',
51
passwordConfirmation: '',
52
}}
53
validationSchema={object().shape({
54
password: string()
55
.required('A new password is required.')
56
.min(8, 'Your new password should be at least 8 characters in length.'),
57
passwordConfirmation: string()
58
.required('Your new password does not match.')
59
// @ts-expect-error this is valid
60
.oneOf([ref('password'), null], 'Your new password does not match.'),
61
})}
62
>
63
{({ isSubmitting }) => (
64
<LoginFormContainer title={'Reset Password'} css={tw`w-full flex`}>
65
<div>
66
<label>Email</label>
67
<Input value={email} isLight disabled />
68
</div>
69
<div css={tw`mt-6`}>
70
<Field
71
light
72
label={'New Password'}
73
name={'password'}
74
type={'password'}
75
description={'Passwords must be at least 8 characters in length.'}
76
/>
77
</div>
78
<div css={tw`mt-6`}>
79
<Field light label={'Confirm New Password'} name={'passwordConfirmation'} type={'password'} />
80
</div>
81
<div css={tw`mt-6`}>
82
<Button size={'xlarge'} type={'submit'} disabled={isSubmitting} isLoading={isSubmitting}>
83
Reset Password
84
</Button>
85
</div>
86
<div css={tw`mt-6 text-center`}>
87
<Link
88
to={'/auth/login'}
89
css={tw`text-xs text-neutral-500 tracking-wide no-underline uppercase hover:text-neutral-600`}
90
>
91
Return to Login
92
</Link>
93
</div>
94
</LoginFormContainer>
95
)}
96
</Formik>
97
);
98
};
99
100