Skip to content

Commit 4b0100b

Browse files
committed
Fixed signin page, still need to work on validation for signin form
1 parent e5a11c6 commit 4b0100b

File tree

5 files changed

+218
-46
lines changed

5 files changed

+218
-46
lines changed

frontend/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"axios": "^1.7.2",
2222
"dotenv": "^16.4.5",
2323
"firebase": "^10.12.2",
24+
"framer-motion": "^11.2.12",
2425
"locomotive-aos": "^1.0.7",
2526
"locomotive-scroll": "^4.1.4",
2627
"pnpm": "^9.4.0",
@@ -29,6 +30,7 @@
2930
"react-dom": "^18.3.1",
3031
"react-google-button": "^0.8.0",
3132
"react-helmet-async": "^2.0.5",
33+
"react-icons": "^5.2.1",
3234
"sonner": "^1.5.0"
3335
},
3436
"devDependencies": {

frontend/pnpm-lock.yaml

+36
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
+178-34
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,196 @@
1-
import { useState } from 'react';
2-
import { auth, signInWithGoogle, signInWithEmailAndPassword } from '../../firebaseConfig';
3-
// import { GoogleButton } from 'react-google-button'
4-
import { UserAuth } from '../context/AuthContext';
1+
// SignIn.jsx
2+
import React, { useState } from 'react';
3+
import {
4+
auth,
5+
signInWithGoogle,
6+
signInWithEmailAndPassword,
7+
signInWithDiscord
8+
} from '../../firebaseConfig';
9+
import { UserAuth } from '../../context/AuthContext';
10+
import { FaGoogle, FaDiscord } from 'react-icons/fa';
11+
import { motion } from 'framer-motion';
512

613
const SignIn = () => {
714
const [email, setEmail] = useState('');
815
const [password, setPassword] = useState('');
916

17+
const [isLoading, setIsLoading] = useState(false);
18+
const [mode, setMode] = useState('signin'); // 'signin', 'signup', 'resetPassword'
19+
20+
21+
const [touched, setTouched] = useState({});
22+
const [errors, setErrors] = useState({});
23+
1024
const { googleSignIn } = UserAuth();
11-
12-
const handleGoogleSignIn = async () => {
13-
try {
14-
const { user } = await googleSignIn();
15-
console.log(user, "Logged in with Google");
16-
} catch (error) {
17-
console.log(error);
18-
}
25+
26+
const handleGoogleSignIn = async () => {
27+
setIsLoading(true);
28+
try {
29+
const { user } = await googleSignIn();
30+
console.log(user, "Logged in with Google");
31+
} catch (error) {
32+
console.log(error);
33+
} finally {
34+
setIsLoading(false);
35+
}
36+
};
37+
38+
const handleEmailSignIn = async (e) => {
39+
e.preventDefault();
40+
if (validate()) {
41+
setIsLoading(true);
42+
try {
43+
await signInWithEmailAndPassword(auth, email, password);
44+
console.log('Logged in');
45+
} catch (error) {
46+
console.error(error);
47+
setErrors({ ...errors, auth: 'Invalid email or password' });
48+
} finally {
49+
setIsLoading(false);
50+
}
1951
}
52+
};
2053

21-
const handleLogin = async () => {
54+
const handleDiscordSignIn = async () => {
55+
setIsLoading(true);
2256
try {
23-
await signInWithEmailAndPassword(auth, email, password);
24-
console.log('Logged in');
57+
await signInWithDiscord();
2558
} catch (error) {
2659
console.error(error);
60+
} finally {
61+
setIsLoading(false);
62+
}
63+
};
64+
65+
const handleResetPassword = async () => {
66+
// Implement password reset logic
67+
};
68+
69+
const handleSignUp = async () => {
70+
// Implement sign up logic
71+
};
72+
73+
const inputClassNames = (field) => {
74+
let baseClasses = "w-full px-4 py-2 bg-white border border-slate-300 rounded-md text-md shadow-sm placeholder-slate-400 focus:outline-none focus:border-sky-500 focus:ring-1 focus:ring-sky-500 transition-colors";
75+
if (errors[field] && touched[field]) {
76+
baseClasses += " border-pink-500 text-pink-600 focus:border-pink-500 focus:ring-pink-500";
77+
}
78+
return baseClasses;
79+
};
80+
81+
const handleBlur = (e) => {
82+
const { name } = e.target;
83+
setTouched({ ...touched, [name]: true });
84+
};
85+
86+
const validate = () => {
87+
let tempErrors = {};
88+
if (!email || !/\S+@\S+\.\S+/.test(email)) {
89+
tempErrors.email = 'Valid email is required';
90+
}
91+
if (mode !== 'resetPassword' && (!password || password.length < 6)) {
92+
tempErrors.password = 'Password must be at least 6 characters';
2793
}
94+
setErrors(tempErrors);
95+
return Object.keys(tempErrors).length === 0;
2896
};
2997

3098
return (
31-
<div className="login-container">
32-
<h1>Login</h1>
33-
<input
34-
type="email"
35-
value={email}
36-
onChange={(e) => setEmail(e.target.value)}
37-
placeholder="Email"
38-
/>
39-
<input
40-
type="password"
41-
value={password}
42-
onChange={(e) => setPassword(e.target.value)}
43-
placeholder="Password"
44-
/>
45-
<button onClick={handleLogin}>Login</button>
46-
<button onClick={handleGoogleSignIn}>Login with Google</button>
47-
<button onClick={() => alert('Implement Discord login')}>Login with Discord</button>
99+
<div className="min-h-screen flex items-center justify-center bg-gradient-to-r from-cyan-500 to-blue-500 p-4" style={{animation: 'bounceIn 1s ease-in-out'}}>
100+
<motion.div
101+
initial={{ opacity: 0, y: -50 }}
102+
animate={{ opacity: 1, y: 0 }}
103+
transition={{ duration: 0.5 }}
104+
className="bg-white p-8 rounded-lg shadow-xl w-full max-w-md"
105+
>
106+
<h2 className="text-3xl font-bold mb-6 text-center text-gray-800">
107+
{mode === 'signin' ? 'Sign In' : mode === 'signup' ? 'Sign Up' : 'Reset Password'}
108+
</h2>
109+
110+
<form onSubmit={handleEmailSignIn} className="space-y-4">
111+
112+
<input
113+
type="email"
114+
name="email"
115+
value={email}
116+
onChange={(e) => setEmail(e.target.value)}
117+
onBlur={handleBlur}
118+
placeholder="Email"
119+
className={inputClassNames('email')}
120+
/>
121+
{errors.email && touched.email && <p className="text-red-500 text-sm mt-1">{errors.email}</p>}
122+
123+
{mode !== 'resetPassword' && (
124+
<>
125+
<input
126+
type="password"
127+
name="password"
128+
value={password}
129+
onChange={(e) => setPassword(e.target.value)}
130+
onBlur={handleBlur}
131+
placeholder="Password"
132+
className={inputClassNames('password')}
133+
/>
134+
{errors.password && touched.password && <p className="text-red-500 text-sm mt-1">{errors.password}</p>}
135+
</>
136+
)}
137+
138+
<motion.button
139+
whileHover={{ scale: 1.05 }}
140+
whileTap={{ scale: 0.95 }}
141+
type="submit"
142+
className="w-full bg-blue-600 text-white py-2 rounded-md hover:bg-blue-700 transition duration-300"
143+
disabled={isLoading}
144+
>
145+
{isLoading ? 'Loading...' : mode === 'signin' ? 'Sign In' : mode === 'signup' ? 'Sign Up' : 'Reset Password'}
146+
</motion.button>
147+
</form>
148+
149+
<div className="mt-4 flex flex-col space-y-2">
150+
<motion.button
151+
whileHover={{ scale: 1.05 }}
152+
whileTap={{ scale: 0.95 }}
153+
onClick={handleGoogleSignIn}
154+
className="flex items-center justify-center w-full bg-white text-gray-700 py-2 px-4 rounded-md border border-gray-300 hover:bg-gray-100 transition duration-300"
155+
disabled={isLoading}
156+
>
157+
<FaGoogle className="mr-2" /> Continue with Google
158+
</motion.button>
159+
<motion.button
160+
whileHover={{ scale: 1.05 }}
161+
whileTap={{ scale: 0.95 }}
162+
onClick={handleDiscordSignIn}
163+
className="flex items-center justify-center w-full bg-indigo-600 text-white py-2 px-4 rounded-md hover:bg-indigo-700 transition duration-300"
164+
disabled={isLoading}
165+
>
166+
<FaDiscord className="mr-2" /> Continue with Discord
167+
</motion.button>
168+
</div>
169+
170+
<div className="mt-4 text-center">
171+
<a
172+
href="#"
173+
onClick={() => setMode('resetPassword')}
174+
className="text-sm text-blue-600 hover:underline"
175+
>
176+
Forgot password?
177+
</a>
178+
</div>
179+
180+
<div className="mt-4 text-center">
181+
<span className="text-sm text-gray-600">
182+
{mode === 'signin' ? "Don't have an account? " : "Already have an account? "}
183+
</span>
184+
<a href="#"
185+
onClick={() => setMode(mode === 'signin' ? 'signup' : 'signin')}
186+
className="text-sm text-blue-600 hover:underline"
187+
>
188+
{mode === 'signin' ? 'Sign up' : 'Sign in'}
189+
</a>
190+
</div>
191+
</motion.div>
48192
</div>
49193
);
50-
};
194+
}
51195

52-
export default SignIn;
196+
export default SignIn;

frontend/src/routes/Login.jsx

+1-11
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,7 @@ function Login() {
2222
}
2323

2424
return (
25-
<>
26-
<SignIn/>
27-
<div>
28-
<div className="flex justify-center items-center h-screen m-auto max-w-80 py-4">
29-
<GoogleButton
30-
onClick={handleGoogleSignIn}
31-
className="custom-google-button"
32-
/>
33-
</div>
34-
</div>
35-
</>
25+
<SignIn/>
3626
)
3727
}
3828

frontend/tailwind.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ module.exports = {
1111
},
1212
fontFamily: {
1313
sans: ['"Bai Jamjuree"', "sans-serif"],
14-
serif: ['"Bebas Neue"', "serif"]
14+
slab: ['"Bebas Neue"', "sans-serif"],
1515
serif: ['"Montserrat"', "serif"]
1616
}
1717
},

0 commit comments

Comments
 (0)