Added confirm password text box and show/hide password toggles in both password fields.
This commit is contained in:
@@ -13,10 +13,14 @@ const SignupPage = (props) => {
|
|||||||
const lastNameElement = useRef();
|
const lastNameElement = useRef();
|
||||||
const emailElement = useRef();
|
const emailElement = useRef();
|
||||||
const passwordElement = useRef();
|
const passwordElement = useRef();
|
||||||
|
const confirmPasswordElement = useRef();
|
||||||
|
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
const [passwordStrength, setPasswordStrength] = useState("");
|
const [passwordStrength, setPasswordStrength] = useState("");
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
|
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const evaluatePasswordStrength = (password) => {
|
const evaluatePasswordStrength = (password) => {
|
||||||
@@ -34,7 +38,7 @@ const SignupPage = (props) => {
|
|||||||
|
|
||||||
const handlePasswordChange = (e) => {
|
const handlePasswordChange = (e) => {
|
||||||
const pwd = e.target.value;
|
const pwd = e.target.value;
|
||||||
passwordElement.current.value = pwd; // sync with ref
|
passwordElement.current.value = pwd;
|
||||||
setPasswordStrength(evaluatePasswordStrength(pwd));
|
setPasswordStrength(evaluatePasswordStrength(pwd));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -43,6 +47,7 @@ const SignupPage = (props) => {
|
|||||||
setError("");
|
setError("");
|
||||||
|
|
||||||
const password = passwordElement.current.value;
|
const password = passwordElement.current.value;
|
||||||
|
const confirmPassword = confirmPasswordElement.current.value;
|
||||||
|
|
||||||
const strongPasswordRegex =
|
const strongPasswordRegex =
|
||||||
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&]).{8,}$/;
|
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&]).{8,}$/;
|
||||||
@@ -54,6 +59,11 @@ const SignupPage = (props) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (password !== confirmPassword) {
|
||||||
|
setError("Passwords do not match.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const pwned = await isPasswordPwned(password);
|
const pwned = await isPasswordPwned(password);
|
||||||
@@ -99,6 +109,7 @@ const SignupPage = (props) => {
|
|||||||
lastNameElement.current.value = "";
|
lastNameElement.current.value = "";
|
||||||
emailElement.current.value = "";
|
emailElement.current.value = "";
|
||||||
passwordElement.current.value = "";
|
passwordElement.current.value = "";
|
||||||
|
confirmPasswordElement.current.value = "";
|
||||||
setPasswordStrength("");
|
setPasswordStrength("");
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
@@ -123,7 +134,7 @@ const SignupPage = (props) => {
|
|||||||
type="text"
|
type="text"
|
||||||
id="firstName"
|
id="firstName"
|
||||||
ref={firstNameElement}
|
ref={firstNameElement}
|
||||||
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg block w-full p-2.5"
|
||||||
placeholder={t("signup_first_name_placeholder", language)}
|
placeholder={t("signup_first_name_placeholder", language)}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
@@ -136,7 +147,7 @@ const SignupPage = (props) => {
|
|||||||
type="text"
|
type="text"
|
||||||
id="lastName"
|
id="lastName"
|
||||||
ref={lastNameElement}
|
ref={lastNameElement}
|
||||||
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg block w-full p-2.5"
|
||||||
placeholder={t("signup_last_name_placeholder", language)}
|
placeholder={t("signup_last_name_placeholder", language)}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
@@ -151,27 +162,37 @@ const SignupPage = (props) => {
|
|||||||
type="email"
|
type="email"
|
||||||
id="email"
|
id="email"
|
||||||
ref={emailElement}
|
ref={emailElement}
|
||||||
className="bg-gray-50 border border-gray-300 text-black text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
className="bg-gray-50 border border-gray-300 text-black text-sm rounded-lg block w-full p-2.5"
|
||||||
placeholder={t("signup_email_placeholder", language)}
|
placeholder={t("signup_email_placeholder", language)}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Password */}
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="password" className="block mb-2 text-sm font-medium text-gray-100">
|
<label htmlFor="password" className="block mb-2 text-sm font-medium text-gray-100">
|
||||||
{t("signup_password_label", language)}
|
{t("signup_password_label", language)}
|
||||||
</label>
|
</label>
|
||||||
|
<div className="relative">
|
||||||
<input
|
<input
|
||||||
type="password"
|
type={showPassword ? "text" : "password"}
|
||||||
id="password"
|
id="password"
|
||||||
ref={passwordElement}
|
ref={passwordElement}
|
||||||
onChange={handlePasswordChange}
|
onChange={handlePasswordChange}
|
||||||
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg block w-full p-2.5 pr-10"
|
||||||
placeholder={t("signup_password_placeholder", language)}
|
placeholder={t("signup_password_placeholder", language)}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setShowPassword((prev) => !prev)}
|
||||||
|
className="absolute right-2 top-2 text-sm text-blue-500"
|
||||||
|
>
|
||||||
|
{showPassword ? "Hide" : "Show"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Password Strength UI */}
|
{/* Password Strength */}
|
||||||
{passwordStrength && (
|
{passwordStrength && (
|
||||||
<>
|
<>
|
||||||
<div className="mt-2 text-sm font-medium">
|
<div className="mt-2 text-sm font-medium">
|
||||||
@@ -203,6 +224,30 @@ const SignupPage = (props) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Confirm Password */}
|
||||||
|
<div>
|
||||||
|
<label htmlFor="confirmPassword" className="block mb-2 text-sm font-medium text-gray-100">
|
||||||
|
Confirm Password
|
||||||
|
</label>
|
||||||
|
<div className="relative">
|
||||||
|
<input
|
||||||
|
type={showConfirmPassword ? "text" : "password"}
|
||||||
|
id="confirmPassword"
|
||||||
|
ref={confirmPasswordElement}
|
||||||
|
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg block w-full p-2.5 pr-10"
|
||||||
|
placeholder="Re-enter your password"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setShowConfirmPassword((prev) => !prev)}
|
||||||
|
className="absolute right-2 top-2 text-sm text-blue-500"
|
||||||
|
>
|
||||||
|
{showConfirmPassword ? "Hide" : "Show"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{error && <p className="text-red-500 text-sm font-medium">{error}</p>}
|
{error && <p className="text-red-500 text-sm font-medium">{error}</p>}
|
||||||
|
|
||||||
{loading && (
|
{loading && (
|
||||||
|
|||||||
Reference in New Issue
Block a user