Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Eye for password toggling #97

Merged
merged 1 commit into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"firebase": "^10.14.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^5.3.0",
"react-router-dom": "^6.27.0",
"react-toastify": "^9.1.3",
"uuid": "^9.0.1"
Expand Down
139 changes: 89 additions & 50 deletions src/components/SignIn.jsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,37 @@
import { useState } from 'react'
import { Link, Navigate } from 'react-router-dom'
import { doSignInWithEmailAndPassword, doSignInWithGoogle } from '../firebase/auth'
import { useAuth } from '../contexts/authContext/index'
import { useState } from 'react';
import { Link, Navigate } from 'react-router-dom';
import { doSignInWithEmailAndPassword, doSignInWithGoogle } from '../firebase/auth';
import { useAuth } from '../contexts/authContext/index';
import { AiFillEye, AiFillEyeInvisible } from 'react-icons/ai'; // Importing React Icons

const SignIn = () => {
const { userLoggedIn } = useAuth();

const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [isSigningIn, setIsSigningIn] = useState(false)
const [errorMessage, setErrorMessage] = useState('')
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [showPassword, setShowPassword] = useState(false); // Added state to toggle password visibility
const [isSigningIn, setIsSigningIn] = useState(false);
const [errorMessage, setErrorMessage] = useState('');

const onSubmit = async (e) => {
e.preventDefault()
e.preventDefault();
if (!isSigningIn) {
setIsSigningIn(true)
await doSignInWithEmailAndPassword(email, password)
// doSendEmailVerification()
setIsSigningIn(true);
await doSignInWithEmailAndPassword(email, password);
// doSendEmailVerification();
}
}
};

const onGoogleSignIn = (e) => {
e.preventDefault()
e.preventDefault();
if (!isSigningIn) {
setIsSigningIn(true)
setIsSigningIn(true);
doSignInWithGoogle().catch(err => {
setIsSigningIn(false)
})
setIsSigningIn(false);
});
}
}
};

if (userLoggedIn) {
return <Navigate to="/" replace />;
}
Expand All @@ -42,63 +45,99 @@ const SignIn = () => {
<h3 className="text-gray-800 text-xl font-semibold sm:text-2xl">Welcome Back</h3>
</div>
</div>
<form
onSubmit={onSubmit}
className="space-y-5"
>
<form onSubmit={onSubmit} className="space-y-5">
<div>
<label className="text-sm text-gray-600 font-bold">
Email
</label>
<label className="text-sm text-gray-600 font-bold">Email</label>
<input
type="email"
autoComplete='email'
autoComplete="email"
required
value={email} onChange={(e) => { setEmail(e.target.value) }}
value={email}
onChange={(e) => setEmail(e.target.value)}
className="w-full mt-2 px-3 py-2 text-gray-500 bg-transparent outline-none border focus:border-green-600 shadow-sm rounded-lg transition duration-300"
/>
</div>


<div>
<label className="text-sm text-gray-600 font-bold">
Password
</label>
<div className="relative">
<label className="text-sm text-gray-600 font-bold">Password</label>
<input
type="password"
autoComplete='current-password'
type={showPassword ? 'text' : 'password'}
autoComplete="current-password"
required
value={password} onChange={(e) => { setPassword(e.target.value) }}
className="w-full mt-2 px-3 py-2 text-gray-500 bg-transparent outline-none border focus:border-green-600 shadow-sm rounded-lg transition duration-300"
value={password}
onChange={(e) => setPassword(e.target.value)}
className="w-full mt-2 px-3 py-2 pr-10 text-gray-500 bg-transparent outline-none border focus:border-green-600 shadow-sm rounded-lg transition duration-300"
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute inset-y-0 right-0 mt-8 flex items-center px-3"
>
{showPassword ? (
<AiFillEyeInvisible className="w-6 h-6 text-gray-500" />
) : (
<AiFillEye className="w-6 h-6 text-gray-500" />
)}
</button>
</div>

{errorMessage && (
<span className='text-red-600 font-bold'>{errorMessage}</span>
<span className="text-red-600 font-bold">{errorMessage}</span>
)}

<button
type="submit"
disabled={isSigningIn}
className={`w-full px-4 py-2 text-white font-medium rounded-lg ${isSigningIn ? 'bg-gray-300 cursor-not-allowed' : 'bg-green-600 hover:bg-green-700 hover:shadow-xl transition duration-300'}`}
className={`w-full px-4 py-2 text-white font-medium rounded-lg ${
isSigningIn
? 'bg-gray-300 cursor-not-allowed'
: 'bg-green-600 hover:bg-green-700 hover:shadow-xl transition duration-300'
}`}
>
{isSigningIn ? 'Signing In...' : 'Sign In'}
</button>
</form>
<p className="text-center text-sm">Don't have an account? <Link to={'/sign-up'} className="hover:underline font-bold">Sign up</Link></p>
<div className='flex flex-row text-center w-full'>
<div className='border-b-2 mb-2.5 mr-2 w-full'></div><div className='text-sm font-bold w-fit'>OR</div><div className='border-b-2 mb-2.5 ml-2 w-full'></div>

<p className="text-center text-sm">
Don't have an account?{' '}
<Link to="/sign-up" className="hover:underline font-bold">
Sign up
</Link>
</p>

<div className="flex flex-row text-center w-full">
<div className="border-b-2 mb-2.5 mr-2 w-full"></div>
<div className="text-sm font-bold w-fit">OR</div>
<div className="border-b-2 mb-2.5 ml-2 w-full"></div>
</div>

<button
disabled={isSigningIn}
onClick={(e) => { onGoogleSignIn(e) }}
className={`w-full flex items-center justify-center gap-x-3 py-2.5 border rounded-lg text-sm font-medium ${isSigningIn ? 'cursor-not-allowed' : 'hover:bg-gray-100 transition duration-300 active:bg-gray-100'}`}>
onClick={(e) => onGoogleSignIn(e)}
className={`w-full flex items-center justify-center gap-x-3 py-2.5 border rounded-lg text-sm font-medium ${
isSigningIn
? 'cursor-not-allowed'
: 'hover:bg-gray-100 transition duration-300 active:bg-gray-100'
}`}
>
<svg className="w-5 h-5" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clipPath="url(#clip0_17_40)">
<path d="M47.532 24.5528C47.532 22.9214 47.3997 21.2811 47.1175 19.6761H24.48V28.9181H37.4434C36.9055 31.8988 35.177 34.5356 32.6461 36.2111V42.2078H40.3801C44.9217 38.0278 47.532 31.8547 47.532 24.5528Z" fill="#4285F4" />
<path d="M24.48 48.0016C30.9529 48.0016 36.4116 45.8764 40.3888 42.2078L32.6549 36.2111C30.5031 37.675 27.7252 38.5039 24.4888 38.5039C18.2275 38.5039 12.9187 34.2798 11.0139 28.6006H3.03296V34.7825C7.10718 42.8868 15.4056 48.0016 24.48 48.0016Z" fill="#34A853" />
<path d="M11.0051 28.6006C9.99973 25.6199 9.99973 22.3922 11.0051 19.4115V13.2296H3.03298C-0.371021 20.0112 -0.371021 28.0009 3.03298 34.7825L11.0051 28.6006Z" fill="#FBBC04" />
<path d="M24.48 9.49932C27.9016 9.44641 31.2086 10.7339 33.6866 13.0973L40.5387 6.24523C36.2 2.17101 30.4414 -0.068932 24.48 0.00161733C15.4055 0.00161733 7.10718 5.11644 3.03296 13.2296L11.005 19.4115C12.901 13.7235 18.2187 9.49932 24.48 9.49932Z" fill="#EA4335" />
<path
d="M47.532 24.5528C47.532 22.9214 47.3997 21.2811 47.1175 19.6761H24.48V28.9181H37.4434C36.9055 31.8988 35.177 34.5356 32.6461 36.2111V42.2078H40.3801C44.9217 38.0278 47.532 31.8547 47.532 24.5528Z"
fill="#4285F4"
/>
<path
d="M24.48 48.0016C30.9529 48.0016 36.4116 45.8764 40.3888 42.2078L32.6549 36.2111C30.5031 37.675 27.7252 38.5039 24.4888 38.5039C18.2275 38.5039 12.9187 34.2798 11.0139 28.6006H3.03296V34.7825C7.10718 42.8868 15.4056 48.0016 24.48 48.0016Z"
fill="#34A853"
/>
<path
d="M11.0051 28.6006C9.99973 25.6199 9.99973 22.3922 11.0051 19.4115V13.2296H3.03298C-0.371021 20.0112 -0.371021 28.0009 3.03298 34.7825L11.0051 28.6006Z"
fill="#FBBC04"
/>
<path
d="M24.48 9.49932C27.9016 9.44641 31.2086 10.7339 33.6866 13.0973L40.5387 6.24523C36.2 2.17101 30.4414 -0.068932 24.48 0.00161733C15.4055 0.00161733 7.10718 5.11644 3.03296 13.2296L11.005 19.4115C12.901 13.7235 18.2187 9.49932 24.48 9.49932Z"
fill="#EA4335"
/>
</g>
<defs>
<clipPath id="clip0_17_40">
Expand All @@ -111,7 +150,7 @@ const SignIn = () => {
</div>
</main>
</div>
)
}
);
};

export default SignIn
export default SignIn;
34 changes: 23 additions & 11 deletions src/components/SignUp.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ import { useState } from 'react'
import { Navigate, Link } from 'react-router-dom'
import { useAuth } from '../contexts/authContext/index'
import { doCreateUserWithEmailAndPassword } from '../firebase/auth'
import { AiFillEye, AiFillEyeInvisible } from 'react-icons/ai'

const Register = () => {


const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [confirmPassword, setconfirmPassword] = useState('')
const [isRegistering, setIsRegistering] = useState(false)
const [errorMessage, setErrorMessage] = useState('')
const [showPassword, setShowPassword] = useState(false);
const [showConfirmPassword, setShowConfirmPassword] = useState(false);

const { userLoggedIn } = useAuth()

Expand All @@ -28,14 +30,12 @@ const Register = () => {

return (
<>

<main className="w-full h-screen flex self-center place-content-center place-items-center">
<div className="w-96 text-gray-600 space-y-5 p-4 shadow-xl border rounded-xl">
<div className="text-center mb-6">
<div className="mt-2">
<h3 className="text-gray-800 text-xl font-semibold sm:text-2xl">Create a New Account</h3>
</div>

</div>
<form
onSubmit={onSubmit}
Expand All @@ -50,36 +50,48 @@ const Register = () => {
autoComplete='email'
required
value={email} onChange={(e) => { setEmail(e.target.value) }}
className="w-full mt-2 px-3 py-2 text-gray-500 bg-transparent outline-none border focus:green-600 shadow-sm rounded-lg transition duration-300"
className="w-full mt-2 px-3 py-2 text-gray-500 bg-transparent outline-none border focus:border-green-600 shadow-sm rounded-lg transition duration-300"
/>
</div>

<div>
<div className="relative">
<label className="text-sm text-gray-600 font-bold">
Password
</label>
<input
disabled={isRegistering}
type="password"
type={showPassword ? 'text' : 'password'}
autoComplete='new-password'
required
value={password} onChange={(e) => { setPassword(e.target.value) }}
className="w-full mt-2 px-3 py-2 text-gray-500 bg-transparent outline-none border focus:border-green-600 shadow-sm rounded-lg transition duration-300"
/>
<button
type="button"
className="absolute inset-y-0 right-2 top-9"
onClick={() => setShowPassword(!showPassword)}
>
{showPassword ? <AiFillEyeInvisible /> : <AiFillEye />}
</button>
</div>

<div>
<div className="relative">
<label className="text-sm text-gray-600 font-bold">
Confirm Password
</label>
<input
disabled={isRegistering}
type="password"
type={showConfirmPassword ? 'text' : 'password'}
autoComplete='off'
required
value={confirmPassword} onChange={(e) => { setconfirmPassword(e.target.value) }}
className="w-full mt-2 px-3 py-2 text-gray-500 bg-transparent outline-none border focus:border-green-600 shadow-sm rounded-lg transition duration-300"
/>
<button
type="button"
className="absolute inset-y-0 right-2 top-9"
onClick={() => setShowConfirmPassword(!showConfirmPassword)}
>
{showConfirmPassword ? <AiFillEyeInvisible /> : <AiFillEye />}
</button>
</div>

{errorMessage && (
Expand All @@ -104,4 +116,4 @@ const Register = () => {
)
}

export default Register
export default Register