History (add/ remove) favorites add remove done

This commit is contained in:
Mann Patel
2025-04-13 12:52:21 -06:00
parent 3bdb8877a6
commit 2ef05ac3af
9 changed files with 220 additions and 92 deletions

View File

@@ -14,7 +14,6 @@ import Favorites from "./pages/Favorites";
import ProductDetail from "./pages/ProductDetail";
import ItemForm from "./pages/MyListings";
import SearchPage from "./pages/SearchPage"; // Make sure to import the SearchPage
import axios from "axios";
function App() {
// Authentication state - initialize from localStorage if available

View File

@@ -0,0 +1,19 @@
// components/FloatingAlert.jsx
import { useEffect } from "react";
const FloatingAlert = ({ message, onClose, duration = 3000 }) => {
useEffect(() => {
const timer = setTimeout(() => {
onClose();
}, duration);
return () => clearTimeout(timer);
}, [onClose, duration]);
return (
<div className="fixed top-4 left-1/2 transform -translate-x-1/2 bg-green-500 text-white px-4 py-2 rounded-xl shadow-lg z-50 text-center">
{message}
</div>
);
};
export default FloatingAlert;

View File

@@ -7,6 +7,7 @@ const Favorites = () => {
const [showFilters, setShowFilters] = useState(false);
const [sortBy, setSortBy] = useState("dateAdded");
const [filterCategory, setFilterCategory] = useState("All");
const storedUser = JSON.parse(sessionStorage.getItem("user"));
const mapCategory = (id) => {
const categories = {
@@ -20,10 +21,41 @@ const Favorites = () => {
return categories[id] || "Other";
};
function reloadPage() {
var doctTimestamp = new Date(performance.timing.domLoading).getTime();
var now = Date.now();
if (now > doctTimestamp) {
location.reload();
}
}
const removeFromFavorites = async (itemID) => {
const response = await fetch(
"http://localhost:3030/api/product/delFavorite",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
userID: storedUser.ID,
productID: itemID,
}),
},
);
const data = await response.json();
if (data.success) {
reloadPage();
}
if (!response.ok) throw new Error("Failed to fetch products");
console.log(response);
console.log(`Add Product -> History: ${itemID}`);
};
useEffect(() => {
const fetchFavorites = async () => {
try {
const user = JSON.parse(sessionStorage.getItem("user"));
const response = await fetch(
"http://localhost:3030/api/product/getFavorites",
{
@@ -31,13 +63,11 @@ const Favorites = () => {
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ userID: user.ID }),
body: JSON.stringify({ userID: storedUser.ID }),
},
);
const data = await response.json();
console.log(user.ID);
console.log(data);
const favoritesData = data.favorites;
@@ -75,11 +105,6 @@ const Favorites = () => {
return `${diffInDays}d ago`;
};
const removeFromFavorites = (id) => {
setFavorites(favorites.filter((item) => item.id !== id));
// Optional: Send DELETE request to backend here
};
const sortedFavorites = [...favorites].sort((a, b) => {
if (sortBy === "dateAdded")
return new Date(b.dateAdded) - new Date(a.dateAdded);

View File

@@ -1,6 +1,8 @@
import { useState, useEffect } from "react";
import { Link, useNavigate } from "react-router-dom";
import { Tag, Heart } from "lucide-react";
import { Tag } from "lucide-react";
import FloatingAlert from "../components/FloatingAlert"; // adjust path if needed
const Home = () => {
const navigate = useNavigate();
@@ -9,10 +11,11 @@ const Home = () => {
const [history, sethistory] = useState([]);
const [error, setError] = useState(null);
const storedUser = JSON.parse(sessionStorage.getItem("user"));
const [showAlert, setShowAlert] = useState(false);
const handleLinkClick = async (id) => {
const toggleFavorite = async (id) => {
const response = await fetch(
"http://localhost:3030/api/product/addFavorites",
"http://localhost:3030/api/product/addFavorite",
{
method: "POST",
headers: {
@@ -20,17 +23,34 @@ const Home = () => {
},
body: JSON.stringify({
userID: storedUser.ID,
productsID: id,
productID: id,
}),
},
);
if (!response.ok) throw new Error("Failed to fetch products");
const data = await response.json();
if (data.success) {
setShowAlert(true);
}
console.log(response);
console.log(`Add Product -> History: ${id}`);
};
const addHistory = async (id) => {
const response = await fetch(
"http://localhost:3030/api/history/addHistory",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
userID: storedUser.ID,
productID: id,
}),
},
);
};
function reloadPage() {
var doctTimestamp = new Date(performance.timing.domLoading).getTime();
var now = Date.now();
@@ -44,7 +64,6 @@ const Home = () => {
useEffect(() => {
const fetchrecomProducts = async () => {
// Get the user's data from localStorage
const storedUser = JSON.parse(sessionStorage.getItem("user"));
console.log(storedUser);
try {
const response = await fetch(
@@ -126,7 +145,6 @@ const Home = () => {
useEffect(() => {
const fetchrecomProducts = async () => {
// Get the user's data from localStorage
const storedUser = JSON.parse(sessionStorage.getItem("user"));
console.log(storedUser);
try {
const response = await fetch(
@@ -155,7 +173,6 @@ const Home = () => {
image: product.ProductImage, // Use the alias for image URL
seller: product.SellerName, // Fetch seller name properly
datePosted: product.DateUploaded, // Use the actual date
isFavorite: false, // Default state
})),
);
} else {
@@ -169,18 +186,6 @@ const Home = () => {
fetchrecomProducts();
}, []);
// Toggle favorite status
const toggleFavorite = (id, e) => {
e.preventDefault(); // Prevent navigation when clicking the heart icon
setListings((prevListings) =>
prevListings.map((listing) =>
listing.id === id
? { ...listing, isFavorite: !listing.isFavorite }
: listing,
),
);
};
const handleSelling = () => {
navigate("/selling");
};
@@ -218,6 +223,12 @@ const Home = () => {
</div>
{/* Recent Listings */}
{showAlert && (
<FloatingAlert
message="Product added to favorites!"
onClose={() => setShowAlert(false)}
/>
)}
<div className="relative py-4">
<h2 className="text-xl font-semibold text-gray-800 mb-4">
Recommendation
@@ -245,6 +256,7 @@ const Home = () => {
<Link
key={recommended.id}
to={`/product/${recommended.id}`}
onClick={() => addHistory(recommended.id)}
className="bg-white border border-gray-200 hover:shadow-md transition-shadow w-70 flex-shrink-0 relative"
>
<div className="relative">
@@ -254,16 +266,14 @@ const Home = () => {
className="w-full h-48 object-cover"
/>
<button
onClick={(e) => toggleFavorite(recommended.id, e)}
className="absolute top-2 right-2 p-2 bg-white rounded-full shadow-sm"
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
toggleFavorite(recommended.id);
}}
className="absolute top-2 right-2 p-2 bg-white rounded-full shadow-sm hover:bg-gray-100 transition"
>
<Heart
className={`h-6 w-6 ${
recommended.isFavorite
? "text-red-500 fill-red-500"
: "text-gray-400"
}`}
/>
<span className="text-xl font-bold text-gray-600">+</span>
</button>
</div>
@@ -308,6 +318,12 @@ const Home = () => {
</div>
{/* Recent Listings */}
{showAlert && (
<FloatingAlert
message="Product added to favorites!"
onClose={() => setShowAlert(false)}
/>
)}
<div className="relative py-4">
<h2 className="text-xl font-semibold text-gray-800 mb-4">
Recent Listings
@@ -335,26 +351,24 @@ 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">
<img
src={listing.image}
alt={listing.title}
onClick={() => addHistory(listing.id)}
className="w-full h-48 object-cover"
/>
<button
onClick={(e) => toggleFavorite(listing.id, e)}
className="absolute top-2 right-2 p-2 bg-white rounded-full shadow-sm"
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
toggleFavorite(listing.id);
}}
className="absolute top-2 right-2 p-2 bg-white rounded-full shadow-sm hover:bg-gray-100 transition"
>
<Heart
className={`h-6 w-6 ${
listing.isFavorite
? "text-red-500 fill-red-500"
: "text-gray-400"
}`}
/>
<span className="text-xl font-bold text-gray-600">+</span>
</button>
</div>
@@ -399,6 +413,12 @@ const Home = () => {
</div>
{/* Recent Listings */}
{showAlert && (
<FloatingAlert
message="Product added to favorites!"
onClose={() => setShowAlert(false)}
/>
)}
<div className="relative py-4">
<h2 className="text-xl font-semibold text-gray-800 mb-4">History</h2>
@@ -433,16 +453,14 @@ const Home = () => {
className="w-full h-48 object-cover"
/>
<button
onClick={(e) => toggleFavorite(history.id, e)}
className="absolute top-2 right-2 p-2 bg-white rounded-full shadow-sm"
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
toggleFavorite(history.id);
}}
className="absolute top-2 right-2 p-2 bg-white rounded-full shadow-sm hover:bg-gray-100 transition"
>
<Heart
className={`h-6 w-6 ${
history.isFavorite
? "text-red-500 fill-red-500"
: "text-gray-400"
}`}
/>
<span className="text-xl font-bold text-gray-600">+</span>
</button>
</div>

View File

@@ -1,5 +1,6 @@
import { useState, useEffect } from "react";
import { User, Lock, Trash2, History, Search, Shield } from "lucide-react";
import FloatingAlert from "../components/FloatingAlert"; // adjust path if needed
const Settings = () => {
const [userData, setUserData] = useState({
@@ -16,6 +17,8 @@ const Settings = () => {
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
const [showAlert, setShowAlert] = useState(false);
const storedUser = JSON.parse(sessionStorage.getItem("user"));
// Fetch user data when component mounts
useEffect(() => {
@@ -88,6 +91,25 @@ const Settings = () => {
}));
};
const removeHistory = async () => {
const response = await fetch(
"http://localhost:3030/api/history/delHistory",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
userID: storedUser.ID,
}),
},
);
if (response.ok) {
setShowAlert(true);
}
};
const handleUpdateProfile = async () => {
try {
// Ensure userId is present
@@ -159,12 +181,6 @@ const Settings = () => {
}
};
const handleDeleteHistory = (type) => {
// TODO: Delete the specified history
console.log(`Deleting ${type} history`);
alert(`${type} history deleted successfully!`);
};
const handleDeleteAccount = async () => {
if (
window.confirm(
@@ -416,6 +432,12 @@ const Settings = () => {
</div>
{/* Privacy Section */}
{showAlert && (
<FloatingAlert
message="Product removed from History!"
onClose={() => setShowAlert(false)}
/>
)}
<div className="bg-white border border-gray-200 mb-6">
<div className="border-b border-gray-200 p-4">
<div className="flex items-center">
@@ -432,33 +454,12 @@ const Settings = () => {
<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
Delete all your history on Market
</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")}
onClick={() => removeHistory()}
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" />