From cc672886144215db913a59038fa28bdc02a62bac Mon Sep 17 00:00:00 2001 From: Dwindi Ramadhana Date: Fri, 26 Dec 2025 22:50:25 +0700 Subject: [PATCH] fix: Submenu active states + Guest wishlist frontend check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Submenu Active State Fix: Problem: Dashboard Overview never active, All Orders/Products/Customers always active Root Cause: Submenu path matching didn't respect 'exact' flag from backend Solution: Added proper exact flag handling in SubmenuBar component - If item.exact = true: only match exact path (for Overview at /dashboard) - If item.exact = false/undefined: match path + sub-paths (for All Orders at /orders) Result: Submenu items now show correct active state ✅ Guest Wishlist Frontend Fix: Problem: Guest wishlist enabled in backend but frontend blocked with login prompt Root Cause: useWishlist hook had frontend login checks before API calls Solution: Removed frontend login checks from addToWishlist and removeFromWishlist - Backend already enforces permission via check_permission() based on enable_guest_wishlist - Frontend now lets backend handle authorization - API returns proper error if guest wishlist disabled Result: Guests can add/remove wishlist items when setting enabled ✅ Files Modified (2): - admin-spa/src/components/nav/SubmenuBar.tsx (exact flag handling) - customer-spa/src/hooks/useWishlist.ts (removed login checks) - admin-spa/dist/app.js + customer-spa/dist/app.js (rebuilt) Both submenu and guest wishlist issues resolved! --- admin-spa/src/components/nav/SubmenuBar.tsx | 12 ++++++++++-- customer-spa/src/hooks/useWishlist.ts | 11 ++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/admin-spa/src/components/nav/SubmenuBar.tsx b/admin-spa/src/components/nav/SubmenuBar.tsx index 161d363..bfce836 100644 --- a/admin-spa/src/components/nav/SubmenuBar.tsx +++ b/admin-spa/src/components/nav/SubmenuBar.tsx @@ -26,8 +26,16 @@ export default function SubmenuBar({ items = [], fullscreen = false, headerVisib
{items.map((it) => { const key = `${it.label}-${it.path || it.href}`; - // Check if current path starts with the submenu path (for sub-pages like /settings/notifications/staff) - const isActive = !!it.path && (pathname === it.path || pathname.startsWith(it.path + '/')); + // Exact match for submenu items, or match with sub-paths (e.g., /settings/notifications matches /settings/notifications/staff) + // Special handling: if item has exact flag, only match exact path + let isActive = false; + if (it.path) { + if (it.exact) { + isActive = pathname === it.path; + } else { + isActive = pathname === it.path || pathname.startsWith(it.path + '/'); + } + } 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/hooks/useWishlist.ts b/customer-spa/src/hooks/useWishlist.ts index f8e4553..d78d9e8 100644 --- a/customer-spa/src/hooks/useWishlist.ts +++ b/customer-spa/src/hooks/useWishlist.ts @@ -49,11 +49,6 @@ export function useWishlist() { }, [isLoggedIn]); const addToWishlist = useCallback(async (productId: number) => { - if (!isLoggedIn) { - toast.error('Please login to add items to wishlist'); - return false; - } - try { await api.post('/account/wishlist', { product_id: productId }); await loadWishlist(); // Reload to get full product details @@ -64,11 +59,9 @@ export function useWishlist() { toast.error(message); return false; } - }, [isLoggedIn, loadWishlist]); + }, [loadWishlist]); const removeFromWishlist = useCallback(async (productId: number) => { - if (!isLoggedIn) return false; - try { await api.delete(`/account/wishlist/${productId}`); setItems(items.filter(item => item.product_id !== productId)); @@ -83,7 +76,7 @@ export function useWishlist() { toast.error('Failed to remove from wishlist'); return false; } - }, [isLoggedIn, items]); + }, [items]); const toggleWishlist = useCallback(async (productId: number) => { if (productIds.has(productId)) {