diff --git a/client/package-lock.json b/client/package-lock.json index 8dc078b..933f7f1 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -45,7 +45,7 @@ "react-dom": "^18.2.0", "react-google-recaptcha": "^3.1.0", "react-hot-toast": "^2.4.1", - "react-icons": "^5.0.1", + "react-icons": "^5.3.0", "react-phone-input-2": "^2.15.1", "react-phone-number-input": "^3.3.10", "react-quill": "^2.0.0", @@ -6671,7 +6671,8 @@ }, "node_modules/react-icons": { "version": "5.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.3.0.tgz", + "integrity": "sha512-DnUk8aFbTyQPSkCfF8dbX6kQjXA9DktMeJqfjrg6cK9vwQVMxmcA3BfP4QoiztVmEHtwlTgLFsPuH2NskKT6eg==", "peerDependencies": { "react": "*" } diff --git a/client/package.json b/client/package.json index df5e27c..a1d99b2 100644 --- a/client/package.json +++ b/client/package.json @@ -47,7 +47,7 @@ "react-dom": "^18.2.0", "react-google-recaptcha": "^3.1.0", "react-hot-toast": "^2.4.1", - "react-icons": "^5.0.1", + "react-icons": "^5.3.0", "react-phone-input-2": "^2.15.1", "react-phone-number-input": "^3.3.10", "react-quill": "^2.0.0", diff --git a/client/src/App.jsx b/client/src/App.jsx index e548ad4..96bf6d1 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -28,6 +28,8 @@ import ScrollTop from "./component/ScrollTop"; import EditProfile from "./component/EditProfile"; import Contributors from "./component/Contributors"; import Discussion from "./component/Discussion"; +import Admin from "./component/Admin"; +import Dashboard from "./component/Dashboard"; import ForgotPassword from "./component/ForgotPassword"; import ResetPassword from "./component/ResetPassword"; import NotFound from "./component/NotFound"; @@ -142,6 +144,8 @@ function App() { } /> } /> } /> + } /> + } /> } /> } /> } /> diff --git a/client/src/component/Admin.jsx b/client/src/component/Admin.jsx new file mode 100644 index 0000000..02901f3 --- /dev/null +++ b/client/src/component/Admin.jsx @@ -0,0 +1,192 @@ +import PropTypes from "prop-types"; +import { useState, useEffect } from "react"; +import { useNavigate } from "react-router-dom"; +const SERVER_URI=import.meta.env.VITE_SERVER_URI; +import { Input, Spin } from "antd"; +import { + UserOutlined, + LockOutlined, + EyeInvisibleOutlined, + EyeTwoTone, +} from "@ant-design/icons"; +import "../css/Login.css"; +import toast from "react-hot-toast"; +import { useAuth } from '../contexts/authContext'; + +const Admin = ({ mode }) => { + const [credentials, setCredentials] = useState({ email: "", password: "" }); + const [loading, setLoading] = useState(false); + const navigate = useNavigate(); + const { userLoggedIn } = useAuth(); + + // Conditional navigation if user is already logged in + useEffect(() => { + if (userLoggedIn) { + navigate('/'); + } + }, [userLoggedIn, navigate]); + + // Handle form submission for login + const handleSubmit = async (e) => { + e.preventDefault(); + + // Check for empty fields + if (!credentials.email || !credentials.password) { + toast.error("Please enter both email and password."); + return; + } + + setLoading(true); + try { + const response = await fetch(`${SERVER_URI}/api/admin/login`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(credentials), + }); + if (!response.ok) { + // Check for network or server errors + if (response.status === 500) { + toast.error("Server error. Please try again later."); + } else { + toast.error("Login failed! Please check your credentials."); + } + throw new Error("Response not ok"); + } + + const json = await response.json(); + + console.log(json) + if (json.success) { + // localStorage.setItem("token", json.authtoken); // this breakes + // setloggedin(!isloggedin); + + navigate("/Dashboard"); + + } else { + toast.error(json.message || "Login failed! Invalid credentials."); + } + } catch (error) { + if (error.message === "NetworkError") { + toast.error("Network error. Please check your connection."); + } else { + toast.error("An unexpected error occurred. Please try again later."); + } + console.error("Error during login:", error); + } finally { + setLoading(false); + } + }; + + // Handle changes in input fields + const onChange = (e) => { + setCredentials({ ...credentials, [e.target.name]: e.target.value }); + }; + + + + + return ( +
+ {userLoggedIn && navigate('/')} +
+ +
+

Admin Login

+ {/* Title Line */} + + + {/* Email Input */} +
+ } + placeholder="Email" + name="email" + value={credentials.email} + onChange={onChange} + autoComplete="on" + required + className="h-10 text-xl" + style={{ + backgroundColor: mode === "dark" ? "black" : "white", + color: mode === "dark" ? "white" : "black", + }} + /> +
+ + {/* Password Input */} +
+ } + placeholder="Password" + name="password" + value={credentials.password} + onChange={onChange} + autoComplete="on" + required + iconRender={(visible) => + visible ? : + } + className="h-10 text-xl" + style={{ + backgroundColor: mode === "dark" ? "black" : "white", + color: mode === "dark" ? "white" : "black", + }} + /> +
+ + + + + + +
+ +
+

+ WELCOME +
+ BACK! +

+

+ Please Sign In here +
+ with your real info +

+
+
+
+ ); +}; + +Admin.propTypes = { + mode: PropTypes.string.isRequired, +}; + +export default Admin; \ No newline at end of file diff --git a/client/src/component/Dashboard.jsx b/client/src/component/Dashboard.jsx new file mode 100644 index 0000000..d738d21 --- /dev/null +++ b/client/src/component/Dashboard.jsx @@ -0,0 +1,183 @@ +// import React from 'react'; +import { FaUsers, FaMicroblog } from 'react-icons/fa'; +import { PiEyesDuotone } from 'react-icons/pi'; + +import PropTypes from "prop-types"; + +const Dashboard = ({ mode }) => { + const isDarkMode = mode === 'dark'; + const blogs = [ + { id: 1, title: 'Understanding React', author: 'John Doe', category: 'Web Development' }, + { id: 2, title: 'CSS Tips and Tricks', author: 'Jane Smith', category: 'Design' }, + { id: 3, title: 'JavaScript Basics', author: 'Alice Johnson', category: 'Programming' }, + ]; + + const handleDelete = (id) => { + console.log(`Blog with id ${id} deleted`); + }; + + return ( +
+ {/* Header */} +
+

Dashboard

+
+ + {/* Insights */} +
+
+
+ + + +
+

Total Views

+

100

+
+
+
+
+ + + + +
+ 80% +
+
+
+ Last 24 Hours +
+ +
+
+ + + +
+

New Users

+

323

+
+
+
+
+ + + + +
+ 50% +
+
+
+ Last 24 Hours +
+ +
+
+ + + +
+

Total Posts

+

12

+
+
+
+
+ + + + +
+ 90% +
+
+
+ Last 24 Hours +
+
+ + {/* Blog Table */} +
+

Blog Posts

+ + + + + + + + + + + {blogs.map((blog) => ( + + + + + + + ))} + +
TitleAuthorCategoryActions
{blog.title}{blog.author}{blog.category} + +
+ + Show All + +
+
+ ); +}; +Dashboard.propTypes = { + mode: PropTypes.string, // Function to notify parent about profile update +}; +export default Dashboard; diff --git a/server/Controllers/adminController.js b/server/Controllers/adminController.js index c4e1e7e..c508b77 100644 --- a/server/Controllers/adminController.js +++ b/server/Controllers/adminController.js @@ -8,13 +8,6 @@ const { body, validationResult } = require("express-validator"); const login= async (req, res) => { let success = false; console.log("see"); - - // Check for validation errors - const errors = validationResult(req); - if (!errors.isEmpty()) { - return res.status(400).json({ errors: errors.array() }); - } - const { email, password } = req.body; try { @@ -37,7 +30,7 @@ const login= async (req, res) => { error: "Please try to login with correct credentials", }); } - + // Create JWT payload const data = { user: {