Skip to content

Commit

Permalink
Merge pull request #366 from Shahharshii/login/signup-responsive
Browse files Browse the repository at this point in the history
Login/signup responsive
  • Loading branch information
RamakrushnaBiswal authored Oct 21, 2024
2 parents 8003bb4 + c38c275 commit 853167b
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 93 deletions.
5 changes: 2 additions & 3 deletions frontend/src/components/Pages/About.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@

import bgpic from "../../assets/img/abt1.jpg";
'use client';
import bgpic from '../../assets/img/abt1.jpg';
import React, { useEffect } from 'react';


export default function About() {
useEffect(() => {
window.scrollTo(0, 0);
Expand Down
75 changes: 44 additions & 31 deletions frontend/src/components/Pages/Login.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ const Login = () => {
password: '',
});
const [hidden, setHidden] = useState(true);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);

const navigate = useNavigate();

const handleChange = (e) => {
setData({ ...data, [e.target.name]: e.target.value });
};
const navigate = useNavigate(); // Correctly initialize useNavigate
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);

const handleSubmit = async (e) => {
e.preventDefault();
Expand All @@ -37,11 +38,7 @@ const Login = () => {
if (!response.ok) {
throw new Error(result.message || 'Login failed');
}
// Handle successful login (e.g., store token, redirect)
Cookies.set('authToken', result.token, {
expire: '1h',
secure: true,
});
Cookies.set('authToken', result.token, { expire: '1h', secure: true });
message.success('Login successful');
navigate('/');
} catch (err) {
Expand All @@ -56,37 +53,44 @@ const Login = () => {
}, []);

return (
<div className="w-screen h-screen flex items-center justify-center pt-10">
<img src={photo} alt="login" loading="lazy" className=" w-3/4 absolute" />
<div className="w-screen h-screen flex items-center justify-center lg:pt-10 px-4">
{/* Background Image */}
<img
src={photo}
alt="login"
loading="lazy"
className="absolute w-3/4 lg:w-auto lg:opacity-100 opacity-10 object-cover"
/>
{/* Login Form */}
<form
onSubmit={(e) => handleSubmit(e)}
className="form z-10 p-16 bg-lightblue flex flex-col items-start justify-center gap-4 rounded-lg border-2 border-black shadow-[4px_4px_0px_0px_black] bg-[#f1e9dc]"
onSubmit={handleSubmit}
className="z-10 p-8 lg:p-16 bg-[#f1e9dc] flex flex-col gap-6 rounded-lg border-2 border-black shadow-[4px_4px_0px_0px_black] w-full max-w-md lg:max-w-xl"
>
<div className="title text-[#323232] font-black text-7xl mb-6">
<div className="text-[#323232] font-black text-4xl lg:text-7xl mb-2">
Welcome,
<br />
<span className="block text-[#666] font-semibold text-2xl ">
<span className="block text-[#666] font-semibold text-lg lg:text-2xl mt-1">
Log in to continue
</span>
</div>

<input
className="input w-full h-10 rounded-md border-2 border-black bg-beige shadow-[4px_4px_0px_0px_black] text-[15px] font-semibold text-[#323232] p-2.5 focus:outline-none focus:border-[#2d8cf0] placeholder-[#666] placeholder-opacity-80"
className="w-full h-12 rounded-md border-2 border-black bg-beige shadow-[4px_4px_0px_0px_black] text-[15px] font-semibold text-[#323232] p-2.5 focus:outline-none focus:border-[#2d8cf0] placeholder-[#666]"
name="email"
placeholder="Email"
type="email"
onChange={(e) => handleChange(e)}
onChange={handleChange}
/>

<div className="relative w-full">
<input
className="input w-full h-10 rounded-md border-2 border-black bg-beige shadow-[4px_4px_0px_0px_black] text-[15px] font-semibold text-[#323232] p-2.5 focus:outline-none focus:border-[#2d8cf0] placeholder-[#666] placeholder-opacity-80"
className="w-full h-12 rounded-md border-2 border-black bg-beige shadow-[4px_4px_0px_0px_black] text-[15px] font-semibold text-[#323232] p-2.5 focus:outline-none focus:border-[#2d8cf0] placeholder-[#666]"
name="password"
placeholder="Password"
type={hidden ? 'password' : 'text'}
onChange={(e) => handleChange(e)}
onChange={handleChange}
/>
<button
className="absolute top-1/2 -translate-y-1/2 right-4"
className="absolute top-1/2 transform -translate-y-1/2 right-4"
onClick={(e) => {
e.preventDefault();
setHidden(!hidden);
Expand All @@ -96,31 +100,40 @@ const Login = () => {
</button>
</div>

<div className="transform hover:text-red-500 transition">
<Link to={'/email-verify'}>Forgot Password?</Link>
</div>
<Link
to="/email-verify"
className="text-sm lg:text-base text-gray-500 hover:text-red-500 transition"
>
Forgot Password?
</Link>

<h3 className="flex items-center justify-between w-full">
Dont have an account?
<span className="block text-[#666] font-semibold text-xl transform hover:scale-110 hover:-translate-y-1 hover:text-green-500 transition">
<Link to={'/signup'}>Register Here</Link>
</span>
<h3 className="flex justify-between items-center w-full text-sm lg:text-base">
Don’t have an account?
<Link
to="/signup"
className="text-green-500 font-semibold hover:scale-110 transition"
>
Register Here
</Link>
</h3>

<a
href={`${API_URL}/api/user/auth/google`}
className="text-[#666] font-semibold text-xl transform hover:scale-110 hover:-translate-y-1 hover:text-green-500 transition w-full"
className="w-full"
>
<button
type="button"
className="button-confirm px-4 w-full h-10 rounded-md border-2 border-black bg-beige shadow-[4px_4px_0px_0px_black] text-[17px] font-semibold text-[#323232] cursor-pointer active:shadow-none active:translate-x-[3px] active:translate-y-[3px]"
className="w-full h-12 rounded-md border-2 border-black bg-beige shadow-[4px_4px_0px_0px_black] text-[17px] font-semibold text-[#323232] transition active:translate-x-[3px] active:translate-y-[3px]"
>
Sign in with Google
</button>
</a>

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

<button
type="submit"
className="button-confirm px-4 w-30 h-10 rounded-md border-2 border-black bg-beige shadow-[4px_4px_0px_0px_black] text-[17px] font-semibold text-[#323232] cursor-pointer active:shadow-none active:translate-x-[3px] active:translate-y-[3px]"
className="w-full h-12 rounded-md border-2 border-black bg-beige shadow-[4px_4px_0px_0px_black] text-[17px] font-semibold text-[#323232] transition active:translate-x-[3px] active:translate-y-[3px]"
>
{isLoading ? 'Loading...' : 'Let’s Log you in →'}
</button>
Expand Down
90 changes: 34 additions & 56 deletions frontend/src/components/Pages/Signup.jsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,24 @@
import { useState, useEffect } from 'react';
import photo from '../../assets/login.png';
import { useNavigate } from 'react-router-dom';
import { Link } from 'react-router-dom';
import { useNavigate, Link } from 'react-router-dom';
import { FaEye } from 'react-icons/fa';
import { FaEyeSlash } from 'react-icons/fa6';
import zxcvbn from 'zxcvbn'; // Import zxcvbn for password strength check
import zxcvbn from 'zxcvbn'; // Password strength checker

const Signup = () => {
const API_URL = import.meta.env.VITE_BACKEND_URL || 'http://localhost:3000';
const navigate = useNavigate();
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const [passwordStrength, setPasswordStrength] = useState(0); // State to track password strength
const [data, setData] = useState({
name: '',
email: '',
password: '',
});
const [passwordStrength, setPasswordStrength] = useState(0);
const [data, setData] = useState({ name: '', email: '', password: '' });
const [hidden, setHidden] = useState(true);

const handleChange = (e) => {
setData({ ...data, [e.target.name]: e.target.value });

if (e.target.name === 'password') {
const result = zxcvbn(e.target.value);
setPasswordStrength(result.score); // Update password strength score
setPasswordStrength(result.score);
}
};

Expand All @@ -36,42 +30,33 @@ const Signup = () => {
setIsLoading(false);
return;
}

if (data.password.length < 8) {
setError('Password must be at least 8 characters long');
setIsLoading(false);
return;
}

if (data.name.length < 3) {
setError('Name must be at least 3 characters long');
setIsLoading(false);
return;
}

if (!data.email.includes('@')) {
setError('Please enter a valid email address');
setIsLoading(false);
return;
}

try {
const response = await fetch(`${API_URL}/api/user/register`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
const result = await response.json();

if (!response.ok) {
setIsLoading(false);
setError(result.error);
return;
}

// Handle successful registration
alert('Registered successfully! Please log in.');
navigate('/');
} catch (error) {
Expand All @@ -95,43 +80,42 @@ const Signup = () => {
};

return (
<div className="w-screen h-screen flex items-center justify-center pt-10">
<img src={photo} alt="login" loading="lazy" className=" w-3/4 absolute" />
<form className="form z-10 p-16 bg-lightblue flex flex-col items-start justify-center gap-5 rounded-lg border-2 border-black shadow-[4px_4px_0px_0px_black] bg-[#f1e9dc]">
<div className="title text-[#323232] font-black text-7xl mb-6">
<div className="w-screen h-screen flex items-center justify-center pt-10 relative overflow-hidden">
<img
src={photo}
alt="login"
loading="lazy"
className="w-3/4 absolute inset-0"
/>
<form className="z-10 p-8 sm:p-16 bg-[#f1e9dc] rounded-lg border-2 border-black shadow-[4px_4px_0px_0px_black] flex flex-col gap-5 w-11/12 sm:w-auto px-[3vw] pt-[5vh]">
<div className="text-[#323232] font-black text-4xl sm:text-7xl mb-4 sm:mb-6 mt-4">
Play Cafe,
<br />
<span className="block text-[#666] font-semibold text-2xl ">
<span className="block text-[#666] font-semibold text-xl sm:text-2xl">
Register to continue
</span>
</div>
<label htmlFor="name" className="sr-only"></label>
<input
className="input w-full h-10 rounded-md border-2 border-black bg-beige shadow-[4px_4px_0px_0px_black] text-[15px] font-semibold text-[#323232] p-2.5 focus:outline-none focus:border-[#2d8cf0] placeholder-[#666] placeholder-opacity-80"
className="input w-full h-10 rounded-md border-2 border-black bg-beige p-2.5 shadow-[4px_4px_0px_0px_black] focus:outline-none"
name="name"
placeholder="Name"
type="name"
autoComplete="name"
aria-required="true"
onChange={(e) => handleChange(e)}
type="text"
onChange={handleChange}
/>
<label htmlFor="email" className="sr-only"></label>
<input
className="input w-full h-10 rounded-md border-2 border-black bg-beige shadow-[4px_4px_0px_0px_black] text-[15px] font-semibold text-[#323232] p-2.5 focus:outline-none focus:border-[#2d8cf0] placeholder-[#666] placeholder-opacity-80"
className="input w-full h-10 rounded-md border-2 border-black bg-beige p-2.5 shadow-[4px_4px_0px_0px_black] focus:outline-none"
name="email"
placeholder="Email"
autoComplete="email"
type="email"
onChange={(e) => handleChange(e)}
onChange={handleChange}
/>
<label htmlFor="password" className="sr-only"></label>
<div className="relative w-full">
<input
className="input w-full h-10 rounded-md border-2 border-black bg-beige shadow-[4px_4px_0px_0px_black] text-[15px] font-semibold text-[#323232] p-2.5 focus:outline-none focus:border-[#2d8cf0] placeholder-[#666] placeholder-opacity-80"
className="input w-full h-10 rounded-md border-2 border-black bg-beige p-2.5 shadow-[4px_4px_0px_0px_black] focus:outline-none"
name="password"
placeholder="Password"
type={hidden ? 'password' : 'text'}
onChange={(e) => handleChange(e)}
onChange={handleChange}
/>
<button
className="absolute top-1/2 -translate-y-1/2 right-4"
Expand All @@ -143,8 +127,6 @@ const Signup = () => {
{hidden ? <FaEyeSlash /> : <FaEye />}
</button>
</div>

{/* Password Strength Meter */}
<div className="w-full mt-2">
<div
className="h-2 rounded-full"
Expand All @@ -157,32 +139,28 @@ const Signup = () => {
Strength: {getPasswordStrengthText(passwordStrength)}
</p>
</div>

{error && (
<div className="w-full p-2 bg-red-100 text-red-700 border border-red-400 rounded-md">
{error}
</div>
)}
<h3 className="flex items-center justify-between w-full">
<h3 className="flex justify-between w-full">
Already have an account?
<span className="block text-[#666] font-semibold text-xl transform hover:scale-110 hover:-translate-y-1 hover:text-green-500 transition">
<Link to={'/login'}>Login</Link>
</span>
</h3>
<a
href={`${import.meta.env.VITE_BACKEND_URL}/api/user/auth/google`}
className="text-[#666] font-semibold text-xl transform hover:scale-110 hover:-translate-y-1 hover:text-green-500 transition w-full "
>
<button
type="button"
className="button-confirm px-4 w-full h-10 rounded-md border-2 border-black bg-beige shadow-[4px_4px_0px_0px_black] text-[17px] font-semibold text-[#323232] cursor-pointer active:shadow-none active:translate-x-[3px] active:translate-y-[3px]"
<Link
to="/login"
className="text-[#666] font-semibold hover:text-green-500"
>
Login
</Link>
</h3>
<a href={`${API_URL}/api/user/auth/google`} className="w-full">
<button className="button-confirm w-full h-10 rounded-md border-2 border-black bg-beige text-[17px] font-semibold shadow-[4px_4px_0px_0px_black]">
Sign up with Google
</button>
</a>
<button
className="button-confirm mx-auto px-4 w-30 h-10 rounded-md border-2 border-black bg-beige shadow-[4px_4px_0px_0px_black] text-[17px] font-semibold text-[#323232] cursor-pointer active:shadow-none active:translate-x-[3px] active:translate-y-[3px]"
onClick={(e) => handleSubmit(e)}
className="button-confirm w-full h-10 rounded-md border-2 border-black bg-beige text-[17px] font-semibold shadow-[4px_4px_0px_0px_black] mb-2"
onClick={handleSubmit}
>
{isLoading ? 'Loading...' : "Let's go →"}
</button>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/Shared/Navbar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const Navbar = () => {
{ name: 'BOARDGAMES', path: '/boardgame' },
{ name: 'MEMBERSHIP', path: '/membership' }, // Add Membership here
];

useEffect(() => {
setToken(Cookies.get('authToken'));
});
Expand Down Expand Up @@ -107,7 +107,7 @@ const Navbar = () => {
</ul>
</div>

<div className="hidden md:flex font-semibold Poppins text-lg">
<div className="hidden md:flex font-semibold Poppins text-lg hover:bg-lime-200">
{token ? (
<button
className={`${baseTextColorClass} ${hoverTextColorClass} px-4 py-1 rounded-md border-2 border-black bg-beige shadow-[4px_4px_0px_0px_black] font-semibold text-[#323232]`}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/ui/Landing.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function Landing() {
<div className="flex-col md:flex pt-20 z-1">
{/* Text Content */}
<div className="p-4 md:w-1/2 mb-6 md:mb-0 text-center md:text-left z-10 pt-14">
<h1 className="text-6xl md:text-9xl font-bold ml-4" ref={textRef}>
<h1 className="text-5xl md:text-9xl font-bold ml-4" ref={textRef}>
A unique café experience awaits you
</h1>
</div>
Expand Down

0 comments on commit 853167b

Please sign in to comment.