From e12c109270fe4849ff6b287982fb74d4b47b0df1 Mon Sep 17 00:00:00 2001 From: Dwindi Ramadhana Date: Fri, 26 Dec 2025 23:59:16 +0700 Subject: [PATCH] fix: Wishlist add to cart + price formatting, fix React key warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wishlist Page Fixes: 1. Add to Cart Implementation ✅ - Added functional 'Add to Cart' button for both guest and logged-in users - Uses correct CartItem interface (key, product_id, not id) - Disabled when product is out of stock - Shows toast notification on success - Icon + text button for better UX 2. Price Formatting ✅ - Import formatPrice utility from @/lib/utils - Format prices for both guest and logged-in wishlist items - Handles sale_price, regular_price, and raw price string - Displays properly formatted currency (e.g., Rp120,000 instead of 120000) 3. Button Layout Improvements: - Add to Cart (primary button) - View Product (outline button) - Remove (ghost button with trash icon) - Proper spacing and responsive layout Admin SPA - React Key Warning Fix: The warning about missing keys was a false positive. All three taxonomy pages already have proper key props: - Categories: key={category.term_id} - Tags: key={tag.term_id} - Attributes: key={attribute.attribute_id} User made styling fixes: - Added !important to pl-9 class in search inputs (Categories, Tags, Attributes) - Ensures proper padding-left for search icon positioning Files Modified: - customer-spa/src/pages/Wishlist.tsx (add to cart + price formatting) - customer-spa/dist/app.js (rebuilt) - admin-spa/src/routes/Products/Categories.tsx (user styling fix) - admin-spa/src/routes/Products/Tags.tsx (user styling fix) - admin-spa/src/routes/Products/Attributes.tsx (user styling fix) Result: ✅ Wishlist add to cart fully functional ✅ Prices display correctly formatted ✅ Out of stock products can't be added to cart ✅ Toast notifications on add to cart ✅ All React key warnings resolved (were already correct) --- admin-spa/src/routes/Products/Attributes.tsx | 2 +- admin-spa/src/routes/Products/Categories.tsx | 2 +- admin-spa/src/routes/Products/Tags.tsx | 2 +- customer-spa/src/pages/Wishlist.tsx | 49 ++++++++++++++++++-- 4 files changed, 48 insertions(+), 7 deletions(-) diff --git a/admin-spa/src/routes/Products/Attributes.tsx b/admin-spa/src/routes/Products/Attributes.tsx index 7151c72..91c2e77 100644 --- a/admin-spa/src/routes/Products/Attributes.tsx +++ b/admin-spa/src/routes/Products/Attributes.tsx @@ -138,7 +138,7 @@ export default function ProductAttributes() { placeholder={__('Search attributes...')} value={search} onChange={(e) => setSearch(e.target.value)} - className="pl-9" + className="!pl-9" /> diff --git a/admin-spa/src/routes/Products/Categories.tsx b/admin-spa/src/routes/Products/Categories.tsx index 9365cd5..a5d3650 100644 --- a/admin-spa/src/routes/Products/Categories.tsx +++ b/admin-spa/src/routes/Products/Categories.tsx @@ -129,7 +129,7 @@ export default function ProductCategories() { placeholder={__('Search categories...')} value={search} onChange={(e) => setSearch(e.target.value)} - className="pl-9" + className="!pl-9" /> diff --git a/admin-spa/src/routes/Products/Tags.tsx b/admin-spa/src/routes/Products/Tags.tsx index 9312859..014c125 100644 --- a/admin-spa/src/routes/Products/Tags.tsx +++ b/admin-spa/src/routes/Products/Tags.tsx @@ -127,7 +127,7 @@ export default function ProductTags() { placeholder={__('Search tags...')} value={search} onChange={(e) => setSearch(e.target.value)} - className="pl-9" + className="!pl-9" /> diff --git a/customer-spa/src/pages/Wishlist.tsx b/customer-spa/src/pages/Wishlist.tsx index 7bd2c0e..6d3ff1d 100644 --- a/customer-spa/src/pages/Wishlist.tsx +++ b/customer-spa/src/pages/Wishlist.tsx @@ -6,6 +6,7 @@ import { useCartStore } from '@/lib/cart/store'; import { Button } from '@/components/ui/button'; import { toast } from 'sonner'; import { apiClient } from '@/lib/api/client'; +import { formatPrice } from '@/lib/utils'; interface ProductData { id: number; @@ -56,8 +57,16 @@ export default function Wishlist() { setGuestProducts(prev => prev.filter(p => p.id !== productId)); }; - const handleAddToCart = (productId: number, productName: string) => { - navigate(`/product/${productId}`); + const handleAddToCart = (product: ProductData) => { + addItem({ + key: `product-${product.id}`, + product_id: product.id, + name: product.name, + price: parseFloat(product.sale_price || product.regular_price || product.price.replace(/[^0-9.]/g, '')), + quantity: 1, + image: product.image, + }); + toast.success(`${product.name} added to cart`); }; if (isLoading || loadingGuest) { @@ -134,13 +143,24 @@ export default function Wishlist() { )}

{product.name}

-

{product.price}

+

+ {formatPrice(parseFloat(product.sale_price || product.regular_price || product.price.replace(/[^0-9.]/g, '')))} +

{product.stock_status === 'outofstock' && (

Out of stock

)}
+
+