if there color has sizes then display the information of first color size, its price and qty, etc... Also I want you to add a new three labels, brand, category and sold.
"use client";
import React, { useState, useEffect, useCallback, useMemo } from "react";
import Head from "next/head";
import Image from "next/image";
import { Search, Grid, List, Plus, Edit, Trash2 } from "lucide-react";
import AddProductDialog from "@/components/AddProductDialog";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import debounce from "lodash/debounce";
import EditProduct from "@/components/EditProduct";
import { getToken } from "@/app/auth";

const formatDate = (dateString: string) => {
  const date = new Date(dateString);
  return date.toISOString().split("T")[0]; // This will give you 'yyyy-mm-dd'
};

interface Size {
  id: number;
  name: string;
  price: string;
  qty: number;
  color_id: number | null;
}

interface Color {
  id: number;
  name: string;
  price: string | null;
  qty: number | null;
}

interface Image {
  id: number;
  url: string;
  color_id: number | null;
  size_id: number | null;
}

interface Product {
  id: number;
  name: string;
  description: string;
  brand_id: number;
  has_color: boolean;
  has_size: boolean;
  product_type: string;
  price: string | null;
  qty: number | null;
  created_at: string;
  updated_at: string;
  categories: any[];
  colors: Color[];
  sizes: Size[];
  images: Image[];
}

interface ApiResponse {
  products: Product[];
  pagination: {
    currentPage: number;
    totalPages: number;
    totalProducts: number;
    limit: number;
  };
}
const PRODUCTS_PER_PAGE = 10;
export default function ProductsPage() {
  const [products, setProducts] = useState<Product[]>([]);
  const [currentPage, setCurrentPage] = useState<number>(1);
  const [searchTerm, setSearchTerm] = useState<string>("");
  const [viewMode, setViewMode] = useState<"grid" | "list">("grid");
  const [sortBy, setSortBy] = useState<keyof Product>("name");
  const [isAddProductDialogOpen, setIsAddProductDialogOpen] =
    useState<boolean>(false);
  const [isEditProductDialogOpen, setIsEditProductDialogOpen] =
    useState<boolean>(false);
  const [productToEdit, setProductToEdit] = useState<Product | null>(null);
  const [isDeleteConfirmOpen, setIsDeleteConfirmOpen] =
    useState<boolean>(false);
  const [productToDelete, setProductToDelete] = useState<Product | null>(null);
  const [isDeleting, setIsDeleting] = useState<boolean>(false);
  const [totalPages, setTotalPages] = useState<number>(1);
  const [isLoading, setIsLoading] = useState<boolean>(false);
  const [searchInput, setSearchInput] = useState<string>("");

  const debouncedSearch = useMemo(
    () =>
      debounce((term: string) => {
        setSearchTerm(term);
        setCurrentPage(1);
      }, 300),
    [],
  );

  useEffect(() => {
    debouncedSearch(searchInput);
    return () => {
      debouncedSearch.cancel();
    };
  }, [searchInput, debouncedSearch]);

  const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setSearchInput(e.target.value);
  };

  const fetchProducts = useCallback(async () => {
    setIsLoading(true);
    const token = getToken(); // Retrieve the token from localStorage

    if (!token) {
      toast.error("You must be logged in.");
      return;
    }
    try {
      const response = await fetch(
        `http://localhost:4000/products?page=${currentPage}&limit=${PRODUCTS_PER_PAGE}&search=${searchTerm}`,
        {
          cache: "no-cache",
          headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${token}`, // Include the token here
          },
        },
      );
      const data: ApiResponse = await response.json();
      setProducts(data.products);
      setTotalPages(data.pagination.totalPages);
    } catch (error) {
      console.error("Error fetching products:", error);
      toast.error("Failed to fetch products. Please try again.");
    } finally {
      setIsLoading(false);
    }
  }, [currentPage, searchTerm]);

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

  const filteredProducts = products
    .filter((product) =>
      product.name.toLowerCase().includes(searchTerm.toLowerCase()),
    )
    .sort((a, b) => {
      if (a[sortBy] === null) return 1;
      if (b[sortBy] === null) return -1;
      return a[sortBy]!.toString().localeCompare(b[sortBy]!.toString());
    });

  const handleEditClick = (product: Product) => {
    setProductToEdit(product);
    setIsEditProductDialogOpen(true);
  };
  const renderPagination = () => {
    const pageNumbers = [];
    const maxVisiblePages = 5;
    let startPage = Math.max(1, currentPage - Math.floor(maxVisiblePages / 2));
    let endPage = Math.min(totalPages, startPage + maxVisiblePages - 1);

    if (endPage - startPage + 1 < maxVisiblePages) {
      startPage = Math.max(1, endPage - maxVisiblePages + 1);
    }

    for (let i = startPage; i <= endPage; i++) {
      pageNumbers.push(i);
    }

    const handlePageChange = (newPage: number) => {
      setCurrentPage(newPage);
      window.scrollTo({ top: 0, behavior: "smooth" });
    };

    return (
      <div className="mt-8 flex items-center justify-center space-x-2">
        <button
          className="rounded-md bg-gray-200 px-3 py-1 text-sm text-gray-700 disabled:opacity-50"
          onClick={() => handlePageChange(Math.max(currentPage - 1, 1))}
          disabled={currentPage === 1}
        >
          Previous
        </button>
        {startPage > 1 && (
          <>
            <button
              className="rounded-md px-3 py-1 text-sm text-gray-700"
              onClick={() => handlePageChange(1)}
            >
              1
            </button>
            {startPage > 2 && <span className="text-gray-500">...</span>}
          </>
        )}
        {pageNumbers.map((number) => (
          <button
            key={number}
            className={`rounded-md px-3 py-1 text-sm ${
              currentPage === number
                ? "bg-blue-500 text-white"
                : "bg-gray-200 text-gray-700"
            }`}
            onClick={() => handlePageChange(number)}
          >
            {number}
          </button>
        ))}
        {endPage < totalPages && (
          <>
            {endPage < totalPages - 1 && (
              <span className="text-gray-500">...</span>
            )}
            <button
              className="rounded-md px-3 py-1 text-sm text-gray-700"
              onClick={() => handlePageChange(totalPages)}
            >
              {totalPages}
            </button>
          </>
        )}
        <button
          className="rounded-md bg-gray-200 px-3 py-1 text-sm text-gray-700 disabled:opacity-50"
          onClick={() =>
            handlePageChange(Math.min(currentPage + 1, totalPages))
          }
          disabled={currentPage === totalPages}
        >
          Next
        </button>
      </div>
    );
  };
  const handleEditClose = () => {
    setIsEditProductDialogOpen(false);
    setProductToEdit(null);
    fetchProducts(); // Refresh the product list after editing
  };

  const handleDeleteClick = (product: Product) => {
    setProductToDelete(product);
    setIsDeleteConfirmOpen(true);
  };

  const handleDeleteConfirm = async () => {
    if (productToDelete) {
      setIsDeleting(true);
      const token = getToken(); // the token from localStorage

      if (!token) {
        toast.error("You must be logged in.");
        return;
      }
      try {
        const response = await fetch(
          `http://localhost:4000/products/${productToDelete.id}`,
          {
            method: "DELETE",
            headers: {
              "Content-Type": "application/json",
              Authorization: `Bearer ${token}`, // Include the token here
            },
          },
        );

        if (!response.ok) {
          throw new Error("Failed to delete product");
        }

        setProducts(products.filter((p) => p.id !== productToDelete.id));
        setIsDeleteConfirmOpen(false);
        toast.success("Product deleted successfully");
      } catch (error) {
        console.error("Error deleting product:", error);
        toast.error("Failed to delete product. Please try again.");
      } finally {
        setIsDeleting(false);
      }
    }
  };

  const getProductPrice = (product: Product): string => {
    if (!product.has_color && !product.has_size && product.price)
      return product.price;
    if (product.colors.length > 0 && product.colors[0].price)
      return product.colors[0].price;
    if (product.sizes.length > 0) return product.sizes[0].price;
    return "N/A";
  };

  const getProductQuantity = (product: Product): number | string => {
    if (product.qty !== null && product.qty !== 0) return product.qty;
    if (product.colors.length > 0 && product.colors[0].qty !== null)
      return product.colors[0].qty;
    if (product.sizes.length > 0) return product.sizes[0].qty;
    return "N/A";
  };

  return (
    <div className="min-h-screen bg-gray-100">
      <Head>
        <title>Products - Naay Store</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main className="container mx-auto px-4 py-8">
        <div className="mb-8 flex items-center justify-between">
          <h1 className="text-3xl font-bold text-gray-900">All Products</h1>
          <button
            className="flex items-center rounded-md bg-green-500 px-4 py-2 text-white transition duration-300 hover:bg-green-600"
            onClick={() => setIsAddProductDialogOpen(true)}
          >
            <Plus className="mr-2" size={20} />
            Add Product
          </button>
        </div>

        <div className="mb-8 flex flex-col items-center justify-between md:flex-row">
          <div className="relative mb-4 w-full md:mb-0 md:w-96">
            <input
              type="text"
              placeholder="Search products..."
              className="w-full rounded-lg border border-gray-300 py-2 pl-10 pr-4 focus:outline-none focus:ring-2 focus:ring-blue-500"
              value={searchInput}
              onChange={handleSearchChange}
            />
            <Search className="absolute left-3 top-2.5 h-5 w-5 text-gray-400" />
          </div>

          <div className="flex items-center space-x-4">
            <select
              className="rounded-md border border-gray-300 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
              value={sortBy}
              onChange={(e) => setSortBy(e.target.value as keyof Product)}
            >
              <option value="name">Sort by Name</option>
              <option value="created_at">Sort by Created At</option>
              <option value="product_type">Sort by Product Type</option>
            </select>

            <button
              className={`rounded-md p-2 ${
                viewMode === "grid" ? "bg-blue-500 text-white" : "bg-gray-200"
              }`}
              onClick={() => setViewMode("grid")}
            >
              <Grid className="h-5 w-5" />
            </button>
            <button
              className={`rounded-md p-2 ${
                viewMode === "list" ? "bg-blue-500 text-white" : "bg-gray-200"
              }`}
              onClick={() => setViewMode("list")}
            >
              <List className="h-5 w-5" />
            </button>
          </div>
        </div>

        <div
          className={`grid ${
            viewMode === "grid"
              ? "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"
              : "grid-cols-1"
          } gap-6`}
        >
          {filteredProducts.map((product) => (
            <div
              key={product.id}
              className={`overflow-hidden rounded-lg bg-white shadow-md ${
                viewMode === "list" ? "flex" : ""
              }`}
            >
              <div
                className={`${
                  viewMode === "list" ? "w-1/3" : "w-full"
                } relative pb-[100%]`}
              >
                {product.images.length > 0 && (
                  <Image
                    src={`https://storage.naayiq.com/resources/${product.images[0].url}`}
                    alt={product.name}
                    fill={true}
                    className="object-cover"
                  />
                )}
              </div>
              <div className={`p-4 ${viewMode === "list" ? "w-2/3" : ""}`}>
                <h2 className="text-xl font-semibold text-gray-800">
                  {product.name}
                </h2>
                <p
                  className="mb-4 text-sm text-gray-700"
                  style={{ direction: "rtl" }}
                  dangerouslySetInnerHTML={{
                    __html: product.description.replace(/\n/g, "<br />"),
                  }}
                />
                <div className="mb-4">
                  <p className="text-sm text-gray-600">
                    <span className="font-semibold">Price:</span> $
                    {getProductPrice(product)}
                  </p>
                  <p className="text-sm text-gray-600">
                    <span className="font-semibold">Quantity:</span>{" "}
                    {getProductQuantity(product)}
                  </p>
                  <p className="text-sm text-gray-600">
                    <span className="font-semibold">Created at:</span>{" "}
                    {formatDate(product.created_at)}
                  </p>
                  <p className="text-sm text-gray-600">
                    <span className="font-semibold">Has Color:</span>{" "}
                    {product.has_color ? "Yes" : "No"}
                  </p>
                  <p className="text-sm text-gray-600">
                    <span className="font-semibold">Has Size:</span>{" "}
                    {product.has_size ? "Yes" : "No"}
                  </p>
                  <p className="text-sm text-gray-600">
                    <span className="font-semibold">Product Type:</span>{" "}
                    {product.product_type}
                  </p>
                </div>
                <div className="space-x-2">
                  <button
                    className="rounded-md bg-blue-500 px-4 py-2 text-white transition duration-300 hover:bg-blue-600"
                    onClick={() => {
                      console.log(product);
                      handleEditClick(product);
                    }}
                  >
                    <Edit className="mr-1 inline-block" size={16} />
                    Edit
                  </button>
                  <button
                    className="rounded-md bg-red px-4 py-2 text-white transition duration-300 hover:bg-danger"
                    onClick={() => handleDeleteClick(product)}
                  >
                    <Trash2 className="mr-1 inline-block" size={16} />
                    Delete
                  </button>
                </div>
              </div>
            </div>
          ))}
        </div>
        {renderPagination()}
      </main>

      {isAddProductDialogOpen && (
        <AddProductDialog
          isOpen={isAddProductDialogOpen}
          onClose={() => setIsAddProductDialogOpen(false)}
        />
      )}

      {isDeleteConfirmOpen && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50">
          <div className="rounded-lg bg-white p-8">
            <h2 className="mb-4 text-xl font-semibold text-gray-800">
              Confirm Delete
            </h2>
            <p className="mb-8 text-gray-600">
              Are you sure you want to delete{" "}
              <span className="font-semibold">
                {productToDelete?.name ?? "this product"}
              </span>
              ?
            </p>
            <div className="space-x-4">
              <button
                className="rounded-md bg-red px-4 py-2 text-white transition duration-300 hover:bg-danger"
                onClick={handleDeleteConfirm}
                disabled={isDeleting}
              >
                {isDeleting ? "Deleting..." : "Yes, Delete"}
              </button>
              <button
                className="rounded-md bg-gray-300 px-4 py-2 text-gray-700 transition duration-300 hover:bg-gray-400"
                onClick={() => setIsDeleteConfirmOpen(false)}
                disabled={isDeleting}
              >
                Cancel
              </button>
            </div>
          </div>
        </div>
      )}
      {isEditProductDialogOpen && productToEdit && (
        <EditProduct
          isOpen={isEditProductDialogOpen}
          onClose={handleEditClose}
          // @ts-ignore
          product={productToEdit}
        />
      )}

      <ToastContainer />
    </div>
  );
}
json response example:
{"products":[{"id":683,"name":"‏Creat 3D Whitestrip Superme Bright","description":"لصقات تبييض الاسنان مع  كرست بخطوات سهلة وسريعة  للحصول على ابتسامة ناصعة البياض\n-تتكون من عامل التبييض الآمن بالمينا\n-تقنية خالية من الانزلاق تظل ثابتة.\n-سهل الاستخدام للغاية يمكنك التبييض أثناء المشي والتحدث والعمل وحتى شرب الماء\n-طريقة الاستخدام:\nتستخدم مرة واحدة يوميا على اسنان نظيفة ضعي الشرائح على الفك العلوي والسفلي وازيليها بعد 45 دقيقة","brand_id":225,"has_color":false,"has_size":true,"product_type":"size","price":0,"qty":0,"sold":0,"created_at":"2024-09-09T09:40:47.835Z","updated_at":"2024-09-14T11:27:34.532Z","categories":[{"id":226,"name":"Teeth","main_category_id":23,"main_category_name":"Mouth Care"}],"colors":[],"sizes":[{"id":1258,"name":"1 strip","price":5000,"qty":76,"sold":0,"color_id":null,"images":["1795.webp"]},{"id":1259,"name":"20 strips","price":90000,"qty":5,"sold":0,"color_id":null,"images":[]}],"images":[{"id":2172,"url":"1795.webp","color_id":null,"size_id":1258}]}],"total":1,"page":1,"itemsPerPage":15,"totalPages":1,"hasMore":false,"minPrice":0,"maxPrice":250000}