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

[FIX] #73 : updated login-ui #247

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
237 changes: 156 additions & 81 deletions src/Pages/Login.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import React, { useState, useEffect } from "react";
import "./style.css";
import "./utils.css";
import loader_icon from "../assets/icons/loader_icon.gif";
import { useState, useEffect } from "react";
import { useFirebase } from "../context/firebase";
import { getAuth, onAuthStateChanged } from "firebase/auth";
import { useNavigate, Link } from "react-router-dom";
import { FaEye, FaEyeSlash } from "react-icons/fa";
import "../components/Navbar.css";
import { FaEye, FaEyeSlash, FaFilm, FaTicketAlt } from "react-icons/fa";
import { PiPopcorn } from "react-icons/pi";

const Login = () => {
const firebase = useFirebase();
Expand All @@ -17,7 +14,6 @@ const Login = () => {
const [password, setPassword] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [isPasswordVisible, setIsPasswordVisible] = useState(false);

const [error, setError] = useState("");
const [emailError, setEmailError] = useState("");
const [passwordError, setPasswordError] = useState("");
Expand All @@ -28,8 +24,8 @@ const Login = () => {
navigate("/Home");
}
});
document.title = "Login";
}, [auth]);
document.title = "Login - Movie Tickets";
}, [auth, navigate]);

const resetErrors = () => {
setError("");
Expand All @@ -45,29 +41,26 @@ const Login = () => {
const validateForm = () => {
let isValid = true;
if (email === "") {
setEmailError("(Required Field)");
setEmailError("Required");
isValid = false;
} else if (!validateEmailFormat(email)) {
setEmailError("(Invalid Email Format)");
setEmailError("Invalid format");
isValid = false;
}
if (password === "") {
setPasswordError("(Required Field)");
setPasswordError("Required");
isValid = false;
}
return isValid;
};

const handleSignIn = () => {
resetErrors();
let isValid = validateForm();
if (isValid) {
if (validateForm()) {
setIsLoading(true);
setError("");
firebase
.loginUserWithEmailAndPassword(email, password)
.then(() => {
console.log("User logged in successfully!");
setEmail("");
setPassword("");
setError("");
Expand All @@ -76,7 +69,7 @@ const Login = () => {
if (error.message === "Firebase: Error (auth/invalid-credential).")
setError("Incorrect email or password");
else if (error.message === "Firebase: Error (auth/invalid-email).")
setEmailError("(Invalid Email)");
setEmailError("Invalid Email");
else setError("Can't Sign In, Unexpected error occurred!");
})
.finally(() => {
Expand All @@ -90,77 +83,159 @@ const Login = () => {
};

return (
<>
<div
className="flex justify-center align-center"
style={{ marginTop: "70px" }}
>
<div className="signup-card">
<div className="signup-heading text-center myb-20">Login</div>
<div className="signup-subheading myb-20">
Please provide your email address and password.
<div className="flex h-screen bg-gray-100">
{/* Left side - Image and overlay */}
<div className="hidden lg:flex lg:w-1/2 relative">
<img
src="https://images.unsplash.com/photo-1536440136628-849c177e76a1?q=80&w=1925&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
alt="Movie Theater"
className="object-cover blur-sm w-full h-full"
/>
<div className="absolute inset-0 bg-black bg-opacity-50 flex flex-col justify-center items-center text-white p-8">
<h1 className="text-4xl font-bold mb-4 animate-fade-in-down">
Welcome to Ticketify
</h1>
<p className="text-xl mb-8 animate-fade-in-up">
Your gateway to cinematic adventures
</p>
<div className="flex space-x-4">
<FaFilm className="text-5xl animate-bounce" />
<FaTicketAlt className="text-5xl animate-pulse" />
<PiPopcorn className="text-5xl animate-wiggle" />
</div>
</div>
</div>

<label htmlFor="email" className="label-text">
Email <span className="error-inline mxl-10">{emailError}</span>
</label>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
className={`input-field ${
emailError !== "" ? "error-input-field" : ""
}`}
placeholder="e.g. [email protected]"
/>

<label htmlFor="password" className="label-text">
Password{" "}
<span className="error-inline mxl-10">{passwordError}</span>
</label>
<div className="input-wrapper">
<input
type={isPasswordVisible ? "text" : "password"}
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
className={`input-field ${
passwordError !== "" ? "error-input-field" : ""
}`}
/>
<button
type="button"
className="password-toggle"
onClick={togglePasswordVisibility}
>
{isPasswordVisible ? <FaEyeSlash /> : <FaEye />}
</button>
{/* Right side - Login form */}
<div className="w-full lg:w-1/2 flex items-center justify-center p-8">
<div className="max-w-md w-full space-y-8">
<div>
<h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900">
Sign in to your account
</h2>
</div>
<div className={isLoading ? "show-loader" : "hide-div"}>
<img src={loader_icon} alt="Loader Icon" />
</div>
<span className="error">{error}</span>
<form className="mt-8 space-y-6" onSubmit={(e) => e.preventDefault()}>
<div className="rounded-md shadow-sm -space-y-px">
<div>
<label htmlFor="email-address" className="sr-only">
Email address
</label>
<input
id="email-address"
name="email"
type="email"
autoComplete="email"
required
className={`appearance-none rounded-none relative block w-full px-3 py-2 border ${
emailError ? "border-red-300" : "border-gray-300"
} placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:ring-red-500 focus:border-red-500 focus:z-10 sm:text-sm`}
placeholder="Email address"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
{emailError && (
<p className="mt-2 text-sm text-red-600">{emailError}</p>
)}
</div>
<div className="relative">
<label htmlFor="password" className="sr-only">
Password
</label>
<input
id="password"
name="password"
type={isPasswordVisible ? "text" : "password"}
autoComplete="current-password"
required
className={`appearance-none rounded-none relative block w-full px-3 py-2 border ${
passwordError ? "border-red-300" : "border-gray-300"
} placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:ring-red-500 focus:border-red-500 focus:z-10 sm:text-sm`}
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<button
type="button"
className="absolute inset-y-0 right-0 pr-3 flex items-center text-sm leading-5"
onClick={togglePasswordVisibility}
>
{isPasswordVisible ? (
<FaEyeSlash className="h-5 w-5 text-gray-400" />
) : (
<FaEye className="h-5 w-5 text-gray-400" />
)}
</button>
{passwordError && (
<p className="mt-2 text-sm text-red-600">{passwordError}</p>
)}
</div>
</div>

{error && <p className="mt-2 text-sm text-red-600">{error}</p>}

<button className="btn" onClick={handleSignIn}>
Login
</button>
<span
style={{
marginTop: "20px",
fontSize: "15px",
display: "block",
textAlign: "center",
}}
>
Don't have an account{" "}
<Link to="/SignUp" style={{ color: "#f84464" }}>
Sign Up
<div>
<button
type="submit"
className={`group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-[#f84464] hover:bg-[#df315d] focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 ${
isLoading ? "opacity-50 cursor-not-allowed" : ""
}`}
onClick={handleSignIn}
disabled={isLoading}
>
<span className="absolute left-0 inset-y-0 flex items-center pl-3">
{isLoading ? (
<svg
className="animate-spin h-5 w-5 text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
) : (
<svg
className="h-5 w-5 text-white"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
>
<path
fillRule="evenodd"
d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z"
clipRule="evenodd"
/>
</svg>
)}
</span>
{isLoading ? "Signing in..." : "Sign in"}
</button>
</div>
</form>
<div className="text-sm text-center">
<Link
to="/SignUp"
className="font-medium text-[#f84464] hover:text-[#752152]"
>
Don't have an account? Sign up
</Link>
</span>
</div>
</div>
</div>
</>
</div>
);
};

export default Login;
export default Login;