mirgate the new api to the wishlist cart... it uses token barer instead of cors credenintals.
'use client'
import Image from "next/image";
import React, { useState, useEffect, useOptimistic } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { CircleArrowLeft, X } from "lucide-react";
import ShoppingBag from "@/components/ShoppingBag";
import Loading from "@/components/Loading";

const WishlistItem = ({ id, name, price, imageUrl, onRemove }) => {
    const router = useRouter();

    const handleShoppingBagClick = () => {
        router.push(`/products/${id}`);
    };

    return (
        <div className="bg-white rounded-lg p-4 flex items-stretch space-x-4 mb-4">
            <div className="relative w-[30%] min-h-[120px]">
                <Image
                    src={imageUrl}
                    alt={name}
                    fill={true}
                    unoptimized={true}
                    className="object-cover rounded-md"
                />
            </div>
            <div className="flex-grow flex flex-col justify-center">
                <h3 className="font-serif font-medium text-base text-center">{name}</h3>
            </div>
            <div className="flex flex-col justify-center items-center space-y-2">
                <button onClick={() => onRemove(id)} className="p-1">
                    <X size={24} />
                </button>
                <button onClick={handleShoppingBagClick} className="bg-[#3B5345] rounded-full p-2">
                    <ShoppingBag width={24} height={24} />
                </button>
            </div>
        </div>
    );
};

export default function Wishlist() {
    const router = useRouter();
    const [wishlistItems, setWishlistItems] = useState([]);
    const [isLoading, setIsLoading] = useState(true);

    const [optimisticWishlist, addOptimisticWishlistItem] = useOptimistic(
        wishlistItems,
        (state, newItem) => [...state, newItem]
    );

    const fetchWishlist = async () => {
        try {
            const response = await fetch(`${process.env.NEXT_PUBLIC_API}/wishlist`,
                {
                    credentials: "include"
                });
            if (!response.ok) {
                throw new Error('Failed to fetch wishlist');
            }
            const data = await response.json();
            setWishlistItems(data);
        } catch (error) {
            console.error('Error fetching wishlist:', error);
        } finally {
            setIsLoading(false);
        }
    };

    useEffect(() => {
        fetchWishlist();
    }, []);

    const handleRemoveItem = async (id) => {
        // Optimistically remove the item from the UI
        const updatedItems = optimisticWishlist.filter(item => item.id !== id);
        addOptimisticWishlistItem(updatedItems);

        try {
            const response = await fetch(`${process.env.NEXT_PUBLIC_API}/wishlist/${id}`, {
                method: 'DELETE',
                credentials: "include"
            });
            if (!response.ok) {
                throw new Error('Failed to delete item from wishlist');
            }
            // Update the actual state after successful deletion
            setWishlistItems(updatedItems);
        } catch (error) {
            console.error('Error removing item from wishlist:', error);
            // Revert the optimistic update if the server request fails
            await fetchWishlist();
        }
    };

    return (
        <>
            <header className="flex items-center mb-6">
                <CircleArrowLeft size={52} strokeWidth={0.7} onClick={router.back} className="p-2 relative z-20" />
                <h1 className="text-3xl z-10 text-[#181717] left-0 right-0 absolute font-sans text-center font-medium">
                    Wishlist
                </h1>
            </header>
            <main className="flex-grow flex flex-col items-center">
                {isLoading ? (
                    <Loading />
                ) : optimisticWishlist.length === 0 ? (
                    <>
                        <div className="relative w-full h-[33vh]">
                            <Image
                                src="https://storage.naayiq.com/resources/empty_wishlist.gif"
                                alt="Empty wishlist"
                                fill
                                unoptimized={true}
                                priority={true}
                                quality={100}
                                className="object-contain"
                            />
                        </div>
                        <section>
                            <p className="font-serif text-3xl text-center mb-2 font-semibold">Wishlist is empty!</p>
                            <p className="font-serif text-lg text-center leading-none">Tab Heart Button to start</p>
                            <p className="font-serif text-lg text-center">saving your favorite item.</p>
                            <Link href={"/"} className="min-h-[56px] mt-4 items-center font-serif px-3 ssm:px-6 bg-[#3B5345] flex justify-center text-white text-xl rounded-lg">
                                Start Browsing
                            </Link>
                        </section>
                    </>
                ) : (
                    <div className="w-full max-w-md">
                        {optimisticWishlist.map(item => (
                            <WishlistItem
                                key={item.id}
                                id={item.id}
                                name={item.name}
                                price={item.price}
                                imageUrl={`https://storage.naayiq.com/resources/${item.images[0]}`}
                                onRemove={handleRemoveItem}
                            />
                        ))}
                    </div>
                )}
            </main>
        </>
    );
}
backend:
// controllers/wishlistController.ts
import { Request, Response } from 'express';
import {pool} from "../config/database";

// Fetch all product IDs from the user's wishlist
export const getWishlist = async (req: Request, res: Response) => {
    const userId = req.user?.userId;

    if (!userId) {
        return res.status(400).json({ message: 'User ID not found in token' });
    }

    try {
        const query = `
            SELECT p.id
            FROM wishlist w
            JOIN products p ON w.product_id = p.id
            WHERE w.user_id = $1
        `;
        const { rows } = await pool.query(query, [userId]);

        res.status(200).json({ wishlist: rows });
    } catch (error) {
        console.error('Error fetching wishlist:', error);
        res.status(500).json({ message: 'Internal server error' });
    }
};

// Add a product to the user's wishlist
export const addToWishlist = async (req: Request, res: Response) => {
    const userId = req.user?.userId;
    const { product_id } = req.body;

    if (!userId) {
        return res.status(400).json({ message: 'User ID not found in token' });
    }

    if (!product_id) {
        return res.status(400).json({ message: 'Product ID is required' });
    }

    try {
        const query = `
            INSERT INTO wishlist (user_id, product_id)
            VALUES ($1, $2)
            ON CONFLICT (user_id, product_id) DO NOTHING
        `;
        await pool.query(query, [userId, product_id]);

        res.status(201).json({ message: 'Product added to wishlist' });
    } catch (error) {
        console.error('Error adding to wishlist:', error);
        res.status(500).json({ message: 'Internal server error' });
    }
};

// Remove a product from the user's wishlist
export const removeFromWishlist = async (req: Request, res: Response) => {
    const userId = req.user?.userId;
    const { product_id } = req.body;

    if (!userId) {
        return res.status(400).json({ message: 'User ID not found in token' });
    }

    if (!product_id) {
        return res.status(400).json({ message: 'Product ID is required' });
    }

    try {
        const query = `
            DELETE FROM wishlist
            WHERE user_id = $1 AND product_id = $2
        `;
        const result = await pool.query(query, [userId, product_id]);

        if (result.rowCount === 0) {
            return res.status(404).json({ message: 'Product not found in wishlist' });
        }

        res.status(200).json({ message: 'Product removed from wishlist' });
    } catch (error) {
        console.error('Error removing from wishlist:', error);
        res.status(500).json({ message: 'Internal server error' });
    }
};
example of using the api:
'use client';

import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { usePathname } from 'next/navigation';
import { useInView } from 'react-intersection-observer';
import dynamic from 'next/dynamic';
import ProductItem from './ProductItem';
import ProductLoading from '@/components/ProductLoading';
import NoProductsFound from '@/components/NoProductsFound';
import ProductDetail from '@/components/ProductDetail';
import {NotificationProvider, useNotification} from '@/components/NotificationContext';

const SearchComponent = dynamic(() => import('@/components/SearchComponent'), {
    ssr: false,
    loading: () => <SearchComponentSkeleton />
});

const ProductModal = dynamic(() => import('@/components/ProductDetailModal'), {
    ssr: false
});

export default function ProductList({ initialFilters }) {
    const { c, sc, b, title, sortBy } = initialFilters;
    const [products, setProducts] = useState([]);
    const [page, setPage] = useState(1);
    const [hasMore, setHasMore] = useState(true);
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState(null);
    const [filter, setFilter] = useState('');
    const [query, setQuery] = useState('');
    const [wishlist, setWishlist] = useState([])
    const [minPrice, setMinPrice] = useState(0);
    const [maxPrice, setMaxPrice] = useState(250000); // Adjust based on your data
    const [detail, setDetail] = useState(null);
    const [selectedProduct, setSelectedProduct] = useState(null);
    const first = useRef(true);
    const { ref, inView } = useInView({
        threshold: 0,
        triggerOnce: false
    });
    const { addNotification } = useNotification(); // Using Notification Context

    const fetchWishlist = useCallback(async () => {
        const token = localStorage.getItem("token");
        if (!token) return;

        try {
            const response = await fetch(`${process.env.NEXT_PUBLIC_API}/wishlist`, {
                headers: {
                    'Authorization': `Bearer ${token}`,
                },
            });
            if (response.ok) {
                const w = await response.json();
                console.log('Fetched wishlist:', w.wishlist);
                const wishlistIds = w.wishlist.map(item => item.id);
                setWishlist(wishlistIds);
            }
        } catch (error) {
            console.error('Error fetching wishlist:', error);
        }
    }, [wishlist, setWishlist]);

    const pathname = usePathname(); // Import and use usePathname

    const fetchProducts = useCallback(async (currentPage, searchQuery) => { // Added searchQuery
        setLoading(true);
        setError(null);
        try {
            await fetchWishlist()
            const params = new URLSearchParams({
                page: currentPage,
                itemsPerPage: 15, // Can be adjusted or made dynamic
            });

            if (c) params.append('c', c);
            if (sc) params.append('sc', sc);
            if (b) params.append('b', b);
            if (sortBy) params.append("sortBy", sortBy);
            if (searchQuery) params.append('search', searchQuery); // Use searchQuery
            if (minPrice) params.append('minPrice', minPrice);
            if (maxPrice && maxPrice !== Infinity) params.append('maxPrice', maxPrice);
            if (filter) params.append('filter', filter); // Ensure filter is appended correctly


            const response = await fetch(`${process.env.NEXT_PUBLIC_API}/products?${params.toString()}&${filter}`);
            if (!response.ok) {
                throw new Error('Failed to fetch products');
            }
            const data = await response.json();
            setProducts((prev) => [...prev, ...data.products]);
            setHasMore(data.hasMore);
            setPage((prev) => prev + 1);
            // After the initial fetch, set first.current to false
            if (first.current) {
                first.current = false;
            }
        } catch (err) {
            console.error('Error fetching products:', err);
            setError(err.message || 'An error occurred');
        } finally {
            setLoading(false);
        }
    }, [c, sc, b, minPrice, maxPrice, filter]);

    // Initial fetch on mount
    useEffect(() => {
        fetchProducts(page, query); // Pass current query
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []); // Only run on mount

    // Fetch more products when in view
    useEffect(() => {
        if (inView && hasMore && !loading) {
            fetchProducts(page, query); // Pass current query
        }
    }, [inView, hasMore, loading, fetchProducts, page, query]);

    // Handle search functionality
    const handleSearch = useCallback((newQuery) => {
        setQuery(newQuery);
        setProducts([]);
        setPage(1);
        setHasMore(true);
        first.current = true;
        fetchProducts(1, newQuery); // Pass newQuery
    }, [fetchProducts]);

    // Handle filter changes
    const handleFilterChange = useCallback(() => {
        setProducts([]);
        setPage(1);
        setHasMore(true);
        first.current = true; // Reset first ref when filtering
        fetchProducts(1, query); // Pass current query
    }, [fetchProducts, query]);

    // Watch for filter changes
    useEffect(() => {
        if (!first.current) {
            handleFilterChange();
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [filter]);

    useEffect(() => {
        if (pathname === '/products') {
            setDetail(null);
        }
    }, [pathname]);

    const handleProductClick = useCallback((product) => {
        setDetail(product);
        const newURL = `/products/${product.id}`;
        window.history.pushState({ path: newURL }, '', newURL);
    }, []);

    useEffect(() => {
        const handlePopState = (event) => {
            const currentPath = window.location.pathname;
            if (currentPath === '/products') {
                setDetail(null);
            } else {
            }
        };

        window.addEventListener('popstate', handlePopState);

        return () => {
            window.removeEventListener('popstate', handlePopState);
        };
    }, []);

    // Handle cart interactions
    const handleCartClick = useCallback((product) => {
        setSelectedProduct(product);
    }, []);

    const handleModalClose = useCallback(() => {
        setSelectedProduct(null);
    }, []);

    const memoizedProducts = useMemo(() => products.map((product) => ({
        ...product,
        cheapestPrice: getCheapestPrice(product),
    })), [products]);

    return (
        <>
            {detail ? (
                <NotificationProvider>
                    <ProductDetail product={detail} isInWishlist={wishlist.includes(detail.id)} />
                </NotificationProvider>
            ) : (
                <>
                    <header className="flex justify-center relative mt-20 mb-4">
                        <h1 className="text-3xl z-10 text-[#181717] font-sans text-center font-medium">
                            {title || 'All Products'}
                        </h1>
                    </header>
                    <SearchComponent
                        minPrice={minPrice}
                        maxPrice={maxPrice}
                        query={query}
                        setQuery={handleSearch}
                        filterQuery={filter}
                        setFilterQuery={setFilter}
                    />
                    {error && <div className="text-red-500 text-center">{error}</div>}
                    {memoizedProducts.length > 0 ? (
                        <div className="grid grid-cols-2 w-full justify-between gap-4 sm:gap-6 ssm3:grid-cols-3 md:grid-cols-4 lg:grid-cols-5">
                            {memoizedProducts.map((product) => (
                                <ProductItem
                                    key={product.id}
                                    id={product.id}
                                    name={product.name}
                                    isInWishlist={wishlist.includes(product.id)}
                                    product={product}
                                    handleClick={() => handleProductClick(product)}
                                    price={formatPrice(product.cheapestPrice)}
                                    imageUrl={product.images[0]?.url || ''}
                                    onCartClick={handleCartClick}
                                />
                            ))}
                        </div>
                    ) : (
                        // Only show NoProductsFound if not loading and not the first load
                        !loading && !first.current && <NoProductsFound />
                    )}
                    {loading && <ProductLoading />}
                    {!loading && hasMore && (
                        <div ref={ref} style={{ height: '20px' }}></div>
                    )}
                </>
            )}
            {selectedProduct && (
                <NotificationProvider>
                    <ProductModal
                        productData={{ product: selectedProduct }}
                        isOpen={!!selectedProduct}
                        onClose={handleModalClose}
                    />
                </NotificationProvider>
            )}
        </>
    );
}

const getCheapestPrice = (product) => {
    const prices = [
        product.price && product.price !== '0.00'
            ? parseFloat(product.price)
            : Infinity,
        ...(product.sizes?.map((size) => parseFloat(size.price)) || []),
        ...(product.colors?.flatMap((color) => [
            parseFloat(color.price),
            ...(color.sizes?.map((size) => parseFloat(size.price)) || []),
        ]) || []),
    ].filter((price) => !isNaN(price) && isFinite(price));

    return prices.length > 0 ? Math.min(...prices) : null;
};

const formatPrice = (price) => {
    if (price == null || price === Infinity) return 'N/A';
    return `${price >= 10000 ? price.toLocaleString() : price} IQD`;
};

const SearchComponentSkeleton = () => (
    <div className="flex mb-4 items-center space-x-2 animate-pulse">
        <div className="h-10 bg-gray-200 rounded-md flex-grow"></div>
        <div className="h-10 w-[5.5rem] bg-gray-200 rounded-md"></div>
    </div>
);

I want you to display the name of the product and its price... use getCheapestPrice function to do so...
Keep the design as it is... make it more smooth and stable and compatiable especially for Safari users.