added review functionality

This commit is contained in:
Mann Patel
2025-04-12 11:27:27 -06:00
parent d8ed58f572
commit 10f0469b56
6 changed files with 139 additions and 89 deletions

View File

@@ -14,6 +14,7 @@ exports.addToFavorite = async (req, res) => {
success: true, success: true,
message: "Product added to favorites successfully", message: "Product added to favorites successfully",
}); });
console.log(result);
} catch (error) { } catch (error) {
console.error("Error adding favorite product:", error); console.error("Error adding favorite product:", error);
return res.json({ error: "Could not add favorite product" }); return res.json({ error: "Could not add favorite product" });

View File

@@ -8,6 +8,29 @@ const Home = () => {
const [recommended, setRecommended] = useState([]); const [recommended, setRecommended] = useState([]);
const [history, sethistory] = useState([]); const [history, sethistory] = useState([]);
const [error, setError] = useState(null); const [error, setError] = useState(null);
const storedUser = JSON.parse(sessionStorage.getItem("user"));
const handleLinkClick = async (id) => {
// Example: append to localStorage or call analytics
const response = await fetch(
"http://localhost:3030/api/product/add_fav_product",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
userID: storedUser.ID,
productsID: id,
}),
},
);
if (!response.ok) throw new Error("Failed to fetch products");
console.log(response);
console.log(`Add Product -> History: ${id}`);
};
useEffect(() => { useEffect(() => {
const fetchrecomProducts = async () => { const fetchrecomProducts = async () => {
@@ -298,6 +321,7 @@ const Home = () => {
<Link <Link
key={listing.id} key={listing.id}
to={`/product/${listing.id}`} to={`/product/${listing.id}`}
onClick={() => handleLinkClick(listing.id)}
className="bg-white border border-gray-200 hover:shadow-md transition-shadow w-70 flex-shrink-0 relative" className="bg-white border border-gray-200 hover:shadow-md transition-shadow w-70 flex-shrink-0 relative"
> >
<div className="relative"> <div className="relative">

View File

@@ -14,7 +14,7 @@ const ProductDetail = () => {
reviews: null, reviews: null,
}); });
const [isFavorite, setIsFavorite] = useState(false); const [isFavorite, setIsFavorite] = useState(false);
const [showContactForm, setShowContactForm] = useState(false); const [contactForm, showContactForm, setShowContactForm] = useState(false);
const [currentImage, setCurrentImage] = useState(0); const [currentImage, setCurrentImage] = useState(0);
const [reviews, setReviews] = useState([]); const [reviews, setReviews] = useState([]);
const [showReviewForm, setShowReviewForm] = useState(false); const [showReviewForm, setShowReviewForm] = useState(false);
@@ -417,81 +417,15 @@ const ProductDetail = () => {
</p> </p>
</div> </div>
<button {/* <button
onClick={() => setShowContactForm(!showContactForm)} onClick={() => setShowContactForm(!showContactForm)}
className="w-full bg-green-500 hover:bg-green-600 text-white font-medium py-3 px-4 mb-3" className="w-full bg-green-500 hover:bg-green-600 text-white font-medium py-3 px-4 mb-3"
> >
Contact Seller Contact Seller
</button> </button> */}
{showContactForm && (
<div className="border border-gray-200 p-4 mb-4">
<h3 className="font-medium text-gray-800 mb-2">
Contact Seller
</h3>
<form onSubmit={handleSendMessage}>
<div className="mb-3">
<label htmlFor="email" className="block text-gray-700 mb-1">
Email <span className="text-red-500">*</span>
</label>
<input
type="email"
id="email"
value={contactForm.email}
onChange={handleContactInputChange}
className="w-full p-3 border border-gray-300 focus:outline-none focus:border-green-500"
required
/>
</div>
<div className="mb-3">
<label htmlFor="phone" className="block text-gray-700 mb-1">
Phone Number <span className="text-red-500">*</span>
</label>
<input
type="tel"
id="phone"
value={contactForm.phone}
onChange={handleContactInputChange}
className="w-full p-3 border border-gray-300 focus:outline-none focus:border-green-500"
required
/>
</div>
<div className="mb-3">
<label
htmlFor="message"
className="block text-gray-700 mb-1"
>
Message
</label>
<textarea
id="message"
value={contactForm.message}
onChange={handleContactInputChange}
placeholder="Hi, is this item still available?"
className="w-full p-3 border border-gray-300 focus:outline-none focus:border-green-500"
rows="3"
/>
</div>
<div className="flex justify-between">
<button
type="submit"
className="bg-green-500 hover:bg-green-600 text-white font-medium py-2 px-4"
>
Send Contact Info
</button>
<button
type="button"
onClick={() => setShowContactForm(false)}
className="bg-gray-200 hover:bg-gray-300 text-gray-800 font-medium py-2 px-4"
>
Cancel
</button>
</div>
</form>
</div>
)}
<div className="pt-4 border-t border-gray-200"> <div className="pt-4 border-t border-gray-200">
{/* Seller Info */}
<div className="flex items-center mb-3"> <div className="flex items-center mb-3">
<div className="mr-3"> <div className="mr-3">
<div className="h-12 w-12 rounded-full bg-gray-200 flex items-center justify-center"> <div className="h-12 w-12 rounded-full bg-gray-200 flex items-center justify-center">
@@ -507,23 +441,33 @@ const ProductDetail = () => {
</p> </p>
</div> </div>
</div> </div>
<div className="text-sm text-gray-600">
<div> {/* Contact Options */}
<span className="font-medium">Rating:</span>{" "} {showContactForm && (
{product.seller?.rating ? ( <div className="mt-4 border border-gray-200 p-4">
<div className="flex items-center"> <h3 className="font-medium text-gray-800 mb-2">
{renderStars(product.seller.rating)} Contact Seller
<span className="ml-1">{product.seller.rating}/5</span> </h3>
<div className="flex flex-col sm:flex-row gap-3">
<a
href={`tel:${contactForm.phone}`}
className="bg-green-500 hover:bg-green-600 text-white font-medium py-2 px-4 text-center "
>
Call Seller
</a>
<a
href={`mailto:${contactForm.email}`}
className="bg-green-500 hover:bg-green-600 text-white font-medium py-2 px-4 text-center "
>
Email Seller
</a>
</div>
</div> </div>
) : (
"N/A"
)} )}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
</div>
{/* Reviews Section */} {/* Reviews Section */}
<div className="mt-8"> <div className="mt-8">

View File

@@ -415,6 +415,60 @@ const Settings = () => {
</div> </div>
</div> </div>
{/* Privacy Section */}
<div className="bg-white border border-gray-200 mb-6">
<div className="border-b border-gray-200 p-4">
<div className="flex items-center">
<Shield className="h-5 w-5 text-gray-500 mr-2" />
<h2 className="text-lg font-medium text-gray-800">Privacy</h2>
</div>
</div>
<div className="p-4">
<div className="space-y-4">
<div className="flex justify-between items-center pb-4 border-b border-gray-100">
<div className="flex items-start">
<Search className="h-5 w-5 text-gray-500 mr-2 mt-0.5" />
<div>
<h3 className="font-medium text-gray-800">Search History</h3>
<p className="text-sm text-gray-500">
Delete all your search history on StudentMarket
</p>
</div>
</div>
<button
onClick={() => handleDeleteHistory("search")}
className="bg-gray-100 hover:bg-gray-200 text-gray-700 font-medium py-2 px-4 flex items-center"
>
<Trash2 className="h-4 w-4 mr-1" />
Delete
</button>
</div>
<div className="flex justify-between items-center">
<div className="flex items-start">
<History className="h-5 w-5 text-gray-500 mr-2 mt-0.5" />
<div>
<h3 className="font-medium text-gray-800">
Browsing History
</h3>
<p className="text-sm text-gray-500">
Delete all your browsing history on StudentMarket
</p>
</div>
</div>
<button
onClick={() => handleDeleteHistory("browsing")}
className="bg-gray-100 hover:bg-gray-200 text-gray-700 font-medium py-2 px-4 flex items-center"
>
<Trash2 className="h-4 w-4 mr-1" />
Delete
</button>
</div>
</div>
</div>
</div>
{/* Delete Account (Danger Zone) */} {/* Delete Account (Danger Zone) */}
<div className="bg-white border border-red-200 mb-6"> <div className="bg-white border border-red-200 mb-6">
<div className="border-b border-red-200 p-4 bg-red-50"> <div className="border-b border-red-200 p-4 bg-red-50">

View File

@@ -1,4 +1,6 @@
# pip install mysql.connector # pip install mysql.connector
#
import mysql.connector import mysql.connector
from sklearn.metrics.pairwise import cosine_similarity from sklearn.metrics.pairwise import cosine_similarity
@@ -15,6 +17,28 @@ def database():
) )
return db_connection return db_connection
def get_popular_products():
pass
def delete_user_recommendation(userID, Array):
db_con = database()
cursor = db_con.cursor()
try:
for item in Array:
#Product ID starts form index 1
item_value = item + 1
print(item_value)
# Use parameterized queries to prevent SQL injection
cursor.execute(f"INTO Recommendation (UserID, RecommendedProductID) VALUES ({userID}, {item_value});")
db_con.commit()
#results = cursor.fetchall()
#print(results)
except:
pass
def get_all_products(): def get_all_products():
@@ -89,9 +113,9 @@ def get_recommendations(user_id, top_n=10):
# Get all products and user history with their category vectors # Get all products and user history with their category vectors
all_products = get_all_products() all_products = get_all_products()
user_history = get_user_history(user_id) user_history = get_user_history(user_id)
# if not user_history: if not user_history:
# # Cold start: return popular products #Cold start: return popular products
# return get_popular_products(top_n) return get_popular_products(top_n)
# Calculate similarity between all products and user history # Calculate similarity between all products and user history
user_profile = np.mean(user_history, axis=0) # Average user preferences user_profile = np.mean(user_history, axis=0) # Average user preferences
similarities = cosine_similarity([user_profile], all_products) similarities = cosine_similarity([user_profile], all_products)
@@ -128,8 +152,8 @@ def history_upload(userID, anrr):
db_con.commit() db_con.commit()
# If you need results, you'd typically fetch them after a SELECT query # If you need results, you'd typically fetch them after a SELECT query
# results = cursor.fetchall() #results = cursor.fetchall()
# print(results) #print(results)
except Exception as e: except Exception as e:
print(f"Error: {e}") print(f"Error: {e}")

View File

@@ -1,9 +1,12 @@
from flask import Flask, request, jsonify from flask import Flask, request, jsonify
from flask_cors import CORS from flask_cors import CORS
from app import get_recommendations from app import get_recommendations
from app import history_upload
import time #import time
app = Flask(__name__) app = Flask(__name__)