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"}