From c2e13d56f2c284bf161c119877de54d7269afdf7 Mon Sep 17 00:00:00 2001 From: aruhani <163067503+aruhani@users.noreply.github.com> Date: Mon, 24 Mar 2025 22:43:06 -0600 Subject: [PATCH 01/13] Removing Password Temporarily --- backend/utils/database.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/utils/database.js b/backend/utils/database.js index 020e67c..adecb39 100644 --- a/backend/utils/database.js +++ b/backend/utils/database.js @@ -5,7 +5,7 @@ const pool = mysql.createPool({ host: "localhost", user: "root", database: "marketplace", - password: "12345678", + //password: "12345678", }); //Export a promise for promise-based query From f7e4b49ac8c5aea86d74abd9e5566046f6b98f57 Mon Sep 17 00:00:00 2001 From: aruhani <163067503+aruhani@users.noreply.github.com> Date: Sun, 20 Apr 2025 10:42:52 -0600 Subject: [PATCH 02/13] Backend for Transactions Added in 3 files, for the backend --- backend/controllers/transaction.js | 153 +++++++++++++++++++++++++++++ backend/index.js | 2 + backend/routes/transaction.js | 30 ++++++ 3 files changed, 185 insertions(+) create mode 100644 backend/controllers/transaction.js create mode 100644 backend/routes/transaction.js diff --git a/backend/controllers/transaction.js b/backend/controllers/transaction.js new file mode 100644 index 0000000..6072d2f --- /dev/null +++ b/backend/controllers/transaction.js @@ -0,0 +1,153 @@ +// controllers/transaction.js + +const db = require("../utils/database"); + +// Create a new transaction +exports.createTransaction = async (req, res) => { + const { userID, productID, date, paymentStatus } = req.body; + + try { + const [result] = await db.execute( + `INSERT INTO Transaction (UserID, ProductID, Date, PaymentStatus) + VALUES (?, ?, ?, ?)`, + [userID, productID, date, paymentStatus] + ); + + res.json({ + success: true, + message: "Transaction created successfully", + transactionID: result.insertId, + }); + } catch (error) { + console.error("Error creating transaction:", error); + res.status(500).json({ error: "Could not create transaction" }); + } +}; + +// Get all transactions for a given product +exports.getTransactionsByProduct = async (req, res) => { + const { productID } = req.params; + + try { + const [transactions] = await db.execute( + `SELECT + TransactionID, + UserID, + ProductID, + Date, + PaymentStatus + FROM Transaction + WHERE ProductID = ?`, + [productID] + ); + + res.json({ + success: true, + transactions, + }); + } catch (error) { + console.error("Error fetching transactions by product:", error); + res.status(500).json({ error: "Could not retrieve transactions" }); + } +}; + +// Get all transactions for a given user +exports.getTransactionsByUser = async (req, res) => { + const { userID } = req.body; + + try { + const [transactions] = await db.execute( + `SELECT + TransactionID, + UserID, + ProductID, + Date, + PaymentStatus + FROM Transaction + WHERE UserID = ?`, + [userID] + ); + + res.json({ + success: true, + transactions, + }); + } catch (error) { + console.error("Error fetching transactions by user:", error); + res.status(500).json({ error: "Could not retrieve transactions" }); + } +}; + +// Get all transactions in the system +exports.getAllTransactions = async (req, res) => { + try { + const [transactions] = await db.execute( + `SELECT + TransactionID, + UserID, + ProductID, + Date, + PaymentStatus + FROM Transaction` + ); + + res.json({ + success: true, + transactions, + }); + } catch (error) { + console.error("Error fetching all transactions:", error); + res.status(500).json({ error: "Could not retrieve transactions" }); + } +}; + +// Update the payment status of a transaction +exports.updatePaymentStatus = async (req, res) => { + const { transactionID, paymentStatus } = req.body; + + try { + const [result] = await db.execute( + `UPDATE Transaction + SET PaymentStatus = ? + WHERE TransactionID = ?`, + [paymentStatus, transactionID] + ); + + if (result.affectedRows === 0) { + return res.status(404).json({ success: false, message: "Transaction not found" }); + } + + res.json({ + success: true, + message: "Payment status updated successfully", + }); + } catch (error) { + console.error("Error updating payment status:", error); + res.status(500).json({ error: "Could not update payment status" }); + } +}; + +// Delete a transaction +exports.deleteTransaction = async (req, res) => { + const { transactionID } = req.body; + + try { + const [result] = await db.execute( + `DELETE FROM Transaction + WHERE TransactionID = ?`, + [transactionID] + ); + + if (result.affectedRows === 0) { + return res.status(404).json({ success: false, message: "Transaction not found" }); + } + + res.json({ + success: true, + message: "Transaction deleted successfully", + }); + } catch (error) { + console.error("Error deleting transaction:", error); + res.status(500).json({ error: "Could not delete transaction" }); + } +}; diff --git a/backend/index.js b/backend/index.js index 7afa3fe..e3b875f 100644 --- a/backend/index.js +++ b/backend/index.js @@ -9,6 +9,7 @@ const searchRouter = require("./routes/search"); const recommendedRouter = require("./routes/recommendation"); const history = require("./routes/history"); const review = require("./routes/review"); +const transactionRouter = require("./routes/transaction"); const { generateEmailTransporter } = require("./utils/mail"); const { @@ -42,6 +43,7 @@ app.use("/api/search", searchRouter); app.use("/api/engine", recommendedRouter); app.use("/api/history", history); app.use("/api/review", review); +app.use("/api/transaction", transactionRouter); // Set up a scheduler to run cleanup every hour diff --git a/backend/routes/transaction.js b/backend/routes/transaction.js new file mode 100644 index 0000000..b9ccb75 --- /dev/null +++ b/backend/routes/transaction.js @@ -0,0 +1,30 @@ +// routes/transaction.js +const express = require("express"); +const txCtrl = require("../controllers/transaction"); // <— grab the module +const router = express.Router(); + +// logging middleware +router.use((req, res, next) => { + console.log(`Incoming ${req.method} ${req.originalUrl}`); + next(); +}); + +// Create a new transaction +router.post("/createTransaction", txCtrl.createTransaction); + +// Get all transactions for a specific product +router.get("/getTransactionsByProduct/:productID", txCtrl.getTransactionsByProduct); + +// Get all transactions for a specific user +router.post("/getTransactionsByUser", txCtrl.getTransactionsByUser); + +// Get all transactions in the system +router.get("/getAllTransactions", txCtrl.getAllTransactions); + +// Update payment status on a transaction +router.patch("/updatePaymentStatus", txCtrl.updatePaymentStatus); + +// Delete a transaction +router.delete("/deleteTransaction", txCtrl.deleteTransaction); + +module.exports = router; From 25f2c3d8af8dda75244651a705ce40d82c69d6b8 Mon Sep 17 00:00:00 2001 From: noahnghg <157671712+noahnghg@users.noreply.github.com> Date: Sun, 20 Apr 2025 21:18:43 -0600 Subject: [PATCH 03/13] adding stuff to the onClick --- backend/controllers/transaction.js | 3 ++- backend/utils/database.js | 1 + backend/utils/helper.js | 2 +- frontend/src/pages/ProductDetail.jsx | 34 +++++++++++++++++++++++++++- mysql-code/Schema.sql | 3 ++- 5 files changed, 39 insertions(+), 4 deletions(-) diff --git a/backend/controllers/transaction.js b/backend/controllers/transaction.js index 6072d2f..22c17b3 100644 --- a/backend/controllers/transaction.js +++ b/backend/controllers/transaction.js @@ -7,10 +7,11 @@ exports.createTransaction = async (req, res) => { const { userID, productID, date, paymentStatus } = req.body; try { + const formattedDate = new Date(date).toISOString().slice(0, 19).replace("T", " "); const [result] = await db.execute( `INSERT INTO Transaction (UserID, ProductID, Date, PaymentStatus) VALUES (?, ?, ?, ?)`, - [userID, productID, date, paymentStatus] + [userID, productID, formattedDate, paymentStatus] ); res.json({ diff --git a/backend/utils/database.js b/backend/utils/database.js index 6e75c3a..4459545 100644 --- a/backend/utils/database.js +++ b/backend/utils/database.js @@ -4,6 +4,7 @@ const pool = mysql.createPool({ host: "localhost", user: "root", database: "Marketplace", + password: "12345678" }); module.exports = pool.promise(); diff --git a/backend/utils/helper.js b/backend/utils/helper.js index 406a897..1d39b48 100644 --- a/backend/utils/helper.js +++ b/backend/utils/helper.js @@ -18,7 +18,7 @@ async function sendVerificationEmail(email, verificationCode) { // Clean up expired verification codes (run this periodically) function cleanupExpiredCodes() { - db_con.query( + db.query( "DELETE FROM AuthVerification WHERE Date < DATE_SUB(NOW(), INTERVAL 15 MINUTE) AND Authenticated = 0", (err, result) => { if (err) { diff --git a/frontend/src/pages/ProductDetail.jsx b/frontend/src/pages/ProductDetail.jsx index a5f0d73..4bae56e 100644 --- a/frontend/src/pages/ProductDetail.jsx +++ b/frontend/src/pages/ProductDetail.jsx @@ -417,7 +417,39 @@ const ProductDetail = () => {
+
{tx.image ? ( @@ -153,7 +172,10 @@ const Transactions = () => {
  • - + Sell an Item
  • @@ -177,7 +199,10 @@ const Transactions = () => {
    -

    © {new Date().getFullYear()} Campus Marketplace. All rights reserved.

    +

    + © {new Date().getFullYear()} Campus Marketplace. All rights + reserved. +

    @@ -185,4 +210,4 @@ const Transactions = () => { ); }; -export default Transactions; \ No newline at end of file +export default Transactions; From eff9d9d91b134bbbc07219730aa6a40784758de3 Mon Sep 17 00:00:00 2001 From: aruhani <163067503+aruhani@users.noreply.github.com> Date: Sun, 20 Apr 2025 23:22:15 -0600 Subject: [PATCH 09/13] Updating Image URL --- frontend/src/pages/Transactions.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/pages/Transactions.jsx b/frontend/src/pages/Transactions.jsx index fa096fb..01ace39 100644 --- a/frontend/src/pages/Transactions.jsx +++ b/frontend/src/pages/Transactions.jsx @@ -26,7 +26,7 @@ const Transactions = () => { productId: tx.ProductID, name: tx.ProductName || "Unnamed Product", price: tx.Price != null ? parseFloat(tx.Price) : null, - image: tx.image_url || "/default-image.jpg", + image: tx.Image_URL || "/default-image.jpg", date: tx.Date, status: tx.PaymentStatus, })) From 46bd77025f96764905efe9351813a3ea4018cc17 Mon Sep 17 00:00:00 2001 From: noahnghg <157671712+noahnghg@users.noreply.github.com> Date: Sun, 20 Apr 2025 23:36:58 -0600 Subject: [PATCH 10/13] fix the routers and UI --- backend/controllers/transaction.js | 17 +++++++++++------ backend/routes/transaction.js | 2 +- frontend/src/pages/Transactions.jsx | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/backend/controllers/transaction.js b/backend/controllers/transaction.js index 60592e4..63e59a0 100644 --- a/backend/controllers/transaction.js +++ b/backend/controllers/transaction.js @@ -91,12 +91,17 @@ exports.getAllTransactions = async (req, res) => { try { const [transactions] = await db.execute( `SELECT - TransactionID, - UserID, - ProductID, - Date, - PaymentStatus - FROM Transaction` + T.TransactionID, + T.UserID, + T.ProductID, + T.Date, + T.PaymentStatus, + P.Name AS ProductName, + MIN(I.URL) AS Image_URL + FROM Transaction T + JOIN Product P ON T.ProductID = P.ProductID + LEFT JOIN Image_URL I ON P.ProductID = I.ProductID + GROUP BY T.TransactionID, T.UserID, T.ProductID, T.Date, T.PaymentStatus, P.Name` ); res.json({ diff --git a/backend/routes/transaction.js b/backend/routes/transaction.js index b9ccb75..ba84a6a 100644 --- a/backend/routes/transaction.js +++ b/backend/routes/transaction.js @@ -19,7 +19,7 @@ router.get("/getTransactionsByProduct/:productID", txCtrl.getTransactionsByProdu router.post("/getTransactionsByUser", txCtrl.getTransactionsByUser); // Get all transactions in the system -router.get("/getAllTransactions", txCtrl.getAllTransactions); +router.post("/getAllTransactions", txCtrl.getAllTransactions); // Update payment status on a transaction router.patch("/updatePaymentStatus", txCtrl.updatePaymentStatus); diff --git a/frontend/src/pages/Transactions.jsx b/frontend/src/pages/Transactions.jsx index 01ace39..147656b 100644 --- a/frontend/src/pages/Transactions.jsx +++ b/frontend/src/pages/Transactions.jsx @@ -9,7 +9,7 @@ const Transactions = () => { const fetchTransactions = async () => { try { const response = await fetch( - "http://localhost:3030/api/transaction/getTransactionsByUser", + "http://localhost:3030/api/transaction/getAllTransactions", { method: "POST", headers: { "Content-Type": "application/json" }, From 3c7a1a876a2339181c5ca127f661554a29bd4179 Mon Sep 17 00:00:00 2001 From: noahnghg <157671712+noahnghg@users.noreply.github.com> Date: Sun, 20 Apr 2025 23:42:22 -0600 Subject: [PATCH 11/13] fix duplicate products --- backend/controllers/transaction.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/backend/controllers/transaction.js b/backend/controllers/transaction.js index 63e59a0..0753975 100644 --- a/backend/controllers/transaction.js +++ b/backend/controllers/transaction.js @@ -7,7 +7,23 @@ exports.createTransaction = async (req, res) => { const { userID, productID, date, paymentStatus } = req.body; try { + // Check if the transaction already exists for the same user and product + const [existingTransaction] = await db.execute( + `SELECT TransactionID FROM Transaction WHERE UserID = ? AND ProductID = ?`, + [userID, productID] + ); + + if (existingTransaction.length > 0) { + return res.status(400).json({ + success: false, + message: "Transaction already exists for this user and product", + }); + } + + // Format the date const formattedDate = new Date(date).toISOString().slice(0, 19).replace("T", " "); + + // Insert the new transaction const [result] = await db.execute( `INSERT INTO Transaction (UserID, ProductID, Date, PaymentStatus) VALUES (?, ?, ?, ?)`, From 7670bb2b99482e47e2d2486fd8fe6c8ef6ac63b3 Mon Sep 17 00:00:00 2001 From: aruhani <163067503+aruhani@users.noreply.github.com> Date: Sun, 20 Apr 2025 23:46:22 -0600 Subject: [PATCH 12/13] Pushing new delete icon --- frontend/src/pages/Transactions.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/pages/Transactions.jsx b/frontend/src/pages/Transactions.jsx index 147656b..e4051de 100644 --- a/frontend/src/pages/Transactions.jsx +++ b/frontend/src/pages/Transactions.jsx @@ -105,8 +105,8 @@ const Transactions = () => { e.preventDefault(); deleteTransaction(tx.id); }} - className="absolute top-2 right-2 text-red-500 hover:text-red-600 z-10" - > + className="absolute bottom-2 right-2 text-red-500 hover:text-red-600 z-10" + > From 6d2f736541e8f04c82f6df9b26b4dfffc56715b2 Mon Sep 17 00:00:00 2001 From: aruhani <163067503+aruhani@users.noreply.github.com> Date: Sun, 20 Apr 2025 23:52:28 -0600 Subject: [PATCH 13/13] Updated transaction route file --- backend/routes/transaction.js | 53 ++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/backend/routes/transaction.js b/backend/routes/transaction.js index ba84a6a..9d0df2f 100644 --- a/backend/routes/transaction.js +++ b/backend/routes/transaction.js @@ -1,6 +1,45 @@ +// // routes/transaction.js +// const express = require("express"); +// const txCtrl = require("../controllers/transaction"); // <— grab the module +// const router = express.Router(); + +// // logging middleware +// router.use((req, res, next) => { +// console.log(`Incoming ${req.method} ${req.originalUrl}`); +// next(); +// }); + +// // Create a new transaction +// router.post("/createTransaction", txCtrl.createTransaction); + +// // Get all transactions for a specific product +// router.get("/getTransactionsByProduct/:productID", txCtrl.getTransactionsByProduct); + +// // Get all transactions for a specific user +// router.post("/getTransactionsByUser", txCtrl.getTransactionsByUser); + +// // Get all transactions in the system +// router.post("/getAllTransactions", txCtrl.getAllTransactions); + +// // Update payment status on a transaction +// router.patch("/updatePaymentStatus", txCtrl.updatePaymentStatus); + +// // Delete a transaction +// router.delete("/deleteTransaction", txCtrl.deleteTransaction); + +// module.exports = router; + + // routes/transaction.js const express = require("express"); -const txCtrl = require("../controllers/transaction"); // <— grab the module +const { + createTransaction, + getTransactionsByProduct, + getTransactionsByUser, + getAllTransactions, + updatePaymentStatus, + deleteTransaction, +} = require("../controllers/transaction"); const router = express.Router(); // logging middleware @@ -10,21 +49,21 @@ router.use((req, res, next) => { }); // Create a new transaction -router.post("/createTransaction", txCtrl.createTransaction); +router.post("/createTransaction", createTransaction); // Get all transactions for a specific product -router.get("/getTransactionsByProduct/:productID", txCtrl.getTransactionsByProduct); +router.get("/getTransactionsByProduct/:productID", getTransactionsByProduct); // Get all transactions for a specific user -router.post("/getTransactionsByUser", txCtrl.getTransactionsByUser); +router.post("/getTransactionsByUser", getTransactionsByUser); // Get all transactions in the system -router.post("/getAllTransactions", txCtrl.getAllTransactions); +router.post("/getAllTransactions", getAllTransactions); // Update payment status on a transaction -router.patch("/updatePaymentStatus", txCtrl.updatePaymentStatus); +router.patch("/updatePaymentStatus", updatePaymentStatus); // Delete a transaction -router.delete("/deleteTransaction", txCtrl.deleteTransaction); +router.delete("/deleteTransaction", deleteTransaction); module.exports = router;