added review functionality
This commit is contained in:
@@ -14,6 +14,7 @@ exports.addToFavorite = async (req, res) => {
|
||||
success: true,
|
||||
message: "Product added to favorites successfully",
|
||||
});
|
||||
console.log(result);
|
||||
} catch (error) {
|
||||
console.error("Error adding favorite product:", error);
|
||||
return res.json({ error: "Could not add favorite product" });
|
||||
|
||||
@@ -8,6 +8,29 @@ const Home = () => {
|
||||
const [recommended, setRecommended] = useState([]);
|
||||
const [history, sethistory] = useState([]);
|
||||
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(() => {
|
||||
const fetchrecomProducts = async () => {
|
||||
@@ -298,6 +321,7 @@ const Home = () => {
|
||||
<Link
|
||||
key={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"
|
||||
>
|
||||
<div className="relative">
|
||||
|
||||
@@ -14,7 +14,7 @@ const ProductDetail = () => {
|
||||
reviews: null,
|
||||
});
|
||||
const [isFavorite, setIsFavorite] = useState(false);
|
||||
const [showContactForm, setShowContactForm] = useState(false);
|
||||
const [contactForm, showContactForm, setShowContactForm] = useState(false);
|
||||
const [currentImage, setCurrentImage] = useState(0);
|
||||
const [reviews, setReviews] = useState([]);
|
||||
const [showReviewForm, setShowReviewForm] = useState(false);
|
||||
@@ -417,81 +417,15 @@ const ProductDetail = () => {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
{/* <button
|
||||
onClick={() => setShowContactForm(!showContactForm)}
|
||||
className="w-full bg-green-500 hover:bg-green-600 text-white font-medium py-3 px-4 mb-3"
|
||||
>
|
||||
Contact Seller
|
||||
</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>
|
||||
)}
|
||||
</button> */}
|
||||
|
||||
<div className="pt-4 border-t border-gray-200">
|
||||
{/* Seller Info */}
|
||||
<div className="flex items-center mb-3">
|
||||
<div className="mr-3">
|
||||
<div className="h-12 w-12 rounded-full bg-gray-200 flex items-center justify-center">
|
||||
@@ -507,23 +441,33 @@ const ProductDetail = () => {
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-sm text-gray-600">
|
||||
<div>
|
||||
<span className="font-medium">Rating:</span>{" "}
|
||||
{product.seller?.rating ? (
|
||||
<div className="flex items-center">
|
||||
{renderStars(product.seller.rating)}
|
||||
<span className="ml-1">{product.seller.rating}/5</span>
|
||||
|
||||
{/* Contact Options */}
|
||||
{showContactForm && (
|
||||
<div className="mt-4 border border-gray-200 p-4">
|
||||
<h3 className="font-medium text-gray-800 mb-2">
|
||||
Contact Seller
|
||||
</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>
|
||||
) : (
|
||||
"N/A"
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Reviews Section */}
|
||||
<div className="mt-8">
|
||||
|
||||
@@ -415,6 +415,60 @@ const Settings = () => {
|
||||
</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) */}
|
||||
<div className="bg-white border border-red-200 mb-6">
|
||||
<div className="border-b border-red-200 p-4 bg-red-50">
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# pip install mysql.connector
|
||||
#
|
||||
|
||||
|
||||
import mysql.connector
|
||||
from sklearn.metrics.pairwise import cosine_similarity
|
||||
@@ -15,6 +17,28 @@ def database():
|
||||
)
|
||||
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():
|
||||
|
||||
@@ -89,9 +113,9 @@ def get_recommendations(user_id, top_n=10):
|
||||
# Get all products and user history with their category vectors
|
||||
all_products = get_all_products()
|
||||
user_history = get_user_history(user_id)
|
||||
# if not user_history:
|
||||
# # Cold start: return popular products
|
||||
# return get_popular_products(top_n)
|
||||
if not user_history:
|
||||
#Cold start: return popular products
|
||||
return get_popular_products(top_n)
|
||||
# Calculate similarity between all products and user history
|
||||
user_profile = np.mean(user_history, axis=0) # Average user preferences
|
||||
similarities = cosine_similarity([user_profile], all_products)
|
||||
@@ -128,8 +152,8 @@ def history_upload(userID, anrr):
|
||||
db_con.commit()
|
||||
|
||||
# If you need results, you'd typically fetch them after a SELECT query
|
||||
# results = cursor.fetchall()
|
||||
# print(results)
|
||||
#results = cursor.fetchall()
|
||||
#print(results)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
|
||||
|
||||
|
||||
|
||||
from flask import Flask, request, jsonify
|
||||
from flask_cors import CORS
|
||||
from app import get_recommendations
|
||||
from app import history_upload
|
||||
|
||||
import time
|
||||
#import time
|
||||
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
Reference in New Issue
Block a user