Skip to content

Commit 5ce90fb

Browse files
authored
added passwort reset form (#496)
1 parent b4bac37 commit 5ce90fb

File tree

1 file changed

+137
-15
lines changed

1 file changed

+137
-15
lines changed
Lines changed: 137 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,143 @@
1-
import { Grid2, Link, Typography } from "@mui/material";
1+
import { ErrorMessage } from "@hookform/error-message";
2+
import {
3+
Button,
4+
Checkbox,
5+
Divider,
6+
FormControlLabel,
7+
FormGroup,
8+
FormHelperText,
9+
Stack,
10+
Typography,
11+
} from "@mui/material";
12+
import { useRef, useState } from "react";
13+
import { SubmitErrorHandler, SubmitHandler, useForm } from "react-hook-form";
14+
import UserHooks from "../../../api/UserHooks.ts";
15+
import FormPassword from "../../../components/FormInputs/FormPassword.tsx";
16+
import { useOpenSnackbar } from "../../../components/SnackbarDialog/useOpenSnackbar.ts";
217
import { SUPPORT_EMAIL } from "../../../utils/GlobalConstants.ts";
318

4-
export default function PasswordReset() {
19+
type UpdatePasswordValues = {
20+
password: string;
21+
confirmPassword: string;
22+
};
23+
24+
export default function UpdatePassword() {
25+
const updateUserMutation = UserHooks.useUpdate();
26+
const {
27+
handleSubmit,
28+
formState: { errors },
29+
watch,
30+
control,
31+
} = useForm<UpdatePasswordValues>({
32+
defaultValues: {
33+
password: "",
34+
confirmPassword: "",
35+
},
36+
});
37+
38+
// password
39+
const password = useRef<string>();
40+
password.current = watch("password", "");
41+
const [showPassword, setShowPassword] = useState(false);
42+
const handleShowPasswordChange = (event: React.ChangeEvent<HTMLInputElement>) => {
43+
setShowPassword(event.target.checked);
44+
};
45+
46+
// snack bar
47+
const openSnackbar = useOpenSnackbar();
48+
49+
const handleUpdate: SubmitHandler<UpdatePasswordValues> = (data) => {
50+
updateUserMutation.mutate(
51+
{
52+
requestBody: {
53+
password: data.password,
54+
},
55+
},
56+
{
57+
onSuccess: () => {
58+
openSnackbar({
59+
text: `Hurray! Your password updated successfully.`,
60+
severity: "success",
61+
});
62+
},
63+
onError: () => {
64+
openSnackbar({
65+
text: `Sorry! Your password update failed. Please contact` + { SUPPORT_EMAIL },
66+
severity: "error",
67+
});
68+
},
69+
},
70+
);
71+
};
72+
73+
const handleError: SubmitErrorHandler<UpdatePasswordValues> = (data) => console.error(data);
74+
575
return (
6-
<>
7-
<Typography variant={"h5"} gutterBottom sx={{ pb: 1 }}>
8-
Reset Password
76+
<form onSubmit={handleSubmit(handleUpdate, handleError)}>
77+
<Typography variant={"h5"} sx={{ pb: 1 }}>
78+
Update Password
979
</Typography>
10-
11-
<Grid2 container spacing={1} sx={{ borderTop: 1, borderColor: "divider" }}>
12-
<Grid2 size={{ xs: 12 }}>
13-
<Typography variant={"body1"} gutterBottom>
14-
To reset your password, please write an e-mail to{" "}
15-
<Link href={"mailto:" + SUPPORT_EMAIL}>{SUPPORT_EMAIL}</Link> from your registered e-mail address.
16-
</Typography>
17-
</Grid2>
18-
</Grid2>
19-
</>
80+
<Divider />
81+
<Stack direction="row" spacing={2} sx={{ mt: 1, mb: 0.5 }}>
82+
<FormPassword
83+
name="password"
84+
control={control}
85+
showPassword={showPassword}
86+
rules={{
87+
required: "Password is required",
88+
validate: (value) => {
89+
return (
90+
[
91+
/[a-z]/, // lowercase
92+
/[A-Z]/, // uppercase
93+
/[0-9]/, // number
94+
/[^a-zA-Z0-9]/, // special character
95+
].every((pattern) => pattern.test(value)) ||
96+
"Password must contain at least one lowercase letter, uppercase letter, number and special character!"
97+
);
98+
},
99+
minLength: {
100+
value: 8,
101+
message: "Password too short! (minimum 8 characters)",
102+
},
103+
}}
104+
textFieldProps={{
105+
label: "Password",
106+
variant: "outlined",
107+
fullWidth: true,
108+
error: Boolean(errors.password),
109+
helperText: <ErrorMessage errors={errors} name="password" />,
110+
}}
111+
/>
112+
<FormPassword
113+
name="confirmPassword"
114+
control={control}
115+
showPassword={showPassword}
116+
rules={{
117+
required: "Password is required",
118+
validate: (value) => value === password.current || "Passwords do not match!",
119+
}}
120+
textFieldProps={{
121+
label: "Password Confirm",
122+
variant: "outlined",
123+
fullWidth: true,
124+
error: Boolean(errors.confirmPassword),
125+
helperText: <ErrorMessage errors={errors} name="confirmPassword" />,
126+
}}
127+
/>
128+
</Stack>
129+
<FormHelperText sx={{ ml: 1.8 }}>
130+
Use 8 or more characters with a mix of uppercase letters, lowercase letters, numbers & symbols
131+
</FormHelperText>
132+
<FormGroup sx={{ ml: 1 }}>
133+
<FormControlLabel
134+
control={<Checkbox value={showPassword} onChange={handleShowPasswordChange} />}
135+
label="Show Password"
136+
/>
137+
</FormGroup>
138+
<Button aria-label="Update Email" variant="contained" type="submit">
139+
Update
140+
</Button>
141+
</form>
20142
);
21143
}

0 commit comments

Comments
 (0)