TypeError: Image constructor: 'new' is required
I think the issue in the wishlistItem component..
'use client';

import React from "react";
import { useRouter } from "next/navigation";
import { X } from "lucide-react";
import ShoppingBag from "@/components/ShoppingBag";
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 WishlistItem = ({ product, onRemove }) => {
    const router = useRouter();

    const handleShoppingBagClick = () => {
        router.push(`/products/${product.id}`);
    };
    const image = product.images > 0 ? `https://storage.naayiq.com/resources/${product.images[0]?.url}` : "https://storage.naayiq.com/resources/noimage.webp"
    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={image}
                    alt={product.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">{product.name}</h3>
                <h3 className="font-serif font-medium text-base text-center">{getCheapestPrice(product)}</h3>
            </div>
            <div className="flex flex-col justify-center items-center space-y-2">
                <button onClick={() => onRemove(product.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 WishlistItem;
'use client';

import { useState, useEffect, useCallback } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { CircleArrowLeft } from "lucide-react";
import WishlistItem from "@/components/WishlistItem";

export const getToken = () => {
    if (typeof window === 'undefined') return null;
    return localStorage.getItem('token'); // Adjust based on your token storage strategy
};

export const fetchWithAuth = async (url, options = {}) => {
    const token = getToken();
    if (!token) {
        throw new Error('No authentication token found');
    }

    const headers = {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${token}`,
        ...options.headers,
    };

    const response = await fetch(url, {
        ...options,
        headers,
    });

    if (!response.ok) {
        const errorData = await response.json();
        throw new Error(errorData.message || 'API request failed');
    }

    return response.json();
};

export default function Wishlist() {
    const router = useRouter();
    const [wishlistProductIds, setWishlistProductIds] = useState([]);
    const [wishlistProducts, setWishlistProducts] = useState([]);
    const [loadingStates, setLoadingStates] = useState([]); // Track loading states for each product
    const [error, setError] = useState(null);

    // Fetch Wishlist IDs
    const fetchWishlistIds = useCallback(async () => {
        try {
            const data = await fetchWithAuth(`${process.env.NEXT_PUBLIC_API}/wishlist`);
            setWishlistProductIds(data.wishlist); // Assuming data.wishlist is an array of IDs
            setLoadingStates(new Array(data.wishlist.length).fill(true)); // Initialize loading states
        } catch (err) {
            console.error('Error fetching wishlist IDs:', err);
            setError(err.message);
        }
    }, []);

    // Fetch Product Details Sequentially
    const fetchWishlistProductsSequentially = useCallback(async (ids) => {
        const products = [];
        for (let i = 0; i < ids.length; i++) {
            try {
                const data = await fetchWithAuth(`${process.env.NEXT_PUBLIC_API}/products/${ids[i].id}`);
                products.push(data.product);
                setWishlistProducts([...products]); // Update state incrementally
            } catch (err) {
                console.error(`Error fetching product with ID ${ids[i].id}:`, err);
                setError('Some wishlist items failed to load.');
            } finally {
                setLoadingStates(prev => {
                    const newLoadingStates = [...prev];
                    newLoadingStates[i] = false;
                    return newLoadingStates;
                });
            }
        }
    }, []);

    // Initial Data Fetch
    useEffect(() => {
        const initializeWishlist = async () => {
            await fetchWishlistIds();
        };
        initializeWishlist();
    }, [fetchWishlistIds]);

    // Fetch Products Once IDs are Available
    useEffect(() => {
        if (wishlistProductIds.length > 0) {
            fetchWishlistProductsSequentially(wishlistProductIds);
        }
    }, [wishlistProductIds, fetchWishlistProductsSequentially]);

    // Handle Remove Item
    const handleRemoveItem = async (productId, index) => {
        // Optimistically remove the item from UI
        const updatedProductIds = wishlistProductIds.filter(id => id.id !== productId);
        setWishlistProductIds(updatedProductIds);
        setWishlistProducts(prevProducts => prevProducts.filter(p => p.id !== productId));
        setLoadingStates(prevStates => prevStates.filter((_, i) => i !== index));

        try {
            await fetchWithAuth(`${process.env.NEXT_PUBLIC_API}/wishlist/${productId}`, {
                method: 'DELETE',
            });
            // Successfully removed on server
        } catch (err) {
            console.error('Error removing item:', err);
            setError('Failed to remove item from wishlist.');
            // Revert UI changes
            await fetchWishlistIds();
        }
    };

    return (
        <>
            <header className="flex items-center mb-6 px-4">
                <CircleArrowLeft
                    size={52}
                    strokeWidth={0.7}
                    onClick={() => router.back()}
                    className="p-2 relative z-20 cursor-pointer"
                />
                <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 px-4">
                {error && (
                    <div className="text-red-500 text-center mb-4">{error}</div>
                )}
                {wishlistProductIds.length === 0 && !error ? (
                    <EmptyWishlist />
                ) : (
                    <div className="w-full max-w-md">
                        {wishlistProductIds.map((id, index) => (
                            <div key={id.id} className="mb-4">
                                {loadingStates[index] ? (
                                    <WishlistSkeleton />
                                ) : (
                                    <WishlistItem
                                        product={wishlistProducts.find(p => p.id === id.id)}
                                        onRemove={() => handleRemoveItem(id.id, index)}
                                    />
                                )}
                            </div>
                        ))}
                    </div>
                )}
            </main>
        </>
    );
}

const EmptyWishlist = () => (
    <>
        <div className="relative w-full h-[33vh]">
            <img
                src="https://storage.naayiq.com/resources/empty_wishlist.gif"
                alt="Empty wishlist"
                className="object-contain w-full h-full"
            />
        </div>
        <section className="text-center">
            <p className="font-serif text-3xl mb-2 font-semibold">Wishlist is empty!</p>
            <p className="font-serif text-lg leading-none">Tap the Heart Button to start</p>
            <p className="font-serif text-lg">saving your favorite items.</p>
            <Link href="/" className="min-h-[56px] mt-4 inline-flex items-center justify-center px-3 sm:px-6 bg-[#3B5345] text-white text-xl rounded-lg">
                Start Browsing
            </Link>
        </section>
    </>
);

const WishlistSkeleton = () => {
    return (
        <div className="bg-white rounded-lg p-4 flex items-stretch justify-between mb-4 shadow-sm animate-pulse">
            {/* Skeleton for Product Details */}
            <div className="flex-grow flex flex-col justify-center space-y-2">
                <div className="h-6 bg-gray-200 rounded w-3/4"></div>
                <div className="h-6 bg-gray-200 rounded w-1/2"></div>
            </div>

            {/* Skeleton for Action Buttons */}
            <div className="flex flex-col justify-center items-center space-y-2">
                <div className="h-6 w-6 bg-gray-200 rounded-full"></div>
                <div className="h-10 w-10 bg-gray-200 rounded-full"></div>
            </div>
        </div>
    );
};