diff --git a/client/src/App.js b/client/src/App.js
index eb5a9628..bc4dcd93 100644
--- a/client/src/App.js
+++ b/client/src/App.js
@@ -34,7 +34,10 @@ import CustomerProfile from "./Pages/CustomerProfile.jsx";
import GiftCards from "./Pages/GiftCards.jsx";
import Careers from "./Pages/Careers.jsx";
import NotFound from "./Pages/NotFound.jsx";
-//import ChatBotEmbed from "./Components/ChatBotEmbed.jsx";
+
+import ResetPassword from "./Pages/ResetPassword.jsx";
+import ChatBotEmbed from './chatbot';
+
function App() {
const [darkMode, setDarkMode] = useState(false);
@@ -82,12 +85,15 @@ function App() {
} />
} />
} /> {/* Fallback route */}
+ } />
{/* Pass darkMode prop here */}
{/* Ensure Preloader is correctly styled */}
{/* Added GoToTop component */}
-
+
+
+
);
diff --git a/client/src/Pages/LoginPage.jsx b/client/src/Pages/LoginPage.jsx
index 454f3aae..a69ab5d3 100644
--- a/client/src/Pages/LoginPage.jsx
+++ b/client/src/Pages/LoginPage.jsx
@@ -137,11 +137,20 @@ const LoginPage = () => {
{/* Google Login Button */}
-
-
- Don't have an account?{' '} Sign up
-
-
+
+ {/* Sign up link */}
+
+ Don't have an account?{' '} Sign up
+
+
+ {/* Add spacing between the two sections */}
+
{/* This adds vertical spacing */}
+
+ {/* Forgot password link */}
+
+ Forgot Password?{' '} Reset here {/* Update link if necessary */}
+
+
diff --git a/client/src/Pages/ResetPassword.jsx b/client/src/Pages/ResetPassword.jsx
new file mode 100644
index 00000000..432855b6
--- /dev/null
+++ b/client/src/Pages/ResetPassword.jsx
@@ -0,0 +1,179 @@
+import React, { useState } from "react";
+import TextField from "@mui/material/TextField";
+import Button from "@mui/material/Button";
+import IconButton from "@mui/material/IconButton";
+import VisibilityIcon from "@mui/icons-material/Visibility";
+import VisibilityOffIcon from "@mui/icons-material/VisibilityOff";
+import { Box, Container, Grid, Typography } from "@mui/material";
+import Lottie from "lottie-react";
+import loginAnimation from "../Lottie-animation/loginAnimation.json"; // Ensure the animation is correct for this page
+import axios from "axios";
+import toast, { Toaster } from "react-hot-toast";
+import { Link, useNavigate } from "react-router-dom";
+
+const ResetPassword = () => {
+ const [email, setEmail] = useState("");
+ const [password, setPassword] = useState("");
+ const [confirmPassword, setConfirmPassword] = useState(""); // Added state for confirm password
+ const [showPassword, setShowPassword] = useState(false); // State for toggling password visibility
+ const [error, setError] = useState("");
+ let navigate = useNavigate();
+
+ const handleSubmit = async (e) => {
+ e.preventDefault();
+
+ // Reset error state
+ setError("");
+
+ // Validate that password and confirmPassword match
+ if (password !== confirmPassword) {
+ setError("Re-enter password does not match with new password!");
+ return;
+ }
+
+ try {
+ const response = await axios.post("http://localhost:8080/customer/resetpassword", {
+ email,
+ newPassword: password, // Send new password
+ });
+ toast.success("Password reset successfully!");
+ navigate("/login", { replace: true });
+ } catch (err) {
+ // Handle different error responses
+ if (err.response && err.response.data && err.response.data.error) {
+ setError(err.response.data.error);
+ } else {
+ setError("An unexpected error occurred.");
+ }
+ }
+ };
+
+ // Function to toggle password visibility
+ const togglePasswordVisibility = () => {
+ setShowPassword(!showPassword);
+ };
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+ {/* Add a Box with hover effect */}
+
+
+
+
+
+
+
+ >
+ );
+};
+
+export default ResetPassword;
diff --git a/controllers/customerController.js b/controllers/customerController.js
index 43046da6..58acad16 100644
--- a/controllers/customerController.js
+++ b/controllers/customerController.js
@@ -6,6 +6,8 @@ const errorHandler = require("../utils/errorHandler");
const responseHandler = require("../utils/responseHandler");
const jwt = require("jsonwebtoken");
require("dotenv").config();
+const bcrypt = require("bcryptjs");
+const saltRounds = 10;
const validator = require("validator");
const disposableEmailDomains = require("disposable-email-domains");
@@ -270,6 +272,37 @@ exports.updateProfile = catchAsyncErrors(async (req, res, next) => {
});
});
+
+// Move the resetPassword function outside and export it
+exports.resetPassword = async (req, res) => {
+ const { email, newPassword } = req.body;
+
+ if (!newPassword) {
+ return res.status(400).json({ error: "New password is required." });
+ }
+
+ try {
+ const saltRounds = 10; // You might want to ensure this value is defined
+ const hashedPassword = await bcrypt.hash(newPassword, saltRounds); // Hash new password
+
+ const updatedUser = await Customer.findOneAndUpdate(
+ { email }, // Find user by email
+ { $set: { password: hashedPassword } }, // Set new hashed password
+ { new: true }
+ );
+
+ if (updatedUser) {
+ return res.json({ message: "Password updated successfully." });
+ } else {
+ return res.status(404).json({ error: "User not found." });
+ }
+ } catch (error) {
+ console.error("Error updating password:", error.message);
+ res.status(500).json({ error: "Internal Server Error" });
+ }
+};
+
+
exports.addFeedback = catchAsyncErrors(async (req, res, next) => {
const { feedback, topic } = req.body;
const newFeedback = await Feedback.create({
diff --git a/index.js b/index.js
index a616c42e..345f44f7 100644
--- a/index.js
+++ b/index.js
@@ -17,6 +17,7 @@ console.log(process.env.sample.MONGO_URL);
/* MONGODB CONNECTION START */
const MONGO_URL = process.env.sample.MONGO_URL;
+
// CORS
const cors = require("cors");
app.use(
@@ -181,4 +182,4 @@ function closeModal() {
function purchaseBook() {
alert('Book purchased!');
closeModal();
-}
\ No newline at end of file
+}
diff --git a/package-lock.json b/package-lock.json
index dceeab36..2e790c6f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -20,6 +20,7 @@
"cors": "^2.8.5",
"disposable-email-domains": "^1.0.62",
"dotenv": "^16.4.5",
+ "env": "^0.0.2",
"express": "^4.21.0",
"jsonwebtoken": "^9.0.2",
"mongoose": "^7.6.11",
@@ -1176,7 +1177,6 @@
"version": "16.4.5",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
"integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
- "license": "BSD-2-Clause",
"engines": {
"node": ">=12"
},
@@ -1206,6 +1206,14 @@
"node": ">= 0.8"
}
},
+ "node_modules/env": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/env/-/env-0.0.2.tgz",
+ "integrity": "sha512-yP8LfjO4ughSHD/3HgLPinWzexmaOGvRfs2TFx0SZhOm7j1xPi9evjuGcLiNVHIGLmcsgMak4eDbBzlYqGIVxw==",
+ "engines": {
+ "node": ">= 0.5.9"
+ }
+ },
"node_modules/error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
diff --git a/package.json b/package.json
index fd8d9a6e..cb828dd4 100644
--- a/package.json
+++ b/package.json
@@ -22,6 +22,7 @@
"cors": "^2.8.5",
"disposable-email-domains": "^1.0.62",
"dotenv": "^16.4.5",
+ "env": "^0.0.2",
"express": "^4.21.0",
"jsonwebtoken": "^9.0.2",
"mongoose": "^7.6.11",
diff --git a/routes/customerRoutes.js b/routes/customerRoutes.js
index 4bd14b4f..ac6547ce 100644
--- a/routes/customerRoutes.js
+++ b/routes/customerRoutes.js
@@ -6,7 +6,8 @@ const {
updatePassword,
updateProfile,
logoutCustomer,
- addFeedback
+ addFeedback,
+ resetPassword
} = require("../controllers/customerController.js");
@@ -32,8 +33,7 @@ router.route("/password/update").put(isAuthenticatedUser, updatePassword);
router.route("/me/update").put(isAuthenticatedUser, updateProfile);
-
-
+router.route("/resetpassword").post(resetPassword);
//cart routes
@@ -56,4 +56,4 @@ router.route("/cart").get(isAuthenticatedUser,getCartItems);
//giving feedback
router.route("/add-feedback").post(isAuthenticatedUser,addFeedback);
-module.exports = router;
\ No newline at end of file
+module.exports = router;