updating the transaction
This commit is contained in:
@@ -96,7 +96,7 @@ exports.getTransactionsByProduct = async (req, res) => {
|
||||
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
|
||||
JOIN Image_URL I ON I.ProductID = T.ProductID
|
||||
GROUP BY T.TransactionID, T.UserID, T.ProductID, T.Date, T.PaymentStatus, P.Name`,
|
||||
);
|
||||
|
||||
@@ -123,11 +123,19 @@ exports.getTransactionsByUser = async (req, res) => {
|
||||
T.Date,
|
||||
T.PaymentStatus,
|
||||
P.Name AS ProductName,
|
||||
I.URL AS Image_URL
|
||||
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
|
||||
WHERE T.UserID = ?`,
|
||||
JOIN Image_URL I ON I.ProductID = T.ProductID
|
||||
WHERE T.UserID = ?
|
||||
GROUP BY
|
||||
T.TransactionID,
|
||||
T.UserID,
|
||||
T.ProductID,
|
||||
T.Date,
|
||||
T.PaymentStatus,
|
||||
P.Name;
|
||||
`,
|
||||
[userID],
|
||||
);
|
||||
|
||||
@@ -155,7 +163,7 @@ exports.getAllTransactions = async (req, res) => {
|
||||
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
|
||||
JOIN Image_URL I ON P.ProductID = I.ProductID
|
||||
GROUP BY T.TransactionID, T.UserID, T.ProductID, T.Date, T.PaymentStatus, P.Name`,
|
||||
);
|
||||
|
||||
@@ -169,34 +177,6 @@ exports.getAllTransactions = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 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;
|
||||
@@ -223,3 +203,24 @@ exports.deleteTransaction = async (req, res) => {
|
||||
res.status(500).json({ error: "Could not delete transaction" });
|
||||
}
|
||||
};
|
||||
|
||||
exports.updateTransactionStatus = async (req, res) => {
|
||||
const { transactionID } = req.body;
|
||||
|
||||
try {
|
||||
const [result] = await db.execute(
|
||||
`UPDATE Transaction
|
||||
SET PaymentStatus = 'completed'
|
||||
WHERE TransactionID = ?;`,
|
||||
[transactionID],
|
||||
);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: "Transaction updated successfully",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error deleting transaction:", error);
|
||||
res.status(500).json({ error: "Could not delete transaction" });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,10 +5,10 @@ const {
|
||||
getTransactionsByProduct,
|
||||
getTransactionsByUser,
|
||||
getAllTransactions,
|
||||
updatePaymentStatus,
|
||||
deleteTransaction,
|
||||
getTransactionWithPagination,
|
||||
removeTransation,
|
||||
updateTransactionStatus,
|
||||
} = require("../controllers/transaction");
|
||||
const router = express.Router();
|
||||
|
||||
@@ -18,24 +18,12 @@ router.use((req, res, next) => {
|
||||
next();
|
||||
});
|
||||
|
||||
// Create a new transaction
|
||||
router.post("/createTransaction", createTransaction);
|
||||
|
||||
// Get all transactions for a specific product
|
||||
router.get("/getTransactionsByProduct/:productID", getTransactionsByProduct);
|
||||
|
||||
// Get all transactions for a specific user
|
||||
router.post("/getTransactionsByUser", getTransactionsByUser);
|
||||
|
||||
// Get all transactions in the system
|
||||
router.post("/updateStatus", updateTransactionStatus);
|
||||
router.post("/getAllTransactions", getAllTransactions);
|
||||
|
||||
// Update payment status on a transaction
|
||||
router.patch("/updatePaymentStatus", updatePaymentStatus);
|
||||
|
||||
// Delete a transaction
|
||||
router.delete("/deleteTransaction", deleteTransaction);
|
||||
|
||||
router.get("/getTransactions", getTransactionWithPagination);
|
||||
router.delete("/:id", removeTransation);
|
||||
|
||||
|
||||
@@ -1,32 +1,45 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Calendar, CreditCard, Trash2 } from "lucide-react";
|
||||
import FloatingAlert from "../components/FloatingAlert"; // adjust path if needed
|
||||
|
||||
const Transactions = () => {
|
||||
const [transactions, setTransactions] = useState([]);
|
||||
const [showAlert, setShowAlert] = useState(false);
|
||||
const storedUser = JSON.parse(sessionStorage.getItem("user"));
|
||||
|
||||
function reloadPage() {
|
||||
const docTimestamp = new Date(performance.timing.domLoading).getTime();
|
||||
const now = Date.now();
|
||||
if (now > docTimestamp) {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const fetchTransactions = async () => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
"http://localhost:3030/api/transaction/getAllTransactions",
|
||||
"http://localhost:3030/api/transaction/getTransactionsByUser",
|
||||
{
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ userID: 1 }), // replace with actual userID
|
||||
body: JSON.stringify({ userID: storedUser.ID }),
|
||||
},
|
||||
);
|
||||
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
||||
const { transactions: txData } = await response.json();
|
||||
if (!Array.isArray(txData)) return;
|
||||
|
||||
console.log(txData);
|
||||
|
||||
setTransactions(
|
||||
txData.map((tx) => ({
|
||||
id: tx.TransactionID,
|
||||
productId: tx.ProductID,
|
||||
name: tx.ProductName || "Unnamed Product",
|
||||
name: tx.ProductName,
|
||||
price: tx.Price != null ? parseFloat(tx.Price) : null,
|
||||
image: tx.Image_URL || "/default-image.jpg",
|
||||
image: tx.Image_URL,
|
||||
date: tx.Date,
|
||||
status: tx.PaymentStatus,
|
||||
})),
|
||||
@@ -52,6 +65,7 @@ const Transactions = () => {
|
||||
const data = await res.json();
|
||||
if (data.success) {
|
||||
setTransactions((prev) => prev.filter((tx) => tx.id !== id));
|
||||
reloadPage();
|
||||
} else {
|
||||
console.error("Delete failed:", data.message);
|
||||
}
|
||||
@@ -60,6 +74,26 @@ const Transactions = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const updateTransaction = async (id) => {
|
||||
try {
|
||||
const res = await fetch(
|
||||
"http://localhost:3030/api/transaction/updateStatus",
|
||||
{
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ transactionID: id }),
|
||||
},
|
||||
);
|
||||
const data = await res.json();
|
||||
if (data) {
|
||||
setShowAlert(true);
|
||||
reloadPage();
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Error deleting transaction:", err);
|
||||
}
|
||||
};
|
||||
|
||||
const formatDate = (dateString) => {
|
||||
const d = new Date(dateString);
|
||||
return d.toLocaleDateString("en-US", {
|
||||
@@ -71,6 +105,12 @@ const Transactions = () => {
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto">
|
||||
{showAlert && (
|
||||
<FloatingAlert
|
||||
message="Status Updated"
|
||||
onClose={() => setShowAlert(false)}
|
||||
/>
|
||||
)}
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<h1 className="text-2xl font-bold text-gray-800">My Transactions</h1>
|
||||
</div>
|
||||
@@ -99,28 +139,34 @@ const Transactions = () => {
|
||||
key={tx.id}
|
||||
className="relative border-2 border-gray-200 overflow-hidden hover:shadow-md transition-shadow"
|
||||
>
|
||||
{/* Delete Button */}
|
||||
<div className="absolute bottom-2 right-2 flex gap-2 z-10">
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
updateTransaction(tx.id);
|
||||
}}
|
||||
className="text-emerald-600 hover:text-emerald-700 text-sm font-medium"
|
||||
>
|
||||
Complete
|
||||
</button>
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
deleteTransaction(tx.id);
|
||||
}}
|
||||
className="absolute bottom-2 right-2 text-red-500 hover:text-red-600 z-10"
|
||||
className="text-red-500 hover:text-red-600"
|
||||
>
|
||||
<Trash2 size={20} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<Link to={`/product/${tx.productId}`}>
|
||||
<div className="h-48 bg-gray-200 flex items-center justify-center">
|
||||
{tx.image ? (
|
||||
<img
|
||||
src={tx.image}
|
||||
alt={tx.name}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
) : (
|
||||
<div className="text-gray-400">No image</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<h3 className="text-lg font-semibold text-gray-800">
|
||||
|
||||
@@ -370,7 +370,6 @@ VALUES
|
||||
(1, 5), -- User 4 likes Basketball
|
||||
(2, 8);
|
||||
|
||||
-- User 5 likes Mini Fridge
|
||||
-- Insert Transactions
|
||||
INSERT INTO
|
||||
Transaction (
|
||||
|
||||
Reference in New Issue
Block a user