From a5bd00d9e500f58cfcf1ec0ad93840e8bd5d6e6e Mon Sep 17 00:00:00 2001 From: Yash Seth Date: Wed, 15 Oct 2025 02:41:04 +0530 Subject: [PATCH 1/8] added wishlist slice --- src/store/index.js | 4 +++- src/store/wishListSlice.js | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/store/wishListSlice.js diff --git a/src/store/index.js b/src/store/index.js index 067b8c77..c7def023 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -2,12 +2,14 @@ import { configureStore } from '@reduxjs/toolkit'; import productSlice from './productSlice'; import cartSlice from './cartSlice'; import authSlice from './authSlice'; +import wishListSlice from './wishListSlice'; const store = configureStore({ reducer: { products: productSlice, cart: cartSlice, auth: authSlice, + wishList: wishListSlice, }, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ @@ -17,4 +19,4 @@ const store = configureStore({ }), }); -export default store; \ No newline at end of file +export default store; diff --git a/src/store/wishListSlice.js b/src/store/wishListSlice.js new file mode 100644 index 00000000..8c3724b1 --- /dev/null +++ b/src/store/wishListSlice.js @@ -0,0 +1,24 @@ +import { createSlice } from '@reduxjs/toolkit'; + +//initialState for wishlist +const initialState = { + items: [], +}; + +//wishlist slice (stub implementation) +const wishListSlice = createSlice({ + name: 'wishList', + initialState, + reducers: { + addToWishList: (state, action) => { + state.items.push(action.payload); + }, + RemoveFromWishList: (state, action) => { + state.items = state.items.filter((item) => item.id != action.payload.id); + }, + }, +}); + +export const { addToWishList, RemoveFromWishList } = wishListSlice.actions; + +export default wishListSlice.reducer; From 7567f3afcb53d0ae3751c3dc70042ee7190853cf Mon Sep 17 00:00:00 2001 From: Yash Seth Date: Wed, 15 Oct 2025 02:41:55 +0530 Subject: [PATCH 2/8] add/remove to wishlist on heart icon on product page --- src/components/Products/ProductCard.jsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/Products/ProductCard.jsx b/src/components/Products/ProductCard.jsx index c3d9fd67..200359d8 100644 --- a/src/components/Products/ProductCard.jsx +++ b/src/components/Products/ProductCard.jsx @@ -2,6 +2,8 @@ import { useState, forwardRef, useRef, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { addRecentlyViewed } from '../../utils/recentlyViewed'; +import { addToWishList, RemoveFromWishList } from '../../store/wishListSlice'; +import { useDispatch } from 'react-redux'; const HeartIcon = ({ isWishlisted = false, animate = false, @@ -55,7 +57,7 @@ const ProductCard = forwardRef( const [cartAdded, setCartAdded] = useState(false); const cartLoadingTimeoutRef = useRef(null); const cartAddedTimeoutRef = useRef(null); - + const dispatch = useDispatch(); // Check if current product+flavor is in cart const itemIsInCart = isInCart ? isInCart(selectedFlavor) : false; @@ -108,8 +110,10 @@ const ProductCard = forwardRef( if (likeTimeoutRef.current) clearTimeout(likeTimeoutRef.current); likeTimeoutRef.current = setTimeout(() => setAnimateLike(false), 520); // Call the toggle wishlist function - if (onAddToWishlist) { - onAddToWishlist(product); + if (isWishlisted) { + dispatch(RemoveFromWishList(product)); + } else { + dispatch(addToWishList(product)); } }; From af91da2dbd894a3781ae4065a99f8e4ca85dd319 Mon Sep 17 00:00:00 2001 From: Yash Seth Date: Wed, 15 Oct 2025 02:42:22 +0530 Subject: [PATCH 3/8] Rendering current wishlist --- src/components/Header/MainHeader.jsx | 93 +++++++++++++++++++-- src/components/Products/WishListProduct.jsx | 50 +++++++++++ 2 files changed, 137 insertions(+), 6 deletions(-) create mode 100644 src/components/Products/WishListProduct.jsx diff --git a/src/components/Header/MainHeader.jsx b/src/components/Header/MainHeader.jsx index 3afa40e9..8dd61e7b 100644 --- a/src/components/Header/MainHeader.jsx +++ b/src/components/Header/MainHeader.jsx @@ -1,4 +1,4 @@ -import React, { useState, useRef } from 'react'; +import { useState, useRef, useMemo } from 'react'; import { Link } from 'react-router-dom'; import { Menu, @@ -12,13 +12,84 @@ import { import SearchBox from '../Search/SearchBox'; import TopHeader from '../TopHeader/TopHeader'; import ShopMenu from '../ShopMenu'; - +import { useSelector } from 'react-redux'; +import WishListProductCard from '../Products/WishListProduct'; +import { RemoveFromWishList } from '../../store/wishListSlice'; export default function Header() { const [mobileOpen, setMobileOpen] = useState(false); const [shopOpen, setShopOpen] = useState(false); const [search, setSearch] = useState(false); const mobileMenuRef = useRef(null); + const [wishListOpen, setWishListOpen] = useState(false); + + const wishListData = useSelector((state) => state.wishList); + const wishListScreen = useMemo(() => { + return ( +
setWishListOpen(false)} + > + {/* Drawer */} +
e.stopPropagation()} + > + {/* Header */} +
+

+ WISHLIST +

+ +
+ {/* Wishlist Content */} + {wishListData.items.length === 0 ? ( + // Empty State +
+

Your wishlist is empty.

+ +
+ ) : ( + // Populated State + <> +
+ {wishListData.items.map((prod) => ( + + ))} +
+ +
+ +
+ + )} +
+
+ ); + }, [wishListData]); // Handle shop button click const handleShopClick = () => { setShopOpen(!shopOpen); @@ -100,13 +171,22 @@ export default function Header() { - setWishListOpen(true)} + className="relative transform transition-transform duration-200 hover:scale-110 hover:text-black cursor-pointer" > - + + {wishListData.items.length > 0 && ( + + {wishListData.items.length} + + )} + {/* Search Drawer */} + {wishListOpen && wishListScreen} {search && setSearch(false)} />} ); diff --git a/src/components/Products/WishListProduct.jsx b/src/components/Products/WishListProduct.jsx new file mode 100644 index 00000000..22839bfc --- /dev/null +++ b/src/components/Products/WishListProduct.jsx @@ -0,0 +1,50 @@ +import { Heart } from 'lucide-react'; +import { useDispatch } from 'react-redux'; + +const WishListProductCard = ({ product, RemoveFromWishList }) => { + const { name, price, imageUrl, salePercentage, flavor } = product; + + const dispatch = useDispatch(); + + const handleWishlistClick = () => { + dispatch(RemoveFromWishList(product)); + }; + + return ( +
+ {/* Left side container for image and product info */} +
+ {/* Product Image */} + {name} + + {/* Product Info */} +
+

{name}

+
+ ${price.toFixed(2)} + + {salePercentage}% OFF + +
+

{flavor}

+
+
+ {/* Wishlist Icon on the far right */} + +
+
+
+ ); +}; + +export default WishListProductCard; From 32e638cdaad5e0f81ec37a45dd7d573e67c814ea Mon Sep 17 00:00:00 2001 From: Yash Seth Date: Sat, 18 Oct 2025 00:55:21 +0530 Subject: [PATCH 4/8] changes updated --- src/components/Header/MainHeader.jsx | 77 ++---------- src/components/Products/ProductCard.jsx | 10 +- src/components/Products/WishListProduct.jsx | 24 ++-- src/components/Products/WishiListScreen.jsx | 127 ++++++++++++++++++++ src/store/wishListSlice.js | 5 +- 5 files changed, 151 insertions(+), 92 deletions(-) create mode 100644 src/components/Products/WishiListScreen.jsx diff --git a/src/components/Header/MainHeader.jsx b/src/components/Header/MainHeader.jsx index 0a8d35db..3d99e1b8 100644 --- a/src/components/Header/MainHeader.jsx +++ b/src/components/Header/MainHeader.jsx @@ -13,8 +13,7 @@ import { ShoppingCart, } from 'lucide-react'; import { useSelector } from 'react-redux'; -import WishListProductCard from '../Products/WishListProduct'; -import { RemoveFromWishList } from '../../store/wishListSlice'; +import WishListScreen from '../Products/WishiListScreen'; export default function Header() { const [mobileOpen, setMobileOpen] = useState(false); const [shopOpen, setShopOpen] = useState(false); @@ -23,73 +22,6 @@ export default function Header() { const [wishListOpen, setWishListOpen] = useState(false); const wishListData = useSelector((state) => state.wishList); - const wishListScreen = useMemo(() => { - return ( -
setWishListOpen(false)} - > - {/* Drawer */} -
e.stopPropagation()} - > - {/* Header */} -
-

- WISHLIST -

- -
- - {/* Wishlist Content */} - {wishListData.items.length === 0 ? ( - // Empty State -
-

Your wishlist is empty.

- -
- ) : ( - // Populated State - <> -
- {wishListData.items.map((prod) => ( - - ))} -
- -
- -
- - )} -
-
- ); - }, [wishListData]); // Handle shop button click const handleShopClick = () => { setShopOpen(!shopOpen); @@ -410,7 +342,12 @@ export default function Header() { {/* Search Drawer */} - {wishListOpen && wishListScreen} + {wishListOpen && ( + + )} {search && setSearch(false)} />} ); diff --git a/src/components/Products/ProductCard.jsx b/src/components/Products/ProductCard.jsx index 200359d8..6d19f7ef 100644 --- a/src/components/Products/ProductCard.jsx +++ b/src/components/Products/ProductCard.jsx @@ -1,7 +1,7 @@ import { useState, forwardRef, useRef, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { addRecentlyViewed } from '../../utils/recentlyViewed'; - +// import { addToWishList, RemoveFromWishList } from '../../store/wishListSlice'; import { useDispatch } from 'react-redux'; const HeartIcon = ({ @@ -35,13 +35,7 @@ const CartIcon = ({ className = 'h-6 w-6' }) => ( const ProductCard = forwardRef( ( - { - product, - onAddToWishlist, - onAddToCart, - isWishlisted: initialWishlisted = false, - isInCart, - }, + { product, onAddToCart, isWishlisted: initialWishlisted = false, isInCart }, ref ) => { const navigate = useNavigate(); diff --git a/src/components/Products/WishListProduct.jsx b/src/components/Products/WishListProduct.jsx index 22839bfc..4ef428e3 100644 --- a/src/components/Products/WishListProduct.jsx +++ b/src/components/Products/WishListProduct.jsx @@ -1,31 +1,31 @@ import { Heart } from 'lucide-react'; -import { useDispatch } from 'react-redux'; const WishListProductCard = ({ product, RemoveFromWishList }) => { + if (!product) return null; const { name, price, imageUrl, salePercentage, flavor } = product; - - const dispatch = useDispatch(); - - const handleWishlistClick = () => { - dispatch(RemoveFromWishList(product)); - }; - + const priceStr = typeof price === 'number' ? price.toFixed(2) : price; return (
{/* Left side container for image and product info */}
{/* Product Image */} {name} {}} + onError={() => {}} + loading="lazy" /> {/* Product Info */}

{name}

- ${price.toFixed(2)} + ${priceStr} {salePercentage}% OFF @@ -35,7 +35,7 @@ const WishListProductCard = ({ product, RemoveFromWishList }) => {
{/* Wishlist Icon on the far right */} +
+ + {/* Wishlist Content */} + {wishListData.items.length === 0 ? ( +
+

Your wishlist is empty.

+ +
+ ) : ( + <> +
+ {wishListData.items.map((prod) => ( + + dispatch(RemoveFromWishList(prod)) + } + /> + ))} +
+ + {/* Footer */} +
+ +
+ + )} +
+
+ ); + }, [wishListData, dispatch, setWishListOpen]); + + return wishListScreen; +}; + +export default WishListDrawer; diff --git a/src/store/wishListSlice.js b/src/store/wishListSlice.js index 8c3724b1..1e161abd 100644 --- a/src/store/wishListSlice.js +++ b/src/store/wishListSlice.js @@ -11,10 +11,11 @@ const wishListSlice = createSlice({ initialState, reducers: { addToWishList: (state, action) => { - state.items.push(action.payload); + if (!state.items.some((i) => i.id === action.payload.id)) + state.items.push(action.payload); }, RemoveFromWishList: (state, action) => { - state.items = state.items.filter((item) => item.id != action.payload.id); + state.items = state.items.filter((item) => item.id !== action.payload.id); }, }, }); From 5bf8163cf9a357563f89406a8bab3144ff29eced Mon Sep 17 00:00:00 2001 From: Yash Seth Date: Sat, 18 Oct 2025 23:46:40 +0530 Subject: [PATCH 5/8] consistent RemoveFromWishlist,new WishList component --- src/components/Header/MainHeader.jsx | 9 +- src/components/Products/ProductCard.jsx | 1 - src/components/WishList/WishListProduct.jsx | 50 +++++++ .../WishList/WishiListDrawerScreen.jsx | 127 ++++++++++++++++++ src/utils/wishlist.js | 6 +- 5 files changed, 184 insertions(+), 9 deletions(-) create mode 100644 src/components/WishList/WishListProduct.jsx create mode 100644 src/components/WishList/WishiListDrawerScreen.jsx diff --git a/src/components/Header/MainHeader.jsx b/src/components/Header/MainHeader.jsx index c5ddf43c..d0e33b90 100644 --- a/src/components/Header/MainHeader.jsx +++ b/src/components/Header/MainHeader.jsx @@ -1,4 +1,4 @@ -import { useState, useRef, useMemo } from 'react'; +import { useState, useRef } from 'react'; import { Link } from 'react-router-dom'; import { useDispatch, useSelector } from 'react-redux'; import { logout } from '../../store/authSlice'; @@ -14,8 +14,7 @@ import { User, ShoppingCart, } from 'lucide-react'; -import { useSelector } from 'react-redux'; -import WishListScreen from '../Products/WishiListScreen'; +import WishListDrawerScreen from '../WishList/WishiListDrawerScreen'; export default function Header() { const [mobileOpen, setMobileOpen] = useState(false); const [shopOpen, setShopOpen] = useState(false); @@ -27,7 +26,7 @@ export default function Header() { const wishListData = useSelector((state) => state.wishList); const dispatch = useDispatch(); const isAuthenticated = useSelector((state) => state.auth.isAuthenticated); - + // Handle shop button click const handleShopClick = () => { setShopOpen(!shopOpen); @@ -369,7 +368,7 @@ export default function Header() { {/* Search Drawer */} {wishListOpen && ( - diff --git a/src/components/Products/ProductCard.jsx b/src/components/Products/ProductCard.jsx index 6d19f7ef..9fe4a37a 100644 --- a/src/components/Products/ProductCard.jsx +++ b/src/components/Products/ProductCard.jsx @@ -1,7 +1,6 @@ import { useState, forwardRef, useRef, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { addRecentlyViewed } from '../../utils/recentlyViewed'; -// import { addToWishList, RemoveFromWishList } from '../../store/wishListSlice'; import { useDispatch } from 'react-redux'; const HeartIcon = ({ diff --git a/src/components/WishList/WishListProduct.jsx b/src/components/WishList/WishListProduct.jsx new file mode 100644 index 00000000..4ef428e3 --- /dev/null +++ b/src/components/WishList/WishListProduct.jsx @@ -0,0 +1,50 @@ +import { Heart } from 'lucide-react'; + +const WishListProductCard = ({ product, RemoveFromWishList }) => { + if (!product) return null; + const { name, price, imageUrl, salePercentage, flavor } = product; + const priceStr = typeof price === 'number' ? price.toFixed(2) : price; + return ( +
+ {/* Left side container for image and product info */} +
+ {/* Product Image */} + {name} {}} + onError={() => {}} + loading="lazy" + /> + + {/* Product Info */} +
+

{name}

+
+ ${priceStr} + + {salePercentage}% OFF + +
+

{flavor}

+
+
+ {/* Wishlist Icon on the far right */} + +
+
+
+ ); +}; + +export default WishListProductCard; diff --git a/src/components/WishList/WishiListDrawerScreen.jsx b/src/components/WishList/WishiListDrawerScreen.jsx new file mode 100644 index 00000000..bb3be79d --- /dev/null +++ b/src/components/WishList/WishiListDrawerScreen.jsx @@ -0,0 +1,127 @@ +import React, { useEffect, useRef, useMemo } from 'react'; +import { X } from 'lucide-react'; +import { useDispatch } from 'react-redux'; +import { RemoveFromWishList } from '../../store/wishListSlice'; +import WishListProductCard from './WishListProduct'; + +const WishListDrawerScreen = ({ wishListData, setWishListOpen }) => { + const dispatch = useDispatch(); + const drawerRef = useRef(null); + + // 🔹 Close on Escape key + useEffect(() => { + const handleKeyDown = (e) => { + if (e.key === 'Escape') setWishListOpen(false); + + if (e.key === 'Tab' && drawerRef.current) { + const focusableEls = drawerRef.current.querySelectorAll( + 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' + ); + if (!focusableEls.length) return; + + const first = focusableEls[0]; + const last = focusableEls[focusableEls.length - 1]; + + if (e.shiftKey && document.activeElement === first) { + e.preventDefault(); + last.focus(); + } else if (!e.shiftKey && document.activeElement === last) { + e.preventDefault(); + first.focus(); + } + } + }; + + document.addEventListener('keydown', handleKeyDown); + return () => document.removeEventListener('keydown', handleKeyDown); + }, [setWishListOpen]); + + useEffect(() => { + if (drawerRef.current) { + const firstEl = drawerRef.current.querySelector( + 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' + ); + firstEl?.focus(); + } + }, [wishListData]); + + const wishListScreen = useMemo(() => { + return ( +
setWishListOpen(false)} + > + {/* Drawer */} +
e.stopPropagation()} + > + {/* Header */} +
+

+ WISHLIST +

+ +
+ + {/* Wishlist Content */} + {wishListData.items.length === 0 ? ( +
+

Your wishlist is empty.

+ +
+ ) : ( + <> +
+ {wishListData.items.map((prod) => ( + + dispatch(RemoveFromWishList(prod)) + } + /> + ))} +
+ + {/* Footer */} +
+ +
+ + )} +
+
+ ); + }, [wishListData, dispatch, setWishListOpen]); + + return wishListScreen; +}; + +export default WishListDrawerScreen; diff --git a/src/utils/wishlist.js b/src/utils/wishlist.js index f90b3c1f..b47c4c9c 100644 --- a/src/utils/wishlist.js +++ b/src/utils/wishlist.js @@ -50,7 +50,7 @@ export function addToWishlist(product) { } } -export function removeFromWishlist(productId) { +export function RemoveFromWishlist(productId) { if (!productId) return false; try { const current = getWishlist(); @@ -69,7 +69,7 @@ export function toggleWishlist(product) { const isCurrentlyInWishlist = isInWishlist(productId); if (isCurrentlyInWishlist) { - removeFromWishlist(productId); + RemoveFromWishlist(productId); return false; // Removed from wishlist } else { addToWishlist(product); @@ -81,6 +81,6 @@ export default { getWishlist, isInWishlist, addToWishlist, - removeFromWishlist, + RemoveFromWishlist, toggleWishlist, }; From 0fd540845ef04c4deb147121d380342a38dc0b1b Mon Sep 17 00:00:00 2001 From: Yash Seth Date: Tue, 21 Oct 2025 02:16:45 +0530 Subject: [PATCH 6/8] fix: camelCase , duplicate files --- src/components/Header/MainHeader.jsx | 14 +- src/components/Products/ProductCard.jsx | 4 +- src/components/Products/WishListProduct.jsx | 50 ------- src/components/Products/WishiListScreen.jsx | 127 ------------------ src/components/WishList/WishListProduct.jsx | 50 ------- ...stDrawerScreen.jsx => WishiListScreen.jsx} | 54 +++++++- src/store/wishListSlice.js | 4 +- 7 files changed, 58 insertions(+), 245 deletions(-) delete mode 100644 src/components/Products/WishListProduct.jsx delete mode 100644 src/components/Products/WishiListScreen.jsx delete mode 100644 src/components/WishList/WishListProduct.jsx rename src/components/WishList/{WishiListDrawerScreen.jsx => WishiListScreen.jsx} (63%) diff --git a/src/components/Header/MainHeader.jsx b/src/components/Header/MainHeader.jsx index 514a9ef3..51c8506a 100644 --- a/src/components/Header/MainHeader.jsx +++ b/src/components/Header/MainHeader.jsx @@ -3,15 +3,9 @@ import { Link } from 'react-router-dom'; import SearchBox from '../Search/SearchBox'; import TopHeader from '../TopHeader/TopHeader'; import ShopMenu from '../ShopMenu'; -import { - Menu, - X, - ChevronDown, - Search, - Heart, - User, -} from 'lucide-react'; -import WishListDrawerScreen from '../WishList/WishiListDrawerScreen'; +import { Menu, X, ChevronDown, Search, Heart, User } from 'lucide-react'; + +import WishListDrawerScreen from '../WishList/WishiListScreen'; import CartIcon from '../cart/CartIcon'; import CartDrawer from '../cart/CartDrawer'; @@ -132,7 +126,7 @@ export default function Header() { > - + setCartOpen(true)} />
diff --git a/src/components/Products/ProductCard.jsx b/src/components/Products/ProductCard.jsx index 9fe4a37a..47f20122 100644 --- a/src/components/Products/ProductCard.jsx +++ b/src/components/Products/ProductCard.jsx @@ -1,7 +1,7 @@ import { useState, forwardRef, useRef, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { addRecentlyViewed } from '../../utils/recentlyViewed'; -import { addToWishList, RemoveFromWishList } from '../../store/wishListSlice'; +import { addToWishList, removeFromWishList } from '../../store/wishListSlice'; import { useDispatch } from 'react-redux'; const HeartIcon = ({ isWishlisted = false, @@ -104,7 +104,7 @@ const ProductCard = forwardRef( likeTimeoutRef.current = setTimeout(() => setAnimateLike(false), 520); // Call the toggle wishlist function if (isWishlisted) { - dispatch(RemoveFromWishList(product)); + dispatch(removeFromWishList(product)); } else { dispatch(addToWishList(product)); } diff --git a/src/components/Products/WishListProduct.jsx b/src/components/Products/WishListProduct.jsx deleted file mode 100644 index 4ef428e3..00000000 --- a/src/components/Products/WishListProduct.jsx +++ /dev/null @@ -1,50 +0,0 @@ -import { Heart } from 'lucide-react'; - -const WishListProductCard = ({ product, RemoveFromWishList }) => { - if (!product) return null; - const { name, price, imageUrl, salePercentage, flavor } = product; - const priceStr = typeof price === 'number' ? price.toFixed(2) : price; - return ( -
- {/* Left side container for image and product info */} -
- {/* Product Image */} - {name} {}} - onError={() => {}} - loading="lazy" - /> - - {/* Product Info */} -
-

{name}

-
- ${priceStr} - - {salePercentage}% OFF - -
-

{flavor}

-
-
- {/* Wishlist Icon on the far right */} - -
-
-
- ); -}; - -export default WishListProductCard; diff --git a/src/components/Products/WishiListScreen.jsx b/src/components/Products/WishiListScreen.jsx deleted file mode 100644 index ee9a3767..00000000 --- a/src/components/Products/WishiListScreen.jsx +++ /dev/null @@ -1,127 +0,0 @@ -import React, { useEffect, useRef, useMemo } from 'react'; -import { X } from 'lucide-react'; -import { useDispatch } from 'react-redux'; -import { RemoveFromWishList } from '../../store/wishListSlice'; -import WishListProductCard from './WishListProduct'; - -const WishListDrawer = ({ wishListData, setWishListOpen }) => { - const dispatch = useDispatch(); - const drawerRef = useRef(null); - - // 🔹 Close on Escape key - useEffect(() => { - const handleKeyDown = (e) => { - if (e.key === 'Escape') setWishListOpen(false); - - if (e.key === 'Tab' && drawerRef.current) { - const focusableEls = drawerRef.current.querySelectorAll( - 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' - ); - if (!focusableEls.length) return; - - const first = focusableEls[0]; - const last = focusableEls[focusableEls.length - 1]; - - if (e.shiftKey && document.activeElement === first) { - e.preventDefault(); - last.focus(); - } else if (!e.shiftKey && document.activeElement === last) { - e.preventDefault(); - first.focus(); - } - } - }; - - document.addEventListener('keydown', handleKeyDown); - return () => document.removeEventListener('keydown', handleKeyDown); - }, [setWishListOpen]); - - useEffect(() => { - if (drawerRef.current) { - const firstEl = drawerRef.current.querySelector( - 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' - ); - firstEl?.focus(); - } - }, [wishListData]); - - const wishListScreen = useMemo(() => { - return ( -
setWishListOpen(false)} - > - {/* Drawer */} -
e.stopPropagation()} - > - {/* Header */} -
-

- WISHLIST -

- -
- - {/* Wishlist Content */} - {wishListData.items.length === 0 ? ( -
-

Your wishlist is empty.

- -
- ) : ( - <> -
- {wishListData.items.map((prod) => ( - - dispatch(RemoveFromWishList(prod)) - } - /> - ))} -
- - {/* Footer */} -
- -
- - )} -
-
- ); - }, [wishListData, dispatch, setWishListOpen]); - - return wishListScreen; -}; - -export default WishListDrawer; diff --git a/src/components/WishList/WishListProduct.jsx b/src/components/WishList/WishListProduct.jsx deleted file mode 100644 index 4ef428e3..00000000 --- a/src/components/WishList/WishListProduct.jsx +++ /dev/null @@ -1,50 +0,0 @@ -import { Heart } from 'lucide-react'; - -const WishListProductCard = ({ product, RemoveFromWishList }) => { - if (!product) return null; - const { name, price, imageUrl, salePercentage, flavor } = product; - const priceStr = typeof price === 'number' ? price.toFixed(2) : price; - return ( -
- {/* Left side container for image and product info */} -
- {/* Product Image */} - {name} {}} - onError={() => {}} - loading="lazy" - /> - - {/* Product Info */} -
-

{name}

-
- ${priceStr} - - {salePercentage}% OFF - -
-

{flavor}

-
-
- {/* Wishlist Icon on the far right */} - -
-
-
- ); -}; - -export default WishListProductCard; diff --git a/src/components/WishList/WishiListDrawerScreen.jsx b/src/components/WishList/WishiListScreen.jsx similarity index 63% rename from src/components/WishList/WishiListDrawerScreen.jsx rename to src/components/WishList/WishiListScreen.jsx index bb3be79d..2f94acd3 100644 --- a/src/components/WishList/WishiListDrawerScreen.jsx +++ b/src/components/WishList/WishiListScreen.jsx @@ -1,9 +1,55 @@ import React, { useEffect, useRef, useMemo } from 'react'; import { X } from 'lucide-react'; import { useDispatch } from 'react-redux'; -import { RemoveFromWishList } from '../../store/wishListSlice'; -import WishListProductCard from './WishListProduct'; +import { removeFromWishList } from '../../store/wishListSlice'; +import { Heart } from 'lucide-react'; +const WishListProductCard = ({ product, removeFromWishList }) => { + if (!product) return null; + const { name, price, imageUrl, salePercentage, flavor } = product; + const priceStr = typeof price === 'number' ? price.toFixed(2) : price; + return ( +
+ {/* Left side container for image and product info */} +
+ {/* Product Image */} + {name} {}} + onError={() => {}} + loading="lazy" + /> + + {/* Product Info */} +
+

{name}

+
+ ${priceStr} + + {salePercentage}% OFF + +
+

{flavor}

+
+
+ {/* Wishlist Icon on the far right */} + +
+
+
+ ); +}; const WishListDrawerScreen = ({ wishListData, setWishListOpen }) => { const dispatch = useDispatch(); const drawerRef = useRef(null); @@ -96,8 +142,8 @@ const WishListDrawerScreen = ({ wishListData, setWishListOpen }) => { - dispatch(RemoveFromWishList(prod)) + removeFromWishList={() => + dispatch(removeFromWishList(prod)) } /> ))} diff --git a/src/store/wishListSlice.js b/src/store/wishListSlice.js index 1e161abd..218ae0e1 100644 --- a/src/store/wishListSlice.js +++ b/src/store/wishListSlice.js @@ -14,12 +14,12 @@ const wishListSlice = createSlice({ if (!state.items.some((i) => i.id === action.payload.id)) state.items.push(action.payload); }, - RemoveFromWishList: (state, action) => { + removeFromWishList: (state, action) => { state.items = state.items.filter((item) => item.id !== action.payload.id); }, }, }); -export const { addToWishList, RemoveFromWishList } = wishListSlice.actions; +export const { addToWishList, removeFromWishList } = wishListSlice.actions; export default wishListSlice.reducer; From 170da744d4639f80a0b1ccb8ca109880b9cd33f2 Mon Sep 17 00:00:00 2001 From: Yash Seth Date: Tue, 21 Oct 2025 18:43:55 +0530 Subject: [PATCH 7/8] added redux functions , consistent naming --- src/components/Header/MainHeader.jsx | 6 +++--- src/components/WishList/WishiListScreen.jsx | 4 ++-- src/utils/wishlist.js | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/components/Header/MainHeader.jsx b/src/components/Header/MainHeader.jsx index 51c8506a..778d2715 100644 --- a/src/components/Header/MainHeader.jsx +++ b/src/components/Header/MainHeader.jsx @@ -4,8 +4,8 @@ import SearchBox from '../Search/SearchBox'; import TopHeader from '../TopHeader/TopHeader'; import ShopMenu from '../ShopMenu'; import { Menu, X, ChevronDown, Search, Heart, User } from 'lucide-react'; - -import WishListDrawerScreen from '../WishList/WishiListScreen'; +import { useSelector, useDispatch } from 'react-redux'; +import WishListScreen from '../WishList/WishiListScreen'; import CartIcon from '../cart/CartIcon'; import CartDrawer from '../cart/CartDrawer'; @@ -336,7 +336,7 @@ export default function Header() { {/* Search Drawer */} {wishListOpen && ( - diff --git a/src/components/WishList/WishiListScreen.jsx b/src/components/WishList/WishiListScreen.jsx index 2f94acd3..ccd0b0bb 100644 --- a/src/components/WishList/WishiListScreen.jsx +++ b/src/components/WishList/WishiListScreen.jsx @@ -50,7 +50,7 @@ const WishListProductCard = ({ product, removeFromWishList }) => {
); }; -const WishListDrawerScreen = ({ wishListData, setWishListOpen }) => { +const WishListScreen = ({ wishListData, setWishListOpen }) => { const dispatch = useDispatch(); const drawerRef = useRef(null); @@ -170,4 +170,4 @@ const WishListDrawerScreen = ({ wishListData, setWishListOpen }) => { return wishListScreen; }; -export default WishListDrawerScreen; +export default WishListScreen; diff --git a/src/utils/wishlist.js b/src/utils/wishlist.js index b47c4c9c..33e25ce4 100644 --- a/src/utils/wishlist.js +++ b/src/utils/wishlist.js @@ -24,7 +24,7 @@ export function isInWishlist(productId) { } export function addToWishlist(product) { - if (!product || !product.id && !product._id) return false; // Ensure product has an ID + if (!product || (!product.id && !product._id)) return false; // Ensure product has an ID try { const current = getWishlist(); const productId = product.id || product._id; @@ -50,7 +50,7 @@ export function addToWishlist(product) { } } -export function RemoveFromWishlist(productId) { +export function removeFromWishlist(productId) { if (!productId) return false; try { const current = getWishlist(); @@ -63,13 +63,13 @@ export function RemoveFromWishlist(productId) { } export function toggleWishlist(product) { - if (!product || !product.id && !product._id) return false; // Ensure product has an ID + if (!product || (!product.id && !product._id)) return false; // Ensure product has an ID const productId = product.id || product._id; const isCurrentlyInWishlist = isInWishlist(productId); if (isCurrentlyInWishlist) { - RemoveFromWishlist(productId); + removeFromWishlist(productId); return false; // Removed from wishlist } else { addToWishlist(product); @@ -81,6 +81,6 @@ export default { getWishlist, isInWishlist, addToWishlist, - RemoveFromWishlist, + removeFromWishlist, toggleWishlist, }; From 91e6d25edff280e72347740244c35abb85f2f3ae Mon Sep 17 00:00:00 2001 From: Yash Seth Date: Tue, 21 Oct 2025 23:08:05 +0530 Subject: [PATCH 8/8] removed unused code --- src/components/Header/MainHeader.jsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/Header/MainHeader.jsx b/src/components/Header/MainHeader.jsx index 778d2715..e1adbd63 100644 --- a/src/components/Header/MainHeader.jsx +++ b/src/components/Header/MainHeader.jsx @@ -4,7 +4,7 @@ import SearchBox from '../Search/SearchBox'; import TopHeader from '../TopHeader/TopHeader'; import ShopMenu from '../ShopMenu'; import { Menu, X, ChevronDown, Search, Heart, User } from 'lucide-react'; -import { useSelector, useDispatch } from 'react-redux'; +import { useSelector } from 'react-redux'; import WishListScreen from '../WishList/WishiListScreen'; import CartIcon from '../cart/CartIcon'; import CartDrawer from '../cart/CartDrawer'; @@ -18,8 +18,6 @@ export default function Header() { const [wishListOpen, setWishListOpen] = useState(false); const wishListData = useSelector((state) => state.wishList); - const dispatch = useDispatch(); - const isAuthenticated = useSelector((state) => state.auth.isAuthenticated); // Handle shop button click const handleShopClick = () => {