Skip to content

Commit 771237b

Browse files
committed
Fix confirm password error message
1 parent 19ed9a0 commit 771237b

File tree

5 files changed

+86
-28
lines changed

5 files changed

+86
-28
lines changed

frontend/src/components/ChangePasswordModal/index.tsx

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ import { useForm } from "react-hook-form";
1111
import { useProfile } from "../../contexts/ProfileContext";
1212
import { passwordValidator } from "../../utils/validators";
1313
import PasswordTextField from "../PasswordTextField";
14+
import {
15+
PASSWORD_MISMATCH_ERROR_MESSAGE,
16+
USE_PROFILE_ERROR_MESSAGE,
17+
} from "../../utils/constants";
1418

1519
interface ChangePasswordModalProps {
1620
open: boolean;
@@ -26,8 +30,10 @@ const ChangePasswordModal: React.FC<ChangePasswordModalProps> = (props) => {
2630
const {
2731
register,
2832
handleSubmit,
29-
formState: { errors, isDirty, isValid },
33+
formState: { errors, dirtyFields, isDirty, isValid },
3034
watch,
35+
trigger,
36+
reset,
3137
} = useForm<{
3238
oldPassword: string;
3339
newPassword: string;
@@ -39,41 +45,61 @@ const ChangePasswordModal: React.FC<ChangePasswordModalProps> = (props) => {
3945
const profile = useProfile();
4046

4147
if (!profile) {
42-
throw new Error("useProfile() must be used within ProfileContextProvider");
48+
throw new Error(USE_PROFILE_ERROR_MESSAGE);
4349
}
4450

4551
const { updatePassword } = profile;
4652

4753
return (
48-
<Dialog fullWidth open={open} onClose={onClose}>
49-
<DialogTitle fontSize={24}>Change password</DialogTitle>
54+
<Dialog
55+
fullWidth
56+
open={open}
57+
onClose={() => {
58+
onClose();
59+
reset();
60+
}}
61+
>
62+
<DialogTitle fontSize={24} sx={{ paddingBottom: 0 }}>
63+
Change password
64+
</DialogTitle>
5065
<DialogContent>
51-
<Container maxWidth="sm">
66+
<Container maxWidth="sm" disableGutters>
5267
<StyledForm
5368
onSubmit={handleSubmit((data) => {
5469
updatePassword({
5570
oldPassword: data.oldPassword,
5671
newPassword: data.newPassword,
5772
});
5873
onClose();
74+
reset();
5975
})}
6076
>
6177
<PasswordTextField
6278
label="Current password"
6379
required
6480
fullWidth
6581
margin="normal"
66-
{...register("oldPassword", { setValueAs: (value: string) => value.trim() })}
82+
sx={(theme) => ({ marginTop: theme.spacing(1) })}
83+
{...register("oldPassword", {
84+
setValueAs: (value: string) => value.trim(),
85+
})}
6786
/>
6887
<PasswordTextField
6988
displayTooltip
7089
label="New password"
7190
required
7291
fullWidth
7392
margin="normal"
93+
sx={(theme) => ({ marginTop: theme.spacing(1) })}
94+
input={watch("newPassword", "")}
7495
{...register("newPassword", {
7596
setValueAs: (value: string) => value.trim(),
7697
validate: { passwordValidator },
98+
onChange: () => {
99+
if (dirtyFields.confirmPassword) {
100+
trigger("confirmPassword");
101+
}
102+
},
77103
})}
78104
error={!!errors.newPassword}
79105
helperText={errors.newPassword?.message}
@@ -83,11 +109,16 @@ const ChangePasswordModal: React.FC<ChangePasswordModalProps> = (props) => {
83109
required
84110
fullWidth
85111
margin="normal"
112+
sx={(theme) => ({ marginTop: theme.spacing(1) })}
86113
{...register("confirmPassword", {
87114
setValueAs: (value: string) => value.trim(),
88115
validate: {
89-
matchPassword: (value) =>
90-
watch("newPassword") === value || "Password does not match",
116+
matchPassword: (value) => {
117+
return (
118+
watch("newPassword") === value ||
119+
PASSWORD_MISMATCH_ERROR_MESSAGE
120+
);
121+
},
91122
},
92123
})}
93124
error={!!errors.confirmPassword}
@@ -102,7 +133,10 @@ const ChangePasswordModal: React.FC<ChangePasswordModalProps> = (props) => {
102133
fullWidth
103134
variant="contained"
104135
color="secondary"
105-
onClick={onClose}
136+
onClick={() => {
137+
onClose();
138+
reset();
139+
}}
106140
>
107141
Cancel
108142
</Button>

frontend/src/components/EditProfileModal/index.tsx

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
import { useForm } from "react-hook-form";
1212
import { useProfile } from "../../contexts/ProfileContext";
1313
import { bioValidator, nameValidator } from "../../utils/validators";
14+
import { USE_PROFILE_ERROR_MESSAGE } from "../../utils/constants";
1415

1516
interface EditProfileModalProps {
1617
onClose: () => void;
@@ -31,6 +32,7 @@ const EditProfileModal: React.FC<EditProfileModalProps> = (props) => {
3132
register,
3233
formState: { errors, isValid, isDirty },
3334
handleSubmit,
35+
reset,
3436
} = useForm<{
3537
firstName: string;
3638
lastName: string;
@@ -47,29 +49,39 @@ const EditProfileModal: React.FC<EditProfileModalProps> = (props) => {
4749
const profile = useProfile();
4850

4951
if (!profile) {
50-
throw new Error("useProfile() must be used within ProfileContextProvider");
52+
throw new Error(USE_PROFILE_ERROR_MESSAGE);
5153
}
5254

5355
const { updateProfile } = profile;
5456

5557
return (
56-
<Dialog open={open} onClose={onClose}>
57-
<DialogTitle fontSize={24}>Edit profile</DialogTitle>
58+
<Dialog
59+
open={open}
60+
onClose={() => {
61+
onClose();
62+
reset();
63+
}}
64+
>
65+
<DialogTitle fontSize={24} sx={{ paddingBottom: 0 }}>
66+
Edit profile
67+
</DialogTitle>
5868
<DialogContent>
59-
<Container maxWidth="sm">
69+
<Container maxWidth="sm" disableGutters>
6070
<StyledForm
6171
onSubmit={handleSubmit((data) => {
6272
updateProfile(data);
6373
onClose();
74+
reset();
6475
})}
6576
>
6677
<TextField
6778
fullWidth
6879
required
6980
label="First name"
7081
margin="normal"
82+
sx={(theme) => ({ marginTop: theme.spacing(1) })}
7183
{...register("firstName", {
72-
setValueAs: (value: string) => value.trim(),
84+
setValueAs: (value: string) => value.trim(),
7385
validate: { nameValidator },
7486
})}
7587
error={!!errors.firstName}
@@ -80,8 +92,9 @@ const EditProfileModal: React.FC<EditProfileModalProps> = (props) => {
8092
required
8193
label="Last name"
8294
margin="normal"
95+
sx={(theme) => ({ marginTop: theme.spacing(1) })}
8396
{...register("lastName", {
84-
setValueAs: (value: string) => value.trim(),
97+
setValueAs: (value: string) => value.trim(),
8598
validate: { nameValidator },
8699
})}
87100
error={!!errors.lastName}
@@ -92,8 +105,9 @@ const EditProfileModal: React.FC<EditProfileModalProps> = (props) => {
92105
multiline
93106
label="Biography"
94107
margin="normal"
108+
sx={(theme) => ({ marginTop: theme.spacing(1) })}
95109
{...register("biography", {
96-
setValueAs: (value: string) => value.trim(),
110+
setValueAs: (value: string) => value.trim(),
97111
validate: { bioValidator },
98112
})}
99113
/>
@@ -106,7 +120,10 @@ const EditProfileModal: React.FC<EditProfileModalProps> = (props) => {
106120
fullWidth
107121
variant="contained"
108122
color="secondary"
109-
onClick={onClose}
123+
onClick={() => {
124+
onClose();
125+
reset();
126+
}}
110127
>
111128
Cancel
112129
</Button>

frontend/src/pages/Profile/index.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ import ServerError from "../../components/ServerError";
99
import EditProfileModal from "../../components/EditProfileModal";
1010
import ChangePasswordModal from "../../components/ChangePasswordModal";
1111
import { useProfile } from "../../contexts/ProfileContext";
12-
import { USE_AUTH_ERROR_MESSAGE } from "../../utils/constants";
12+
import {
13+
USE_AUTH_ERROR_MESSAGE,
14+
USE_PROFILE_ERROR_MESSAGE,
15+
} from "../../utils/constants";
1316

1417
const ProfilePage: React.FC = () => {
1518
const { userId } = useParams<{ userId: string }>();
@@ -22,7 +25,7 @@ const ProfilePage: React.FC = () => {
2225
}
2326

2427
if (!profile) {
25-
throw new Error("useProfile() must be used within ProfileContextProvider");
28+
throw new Error(USE_PROFILE_ERROR_MESSAGE);
2629
}
2730

2831
const {

frontend/src/utils/constants.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
export const complexityList: string[] = ["Easy", "Medium", "Hard"];
33
export const languageList = ["Python", "Java"];
44

5-
/* AuthProvider Error */
5+
/* Context Provider Errors */
66
export const USE_AUTH_ERROR_MESSAGE =
77
"useAuth() must be used within AuthProvider";
8+
export const USE_PROFILE_ERROR_MESSAGE =
9+
"useProfile() must be used within ProfileContextProvider";
810

911
/* Name Validation */
1012
export const NAME_REQUIRED_ERROR_MESSAGE = "Name is required";
@@ -39,7 +41,8 @@ export const PASSWORD_DIGIT_ERROR_MESSAGE =
3941
"Password must contain at least 1 digit";
4042
export const PASSWORD_SPECIAL_CHAR_ERROR_MESSAGE =
4143
"Password must contain at least 1 special character";
42-
export const PASSWORD_WEAK_MESSAGE = "Password is weak";
44+
export const PASSWORD_WEAK_ERROR_MESSAGE = "Password is weak";
45+
export const PASSWORD_MISMATCH_ERROR_MESSAGE = "Password does not match";
4346

4447
/* Toast Messages */
4548
// Authentication

frontend/src/utils/validators.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
PASSWORD_MIN_LENGTH_ERROR_MESSAGE,
1313
PASSWORD_SPECIAL_CHAR_ERROR_MESSAGE,
1414
PASSWORD_UPPER_CASE_ERROR_MESSAGE,
15-
PASSWORD_WEAK_MESSAGE,
15+
PASSWORD_WEAK_ERROR_MESSAGE,
1616
USERNAME_ALLOWED_CHAR_ERROR_MESSAGE,
1717
USERNAME_LENGTH_ERROR_MESSAGE,
1818
} from "./constants";
@@ -87,13 +87,14 @@ const specialCharValidator = (value: string) => {
8787

8888
export const passwordValidator = (value: string) => {
8989
if (
90-
!minLengthValidator(value) ||
91-
!lowerCaseValidator(value) ||
92-
!upperCaseValidator(value) ||
93-
!digitValidator(value) ||
94-
!specialCharValidator(value)
90+
value &&
91+
(!minLengthValidator(value) ||
92+
!lowerCaseValidator(value) ||
93+
!upperCaseValidator(value) ||
94+
!digitValidator(value) ||
95+
!specialCharValidator(value))
9596
) {
96-
return PASSWORD_WEAK_MESSAGE;
97+
return PASSWORD_WEAK_ERROR_MESSAGE;
9798
}
9899

99100
return true;

0 commit comments

Comments
 (0)