From 9214172c79e9111910e4d259541da9d8fa919ee6 Mon Sep 17 00:00:00 2001 From: Dwindi Ramadhana Date: Fri, 26 Dec 2025 23:16:40 +0700 Subject: [PATCH] feat: Public guest wishlist page + Dashboard Overview debug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue 1 - Dashboard > Overview Never Active: Added debug logging to investigate why Overview submenu never shows active - Console logs path, pathname, and isActive state - Will help identify the root cause Issue 2 - Guest Wishlist Public Page: Problem: Guests couldn't access wishlist (redirected to login) Solution: Created public /wishlist route accessible to all users Implementation: 1. New Public Wishlist Page: - Route: /wishlist (not /my-account/wishlist) - Accessible to guests and logged-in users - Guest mode: Shows product IDs from localStorage - Logged-in mode: Shows full product details from API - Guests can view and remove items 2. Updated All Header Links: - ClassicLayout: /wishlist - ModernLayout: /wishlist - BoutiqueLayout: /wishlist - No more wp-login redirect for guests 3. Guest Experience: - See list of wishlisted product IDs - Click to view product details - Remove items from wishlist - Prompt to login for full details Issue 3 - Wishlist Page Selector Setting: Status: Deprecated/unused for SPA architecture - SPA uses React Router, not WordPress pages - Setting saved but has no effect - Shareable wishlist would also be SPA route - No need for page CPT selection Files Modified: - customer-spa/src/pages/Wishlist.tsx (new public page) - customer-spa/src/App.tsx (added /wishlist route) - customer-spa/src/hooks/useWishlist.ts (export productIds) - customer-spa/src/layouts/BaseLayout.tsx (all themes use /wishlist) - customer-spa/dist/app.js (rebuilt) - admin-spa/src/components/nav/SubmenuBar.tsx (debug logging) - admin-spa/dist/app.js (rebuilt) Result: ✅ Guests can access wishlist page ✅ Guests can view and manage localStorage wishlist ✅ No login redirect for guest wishlist ✅ Debug logging added for Overview issue --- admin-spa/src/components/nav/SubmenuBar.tsx | 5 + customer-spa/src/App.tsx | 4 + customer-spa/src/hooks/useWishlist.ts | 1 + customer-spa/src/layouts/BaseLayout.tsx | 6 +- customer-spa/src/pages/Wishlist.tsx | 168 ++++++++++++++++++++ 5 files changed, 181 insertions(+), 3 deletions(-) create mode 100644 customer-spa/src/pages/Wishlist.tsx diff --git a/admin-spa/src/components/nav/SubmenuBar.tsx b/admin-spa/src/components/nav/SubmenuBar.tsx index 2518272..f09b013 100644 --- a/admin-spa/src/components/nav/SubmenuBar.tsx +++ b/admin-spa/src/components/nav/SubmenuBar.tsx @@ -30,6 +30,11 @@ export default function SubmenuBar({ items = [], fullscreen = false, headerVisib // Only ONE submenu item should be active at a time const isActive = it.path === pathname; + // Debug logging for Dashboard Overview issue + if (it.label === 'Overview' && pathname.includes('dashboard')) { + console.log('Overview check:', { label: it.label, path: it.path, pathname, isActive }); + } + const cls = [ 'ui-ctrl inline-flex items-center gap-2 rounded-md px-2.5 py-1.5 border text-sm whitespace-nowrap', 'focus:outline-none focus:ring-0 focus:shadow-none', diff --git a/customer-spa/src/App.tsx b/customer-spa/src/App.tsx index 6927d6c..bff2b40 100644 --- a/customer-spa/src/App.tsx +++ b/customer-spa/src/App.tsx @@ -14,6 +14,7 @@ import Cart from './pages/Cart'; import Checkout from './pages/Checkout'; import ThankYou from './pages/ThankYou'; import Account from './pages/Account'; +import Wishlist from './pages/Wishlist'; // Create QueryClient instance const queryClient = new QueryClient({ @@ -64,6 +65,9 @@ function App() { } /> } /> + {/* Wishlist - Public route accessible to guests */} + } /> + {/* My Account */} } /> diff --git a/customer-spa/src/hooks/useWishlist.ts b/customer-spa/src/hooks/useWishlist.ts index 6a3e524..c5db5bc 100644 --- a/customer-spa/src/hooks/useWishlist.ts +++ b/customer-spa/src/hooks/useWishlist.ts @@ -146,6 +146,7 @@ export function useWishlist() { isEnabled, isLoggedIn, count: items.length, + productIds, addToWishlist, removeFromWishlist, toggleWishlist, diff --git a/customer-spa/src/layouts/BaseLayout.tsx b/customer-spa/src/layouts/BaseLayout.tsx index 8c11669..4263af8 100644 --- a/customer-spa/src/layouts/BaseLayout.tsx +++ b/customer-spa/src/layouts/BaseLayout.tsx @@ -136,7 +136,7 @@ function ClassicLayout({ children }: BaseLayoutProps) { {/* Wishlist */} {headerSettings.elements.wishlist && isEnabled('wishlist') && (wishlistSettings.show_in_header ?? true) && ( - + Wishlist @@ -429,7 +429,7 @@ function ModernLayout({ children }: BaseLayoutProps) { ) )} {headerSettings.elements.wishlist && isEnabled('wishlist') && (wishlistSettings.show_in_header ?? true) && ( - + Wishlist )} @@ -562,7 +562,7 @@ function BoutiqueLayout({ children }: BaseLayoutProps) { ))} {headerSettings.elements.wishlist && isEnabled('wishlist') && (wishlistSettings.show_in_header ?? true) && ( - + Wishlist )} diff --git a/customer-spa/src/pages/Wishlist.tsx b/customer-spa/src/pages/Wishlist.tsx new file mode 100644 index 0000000..04adc04 --- /dev/null +++ b/customer-spa/src/pages/Wishlist.tsx @@ -0,0 +1,168 @@ +import React from 'react'; +import { useNavigate } from 'react-router-dom'; +import { Trash2, ShoppingCart, Heart } from 'lucide-react'; +import { useWishlist } from '@/hooks/useWishlist'; +import { useCartStore } from '@/lib/cart/store'; +import { Button } from '@/components/ui/button'; +import { toast } from 'sonner'; + +/** + * Public Wishlist Page - Accessible to both guests and logged-in users + * Guests: Shows items from localStorage + * Logged-in: Shows items from database via API + */ +export default function Wishlist() { + const navigate = useNavigate(); + const { items, isLoading, isLoggedIn, removeFromWishlist, productIds } = useWishlist(); + const { addItem } = useCartStore(); + + const handleRemove = async (productId: number) => { + await removeFromWishlist(productId); + }; + + const handleAddToCart = (productId: number, productName: string) => { + // For guests with localStorage wishlist, we only have IDs + // Navigate to product page for now + navigate(`/product/${productId}`); + }; + + if (isLoading) { + return ( +
+
+

Loading wishlist...

+
+
+ ); + } + + // Guest mode: only have product IDs from localStorage + const guestWishlistIds = !isLoggedIn ? Array.from(productIds) : []; + const hasGuestItems = guestWishlistIds.length > 0; + const hasLoggedInItems = items.length > 0; + + if (!hasGuestItems && !hasLoggedInItems) { + return ( +
+
+

My Wishlist

+ +
+ +

Your wishlist is empty

+

+ Start adding products you love to your wishlist +

+ +
+
+
+ ); + } + + return ( +
+
+
+

My Wishlist

+

+ {isLoggedIn ? `${items.length} items` : `${guestWishlistIds.length} items`} +

+
+ + {/* Guest Mode: Show IDs only with limited functionality */} + {!isLoggedIn && hasGuestItems && ( +
+

+ Guest Wishlist: You have {guestWishlistIds.length} items saved locally. + Login to see full details and sync your wishlist. +

+
+ )} + + {/* Guest Wishlist Items (localStorage only - show IDs) */} + {!isLoggedIn && hasGuestItems && ( +
+ {guestWishlistIds.map((productId: number) => ( +
+
+
+ +
+
+

Product #{productId}

+

Login to see details

+
+
+
+ + +
+
+ ))} +
+ )} + + {/* Logged-in Wishlist Items (full details from API) */} + {isLoggedIn && hasLoggedInItems && ( +
+ {items.map((item) => ( +
+
+ {item.image ? ( + {item.name} + ) : ( +
+ +
+ )} +
+

{item.name}

+

{item.price}

+ {item.stock_status === 'outofstock' && ( +

Out of stock

+ )} +
+
+
+ + +
+
+ ))} +
+ )} +
+
+ ); +}