Skip to content

Conversation

@Lagani21
Copy link
Owner

@Lagani21 Lagani21 commented Jan 24, 2026

  • Create WishlistContext with localStorage persistence
  • Add WishlistItem component for displaying saved items
  • Create /wishlist page with add-all-to-cart and clear functionality
  • Update ProductCard with heart toggle button
  • Add wishlist icon with badge to Navbar

Summary by CodeRabbit

New Features

  • Added a Wishlist feature allowing users to save products for later
  • Wishlist icon in the navigation bar displaying saved item count
  • New dedicated Wishlist page to view, manage, and add saved products to cart
  • Wishlist button on product cards for quick saving
  • Bulk actions: add all wishlist items to cart or clear the entire wishlist
  • Wishlist data persists across sessions

✏️ Tip: You can customize this high-level summary in your review settings.

- Create WishlistContext with localStorage persistence
- Add WishlistItem component for displaying saved items
- Create /wishlist page with add-all-to-cart and clear functionality
- Update ProductCard with heart toggle button
- Add wishlist icon with badge to Navbar
@coderabbitai
Copy link

coderabbitai bot commented Jan 24, 2026

Warning

.coderabbit.yaml has a parsing error

The CodeRabbit configuration file in this repository has a parsing error and default settings were used instead. Please fix the error(s) in the configuration file. You can initialize chat with CodeRabbit to get help with the configuration file.

💥 Parsing errors (1)
Validation error: Expected boolean, received number at "reviews.collapse_walkthrough"
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
📝 Walkthrough

Walkthrough

A wishlist feature is introduced to the application with a new WishlistContext providing state management and persistence, a dedicated wishlist page displaying saved items, navbar integration showing wishlist badge, wishlist toggle buttons on product cards, and a WishlistItem component for rendering wishlist entries with cart and removal actions.

Changes

Cohort / File(s) Summary
Context & Provider Setup
src/context/WishlistContext.tsx
New React context with WishlistProvider and useWishlist hook; manages wishlist items with add, remove, toggle, clear operations; includes localStorage persistence with hydration-safe initialization; implements isInWishlist query utility.
Layout Integration
src/app/layout.tsx
Wraps layout tree with WishlistProvider nested inside CartProvider to make wishlist context available throughout the application.
Wishlist Page
src/app/wishlist/page.tsx
New client-side page component rendering wishlist UI with mounting state for skeleton loading, empty state with browse link, header with item count, WishlistItem list rendering, "Add All to Cart" action with batch add functionality, and "Clear All" action with confirmation modal.
Navigation Updates
src/components/Navbar.tsx
Adds wishlist icon/link with badge displaying wishlist count (capped at 99+); integrates into desktop and mobile menus alongside existing cart icon; updates cart badge logic and adds aria-labels for accessibility.
Product Card Enhancement
src/components/ProductCard.tsx
Adds wishlist toggle button at top-right of product card with dynamic styling; integrates useWishlist hook to track and manage wishlist state; repositions Featured badge to accommodate new button.
Wishlist Item Component
src/components/WishlistItem.tsx
New component rendering individual wishlist entries with product image, name, category, 5-star rating, reviews count, pricing (with computed discount badge), stock status, and action buttons (Add to Cart, Remove); includes product page navigation link.

Sequence Diagram

sequenceDiagram
    participant User
    participant ProductCard
    participant WishlistContext as Wishlist Context
    participant WishlistPage
    participant CartContext as Cart Context

    User->>ProductCard: Click Wishlist Button
    ProductCard->>WishlistContext: toggleWishlist(product)
    WishlistContext->>WishlistContext: Update items in state
    WishlistContext->>ProductCard: Re-render with isWishlisted
    ProductCard->>User: Show updated button state

    User->>ProductCard: Navigate to Wishlist
    User->>WishlistPage: View wishlist page
    WishlistPage->>WishlistContext: useWishlist() hook
    WishlistContext->>WishlistPage: Return items & actions
    WishlistPage->>User: Render WishlistItem list

    User->>WishlistPage: Click "Add to Cart"
    WishlistPage->>CartContext: addToCart(product)
    CartContext->>CartContext: Update cart items
    CartContext->>User: Cart updated (badge refreshes)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A wishlist of wonders, so carefully curated,
From ProductCard toggles to items curated,
Click, save, and cart them—context flows free,
A warren of wishes, as far as you see! 🌟

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title directly and concisely describes the main feature being added: a wishlist capability for saving favorite products, which aligns with all the changes across context, components, pages, and UI elements.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@src/app/wishlist/page.tsx`:
- Around line 153-157: Update the copy in the wishlist page paragraph to avoid
promising an unimplemented sale-alert feature: edit the paragraph element with
className "text-gray-600 text-sm" in the wishlist page component
(src/app/wishlist/page.tsx) to remove or rephrase the sentence "Keep an eye on
prices – we'll show you when items go on sale!" so it no longer claims sale
notifications exist; keep the rest of the explanatory text about browser-saved
wishlist and moving items to cart.
- Around line 19-23: The handleAddAllToCart currently iterates over items and
calls addToCart for every product, which adds out-of-stock items; update
handleAddAllToCart to first filter items by product.inStock (e.g.,
items.filter(p => p.inStock)) and call addToCart only for those in-stock
products, and optionally collect/skipped product names to surface user feedback
or a toast for items that were not added so the user knows why some items were
skipped.

In `@src/components/Navbar.tsx`:
- Around line 194-198: The mobile wishlist badge in Navbar.tsx is rendering the
raw wishlistItems value instead of applying the same "99+" cap used by the
desktop badge; update the JSX that renders the mobile badge (the span within the
conditional that checks wishlistItems > 0) to display wishlistItems > 99 ? "99+"
: wishlistItems (or the existing helper used for the desktop badge) so the
mobile and desktop badges show consistent capped values.

In `@src/components/WishlistItem.tsx`:
- Around line 17-23: Prevent adding out-of-stock items by updating
handleAddToCart to check product.inStock and return (or show feedback) if false,
and also reflect this in the UI by disabling the Add to Cart button when
product.inStock is false; specifically, add a guard in handleAddToCart that does
not call addToCart(product) for !product.inStock and wire the button's disabled
prop (and visual/aria state) to product.inStock, optionally invoking a
user-facing message function (e.g., showToast or onError) when the user attempts
to add an out-of-stock product.
🧹 Nitpick comments (5)
src/context/WishlistContext.tsx (2)

31-42: Consider validating localStorage data structure.

Parsed JSON from localStorage is directly assigned to state without schema validation. If the stored data is malformed or from an older schema, this could cause runtime errors in consuming components.

🔧 Suggested validation
   useEffect(() => {
     const savedWishlist = localStorage.getItem(STORAGE_KEY);
     if (savedWishlist) {
       try {
-        setItems(JSON.parse(savedWishlist));
+        const parsed = JSON.parse(savedWishlist);
+        if (Array.isArray(parsed)) {
+          setItems(parsed.filter((item): item is Product => 
+            item && typeof item.id === 'number'
+          ));
+        }
       } catch (e) {
         console.error("Failed to parse wishlist from localStorage:", e);
       }
     }
     setIsInitialized(true);
   }, []);

65-70: isInWishlist recreates on every items change, potentially causing unnecessary re-renders.

Since isInWishlist has items in its dependency array, it gets a new reference whenever items changes. Components that destructure isInWishlist will re-render even if they don't use the result. Consider using useMemo for the lookup or documenting this behavior.

src/components/WishlistItem.tsx (2)

25-29: Discount calculation is duplicated.

This exact calculation exists in ProductCard.tsx (line 30-32). Consider extracting to a shared utility function.


61-79: Star rating SVG is duplicated across components.

The rating display with the star SVG path appears identically in ProductCard.tsx. Consider extracting a reusable StarRating component.

src/app/wishlist/page.tsx (1)

101-127: Modal lacks keyboard accessibility.

The confirmation modal doesn't trap focus, handle Escape key to close, or have proper ARIA attributes (role="dialog", aria-modal, aria-labelledby).

♻️ Suggested improvements
       {showClearConfirm && (
-        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
-          <div className="bg-white rounded-lg p-6 max-w-sm mx-4 shadow-xl">
+        <div 
+          className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"
+          onClick={() => setShowClearConfirm(false)}
+          onKeyDown={(e) => e.key === 'Escape' && setShowClearConfirm(false)}
+        >
+          <div 
+            className="bg-white rounded-lg p-6 max-w-sm mx-4 shadow-xl"
+            role="dialog"
+            aria-modal="true"
+            aria-labelledby="clear-dialog-title"
+            onClick={(e) => e.stopPropagation()}
+          >
             <h3 className="text-lg font-bold text-gray-900 mb-2">
+              id="clear-dialog-title"
               Clear Wishlist?
             </h3>

Comment on lines +19 to +23
const handleAddAllToCart = () => {
items.forEach((product) => {
addToCart(product);
});
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

"Add All to Cart" adds out-of-stock items.

The handler adds all wishlist items to cart without checking product.inStock. Consider filtering or providing user feedback.

🐛 Proposed fix
   const handleAddAllToCart = () => {
-    items.forEach((product) => {
+    const inStockItems = items.filter((product) => product.inStock);
+    inStockItems.forEach((product) => {
       addToCart(product);
     });
+    // Optionally notify user if some items were skipped
   };
🤖 Prompt for AI Agents
In `@src/app/wishlist/page.tsx` around lines 19 - 23, The handleAddAllToCart
currently iterates over items and calls addToCart for every product, which adds
out-of-stock items; update handleAddAllToCart to first filter items by
product.inStock (e.g., items.filter(p => p.inStock)) and call addToCart only for
those in-stock products, and optionally collect/skipped product names to surface
user feedback or a toast for items that were not added so the user knows why
some items were skipped.

Comment on lines +153 to +157
<p className="text-gray-600 text-sm">
Items in your wishlist are saved to your browser. You can easily move
them to your cart when you&apos;re ready to purchase. Keep an eye on
prices – we&apos;ll show you when items go on sale!
</p>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Tips text promises a feature that doesn't exist.

The text says "we'll show you when items go on sale" but this functionality isn't implemented. Consider removing this claim to avoid misleading users.

🐛 Proposed fix
         <p className="text-gray-600 text-sm">
-          Items in your wishlist are saved to your browser. You can easily move
-          them to your cart when you&apos;re ready to purchase. Keep an eye on
-          prices – we&apos;ll show you when items go on sale!
+          Items in your wishlist are saved to your browser. You can easily move
+          them to your cart when you&apos;re ready to purchase.
         </p>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<p className="text-gray-600 text-sm">
Items in your wishlist are saved to your browser. You can easily move
them to your cart when you&apos;re ready to purchase. Keep an eye on
prices we&apos;ll show you when items go on sale!
</p>
<p className="text-gray-600 text-sm">
Items in your wishlist are saved to your browser. You can easily move
them to your cart when you&apos;re ready to purchase.
</p>
🤖 Prompt for AI Agents
In `@src/app/wishlist/page.tsx` around lines 153 - 157, Update the copy in the
wishlist page paragraph to avoid promising an unimplemented sale-alert feature:
edit the paragraph element with className "text-gray-600 text-sm" in the
wishlist page component (src/app/wishlist/page.tsx) to remove or rephrase the
sentence "Keep an eye on prices – we'll show you when items go on sale!" so it
no longer claims sale notifications exist; keep the rest of the explanatory text
about browser-saved wishlist and moving items to cart.

Comment on lines +194 to +198
{wishlistItems > 0 && (
<span className="bg-red-500 text-white text-xs font-bold rounded-full px-2 py-0.5">
{wishlistItems}
</span>
)}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Mobile wishlist badge missing 99+ cap.

The desktop wishlist badge caps at "99+" (line 77), but the mobile badge renders {wishlistItems} without the cap, creating an inconsistency.

🐛 Proposed fix
                 {wishlistItems > 0 && (
                   <span className="bg-red-500 text-white text-xs font-bold rounded-full px-2 py-0.5">
-                    {wishlistItems}
+                    {wishlistItems > 99 ? "99+" : wishlistItems}
                   </span>
                 )}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{wishlistItems > 0 && (
<span className="bg-red-500 text-white text-xs font-bold rounded-full px-2 py-0.5">
{wishlistItems}
</span>
)}
{wishlistItems > 0 && (
<span className="bg-red-500 text-white text-xs font-bold rounded-full px-2 py-0.5">
{wishlistItems > 99 ? "99+" : wishlistItems}
</span>
)}
🤖 Prompt for AI Agents
In `@src/components/Navbar.tsx` around lines 194 - 198, The mobile wishlist badge
in Navbar.tsx is rendering the raw wishlistItems value instead of applying the
same "99+" cap used by the desktop badge; update the JSX that renders the mobile
badge (the span within the conditional that checks wishlistItems > 0) to display
wishlistItems > 99 ? "99+" : wishlistItems (or the existing helper used for the
desktop badge) so the mobile and desktop badges show consistent capped values.

Comment on lines +17 to +23
const handleAddToCart = () => {
addToCart(product);
};

const handleRemove = () => {
removeFromWishlist(product.id);
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add to Cart should respect stock status.

handleAddToCart allows adding out-of-stock items to the cart. Consider disabling the button or showing feedback when product.inStock is false.

🐛 Proposed fix
   const handleAddToCart = () => {
+    if (!product.inStock) return;
     addToCart(product);
   };

Also update the button to show disabled state:

   <button
     onClick={handleAddToCart}
-    className="px-4 py-2 bg-indigo-600 text-white text-sm font-medium rounded-lg hover:bg-indigo-700 transition-colors"
+    disabled={!product.inStock}
+    className={`px-4 py-2 text-sm font-medium rounded-lg transition-colors ${
+      product.inStock
+        ? "bg-indigo-600 text-white hover:bg-indigo-700"
+        : "bg-gray-300 text-gray-500 cursor-not-allowed"
+    }`}
   >
     Add to Cart
   </button>
🤖 Prompt for AI Agents
In `@src/components/WishlistItem.tsx` around lines 17 - 23, Prevent adding
out-of-stock items by updating handleAddToCart to check product.inStock and
return (or show feedback) if false, and also reflect this in the UI by disabling
the Add to Cart button when product.inStock is false; specifically, add a guard
in handleAddToCart that does not call addToCart(product) for !product.inStock
and wire the button's disabled prop (and visual/aria state) to product.inStock,
optionally invoking a user-facing message function (e.g., showToast or onError)
when the user attempts to add an out-of-stock product.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants