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

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