fix: Submenu active states + Guest wishlist frontend check
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!
This commit is contained in:
@@ -26,8 +26,16 @@ export default function SubmenuBar({ items = [], fullscreen = false, headerVisib
|
|||||||
<div className="flex gap-2 overflow-x-auto no-scrollbar">
|
<div className="flex gap-2 overflow-x-auto no-scrollbar">
|
||||||
{items.map((it) => {
|
{items.map((it) => {
|
||||||
const key = `${it.label}-${it.path || it.href}`;
|
const key = `${it.label}-${it.path || it.href}`;
|
||||||
// Check if current path starts with the submenu path (for sub-pages like /settings/notifications/staff)
|
// Exact match for submenu items, or match with sub-paths (e.g., /settings/notifications matches /settings/notifications/staff)
|
||||||
const isActive = !!it.path && (pathname === it.path || pathname.startsWith(it.path + '/'));
|
// 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 = [
|
const cls = [
|
||||||
'ui-ctrl inline-flex items-center gap-2 rounded-md px-2.5 py-1.5 border text-sm whitespace-nowrap',
|
'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',
|
'focus:outline-none focus:ring-0 focus:shadow-none',
|
||||||
|
|||||||
@@ -49,11 +49,6 @@ export function useWishlist() {
|
|||||||
}, [isLoggedIn]);
|
}, [isLoggedIn]);
|
||||||
|
|
||||||
const addToWishlist = useCallback(async (productId: number) => {
|
const addToWishlist = useCallback(async (productId: number) => {
|
||||||
if (!isLoggedIn) {
|
|
||||||
toast.error('Please login to add items to wishlist');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await api.post('/account/wishlist', { product_id: productId });
|
await api.post('/account/wishlist', { product_id: productId });
|
||||||
await loadWishlist(); // Reload to get full product details
|
await loadWishlist(); // Reload to get full product details
|
||||||
@@ -64,11 +59,9 @@ export function useWishlist() {
|
|||||||
toast.error(message);
|
toast.error(message);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}, [isLoggedIn, loadWishlist]);
|
}, [loadWishlist]);
|
||||||
|
|
||||||
const removeFromWishlist = useCallback(async (productId: number) => {
|
const removeFromWishlist = useCallback(async (productId: number) => {
|
||||||
if (!isLoggedIn) return false;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await api.delete(`/account/wishlist/${productId}`);
|
await api.delete(`/account/wishlist/${productId}`);
|
||||||
setItems(items.filter(item => item.product_id !== productId));
|
setItems(items.filter(item => item.product_id !== productId));
|
||||||
@@ -83,7 +76,7 @@ export function useWishlist() {
|
|||||||
toast.error('Failed to remove from wishlist');
|
toast.error('Failed to remove from wishlist');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}, [isLoggedIn, items]);
|
}, [items]);
|
||||||
|
|
||||||
const toggleWishlist = useCallback(async (productId: number) => {
|
const toggleWishlist = useCallback(async (productId: number) => {
|
||||||
if (productIds.has(productId)) {
|
if (productIds.has(productId)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user