Hi i have problem with my Next.js app specifically on frontend. I have user management and when i click Add user it will open Modal windows but after that when i focus Password button it will show password requirements and if im focused on password inputbox i need to click Cancel button twice. Because first click will remove showing password requirements and second one click will close the modal the window and i would like to close it on first click.
This is the code for the modal:
const [showPasswordRequirements, setShowPasswordRequirements] = useState(false);
const handlePasswordFocus = () => {
setShowPasswordRequirements(true);
};
const handlePasswordBlur = () => {
setShowPasswordRequirements(false);
};
const handleCancelAddUser = (e) => {
setPasswordStrength({
score: 0,
feedback: "",
color: "gray",
requirements: {
length: false,
uppercase: false,
lowercase: false,
number: false,
special: false,
},
});
setNewUser({ name: "", email: "", password: "", confirmPassword: "", role: "Read-only" });
setEmailError("");
setBackendError(null);
setFieldErrors({});
setShowPasswordRequirements(false);
setIsAddingUser(false);
};
useEffect(() => {
if (isAddingUser || isEditingUser) {
if (nameInputRef.current) {
nameInputRef.current.focus();
}
}
}, [isAddingUser, isEditingUser]);
{isAddingUser && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center">
<div className="bg-white dark:bg-slate-700 p-6 rounded-lg w-full max-w-md">
<h2 className="text-lg font-medium mb-4 text-slate-800 dark:text-white">Add New User</h2>
{fieldErrors.general && <p className="text-red-500 mb-2">{fieldErrors.general}</p>}
<div className="mb-4">
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300">
Name:
</label>
<input
type="text"
name="name"
value={newUser.name}
onChange={handleNewUserChange}
placeholder="Name"
ref={nameInputRef}
className="mt-1 block w-full border-gray-300 dark:border-slate-600 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-slate-800 dark:text-slate-200"
/>
</div>
<div className="mb-4">
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300">
Email:
</label>
<input
type="email"
name="email"
value={newUser.email}
onChange={handleNewUserChange}
placeholder="Email"
className="mt-1 block w-full border-gray-300 dark:border-slate-600 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-slate-800 dark:text-slate-200"
/>
{emailError && <p className="text-red-500 mt-1">{emailError}</p>}
</div>
<div className="mb-4">
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300">
Password:
</label>
<input
type="password"
name="password"
value={newUser.password}
onChange={handleNewUserChange}
placeholder="Password"
className="mt-1 block w-full border-gray-300 dark:border-slate-600 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-slate-800 dark:text-slate-200"
onFocus={handlePasswordFocus}
onBlur={handlePasswordBlur}
ref={passwordInputRef}
/>
{showPasswordRequirements && (
<div className="mt-2">
<div className={`h-2 rounded-full ${passwordStrength.color === "green" ? "bg-green-500" : passwordStrength.color === "orange" ? "bg-orange-500" : "bg-red-500"} w-${passwordStrength.score * 20}/100`}></div>
<p className="text-xs mt-1">{passwordStrength.feedback}</p>
<ul className="list-disc list-inside text-xs mt-2">
<li className={passwordStrength.requirements.length ? "text-green-500" : "text-red-500"}>At least 8 characters</li>
<li className={passwordStrength.requirements.uppercase ? "text-green-500" : "text-red-500"}>Uppercase letter</li>
<li className={passwordStrength.requirements.lowercase ? "text-green-500" : "text-red-500"}>Lowercase letter</li>
<li className={passwordStrength.requirements.number ? "text-green-500" : "text-red-500"}>Number</li>
<li className={passwordStrength.requirements.special ? "text-green-500" : "text-red-500"}>Special character</li>
</ul>
</div>
)}
</div>
<div className="mb-4">
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300">
Confirm Password:
</label>
<input
type="password"
name="confirmPassword"
value={newUser.confirmPassword}
onChange={handleNewUserChange}
placeholder="Confirm Password"
className="mt-1 block w-full border-gray-300 dark:border-slate-600 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-slate-800 dark:text-slate-200"
/>
{fieldErrors.confirmPassword && <p className="text-red-500 mt-1">{fieldErrors.confirmPassword}</p>}
</div>
<div className="mb-4">
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300">
Role:
</label>
<select
name="role"value={newUser.role}
onChange={handleNewUserChange}
className="mt-1 block w-full border-gray-300 dark:border-slate-600 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-slate-800 dark:text-slate-200"
>
<option value="Admin">Admin</option>
<option value="Read-only">Read-only</option>
</select>
</div>
<div className="flex justify-end">
<button
onClick={handleAddNewUser}
className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded mr-2"
>
Add
</button>
<button
onClick={handleCancelAddUser}
className="text-slate-500 hover:text-slate-600 px-4 py-2 rounded"
>
Cancel
</button>
</div>
{backendError && <p className="text-red-500 mt-2">Error: {backendError}</p>}
{error && <p className="text-red-500 mt-2">Error: {error}</p>}
</div>
</div>
)}