Skip to content

Commit

Permalink
Merge pull request #442 from Sourabh782/admin
Browse files Browse the repository at this point in the history
implemented admin login/signup
  • Loading branch information
RamakrushnaBiswal authored Nov 4, 2024
2 parents e5d522e + 7c09828 commit 3a4fa96
Show file tree
Hide file tree
Showing 13 changed files with 433 additions and 9 deletions.
7 changes: 6 additions & 1 deletion backend/controller/admin.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,16 @@ async function loginAdmin(req, res) {
const token = jwt.sign(payload, process.env.JWT_SECRET, {
expiresIn: "1h",
});
res.cookie("authToken", token, {
maxAge: 1000 * 60 * 60,
httpOnly: true,
secure: true,
});
res.json({
message: "Login successful",
token,
role: "admin",
admin: { id: admin._id, name: admin.name, email: admin.email },
admin: { id: admin._id, name: admin.name, email: admin.email, role: admin.role || "admin" },
});
} catch (error) {
logger.error("Error logging in admin:", {
Expand Down
1 change: 1 addition & 0 deletions backend/controller/customer.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ async function loginCustomer(req, res) {
id: customer._id,
name: customer.name,
email: customer.email,
role: "customer"
},
});
} catch (error) {
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/components/Pages/Admin.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { message } from 'antd';
import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useUser } from '../../context/userContext';

const Admin = () => {
const [events, setEvents] = useState([]);
const [error, setError] = useState(null);
const navigate = useNavigate();
const {user} = useUser();

// Fetch all events
const fetchData = async () => {
Expand Down Expand Up @@ -122,7 +124,7 @@ const Admin = () => {
<div className="h-fit min-h-screen w-screen flex flex-col items-center justify-start p-12 pt-[10vh]">
<div className="Header w-full flex flex-col items-center">
<h1 className="title text-[#323232] font-black text-7xl mb-6">
Hi {Admin.name}!
Hi {user.name}!
</h1>
<h1 className="mt-[-2vh] text-[#666] font-semibold text-2xl">
Welcome to Admin Panel
Expand Down Expand Up @@ -265,7 +267,7 @@ const Admin = () => {
<div className="container grid grid-cols-1 gap-8 px-4 md:grid-cols-2 lg:grid-cols-1 md:px-6">
<div className="event-list">
{error && <p className="text-red-500">{error}</p>}
{events.map((event) => (
{events.length > 0 && events.map((event) => (
<div
key={event._id}
className="grid grid-cols-1 md:grid-cols-2 gap-10 lg:grid-cols-1 xl:grid-cols-2 md:px-6 lg:px-4 xl:px-0"
Expand Down
159 changes: 159 additions & 0 deletions frontend/src/components/Pages/Admin/AdminLogin.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import React, { useState, useEffect } from 'react';
import photo from '../../../assets/login.png';
import { Link, useNavigate } from 'react-router-dom';
import { message } from 'antd';
import Cookies from 'js-cookie';
import { FaEye } from 'react-icons/fa';
import { FaEyeSlash } from 'react-icons/fa6';
import { useUser } from '../../../context/userContext';

const AdminLogin = () => {
const API_URL = import.meta.env.VITE_BACKEND_URL || 'http://localhost:3000';
const [data, setData] = useState({
email: '',
password: '',
});
const [hidden, setHidden] = useState(true);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const {user, setUser} = useUser();

const navigate = useNavigate();

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

const handleSubmit = async (e) => {
e.preventDefault();
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(data.email)) {
setError('Please enter a valid email address');
return;
}
if (data.password.length < 8) {
setError('Password must be at least 8 characters long');
return;
}
setIsLoading(true);
setError(null);
try {
const response = await fetch(`${API_URL}/api/admin/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
const result = await response.json();
if (!response.ok) {
throw new Error(result.message || 'Login failed');
}
const res = JSON.stringify(result.admin)
Cookies.set('authToken', result.token, { expires: 1, secure: true });
Cookies.set("authenticatedUser", res, {expires: 1, secure: true})
setUser(result.admin)
message.success('Login successful');
navigate('/admin');
} catch (err) {
setError(err.message || 'An error occurred. Please try again.');
} finally {
setIsLoading(false);
}
};

useEffect(() => {
window.scrollTo(0, 0);
}, []);

return (
<div className="w-screen h-screen dark:bg-black 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={handleSubmit}
className="z-10 p-8 lg:p-14 bg-[#f1e9dc] dark:bg-amber-800 dark:text-white 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="text-[#323232] dark:text-white font-black text-4xl lg:text-6xl mb-2">
Admin Login,
<span className="block text-[#666] dark:text-gray-400 font-semibold text-lg lg:text-2xl mt-1">
Log in to continue
</span>
</div>

<input
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={handleChange}
/>

<div className="relative w-full">
<input
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={handleChange}
/>
<button
className="absolute top-1/2 transform -translate-y-1/2 right-4"
onClick={(e) => {
e.preventDefault();
setHidden(!hidden);
}}
>
{hidden ? <FaEyeSlash /> : <FaEye />}
</button>
</div>

<Link
to="/email-verify"
className="text-sm lg:text-base text-gray-500 dark:text-gray-200 hover:text-red-500 transition"
>
Forgot Password?
</Link>

<h3 className="flex justify-between items-center w-full text-sm lg:text-base">
Don’t have an account?
<Link
to="/admin-signup"
className="text-green-500 font-semibold hover:scale-110 transition"
>
Register Here
</Link>
</h3>

<Link
to={`${API_URL}/api/user/auth/google`}
className="w-full"
>
<button
type="button"
className="w-full h-12 rounded-md border-2 dark:text-white 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>
</Link>

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

<button
type="submit"
className="w-full h-12 rounded-md dark:text-white 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>
</form>
</div>
);
};

export default AdminLogin;
Loading

0 comments on commit 3a4fa96

Please sign in to comment.