From 22a14cb6a4f7757f223e44dbe2800c99d4738757 Mon Sep 17 00:00:00 2001 From: Mann Patel <130435633+MannPatel0@users.noreply.github.com> Date: Fri, 21 Mar 2025 22:17:57 -0600 Subject: [PATCH 1/9] Updated SQL for Progress Report-3 --- SQL_code/Schema.sql | 323 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 321 insertions(+), 2 deletions(-) diff --git a/SQL_code/Schema.sql b/SQL_code/Schema.sql index 97b93c4..b63a22f 100644 --- a/SQL_code/Schema.sql +++ b/SQL_code/Schema.sql @@ -1,3 +1,7 @@ +-- MySql Version 9.2.0 +CREATE DATABASE Marketplace; + +Use Marketplace -- User Entity CREATE TABLE User ( UserID INT AUTO_INCREMENT PRIMARY KEY, @@ -32,6 +36,7 @@ CREATE TABLE Product ( UserID INT, Description TEXT, CategoryID INT NOT NULL, + Date DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (UserID) REFERENCES User (UserID), FOREIGN KEY (CategoryID) REFERENCES Category (CategoryID) ); @@ -40,8 +45,6 @@ CREATE TABLE Image_URL ( URL VARCHAR(255), FOREIGN KEY (ProductID) REFERENCES Product (ProductID) ) - - -- Review Entity (Many-to-One with User, Many-to-One with Product) CREATE TABLE Review ( ReviewID INT PRIMARY KEY, @@ -113,3 +116,319 @@ CREATE TABLE AuthVerification ( Authenticated BOOLEAN DEFAULT FALSE, Date DATETIME DEFAULT CURRENT_TIMESTAMP ); + +-- Insert sample categories +INSERT INTO + Category (CategoryID, Name) +VALUES + (1, 'Electronics'), + (2, 'Clothing'), + (3, 'Books'), + (4, 'Home & Garden'), + (5, 'Sports & Outdoors'); + +-- USER CRUD OPERATIONS +-- Create User (INSERT) +INSERT INTO + User (Name, Email, UCID, Password, Phone, Address) +VALUES + ( + 'John Doe', + 'john@example.com', + 'UC123456', + 'hashed_password_here', + '555-123-4567', + '123 Main St' + ); + +-- Set user role +INSERT INTO + UserRole (UserID, Client, Admin) +VALUES + (LAST_INSERT_ID (), TRUE, FALSE); + +-- Read User (SELECT) +SELECT + u.*, + ur.Client, + ur.Admin +FROM + User u + JOIN UserRole ur ON u.UserID = ur.UserID +WHERE + u.UserID = 1; + +-- Update User (UPDATE) +UPDATE User +SET + Name = 'John Smith', + Phone = '555-987-6543', + Address = '456 Elm St' +WHERE + UserID = 1; + +-- Update User Role +UPDATE UserRole +SET + Admin = TRUE +WHERE + UserID = 1; + +-- Delete User (DELETE) +DELETE FROM User +WHERE + UserID = 1; + +-- Note: Cascade will delete related UserRole record +-- PRODUCT CRUD OPERATIONS +-- Create Product (INSERT) +INSERT INTO + Product ( + ProductID, + Name, + Price, + StockQuantity, + UserID, + Description, + CategoryID + ) +VALUES + ( + 1, + 'Smartphone', + 599.99, + 50, + 1, + 'Latest model smartphone with amazing features', + 1 + ); + +-- Add product images +INSERT INTO + Image_URL (URL, ProductID) +VALUES + ('https://example.com/images/smartphone1.jpg', 1), + ('https://example.com/images/smartphone2.jpg', 1); + +-- Read Product (SELECT) +SELECT + p.*, + c.Name as CategoryName, + u.Name as SellerName, + i.URL as ImageURL +FROM + Product p + JOIN Category c ON p.CategoryID = c.CategoryID + JOIN User u ON p.UserID = u.UserID + LEFT JOIN Image_URL i ON p.ProductID = i.ProductID +WHERE + p.ProductID = 1; + +-- Update Product (UPDATE) +UPDATE Product +SET + Name = 'Premium Smartphone', + Price = 649.99, + StockQuantity = 45, + Description = 'Updated description with new features' +WHERE + ProductID = 1; + +-- Delete Product (DELETE) +DELETE FROM Product +WHERE + ProductID = 1; + +-- CATEGORY CRUD OPERATIONS (Admin only for delete) +-- Create Category (INSERT) +INSERT INTO + Category (CategoryID, Name) +VALUES + (6, 'Toys & Games'); + +-- Read Category (SELECT) +SELECT + * +FROM + Category +WHERE + CategoryID = 6; + +-- Update Category (UPDATE) +UPDATE Category +SET + Name = 'Toys & Children''s Games' +WHERE + CategoryID = 6; + +-- Delete Category (DELETE) - Admin only +DELETE FROM Category +WHERE + CategoryID = 6; + +-- REVIEW OPERATIONS (Create only as specified) +-- Create Review (INSERT) +INSERT INTO + Review (ReviewID, UserID, ProductID, Comment, Rating) +VALUES + ( + 1, + 1, + 1, + 'Great product, very satisfied with the purchase!', + 5 + ); + +-- TRANSACTION OPERATIONS (Create only as specified) +-- Create Transaction (INSERT) +INSERT INTO + Transaction (TransactionID, UserID, ProductID, PaymentStatus) +VALUES + (1, 1, 1, 'Completed'); + +-- HISTORY CRUD OPERATIONS +-- Create History (INSERT) +INSERT INTO + History (HistoryID, UserID, ProductID) +VALUES + (1, 1, 1); + +-- Read History (SELECT) +SELECT + h.*, + p.Name as ProductName +FROM + History h + JOIN Product p ON h.ProductID = p.ProductID +WHERE + h.UserID = 1 +ORDER BY + h.Date DESC; + +-- Delete History (DELETE) +DELETE FROM History +WHERE + HistoryID = 1; + +-- FAVORITES CRUD OPERATIONS +-- Create Favorite (INSERT) +INSERT INTO + Favorites (UserID, ProductID) +VALUES + (1, 1); + +-- Read Favorites (SELECT) +SELECT + f.*, + p.Name as ProductName, + p.Price +FROM + Favorites f + JOIN Product p ON f.ProductID = p.ProductID +WHERE + f.UserID = 1; + +-- Delete Favorite (DELETE) +DELETE FROM Favorites +WHERE + FavoriteID = 1; + +-- RECOMMENDATION SYSTEM OPERATIONS +-- Create Recommendation (INSERT) +INSERT INTO + Recommendation (RecommendationID_PK, UserID, RecommendedProductID) +VALUES + (1, 1, 2); + +-- Read Recommendations (SELECT) +SELECT + r.*, + p.Name as RecommendedProductName, + p.Price, + p.Description +FROM + Recommendation r + JOIN Product p ON r.RecommendedProductID = p.ProductID +WHERE + r.UserID = 1; + +-- Update Recommendation (UPDATE) +UPDATE Recommendation +SET + RecommendedProductID = 3 +WHERE + RecommendationID_PK = 1; + +-- Delete Recommendation (DELETE) +DELETE FROM Recommendation +WHERE + RecommendationID_PK = 1; + +-- Authentication Operations +-- Create verification code +INSERT INTO + AuthVerification (Email, VerificationCode) +VALUES + ('new_user@example.com', '123456'); + +-- Update authentication status +UPDATE AuthVerification +SET + Authenticated = TRUE +WHERE + Email = 'new_user@example.com' + AND VerificationCode = '123456'; + +-- Complex Queries for Reports and Analysis +-- Get top-selling products +SELECT + p.ProductID, + p.Name, + COUNT(t.TransactionID) as SalesCount, + SUM(p.Price) as TotalRevenue +FROM + Product p + JOIN Transaction t ON p.ProductID = t.ProductID +WHERE + t.PaymentStatus = 'Completed' +GROUP BY + p.ProductID, + p.Name +ORDER BY + SalesCount DESC +LIMIT + 10; + +-- Get highest-rated products +SELECT + p.ProductID, + p.Name, + AVG(r.Rating) as AverageRating, + COUNT(r.ReviewID) as ReviewCount +FROM + Product p + JOIN Review r ON p.ProductID = r.ProductID +GROUP BY + p.ProductID, + p.Name +HAVING + ReviewCount >= 5 +ORDER BY + AverageRating DESC +LIMIT + 10; + +-- Get user purchase history with product details +SELECT + t.TransactionID, + t.Date, + p.Name, + p.Price, + t.PaymentStatus +FROM + Transaction t + JOIN Product p ON t.ProductID = p.ProductID +WHERE + t.UserID = 1 +ORDER BY + t.Date DESC; From 224df3c642dafcaf137833c680d46715429a0346 Mon Sep 17 00:00:00 2001 From: Mann Patel <130435633+MannPatel0@users.noreply.github.com> Date: Fri, 21 Mar 2025 22:59:27 -0600 Subject: [PATCH 2/9] Update Schema.sql --- SQL_code/Schema.sql | 105 ++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 58 deletions(-) diff --git a/SQL_code/Schema.sql b/SQL_code/Schema.sql index b63a22f..220288c 100644 --- a/SQL_code/Schema.sql +++ b/SQL_code/Schema.sql @@ -1,7 +1,8 @@ -- MySql Version 9.2.0 CREATE DATABASE Marketplace; -Use Marketplace +USE Marketplace; + -- User Entity CREATE TABLE User ( UserID INT AUTO_INCREMENT PRIMARY KEY, @@ -21,7 +22,7 @@ CREATE TABLE UserRole ( FOREIGN KEY (UserID) REFERENCES User (UserID) ON DELETE CASCADE ); --- Category Entity (must be created before Product or else error) +-- Category Entity (must be created before Product or else error) CREATE TABLE Category ( CategoryID INT PRIMARY KEY, Name VARCHAR(255) NOT NULL @@ -41,11 +42,14 @@ CREATE TABLE Product ( FOREIGN KEY (CategoryID) REFERENCES Category (CategoryID) ); +-- Fixed Image_URL table CREATE TABLE Image_URL ( URL VARCHAR(255), + ProductID INT, FOREIGN KEY (ProductID) REFERENCES Product (ProductID) -) --- Review Entity (Many-to-One with User, Many-to-One with Product) +); + +-- Fixed Review Entity (Many-to-One with User, Many-to-One with Product) CREATE TABLE Review ( ReviewID INT PRIMARY KEY, UserID INT, @@ -108,7 +112,7 @@ CREATE TABLE Product_Category ( FOREIGN KEY (CategoryID) REFERENCES Category (CategoryID) ); --- Login Authentication table, Store the userID,and a emailed code of user who have not authenticated, +-- Login Authentication table CREATE TABLE AuthVerification ( UserID INT AUTO_INCREMENT PRIMARY KEY, Email VARCHAR(100) UNIQUE NOT NULL, @@ -174,12 +178,6 @@ SET WHERE UserID = 1; --- Delete User (DELETE) -DELETE FROM User -WHERE - UserID = 1; - --- Note: Cascade will delete related UserRole record -- PRODUCT CRUD OPERATIONS -- Create Product (INSERT) INSERT INTO @@ -203,12 +201,41 @@ VALUES 1 ); --- Add product images +-- Add product images with the placeholder URL INSERT INTO Image_URL (URL, ProductID) VALUES - ('https://example.com/images/smartphone1.jpg', 1), - ('https://example.com/images/smartphone2.jpg', 1); + ('https://picsum.photos/id/237/200/300', 1), + ('https://picsum.photos/id/237/200/300', 1); + +-- Create another product for recommendations +INSERT INTO + Product ( + ProductID, + Name, + Price, + StockQuantity, + UserID, + Description, + CategoryID + ) +VALUES + ( + 2, + 'Tablet', + 799.99, + 30, + 1, + 'High-performance tablet', + 1 + ); + +-- Add placeholder images for the second product +INSERT INTO + Image_URL (URL, ProductID) +VALUES + ('https://picsum.photos/id/237/200/300', 2), + ('https://picsum.photos/id/237/200/300', 2); -- Read Product (SELECT) SELECT @@ -234,12 +261,7 @@ SET WHERE ProductID = 1; --- Delete Product (DELETE) -DELETE FROM Product -WHERE - ProductID = 1; - --- CATEGORY CRUD OPERATIONS (Admin only for delete) +-- CATEGORY CRUD OPERATIONS -- Create Category (INSERT) INSERT INTO Category (CategoryID, Name) @@ -261,13 +283,7 @@ SET WHERE CategoryID = 6; --- Delete Category (DELETE) - Admin only -DELETE FROM Category -WHERE - CategoryID = 6; - --- REVIEW OPERATIONS (Create only as specified) --- Create Review (INSERT) +-- REVIEW OPERATIONS INSERT INTO Review (ReviewID, UserID, ProductID, Comment, Rating) VALUES @@ -279,15 +295,13 @@ VALUES 5 ); --- TRANSACTION OPERATIONS (Create only as specified) --- Create Transaction (INSERT) +-- TRANSACTION OPERATIONS INSERT INTO Transaction (TransactionID, UserID, ProductID, PaymentStatus) VALUES (1, 1, 1, 'Completed'); --- HISTORY CRUD OPERATIONS --- Create History (INSERT) +-- HISTORY OPERATIONS INSERT INTO History (HistoryID, UserID, ProductID) VALUES @@ -305,13 +319,7 @@ WHERE ORDER BY h.Date DESC; --- Delete History (DELETE) -DELETE FROM History -WHERE - HistoryID = 1; - --- FAVORITES CRUD OPERATIONS --- Create Favorite (INSERT) +-- FAVORITES OPERATIONS INSERT INTO Favorites (UserID, ProductID) VALUES @@ -328,13 +336,7 @@ FROM WHERE f.UserID = 1; --- Delete Favorite (DELETE) -DELETE FROM Favorites -WHERE - FavoriteID = 1; - --- RECOMMENDATION SYSTEM OPERATIONS --- Create Recommendation (INSERT) +-- RECOMMENDATION OPERATIONS INSERT INTO Recommendation (RecommendationID_PK, UserID, RecommendedProductID) VALUES @@ -352,18 +354,6 @@ FROM WHERE r.UserID = 1; --- Update Recommendation (UPDATE) -UPDATE Recommendation -SET - RecommendedProductID = 3 -WHERE - RecommendationID_PK = 1; - --- Delete Recommendation (DELETE) -DELETE FROM Recommendation -WHERE - RecommendationID_PK = 1; - -- Authentication Operations -- Create verification code INSERT INTO @@ -379,7 +369,6 @@ WHERE Email = 'new_user@example.com' AND VerificationCode = '123456'; --- Complex Queries for Reports and Analysis -- Get top-selling products SELECT p.ProductID, From 148fe95a1182945b6c5a7ffe77960d789d1ca66c Mon Sep 17 00:00:00 2001 From: Mann Patel <130435633+MannPatel0@users.noreply.github.com> Date: Sun, 23 Mar 2025 20:16:19 -0600 Subject: [PATCH 3/9] update --- .gitignore | 2 -- backend/recommondation.go | 43 ----------------------------- backend/utils/database.js | 1 - frontend/src/App.jsx | 21 +++++++------- {SQL_code => mysql-code}/Schema.sql | 0 {SQL_code => mysql-code}/init-db.py | 0 6 files changed, 11 insertions(+), 56 deletions(-) delete mode 100644 backend/recommondation.go rename {SQL_code => mysql-code}/Schema.sql (100%) rename {SQL_code => mysql-code}/init-db.py (100%) diff --git a/.gitignore b/.gitignore index c75f740..c9d2afa 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,6 @@ */node_modules .DS_Store -*~/backend/index.js - .vscode/* !.vscode/extensions.json .idea diff --git a/backend/recommondation.go b/backend/recommondation.go deleted file mode 100644 index 3a82edb..0000000 --- a/backend/recommondation.go +++ /dev/null @@ -1,43 +0,0 @@ -package main - -import ( - "fmt" - "math" -) - -func cosine(x, y []int) float64 { - var dotProduct, normX, normY float64 - for i := 1; i < len(x); i++ { - dotProduct += float64(x[i] * y[i]) - normX += float64(x[i] * x[i]) - normY += float64(y[i] * y[i]) - } - return dotProduct / (math.Sqrt(normX) * math.Sqrt(normY)) -} - -func main() { - history := [][]int{ - {1, 0, 1, 0}, - {0, 1, 0, 1}, - {1, 0, 1, 1}, - } - - productCategory := [][]int{ - {1, 1, 0, 0}, - {0, 0, 0, 1}, - {0, 0, 1, 0}, - {0, 0, 1, 1}, - {0, 1, 0, 0}, - - {0, 1, 1, 1}, - {1, 1, 1, 0}, - {0, 0, 0, 1}, - {1, 1, 1, 1}, - } - - // Calculate similarity between first search and each product - for i, product := range productCategory { - sim := cosine(history[0], product) - fmt.Printf("Similarity with product %d: %f\n", i, sim) - } -} diff --git a/backend/utils/database.js b/backend/utils/database.js index 020e67c..0bd82e5 100644 --- a/backend/utils/database.js +++ b/backend/utils/database.js @@ -5,7 +5,6 @@ const pool = mysql.createPool({ host: "localhost", user: "root", database: "marketplace", - password: "12345678", }); //Export a promise for promise-based query diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 5a65c60..f6f42cd 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -70,7 +70,7 @@ function App() { email: userData.email, // Add any other required fields }), - } + }, ); if (!response.ok) { @@ -119,7 +119,7 @@ function App() { email: tempUserData.email, code: code, }), - } + }, ); if (!response.ok) { @@ -163,7 +163,7 @@ function App() { "Content-Type": "application/json", }, body: JSON.stringify(userData), - } + }, ); if (!response.ok) { @@ -222,11 +222,12 @@ function App() { setError("Email and password are required"); setIsLoading(false); return; - } else if (!formValues.email.endsWith("@ucalgary.ca")) { - setError("Please use your UCalgary email address (@ucalgary.ca)"); - setIsLoading(false); - return; } + // else if (!formValues.email.endsWith("@ucalgary.ca")) { + // setError("Please use your UCalgary email address (@ucalgary.ca)"); + // setIsLoading(false); + // return; + // } try { if (isSignUp) { // Handle Sign Up with verification @@ -265,7 +266,7 @@ function App() { email: formValues.email, password: formValues.password, }), - } + }, ); if (!response.ok) { @@ -509,8 +510,8 @@ function App() { {isLoading ? "Please wait..." : isSignUp - ? "Create Account" - : "Sign In"} + ? "Create Account" + : "Sign In"} diff --git a/SQL_code/Schema.sql b/mysql-code/Schema.sql similarity index 100% rename from SQL_code/Schema.sql rename to mysql-code/Schema.sql diff --git a/SQL_code/init-db.py b/mysql-code/init-db.py similarity index 100% rename from SQL_code/init-db.py rename to mysql-code/init-db.py From e7a6e1dd8b11010a021973bdbe0e6e82abdc2bbe Mon Sep 17 00:00:00 2001 From: Mann Patel <130435633+MannPatel0@users.noreply.github.com> Date: Mon, 24 Mar 2025 23:04:12 -0600 Subject: [PATCH 4/9] Bug fix: Products No image --- backend/controllers/product.js | 56 ++++++++++- backend/routes/product.js | 8 +- frontend/src/pages/Home.jsx | 12 +-- frontend/src/pages/ProductDetail.jsx | 145 ++++++++++----------------- recommondation-engine/server1.py | 24 +++++ 5 files changed, 139 insertions(+), 106 deletions(-) create mode 100644 recommondation-engine/server1.py diff --git a/backend/controllers/product.js b/backend/controllers/product.js index 54f640e..bd40907 100644 --- a/backend/controllers/product.js +++ b/backend/controllers/product.js @@ -7,7 +7,7 @@ exports.addToFavorite = async (req, res) => { // Use parameterized query to prevent SQL injection const [result] = await db.execute( "INSERT INTO Favorites (UserID, ProductID) VALUES (?, ?)", - [userID, productsID] + [userID, productsID], ); res.json({ @@ -20,18 +20,22 @@ exports.addToFavorite = async (req, res) => { } }; -//Get all products +// Get all products along with their image URLs exports.getAllProducts = async (req, res) => { try { - const [data, fields] = await db.execute("SELECT * FROM Product"); + const [data, fields] = await db.execute(` + SELECT p.*, i.URL + FROM Product p + LEFT JOIN Image_URL i ON p.ProductID = i.ProductID + `); res.json({ success: true, - message: "Product added to favorites successfully", + message: "Products fetched successfully", data, }); } catch (error) { - console.error("Error finding user:", error); + console.error("Error finding products:", error); return res.status(500).json({ found: false, error: "Database error occurred", @@ -39,6 +43,48 @@ exports.getAllProducts = async (req, res) => { } }; +// Get a single product by ID along with image URLs +exports.getProductById = async (req, res) => { + const { id } = req.params; + console.log(id); + try { + const [data] = await db.execute( + ` + SELECT p.*, i.URL AS image_url + FROM Product p + LEFT JOIN Image_URL i ON p.ProductID = i.ProductID + WHERE p.ProductID = ? + `, + [id], + ); + + if (data.length === 0) { + return res.status(404).json({ + success: false, + message: "Product not found", + }); + } + + // Assuming that `data` contains product information and the image URLs + const product = { + ...data[0], // First product found in the query + images: data.map((image) => image.image_url), // Collect all image URLs into an array + }; + + res.json({ + success: true, + message: "Product fetched successfully", + data: product, + }); + } catch (error) { + console.error("Error fetching product:", error); + return res.status(500).json({ + success: false, + error: "Database error occurred", + }); + } +}; + // db_con.query( // "SELECT ProductID FROM product WHERE ProductID = ?", // [productID], diff --git a/backend/routes/product.js b/backend/routes/product.js index 55d3761..aeea0d9 100644 --- a/backend/routes/product.js +++ b/backend/routes/product.js @@ -1,5 +1,9 @@ const express = require("express"); -const { addToFavorite, getAllProducts } = require("../controllers/product"); +const { + addToFavorite, + getAllProducts, + getProductById, +} = require("../controllers/product"); const router = express.Router(); @@ -7,4 +11,6 @@ router.post("/add_fav_product", addToFavorite); router.get("/get_product", getAllProducts); +router.post("/get_productID", getProductById); + module.exports = router; diff --git a/frontend/src/pages/Home.jsx b/frontend/src/pages/Home.jsx index 300fd9d..4ae5a6e 100644 --- a/frontend/src/pages/Home.jsx +++ b/frontend/src/pages/Home.jsx @@ -11,7 +11,7 @@ const Home = () => { const fetchProducts = async () => { try { const response = await fetch( - "http://localhost:3030/api/product/get_product" + "http://localhost:3030/api/product/get_product", ); if (!response.ok) throw new Error("Failed to fetch products"); @@ -24,12 +24,12 @@ const Home = () => { title: product.Name, price: product.Price, category: product.CategoryID, - image: product.ImageURL, + image: product.URL, condition: "New", // Modify based on actual data - seller: "Unknown", // Modify if seller info is available + seller: product.UserID, // Modify if seller info is available datePosted: "Just now", isFavorite: false, - })) + })), ); } else { throw new Error(data.message || "Error fetching products"); @@ -50,8 +50,8 @@ const Home = () => { prevListings.map((listing) => listing.id === id ? { ...listing, isFavorite: !listing.isFavorite } - : listing - ) + : listing, + ), ); }; diff --git a/frontend/src/pages/ProductDetail.jsx b/frontend/src/pages/ProductDetail.jsx index 6b32e8e..95a5286 100644 --- a/frontend/src/pages/ProductDetail.jsx +++ b/frontend/src/pages/ProductDetail.jsx @@ -1,83 +1,54 @@ -import { useState } from "react"; +import { useState, useEffect } from "react"; import { useParams, Link } from "react-router-dom"; -import { - Heart, - ArrowLeft, - Tag, - User, - Calendar, - Share, - Flag, -} from "lucide-react"; +import { Heart, ArrowLeft, Tag, User, Calendar } from "lucide-react"; const ProductDetail = () => { const { id } = useParams(); + const [product, setProduct] = useState(null); const [isFavorite, setIsFavorite] = useState(false); const [showContactForm, setShowContactForm] = useState(false); const [message, setMessage] = useState(""); const [currentImage, setCurrentImage] = useState(0); - // Sample data for demonstration - const product = [ - { - id: 0, - title: "Dell XPS 13 Laptop - 2023 Model", - price: 850, - shortDescription: - "Dell XPS 13 laptop in excellent condition. Intel Core i7, 16GB RAM, 512GB SSD. Includes charger and original box.", - description: - "Selling my Dell XPS 13 laptop. Only 6 months old and in excellent condition. Intel Core i7 processor, 16GB RAM, 512GB SSD. Battery life is still excellent (around 10 hours of regular use). Comes with original charger and box. Selling because I'm upgrading to a MacBook for design work.\n\nSpecs:\n- Intel Core i7 11th Gen\n- 16GB RAM\n- 512GB NVMe SSD\n- 13.4\" FHD+ Display (1920x1200)\n- Windows 11 Pro\n- Backlit Keyboard\n- Thunderbolt 4 ports", - condition: "Like New", - category: - "Electronics, Electronics, Electronics, Electronics , Electronics , Electronics, Electronicss", - datePosted: "2023-03-02", - images: [ - "/image1.avif", - "/image2.avif", - "/image3.avif", - "/image3.avif", - "/image3.avif", - ], - seller: { - name: "Michael T.", - rating: 4.8, - memberSince: "January 2022", - avatar: "/Profile.jpg", - }, - }, - ]; + // Fetch product details + useEffect(() => { + const fetchProduct = async () => { + try { + const response = await fetch( + `http://localhost:3030/api/product/get_productID/${id}`, + ); + if (!response.ok) throw new Error("Failed to fetch product"); - console.log(product[id]); + const data = await response.json(); + if (data.success) { + setProduct(data.data); // Update the state with product details + } else { + throw new Error(data.message || "Error fetching product"); + } + } catch (error) { + console.error("Error fetching product:", error); + } + }; + fetchProduct(); + }, [id]); + + // Handle favorite toggle const toggleFavorite = () => { setIsFavorite(!isFavorite); }; + // Handle message submission const handleSendMessage = (e) => { e.preventDefault(); - // TODO: this would send the message to the seller + // Handle message logic here (send to seller) console.log("Message sent:", message); setMessage(""); setShowContactForm(false); - // Show confirmation or success message alert("Message sent to seller!"); }; - // Function to split description into paragraphs - const formatDescription = (text) => { - return text.split("\n\n").map((paragraph, index) => ( -
- {paragraph.split("\n").map((line, i) => (
-
- {line}
- {i < paragraph.split("\n").length - 1 &&
}
-
- ))}
-
{product[id].shortDescription}
+{product.shortDescription}
- Member since {product[id].seller.memberSince} + Member since {product.seller.memberSince}
{error}
+ + Back to Listings + +{product.shortDescription}
+{product.Description}
+ ${Number(listing.price).toFixed(2)} +
+