Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

83 changes: 82 additions & 1 deletion frontend/src/pages/Products/Favorites.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,29 @@ import { Link } from "react-router-dom";
import { useCart } from "../../components/CartContext";
import { toast } from "react-toastify";
import HeartIcon from "./HeartIcon";

import { useState, useMemo } from "react";

import { useState } from "react";
import { useTheme } from "../../context/ThemeContext";


const Favorites = () => {
const favorites = useSelector((state) => state.favorites?.favorites || []);
const { addToCart } = useCart();
const [sortBy, setSortBy] = useState("");

const [isOpen, setIsOpen] = useState(false);

// Optimize sorting using useMemo to avoid unnecessary recalculations
const filteredFavorites = useMemo(() => {
return [...favorites].sort((a, b) => {
if (sortBy === "cheapest") return a.price - b.price;
if (sortBy === "expensive") return b.price - a.price;
return 0; // No sorting
});
}, [favorites, sortBy]);

const { isDarkMode } = useTheme();

// Apply filtering based on the selected filter
Expand All @@ -22,13 +38,50 @@ const Favorites = () => {
return 0;
});


return (
<div className={`min-h-screen p-6 ${isDarkMode ? "bg-gray-900 text-white" : "bg-gray-50 text-black"}`}>
<div className="container mx-auto">
<div className="text-center mb-8">
<h1 className="text-4xl font-bold tracking-wide mb-2">
Your Favorites
</h1>

<p className="text-xl text-white py-4">
{favorites.length === 0
? "No favorite products yet"
: `${favorites.length} favorite products`}
</p>
</div>

{/* Custom Sorting Dropdown */}
<div className="text-center mb-8 relative inline-block">
<label className="text-white font-semibold mr-4">Sort By: Price</label>
<div
className="px-4 py-2 rounded bg-gray-300 text-black font-semibold cursor-pointer transition-all duration-300 ease-in-out transform hover:scale-105 hover:bg-gray-400"
onClick={() => setIsOpen(!isOpen)}
>
{sortBy ? (sortBy === "cheapest" ? "Price: The cheapest" : "Price: The most expensive") : "Select"}
</div>
{isOpen && (
<div className="absolute left-1/2 transform -translate-x-1/2 mt-2 w-48 bg-gray-300 rounded-md shadow-md z-10 transition-all duration-300 ease-in-out transform scale-95 opacity-0 hover:scale-100 hover:opacity-100">
<div className="py-2">
<div
className="px-4 py-2 hover:bg-gray-400 cursor-pointer"
onClick={() => { setSortBy("cheapest"); setIsOpen(false); }}
>
The cheapest
</div>
<div
className="px-4 py-2 hover:bg-gray-400 cursor-pointer"
onClick={() => { setSortBy("expensive"); setIsOpen(false); }}
>
The most expensive
</div>
</div>
</div>
)}

<p className={`text-lg py-4 ${isDarkMode ? "text-gray-400" : "text-gray-600"}`}>
{favorites.length === 0 ? "No favorite products yet" : `${favorites.length} favorite products`}
</p>
Expand All @@ -50,6 +103,7 @@ const Favorites = () => {
<option value="cheapest">Price: The cheapest</option>
<option value="expensive">Price: The most expensive</option>
</select>

</div>

<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-12 mx-16 my-16">
Expand All @@ -61,31 +115,57 @@ const Favorites = () => {
isDarkMode ? "bg-gray-800" : "bg-white"
}`}
>

<h2 className="text-xl font-bold text-white mb-2 pr-8">
{product.name}
</h2>
<p className="text-lg text-white font-semibold mb-4">
${product.price}
</p>

{/* Image with aspect ratio fix */}
<div className="w-full aspect-square bg-gray-200 rounded-md flex items-center justify-center text-gray-500 relative overflow-hidden">

<h2 className="text-xl font-bold mb-2 pr-8">{product.name}</h2>
<p className="text-lg font-semibold mb-4">${product.price}</p>
<div className="w-full h-40 bg-gray-200 rounded-md flex items-center justify-center text-gray-500 relative">

<img
src={product.image}
alt={product.name}
className="object-contain w-full h-full"
/>
<HeartIcon className="absolute top-2 right-2 cursor-pointer z-10" product={product} />
</div>

{/* Updated Add to Cart button styling */}
<button
onClick={() => {
addToCart(product);
toast.success("Added to cart");
}}

className="w-full mt-4 bg-pink-500 text-white px-6 py-3 rounded-lg hover:bg-pink-600 transition-transform transform hover:scale-105"

className={`w-full mt-4 font-semibold py-2 px-4 rounded-lg shadow-md hover:shadow-lg transition duration-300 ease-in-out transform hover:scale-105 ${
isDarkMode ? "bg-rose-500 hover:bg-rose-600" : "bg-rose-600 hover:bg-rose-700 text-white"
}`}

>
Add to Cart
</button>
</div>
))
) : (
<div className="col-span-full text-center">

<p className="text-white text-xl font-semibold mb-4">
Your favorites list is empty πŸ˜”
</p>
<Link
to="/shop"
className="bg-pink-500 text-white px-6 py-3 rounded-lg transition duration-300 ease-in-out transform hover:scale-105 hover:bg-pink-600 cursor-pointer"

<p className={`text-lg mb-4 ${isDarkMode ? "text-gray-400" : "text-gray-600"}`}>
Your favorites list is empty
</p>
Expand All @@ -94,6 +174,7 @@ const Favorites = () => {
className={`px-6 py-3 rounded-lg transition-colors inline-block shadow-md ${
isDarkMode ? "bg-rose-500 hover:bg-rose-600 text-white" : "bg-rose-600 hover:bg-rose-700 text-white"
}`}

>
Go Shopping
</Link>
Expand All @@ -105,4 +186,4 @@ const Favorites = () => {
);
};

export default Favorites;
export default Favorites;
22 changes: 17 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
"license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
"concurrently": "^9.0.1",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
Expand All @@ -30,5 +29,8 @@
"multer": "^1.4.5-lts.1",
"nodemon": "^3.1.7",
"store": "file:"
},
"devDependencies": {
"concurrently": "^9.1.2"
}
}