From 06e045fbff3483f80506e127c70230e0e6419e61 Mon Sep 17 00:00:00 2001
From: Mann Patel <130435633+MannPatel0@users.noreply.github.com>
Date: Tue, 15 Apr 2025 00:18:19 -0600
Subject: [PATCH] fav product from prodDetail page
---
backend/controllers/product.js | 73 ++++++++++++++++------------
backend/index.js | 19 ++++----
frontend/src/components/Navbar.jsx | 4 +-
frontend/src/pages/Home.jsx | 4 --
frontend/src/pages/ProductDetail.jsx | 70 +++++++++++++-------------
frontend/src/pages/SearchPage.jsx | 3 ++
6 files changed, 91 insertions(+), 82 deletions(-)
diff --git a/backend/controllers/product.js b/backend/controllers/product.js
index c5a790c..d594f89 100644
--- a/backend/controllers/product.js
+++ b/backend/controllers/product.js
@@ -47,14 +47,29 @@ exports.getFavorites = async (req, res) => {
const [favorites] = await db.execute(
`
SELECT
- p.*,
- u.Name AS SellerName,
- i.URL AS image_url
- FROM Favorites f
- JOIN Product p ON f.ProductID = p.ProductID
- JOIN User u ON p.UserID = u.UserID
- LEFT JOIN Image_URL i ON p.ProductID = i.ProductID
- WHERE f.UserID = ?
+ p.ProductID,
+ p.Name,
+ p.Description,
+ p.Price,
+ p.CategoryID,
+ p.UserID,
+ p.Date,
+ u.Name AS SellerName,
+ MIN(i.URL) AS image_url
+ FROM Favorites f
+ JOIN Product p ON f.ProductID = p.ProductID
+ JOIN User u ON p.UserID = u.UserID
+ LEFT JOIN Image_URL i ON p.ProductID = i.ProductID
+ WHERE f.UserID = ?
+ GROUP BY
+ p.ProductID,
+ p.Name,
+ p.Description,
+ p.Price,
+ p.CategoryID,
+ p.UserID,
+ p.Date,
+ u.Name;
`,
[userID],
);
@@ -73,31 +88,25 @@ exports.getFavorites = async (req, res) => {
exports.getAllProducts = async (req, res) => {
try {
const [data, fields] = await db.execute(`
- WITH RankedImages AS (
- SELECT
- P.ProductID,
- P.Name AS ProductName,
- P.Price,
- P.Date AS DateUploaded,
- U.Name AS SellerName,
- I.URL AS ProductImage,
- C.Name AS Category,
- ROW_NUMBER() OVER (PARTITION BY P.ProductID ORDER BY I.URL) AS RowNum
- FROM Product P
- JOIN Image_URL I ON P.ProductID = I.ProductID
- JOIN User U ON P.UserID = U.UserID
- JOIN Category C ON P.CategoryID = C.CategoryID
- )
SELECT
- ProductID,
- ProductName,
- Price,
- DateUploaded,
- SellerName,
- ProductImage,
- Category
- FROM RankedImages
- WHERE RowNum = 1;
+ P.ProductID,
+ P.Name AS ProductName,
+ P.Price,
+ P.Date AS DateUploaded,
+ U.Name AS SellerName,
+ MIN(I.URL) AS ProductImage,
+ C.Name AS Category
+FROM Product P
+JOIN Image_URL I ON P.ProductID = I.ProductID
+JOIN User U ON P.UserID = U.UserID
+JOIN Category C ON P.CategoryID = C.CategoryID
+GROUP BY
+ P.ProductID,
+ P.Name,
+ P.Price,
+ P.Date,
+ U.Name,
+ C.Name;
`);
res.json({
diff --git a/backend/index.js b/backend/index.js
index 0d0dbcb..7afa3fe 100644
--- a/backend/index.js
+++ b/backend/index.js
@@ -1,6 +1,6 @@
const express = require("express");
const cors = require("cors");
-//Get the db connection
+
const db = require("./utils/database");
const userRouter = require("./routes/user");
@@ -33,19 +33,20 @@ transporter
console.error("Email connection failed:", error);
});
-//Check database connection
checkDatabaseConnection(db);
//Routes
-app.use("/api/user", userRouter); //prefix with /api/user
-app.use("/api/product", productRouter); //prefix with /api/product
-app.use("/api/search", searchRouter); //prefix with /api/product
-app.use("/api/engine", recommendedRouter); //prefix with /api/
-app.use("/api/history", history); //prefix with /api/
-app.use("/api/review", review); //prefix with /api/
+app.use("/api/user", userRouter);
+app.use("/api/product", productRouter);
+app.use("/api/search", searchRouter);
+app.use("/api/engine", recommendedRouter);
+app.use("/api/history", history);
+app.use("/api/review", review);
+
// Set up a scheduler to run cleanup every hour
-setInterval(cleanupExpiredCodes, 60 * 60 * 1000);
+clean_up_time = 30*60*1000;
+setInterval(cleanupExpiredCodes, clean_up_time);
app.listen(3030, () => {
console.log(`Running Backend on http://localhost:3030/`);
diff --git a/frontend/src/components/Navbar.jsx b/frontend/src/components/Navbar.jsx
index 827399e..711ad26 100644
--- a/frontend/src/components/Navbar.jsx
+++ b/frontend/src/components/Navbar.jsx
@@ -47,8 +47,8 @@ const Navbar = ({ onLogout, userName }) => {
diff --git a/frontend/src/pages/Home.jsx b/frontend/src/pages/Home.jsx
index 90b7009..f4b82e6 100644
--- a/frontend/src/pages/Home.jsx
+++ b/frontend/src/pages/Home.jsx
@@ -34,7 +34,6 @@ const Home = () => {
if (data.success) {
setShowAlert(true);
}
- console.log(response);
console.log(`Add Product -> History: ${id}`);
};
@@ -82,7 +81,6 @@ const Home = () => {
if (!response.ok) throw new Error("Failed to fetch products");
const data = await response.json();
- console.log(data);
if (data.success) {
setRecommended(
data.data.map((product) => ({
@@ -145,7 +143,6 @@ const Home = () => {
useEffect(() => {
const fetchrecomProducts = async () => {
// Get the user's data from localStorage
- console.log(storedUser);
try {
const response = await fetch(
"http://localhost:3030/api/history/getHistory",
@@ -162,7 +159,6 @@ const Home = () => {
if (!response.ok) throw new Error("Failed to fetch products");
const data = await response.json();
- console.log(data);
if (data.success) {
sethistory(
data.data.map((product) => ({
diff --git a/frontend/src/pages/ProductDetail.jsx b/frontend/src/pages/ProductDetail.jsx
index 711d1f3..eb1cd01 100644
--- a/frontend/src/pages/ProductDetail.jsx
+++ b/frontend/src/pages/ProductDetail.jsx
@@ -10,6 +10,8 @@ import {
Phone,
Mail,
} from "lucide-react";
+import FloatingAlert from "../components/FloatingAlert"; // adjust path if needed
+
const ProductDetail = () => {
const { id } = useParams();
@@ -29,8 +31,32 @@ const ProductDetail = () => {
const [currentImage, setCurrentImage] = useState(0);
const [reviews, setReviews] = useState([]);
const [showReviewForm, setShowReviewForm] = useState(false);
+ const [showAlert, setShowAlert] = useState(false);
const storedUser = JSON.parse(sessionStorage.getItem("user"));
+
+ const toggleFavorite = async (id) => {
+ const response = await fetch(
+ "http://localhost:3030/api/product/addFavorite",
+ {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ userID: storedUser.ID,
+ productID: id,
+ }),
+ },
+ );
+ const data = await response.json();
+ if (data.success) {
+ setShowAlert(true);
+ }
+ console.log(`Add Product -> History: ${id}`);
+ };
+
+
const [reviewForm, setReviewForm] = useState({
rating: 3,
comment: "",
@@ -68,7 +94,7 @@ const ProductDetail = () => {
userId: storedUser.ID,
};
- const response = await fetch(`http://localhost:3030/api/review/add`, {
+ const response = await fetch(`http://localhost:3030/api/review/addReview`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(reviewData),
@@ -182,38 +208,6 @@ const ProductDetail = () => {
fetchReviews();
}, [id]);
- // Handle favorite toggle with error handling
- const toggleFavorite = async () => {
- try {
- const response = await fetch(
- "http://localhost:3030/api/product/add_to_favorite",
- {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- userID: 1, // Replace with actual user ID
- productsID: id,
- }),
- },
- );
-
- if (!response.ok) {
- throw new Error(`HTTP error! Status: ${response.status}`);
- }
-
- const result = await response.json();
- if (result.success) {
- setIsFavorite(!isFavorite);
- } else {
- throw new Error(result.message || "Failed to toggle favorite");
- }
- } catch (error) {
- console.error("Error toggling favorite:", error);
- alert(`Failed to add to favorites: ${error.message}`);
- }
- };
// Image navigation
const nextImage = () => {
@@ -296,6 +290,7 @@ const ProductDetail = () => {
// Render product details
return (
+
{
Back
+ {showAlert && (
+
setShowAlert(false)}
+ />
+ )}
@@ -370,7 +371,6 @@ const ProductDetail = () => {
)}
-
@@ -378,7 +378,7 @@ const ProductDetail = () => {
{product.Name || "Unnamed Product"}