import { Link, useNavigate } from "react-router-dom"; import { useState, useEffect, useRef } from "react"; import { Tag, ChevronLeft, ChevronRight, Bookmark, Loader } from "lucide-react"; import FloatingAlert from "../components/FloatingAlert"; // adjust path if needed const Home = () => { const navigate = useNavigate(); const [listings, setListings] = useState([]); const [recommended, setRecommended] = useState([]); const [history, setHistory] = useState([]); const [error, setError] = useState(null); const [showAlert, setShowAlert] = useState(false); const [isLoading, setIsLoading] = useState({ recommendations: true, listings: true, history: true, }); const recommendationsFetched = useRef(false); const historyFetched = useRef(false); //After user data storing the session. const storedUser = JSON.parse(sessionStorage.getItem("user")); const toggleFavorite = async (id) => { try { const response = await fetch( "http://localhost:3030/api/product/addFavorite", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ userID: storedUser.ID, productID: id, }), }, ); const data = await response.json(); if (data.success) { setShowAlert(true); // Close alert after 3 seconds setTimeout(() => setShowAlert(false), 3000); } console.log(`Add Product -> Favorites: ${id}`); } catch (error) { console.error("Error adding favorite:", error); } }; const addHistory = async (id) => { try { await fetch("http://localhost:3030/api/history/addHistory", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ userID: storedUser.ID, productID: id, }), }); } catch (error) { console.error("Error adding to history:", error); } }; // Fetch recommended products useEffect(() => { const fetchRecommendedProducts = async () => { // Skip if already fetched or no user data if (recommendationsFetched.current || !storedUser || !storedUser.ID) return; setIsLoading((prev) => ({ ...prev, recommendations: true })); try { recommendationsFetched.current = true; // Mark as fetched before the API call const response = await fetch( "http://localhost:3030/api/engine/recommended", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ id: storedUser.ID, }), }, ); if (!response.ok) throw new Error("Failed to fetch recommendations"); const data = await response.json(); if (data.success) { setRecommended( data.data.map((product) => ({ id: product.ProductID, title: product.ProductName, price: product.Price, category: product.Category, image: product.ProductImage, seller: product.SellerName, datePosted: product.DateUploaded, isFavorite: false, })), ); } else { throw new Error(data.message || "Error fetching recommendations"); } } catch (error) { console.error("Error fetching recommendations:", error); setError(error.message); // Reset the flag if there's an error so it can try again recommendationsFetched.current = false; } finally { setIsLoading((prev) => ({ ...prev, recommendations: false })); } }; fetchRecommendedProducts(); }, [storedUser]); // Keep dependency // Fetch all products useEffect(() => { const fetchProducts = async () => { setIsLoading((prev) => ({ ...prev, listings: true })); try { const response = await fetch( "http://localhost:3030/api/product/getProduct", ); if (!response.ok) throw new Error("Failed to fetch products"); const data = await response.json(); if (data.success) { setListings( data.data.map((product) => ({ id: product.ProductID, title: product.ProductName, price: product.Price, category: product.Category, image: product.ProductImage, seller: product.SellerName, datePosted: product.DateUploaded, isFavorite: false, })), ); } else { throw new Error(data.message || "Error fetching products"); } } catch (error) { console.error("Error fetching products:", error); setError(error.message); } finally { setIsLoading((prev) => ({ ...prev, listings: false })); } }; fetchProducts(); }, []); // Fetch user history useEffect(() => { const fetchUserHistory = async () => { // Skip if already fetched or no user data if (historyFetched.current || !storedUser || !storedUser.ID) return; setIsLoading((prev) => ({ ...prev, history: true })); try { historyFetched.current = true; // Mark as fetched before the API call const response = await fetch( "http://localhost:3030/api/history/getHistory", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ id: storedUser.ID, }), }, ); if (!response.ok) throw new Error("Failed to fetch history"); const data = await response.json(); if (data.success) { setHistory( data.data.map((product) => ({ id: product.ProductID, title: product.ProductName, price: product.Price, category: product.Category, image: product.ProductImage, seller: product.SellerName, datePosted: product.DateUploaded, })), ); } else { throw new Error(data.message || "Error fetching history"); } } catch (error) { console.error("Error fetching history:", error); setError(error.message); // Reset the flag if there's an error so it can try again historyFetched.current = false; } finally { setIsLoading((prev) => ({ ...prev, history: false })); } }; fetchUserHistory(); }, [storedUser]); // Keep dependency const handleSelling = () => { navigate("/selling"); }; // Loading indicator component const LoadingSection = () => (
The marketplace exclusively for university students. Find everything you need or sell what you don't.