added Review Feature

This commit is contained in:
Mann Patel
2025-04-04 00:02:04 -06:00
parent 643b9e357c
commit 75c7675601
13 changed files with 925 additions and 140 deletions

View File

@@ -0,0 +1,53 @@
const db = require("../utils/database");
// TODO: Get the recommondaed product given the userID
exports.HistoryByUserId = async (req, res) => {
const { id } = req.body;
try {
const [data] = 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
JOIN History H ON H.ProductID = P.ProductID
WHERE U.UserID = ?
)
SELECT
ProductID,
ProductName,
Price,
DateUploaded,
SellerName,
ProductImage,
Category
FROM RankedImages
WHERE RowNum = 1;
`,
[id],
);
console.log(data);
res.json({
success: true,
message: "Products fetched successfully",
data,
});
} catch (error) {
console.error("Error finding products:", error);
return res.status(500).json({
found: false,
error: "Database error occurred",
});
}
};

View File

@@ -24,18 +24,31 @@ exports.addToFavorite = 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
P.ProductID,
P.Name AS ProductName,
P.Price,
P.Date AS DateUploaded,
U.Name AS SellerName,
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;
ProductID,
ProductName,
Price,
DateUploaded,
SellerName,
ProductImage,
Category
FROM RankedImages
WHERE RowNum = 1;
`);
console.log(data);

View File

@@ -6,20 +6,34 @@ exports.RecommondationByUserId = 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
JOIN Recommendation R ON P.ProductID = R.RecommendedProductID
WHERE R.UserID = ?
)
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
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
JOIN Recommendation R ON P.ProductID = R.RecommendedProductID
Where R.UserID = ?;`,
ProductID,
ProductName,
Price,
DateUploaded,
SellerName,
ProductImage,
Category
FROM RankedImages
WHERE RowNum = 1;
`,
[id],
);
@@ -37,3 +51,64 @@ exports.RecommondationByUserId = async (req, res) => {
});
}
};
// Add this to your existing controller file
exports.submitReview = async (req, res) => {
const { productId, reviewerName, rating, comment } = req.body;
// Validate required fields
if (!productId || !reviewerName || !rating || !comment) {
return res.status(400).json({
success: false,
message: "Missing required fields",
});
}
try {
// Insert the review into the database
const [result] = await db.execute(
`
INSERT INTO Review (
ProductID,
ReviewerName,
Rating,
Comment,
ReviewDate
) VALUES (?, ?, ?, ?, NOW())
`,
[productId, reviewerName, rating, comment],
);
// Get the inserted review id
const reviewId = result.insertId;
// Fetch the newly created review to return to client
const [newReview] = await db.execute(
`
SELECT
ReviewID as id,
ProductID,
ReviewerName,
Rating,
Comment,
ReviewDate
FROM Review
WHERE ReviewID = ?
`,
[reviewId],
);
res.status(201).json({
success: true,
message: "Review submitted successfully",
data: newReview[0],
});
} catch (error) {
console.error("Error submitting review:", error);
return res.status(500).json({
success: false,
message: "Database error occurred",
error: error.message,
});
}
};

View File

@@ -0,0 +1,133 @@
const db = require("../utils/database");
exports.getreview = async (req, res) => {
const { id } = req.params;
console.log("Received Product ID:", id);
try {
const [data] = await db.execute(
`
SELECT
R.ReviewID,
R.UserID,
R.ProductID,
R.Comment,
R.Rating,
R.Date AS ReviewDate,
U.Name AS ReviewerName,
P.Name AS ProductName
FROM Review R
JOIN User U ON R.UserID = U.UserID
JOIN Product P ON R.ProductID = P.ProductID
WHERE R.ProductID = ?
UNION
SELECT
R.ReviewID,
R.UserID,
R.ProductID,
R.Comment,
R.Rating,
R.Date AS ReviewDate,
U.Name AS ReviewerName,
P.Name AS ProductName
FROM Review R
JOIN User U ON R.UserID = U.UserID
JOIN Product P ON R.ProductID = P.ProductID
WHERE P.UserID = (
SELECT UserID
FROM Product
WHERE ProductID = ?
)
AND R.UserID != P.UserID;
`,
[id, id],
);
// Log raw data for debugging
console.log("Raw Database Result:", data);
console.log(data);
res.json({
success: true,
message: "Products fetched successfully",
data,
});
} catch (error) {
console.error("Full Error Details:", error);
return res.status(500).json({
success: false,
message: "Database error occurred",
error: error.message,
});
}
};
// Add this to your existing controller file
exports.submitReview = async (req, res) => {
const { productId, userId, rating, comment } = req.body;
// Validate required fields
if (!productId || !userId || !rating || !comment) {
return res.status(400).json({
success: false,
message: "Missing required fields",
});
}
// Validate rating is between 1 and 5
if (rating < 1 || rating > 5) {
return res.status(400).json({
success: false,
message: "Rating must be between 1 and 5",
});
}
try {
// Insert the review into the database
const [result] = await db.execute(
`
INSERT INTO Review (
ProductID,
UserID,
Rating,
Comment
) VALUES (?, ?, ?, ?)
`,
[productId, userId, rating, comment],
);
// Get the inserted review id
const reviewId = result.insertId;
// Fetch the newly created review to return to client
const [newReview] = await db.execute(
`
SELECT
ReviewID as id,
ProductID,
UserID,
Rating,
Comment,
Date as ReviewDate
FROM Review
WHERE ReviewID = ?
`,
[reviewId],
);
res.status(201).json({
success: false,
message: "Review submitted successfully",
data: newReview[0],
});
} catch (error) {
console.error("Error submitting review:", error);
return res.status(500).json({
success: false,
message: "Database error occurred",
error: error.message,
});
}
};

View File

@@ -7,6 +7,9 @@ const userRouter = require("./routes/user");
const productRouter = require("./routes/product");
const searchRouter = require("./routes/search");
const recommendedRouter = require("./routes/recommendation");
const history = require("./routes/history");
const review = require("./routes/review");
const { generateEmailTransporter } = require("./utils/mail");
const {
cleanupExpiredCodes,
@@ -38,6 +41,8 @@ app.use("/api/user", userRouter); //prefix with /api/user
app.use("/api/product", productRouter); //prefix with /api/product
app.use("/api/search_products", searchRouter); //prefix with /api/product
app.use("/api/Engine", recommendedRouter); //prefix with /api/
app.use("/api/get", history); //prefix with /api/
app.use("/api/review", review); //prefix with /api/
// Set up a scheduler to run cleanup every hour
setInterval(cleanupExpiredCodes, 60 * 60 * 1000);

View File

@@ -0,0 +1,8 @@
// routes/product.js
const express = require("express");
const { HistoryByUserId } = require("../controllers/history");
const router = express.Router();
router.post("/history", HistoryByUserId);
module.exports = router;

9
backend/routes/review.js Normal file
View File

@@ -0,0 +1,9 @@
// routes/product.js
const express = require("express");
const { getreview, submitReview } = require("../controllers/review");
const router = express.Router();
router.get("/:id", getreview);
router.post("/add", submitReview);
module.exports = router;