quikfrontend
Version:
A CLI tool for generating React-Vite frontend projects with pre-configured setups
327 lines (301 loc) • 11.8 kB
JSX
import React, { useState } from 'react';
import { Eye, EyeOff } from 'lucide-react';
import { useNavigate } from 'react-router-dom';
import { useDispatch } from 'react-redux';
import { GoogleLogin } from '@react-oauth/google';
import {
login,
loginWithGoogle,
register,
} from '../../services/repository/userRepo';
const Login = () => {
const [isLoginView, setIsLoginView] = useState(true);
const [showPassword, setShowPassword] = useState(false);
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [name, setName] = useState('');
const [mobile, setMobile] = useState('');
const navigate = useNavigate();
const dispatch = useDispatch();
const handleSubmit = (e) => {
e.preventDefault();
if (isLoginView) {
dispatch(login(email, password, navigate));
} else {
dispatch(register(name, email, password, mobile, navigate));
}
};
const handleSuccess = async (credentialResponse) => {
dispatch(loginWithGoogle(credentialResponse, navigate));
};
const handleError = () => {
alert('Google Sign-In failed');
};
const toggleView = () => {
setIsLoginView(!isLoginView);
};
return (
<div className="flex items-center justify-center min-h-screen bg-gray-50">
<div className="w-full max-w-md bg-white rounded-lg shadow-md p-8">
{/* Logo */}
<div className="flex justify-center mb-6">
<div className="w-12 h-12 bg-green-500 rounded-full flex items-center justify-center">
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M17 8C8 10 5.9 16.17 3.82 21.34L5.71 22L6.66 19.7C7.14 19.87 7.64 20 8 20C19 20 22 3 22 3C21 5 14 5.25 9 6.25C4 7.25 2 11.5 2 13.5C2 15.5 3.75 17.25 3.75 17.25C7 8 17 8 17 8Z"
fill="white"
/>
</svg>
</div>
</div>
{isLoginView ? (
<div>
<h2 className="text-2xl font-bold text-center mb-6 text-gray-800">
Sign In
</h2>
<form className="space-y-4" onSubmit={handleSubmit}>
<div>
<label
htmlFor="email"
className="block text-sm font-medium text-gray-700 mb-1"
>
Email
</label>
<input
type="email"
id="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
placeholder="Enter your email"
required
/>
</div>
<div>
<label
htmlFor="password"
className="block text-sm font-medium text-gray-700 mb-1"
>
Password
</label>
<div className="relative">
<input
type={showPassword ? 'text' : 'password'}
id="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
placeholder="Enter your password"
required
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-500"
>
{showPassword ? <EyeOff size={18} /> : <Eye size={18} />}
</button>
</div>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center">
<input
id="remember-me"
name="remember-me"
type="checkbox"
className="h-4 w-4 text-green-600 focus:ring-green-500 border-gray-300 rounded"
/>
<label
htmlFor="remember-me"
className="ml-2 block text-sm text-gray-700"
>
Remember me
</label>
</div>
<a
href="#"
className="text-sm font-medium text-green-600 hover:text-green-500"
>
Forgot password?
</a>
</div>
<button
type="submit"
className="w-full bg-green-600 text-white py-2 px-4 rounded-md hover:bg-green-700 transition"
>
Sign In
</button>
</form>
<div className="mt-6">
<div className="relative">
<div className="absolute inset-0 flex items-center">
<div className="w-full border-t border-gray-300"></div>
</div>
<div className="relative flex justify-center text-sm">
<span className="px-2 bg-white text-gray-500">
Or continue with
</span>
</div>
</div>
<div className="mt-6">
<div className="w-full">
<GoogleLogin
onSuccess={handleSuccess}
onError={handleError}
scope="email profile"
/>
</div>
</div>
</div>
<p className="mt-6 text-center text-sm text-gray-600">
Don't have an account?{' '}
<button
onClick={toggleView}
className="font-medium text-green-600 hover:text-green-500"
>
Sign up
</button>
</p>
</div>
) : (
<div>
<h2 className="text-2xl font-bold text-center mb-6 text-gray-800">
Create Account
</h2>
<form className="space-y-4" onSubmit={handleSubmit}>
<div>
<label
htmlFor="name"
className="block text-sm font-medium text-gray-700 mb-1"
>
Full Name
</label>
<input
type="text"
id="name"
value={name}
onChange={(e) => setName(e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
placeholder="Enter your full name"
required
/>
</div>
<div>
<label
htmlFor="mobile"
className="block text-sm font-medium text-gray-700 mb-1"
>
Mobile Number
</label>
<input
type="tel"
id="mobile"
value={mobile}
onChange={(e) => setMobile(e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
placeholder="Enter your mobile number"
/>
</div>
<div>
<label
htmlFor="register-email"
className="block text-sm font-medium text-gray-700 mb-1"
>
Email
</label>
<input
type="email"
id="register-email"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
placeholder="Enter your email"
required
/>
</div>
<div>
<label
htmlFor="register-password"
className="block text-sm font-medium text-gray-700 mb-1"
>
Password
</label>
<div className="relative">
<input
type={showPassword ? 'text' : 'password'}
id="register-password"
value={password}
onChange={(e) => setPassword(e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
placeholder="Create a password"
required
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-500"
>
{showPassword ? <EyeOff size={18} /> : <Eye size={18} />}
</button>
</div>
</div>
<button
type="submit"
className="w-full bg-green-600 text-white py-2 px-4 rounded-md hover:bg-green-700 transition"
>
Create Account
</button>
</form>
<div className="mt-6">
<div className="relative">
<div className="absolute inset-0 flex items-center">
<div className="w-full border-t border-gray-300"></div>
</div>
<div className="relative flex justify-center text-sm">
<span className="px-2 bg-white text-gray-500">
Or sign up with
</span>
</div>
</div>
<div className="mt-6">
<div className="w-full">
<GoogleLogin
onSuccess={handleSuccess}
onError={handleError}
scope="email profile"
/>
</div>
</div>
</div>
<p className="mt-6 text-center text-sm text-gray-600">
Already have an account?{' '}
<button
onClick={toggleView}
className="font-medium text-green-600 hover:text-green-500"
>
Sign in
</button>
</p>
</div>
)}
<p className="mt-6 text-xs text-center text-gray-500">
By continuing, you agree to our{' '}
<a href="#" className="text-green-600 hover:text-green-500">
Terms of Service
</a>{' '}
and{' '}
<a href="#" className="text-green-600 hover:text-green-500">
Privacy Policy
</a>
</p>
</div>
</div>
);
};
export default Login;