I'm building an app with nextjs 14 app router, tailwind css and nodejs as backend... I want you to enhance the design, ui/ux and the look of the current editproduct and add product...
improve their performance and responsivness...
There is an issue in edit product... in add product notice there is add size "inside" the color so I can Has Color -> Add Color -> Colors -> Has Size? -> Add Size... so they are sizes inside colors...
this doesn't exist in edit product while it does in add product... improve the font as well and don't let any typescript there... consider the code deeply and this is an example of json response from products api:
{"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}]},{"id":1237,"name":"test","description":"test","brand_id":73,"has_color":true,"has_size":false,"product_type":"color_size","price":0,"qty":0,"sold":0,"created_at":"2024-09-25T08:05:58.982Z","updated_at":"2024-09-25T08:05:58.982Z","categories":[{"id":178,"name":"Body Cleansers","main_category_id":2,"main_category_name":"Body Care"}],"colors":[{"id":57,"name":"green","price":50000,"qty":9,"sold":0,"has_size":false,"sizes":[],"images":[]},{"id":56,"name":"red","price":0,"qty":0,"sold":0,"has_size":true,"sizes":[{"id":3013,"name":"20ml","price":15000,"qty":10,"sold":0,"color_id":56,"images":["3066.jpg"]},{"id":3014,"name":"30ml","price":40000,"qty":2,"sold":0,"color_id":56,"images":["3066.jpg"]}],"images":["3066.jpg"]}],"sizes":[],"images":[{"id":199,"url":"3066.jpg","color_id":56,"size_id":3013},{"id":200,"url":"3066.jpg","color_id":56,"size_id":3014}]}],"total":2,"page":1,"itemsPerPage":15,"totalPages":1,"hasMore":false,"minPrice":0,"maxPrice":250000}
ProductsPage:
// pages/products.tsx
"use client";

import React, {
  useState,
  useEffect,
  useCallback,
  useMemo,
  ChangeEvent,
} from "react";
import Head from "next/head";
import Image from "next/image";
import {
  Search,
  Grid,
  List,
  Plus,
  Edit,
  Trash2,
  ChevronLeft,
  ChevronRight,
} from "lucide-react";
import AddProductDialog from "@/components/AddProductDialog";
import EditProduct from "@/components/EditProduct";
import LoadingSpinner from "@/components/LoadingSpinner"; // Ensure this component matches the one in OrdersPage
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import debounce from "lodash/debounce";
import { getToken } from "@/app/auth";
import {
  Product,
  Brand,
  ApiResponse,
  Category,
  Color,
  Size,
} from "@/components/types";

const formatDate = (dateString: string) => {
  const date = new Date(dateString);
  return date.toLocaleDateString(); // 'MM/DD/YYYY' format
};

const PRODUCTS_PER_PAGE = 15; // Adjusted as per JSON response's itemsPerPage

const ProductsPage: React.FC = () => {
  // State Variables
  const [products, setProducts] = useState<Product[]>([]);
  const [brands, setBrands] = useState<Brand[]>([]);
  const [brandMap, setBrandMap] = useState<{ [key: number]: string }>({});
  const [currentPage, setCurrentPage] = useState<number>(1);
  const [searchTerm, setSearchTerm] = useState<string>("");
  const [viewMode, setViewMode] = useState<"grid" | "list">("grid");
  const [sortBy, setSortBy] = useState<keyof Product>("created_at");
  const [sortOrder, setSortOrder] = useState<"asc" | "desc">("desc");
  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>("");

  // Debounce the search input to prevent excessive API calls
  const debouncedSearch = useMemo(
    () =>
      debounce((term: string) => {
        setSearchTerm(term);
        setCurrentPage(1);
      }, 300),
    [],
  );

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

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

  // Fetch Brand Details
  const fetchBrands = useCallback(async () => {
    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/subcategories/brands`,
        {
          headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${token}`, // Include the token here
          },
        },
      );

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

      const data: Brand[] = await response.json();
      setBrands(data);

      // Create a mapping from brand_id to brand_name for easy lookup
      const map: { [key: number]: string } = {};
      data.forEach((brand) => {
        map[brand.id] = brand.name;
      });
      setBrandMap(map);
    } catch (error) {
      console.error("Error fetching brands:", error);
      toast.error("Failed to fetch brands. Please try again.");
    }
  }, []);

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

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

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

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

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

  const handleEditClick = useCallback((product: Product) => {
    setProductToEdit(product);
    setIsEditProductDialogOpen(true);
  }, []);

  const handleDeleteClick = useCallback((product: Product) => {
    setProductToDelete(product);
    setIsDeleteConfirmOpen(true);
  }, []);

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

      if (!token) {
        toast.error("You must be logged in.");
        setIsDeleting(false);
        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((prevProducts) =>
          prevProducts.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);
      }
    }
  }, [productToDelete]);

  // Helper function to get the first color's first size information
  const getFirstColorSizeInfo = useCallback((product: Product) => {
    if (product.has_color && product.has_size) {
      const firstColor = product.colors[0];
      if (firstColor) {
        const sizesForColor = product.sizes.filter(
          (size) => size.color_id === firstColor.id,
        );
        const firstSize = sizesForColor[0];
        if (firstSize) {
          return {
            colorName: firstColor.name,
            sizeName: firstSize.name,
            price: firstSize.price,
            qty: firstSize.qty,
            sold: Math.abs(firstSize.sold), // Ensuring 'sold' is absolute
          };
        }
      }
    }
    return null;
  }, []);

  // Updated helper functions to accommodate the new logic
  const getProductPrice = useCallback(
    (product: Product): string => {
      const colorSizeInfo = getFirstColorSizeInfo(product);
      if (colorSizeInfo) {
        return `$${colorSizeInfo.price.toLocaleString()}`;
      }
      if (!product.has_color && !product.has_size)
        return `$${product.price.toLocaleString()}`;
      if (product.colors.length > 0 && product.colors[0].price !== null)
        return `$${product.colors[0].price.toLocaleString()}`;
      if (product.sizes.length > 0)
        return `$${product.sizes[0].price.toLocaleString()}`;
      return "N/A";
    },
    [getFirstColorSizeInfo],
  );

  const getProductQuantity = useCallback(
    (product: Product): number | string => {
      const colorSizeInfo = getFirstColorSizeInfo(product);
      if (colorSizeInfo) {
        return colorSizeInfo.qty;
      }
      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";
    },
    [getFirstColorSizeInfo],
  );

  const getProductSold = useCallback((product: Product): number => {
    let total = 0;
    if (product.colors) {
      product.colors.forEach((color) => {
        if (color.sizes.length > 0) {
          color.sizes.forEach((size) => (total += size.sold));
        } else {
          total += color.sold;
        }
      });
    }
    if (product.sizes) {
      product.sizes.forEach((size) => {
        total += size.sold;
      });
    }
    total += product.sold;
    return Math.abs(total);
  }, []);

  // Pagination Handler
  const handlePageChange = useCallback((newPage: number) => {
    setCurrentPage(newPage);
    window.scrollTo({ top: 0, behavior: "smooth" });
  }, []);

  return (
    <div className="font-sans min-h-screen bg-gray-100">
      <Head>
        <title>Products - Naay Store</title>
        <link rel="icon" href="/favicon.ico" />
        {/* Link to a better font, e.g., Inter from Google Fonts */}
        <link
          href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap"
          rel="stylesheet"
        />
      </Head>

      <main className="container mx-auto px-4 py-8">
        {/* Header Section */}
        <div className="mb-8 flex flex-col items-center justify-between space-y-4 md:flex-row md:space-y-0">
          <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>

        {/* Search and Filters */}
        <div className="mb-8 flex flex-col items-center justify-between space-y-4 md:flex-row md:space-y-0">
          {/* Search */}
          <div className="relative w-full max-w-md">
            <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>

          {/* Sort & Sort Order & View Modes */}
          <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="price">Sort by Price</option>
              <option value="created_at">Sort by Created Date</option>
            </select>

            <select
              className="rounded-md border border-gray-300 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
              value={sortOrder}
              onChange={(e) => setSortOrder(e.target.value as "asc" | "desc")}
            >
              <option value="asc">Ascending</option>
              <option value="desc">Descending</option>
            </select>

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

        {/* Product List */}
        {isLoading ? (
          <div className="flex justify-center">
            <LoadingSpinner /> {/* Same loader as OrdersPage */}
          </div>
        ) : (
          <div
            className={`grid gap-6 ${
              viewMode === "grid"
                ? "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"
                : "grid-cols-1"
            }`}
          >
            {filteredProducts.map((product) => {
              const colorSizeInfo = getFirstColorSizeInfo(product);
              // Remove displaying unnecessary fields like id and product_type
              return (
                <div
                  key={product.id}
                  className={`overflow-hidden rounded-lg bg-white shadow-md ${
                    viewMode === "list" ? "flex" : ""
                  } transition-transform hover:scale-105`}
                >
                  {/* Product Image */}
                  <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"
                        priority={false}
                        loading="lazy"
                      />
                    ) : (
                      <div className="flex items-center justify-center bg-gray-200">
                        <span className="text-gray-500">No Image</span>
                      </div>
                    )}
                  </div>

                  {/* Product Details */}
                  <div className={`p-4 ${viewMode === "list" ? "w-2/3" : ""}`}>
                    <h2 className="mb-2 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 space-y-1">
                      {/* Display Price */}
                      <p className="text-sm text-gray-600">
                        <span className="font-semibold">Price:</span>{" "}
                        {getProductPrice(product)}
                      </p>
                      {/* Display Quantity */}
                      <p className="text-sm text-gray-600">
                        <span className="font-semibold">Quantity:</span>{" "}
                        {getProductQuantity(product)}
                      </p>
                      {/* Display Sold */}
                      <p className="text-sm text-gray-600">
                        <span className="font-semibold">Sold:</span>{" "}
                        {getProductSold(product)}
                      </p>
                      {/* Display Created At */}
                      <p className="text-sm text-gray-600">
                        <span className="font-semibold">Created at:</span>{" "}
                        {formatDate(product.created_at)}
                      </p>
                      {/* Display Has Color */}
                      <p className="text-sm text-gray-600">
                        <span className="font-semibold">Has Color:</span>{" "}
                        {product.has_color ? "Yes" : "No"}
                      </p>
                      {/* Display Has Size */}
                      <p className="text-sm text-gray-600">
                        <span className="font-semibold">Has Size:</span>{" "}
                        {product.has_size ? "Yes" : "No"}
                      </p>
                      {/* Display Brand */}
                      <p className="text-sm text-gray-600">
                        <span className="font-semibold">Brand:</span>{" "}
                        {brandMap[product.brand_id] ||
                          `ID: ${product.brand_id}`}
                      </p>
                      {/* Display Categories */}
                      <p className="text-sm text-gray-600">
                        <span className="font-semibold">Category:</span>{" "}
                        {product.categories
                          .map((category) => category.name)
                          .join(", ")}
                      </p>
                      {/* Display First Color's First Size Information */}
                      {colorSizeInfo && (
                        <div className="mt-2">
                          <p className="text-sm text-gray-600">
                            <span className="font-semibold">Color:</span>{" "}
                            {colorSizeInfo.colorName}
                          </p>
                          <p className="text-sm text-gray-600">
                            <span className="font-semibold">Size:</span>{" "}
                            {colorSizeInfo.sizeName}
                          </p>
                          <p className="text-sm text-gray-600">
                            <span className="font-semibold">Price:</span> $
                            {colorSizeInfo.price.toLocaleString()}
                          </p>
                          <p className="text-sm text-gray-600">
                            <span className="font-semibold">Quantity:</span>{" "}
                            {colorSizeInfo.qty}
                          </p>
                          <p className="text-sm text-gray-600">
                            <span className="font-semibold">Sold:</span>{" "}
                            {colorSizeInfo.sold}
                          </p>
                        </div>
                      )}
                    </div>

                    {/* Action Buttons */}
                    <div className="flex space-x-2">
                      <button
                        className="flex items-center rounded-md bg-blue-500 px-4 py-2 text-white transition duration-300 hover:bg-blue-600"
                        onClick={() => handleEditClick(product)}
                      >
                        <Edit className="mr-1 inline-block" size={16} />
                        Edit
                      </button>
                      <button
                        className="flex items-center 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>
        )}

        {/* Pagination Controls */}
        {!isLoading && totalPages > 1 && (
          <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:cursor-not-allowed disabled:opacity-50"
              onClick={() => handlePageChange(Math.max(currentPage - 1, 1))}
              disabled={currentPage === 1}
            >
              Previous
            </button>

            {/* Condensed Pagination with Ellipsis */}
            {Array.from({ length: totalPages }, (_, i) => i + 1)
              .filter(
                (number) =>
                  number === 1 ||
                  number === totalPages ||
                  (number >= currentPage - 1 && number <= currentPage + 1),
              )
              .map((number, index, array) => {
                if (index > 0 && number - array[index - 1] > 1) {
                  return (
                    <span key={`ellipsis-${number}`} className="text-gray-500">
                      ...
                    </span>
                  );
                }
                return (
                  <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>
                );
              })}

            <button
              className="rounded-md bg-gray-200 px-3 py-1 text-sm text-gray-700 disabled:cursor-not-allowed disabled:opacity-50"
              onClick={() =>
                handlePageChange(Math.min(currentPage + 1, totalPages))
              }
              disabled={currentPage === totalPages}
            >
              Next
            </button>
          </div>
        )}
      </main>

      {/* Add Product Dialog */}
      {isAddProductDialogOpen && (
        <AddProductDialog
          isOpen={isAddProductDialogOpen}
          onClose={() => setIsAddProductDialogOpen(false)}
          onProductAdded={(newProduct: Product) => {
            setProducts((prevProducts) => [newProduct, ...prevProducts]);
            toast.success("Product added successfully!");
          }}
        />
      )}

      {/* Edit Product Dialog */}
      {isEditProductDialogOpen && productToEdit && (
        <EditProduct
          isOpen={isEditProductDialogOpen}
          onClose={() => {
            setIsEditProductDialogOpen(false);
            setProductToEdit(null);
            fetchProducts(); // Refresh the product list after editing
          }}
          product={productToEdit}
          onProductUpdated={(updatedProduct: Product) => {
            setProducts((prevProducts) =>
              prevProducts.map((prod) =>
                prod.id === updatedProduct.id ? updatedProduct : prod,
              ),
            );
            toast.success("Product updated successfully!");
          }}
        />
      )}

      {/* Delete Confirmation Modal */}
      {isDeleteConfirmOpen && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50">
          <div className="w-11/12 max-w-md 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="flex justify-end space-x-4">
              <button
                className="flex items-center rounded-md bg-red px-4 py-2 text-white transition duration-300 hover:bg-danger"
                onClick={handleDeleteConfirm}
                disabled={isDeleting}
              >
                <Trash2 className="mr-1 inline-block" size={16} />
                {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>
      )}

      {/* Toast Notifications */}
      <ToastContainer />
    </div>
  );
};

export default React.memo(ProductsPage);

EditProduct:
"use client";
import { X, Plus, Trash2 } from "lucide-react";
import { MultipartFileUploader } from "@/components/MultipartFileUploader";
import { toast } from "react-toastify";
import React, { useEffect, useState } from "react";
import { getToken } from "@/app/auth";

interface Category {
  id: number;
  name: string;
}

interface EditProductProps {
  isOpen: boolean;
  onClose: () => void;
  product: Product;
}

interface Brand {
  id: number;
  name: string;
}

interface Size {
  id?: number;
  name: string;
  price: string;
  qty: string;
  images: string[];
  inheritImages?: boolean;
}

interface Color {
  inheritImages?: boolean;
  id?: number;
  name: string;
  price: string | null;
  qty: string | null;
  sizes: Size[];
  images: string[];
}

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

export default function EditProduct({
  isOpen,
  onClose,
  product,
}: EditProductProps) {
  const [editedProduct, setEditedProduct] = useState<Product>({
    ...product,
    sizes: product.sizes || [], // Ensure sizes is always an array
    colors: product.colors.map((color) => ({
      ...color,
      sizes: color.sizes || [], // Ensure sizes is always an array for each color
    })),
    images: [],
  });
  const [categories, setCategories] = useState<Category[]>([]);
  const [brands, setBrands] = useState<Brand[]>([]);

  useEffect(() => {
    fetchCategories();
    fetchBrands();
  }, []);
  const handleDeleteColor = (colorIndex: number) => {
    setEditedProduct((prevProduct) => {
      const newColors = [...prevProduct.colors];
      newColors.splice(colorIndex, 1);
      return { ...prevProduct, colors: newColors };
    });
  };

  const handleDeleteSize = (colorIndex: number, sizeIndex: number) => {
    setEditedProduct((prevProduct) => {
      if (colorIndex === -1) {
        const newSizes = [...prevProduct.sizes];
        newSizes.splice(sizeIndex, 1);
        return { ...prevProduct, sizes: newSizes };
      } else {
        const newColors = [...prevProduct.colors];
        newColors[colorIndex].sizes.splice(sizeIndex, 1);
        return { ...prevProduct, colors: newColors };
      }
    });
  };

  const handleInheritImagesChange = (
    variantType: "color" | "size",
    colorIndex: number,
    sizeIndex: number,
  ) => {
    setEditedProduct((prevProduct) => {
      const updatedProduct = { ...prevProduct };

      if (variantType === "color") {
        updatedProduct.colors[colorIndex].inheritImages =
          !updatedProduct.colors[colorIndex].inheritImages;

        if (updatedProduct.colors[colorIndex].inheritImages && colorIndex > 0) {
          const prevColor = updatedProduct.colors[colorIndex - 1];
          updatedProduct.colors[colorIndex].images = [...prevColor.images];
        }
      } else if (variantType === "size") {
        if (colorIndex === -1) {
          updatedProduct.sizes[sizeIndex].inheritImages =
            !updatedProduct.sizes[sizeIndex].inheritImages;

          if (updatedProduct.sizes[sizeIndex].inheritImages && sizeIndex > 0) {
            const prevSize = updatedProduct.sizes[sizeIndex - 1];
            updatedProduct.sizes[sizeIndex].images = [...prevSize.images];
          }
        } else {
          updatedProduct.colors[colorIndex].sizes[sizeIndex].inheritImages =
            !updatedProduct.colors[colorIndex].sizes[sizeIndex].inheritImages;

          if (
            updatedProduct.colors[colorIndex].sizes[sizeIndex].inheritImages &&
            sizeIndex > 0
          ) {
            const prevSize =
              updatedProduct.colors[colorIndex].sizes[sizeIndex - 1];
            updatedProduct.colors[colorIndex].sizes[sizeIndex].images = [
              ...prevSize.images,
            ];
          }
        }
      }

      return updatedProduct;
    });
  };

  const fetchCategories = async () => {
    try {
      const response = await fetch(
        "http://localhost:4000/subcategories/non-brands",
      );
      const data = await response.json();
      setCategories(data);
    } catch (error) {
      console.error("Error fetching categories:", error);
    }
  };

  const fetchBrands = async () => {
    try {
      const response = await fetch(
        "http://localhost:4000/subcategories/brands",
      );
      const data = await response.json();
      setBrands(data);
    } catch (error) {
      console.error("Error fetching brands:", error);
    }
  };

  const handleCategoryToggle = (categoryId: number) => {
    // @ts-ignore
    setEditedProduct((prevProduct) => {
      const updatedCategories = prevProduct.categories.some(
        // @ts-ignore
        (cat) => cat.id === categoryId,
      )
        ? prevProduct.categories.filter((cat) => {
            // @ts-ignore
            cat.id !== categoryId;
          })
        : [
            ...prevProduct.categories,
            {
              id: categoryId,
              name: categories.find((cat) => cat.id === categoryId)?.name || "",
            },
          ];
      return { ...prevProduct, categories: updatedCategories };
    });
  };

  const handleInputChange = (e: {
    target: { name: string; value: string };
  }) => {
    const { name, value } = e.target;
    setEditedProduct((prevProduct) => ({
      ...prevProduct,
      [name]: value,
    }));
  };

  const handleColorToggle = () => {
    setEditedProduct((prevProduct) => ({
      ...prevProduct,
      has_color: !prevProduct.has_color,
      colors: !prevProduct.has_color ? [] : prevProduct.colors,
    }));
  };

  const handleBrandChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
    setEditedProduct((prevProduct) => ({
      ...prevProduct,
      brand_id: parseInt(e.target.value),
    }));
  };

  const handleSizeToggle = () => {
    setEditedProduct((prevProduct) => ({
      ...prevProduct,
      has_size: !prevProduct.has_size,
      sizes: !prevProduct.has_size ? [] : prevProduct.sizes,
    }));
  };

  const handleAddColor = () => {
    setEditedProduct((prevProduct) => ({
      ...prevProduct,
      colors: [
        ...prevProduct.colors,
        { name: "", price: null, qty: null, sizes: [], images: [] },
      ],
    }));
  };

  const handleAddSize = (colorIndex: number) => {
    setEditedProduct((prevProduct) => {
      if (colorIndex === -1) {
        return {
          ...prevProduct,
          sizes: [
            ...prevProduct.sizes,
            { name: "", price: "", qty: "", images: [] },
          ],
        };
      } else {
        const newColors = [...prevProduct.colors];
        newColors[colorIndex].sizes.push({
          name: "",
          price: "",
          qty: "",
          images: [],
        });
        return {
          ...prevProduct,
          colors: newColors,
        };
      }
    });
  };

  const handleColorChange = (
    index: number,
    field: keyof Color,
    value: string,
  ) => {
    setEditedProduct((prevProduct) => {
      const newColors = [...prevProduct.colors];
      newColors[index] = {
        ...newColors[index],
        [field]: value,
      };
      return { ...prevProduct, colors: newColors };
    });
  };

  const handleSizeChange = (
    colorIndex: number,
    sizeIndex: number,
    field: keyof Size,
    value: string,
  ) => {
    setEditedProduct((prevProduct) => {
      if (colorIndex === -1) {
        const newSizes = [...prevProduct.sizes];
        newSizes[sizeIndex] = {
          ...newSizes[sizeIndex],
          [field]: value,
          images: newSizes[sizeIndex].images || [], // Ensure images array exists
        };
        return { ...prevProduct, sizes: newSizes };
      } else {
        const newColors = [...prevProduct.colors];
        newColors[colorIndex].sizes[sizeIndex] = {
          ...newColors[colorIndex].sizes[sizeIndex],
          [field]: value,
          images: newColors[colorIndex].sizes[sizeIndex].images || [], // Ensure images array exists
        };
        return { ...prevProduct, colors: newColors };
      }
    });
  };

  const handleImageUpload = (
    fileIds: string[],
    variantType: "color" | "size" | "product",
    colorIndex: number,
    sizeIndex: number,
  ) => {
    setEditedProduct((prevProduct) => {
      const updatedProduct = { ...prevProduct };

      if (variantType === "color") {
        updatedProduct.colors[colorIndex].images = fileIds;
      } else if (variantType === "size") {
        if (colorIndex === -1) {
          updatedProduct.sizes[sizeIndex].images = fileIds;
        } else {
          updatedProduct.colors[colorIndex].sizes[sizeIndex].images = fileIds;
        }
      } else {
        updatedProduct.images = fileIds;
      }

      return updatedProduct;
    });
  };

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    const productType =
      editedProduct.has_color && editedProduct.has_size
        ? "color_size"
        : editedProduct.has_color
          ? "color"
          : editedProduct.has_size
            ? "size"
            : "simple";

    const productData = {
      ...editedProduct,
      product_type: productType,
      category_ids: editedProduct.categories.map((cat) => cat.id),
      hasColor: editedProduct.has_color,
      hasSize: editedProduct.has_size,
      colors: editedProduct.has_color
        ? editedProduct.colors.map((color) => ({
            id: color.id, // Include the color ID if it exists
            name: color.name,
            price: color.price ? parseFloat(color.price) : null,
            qty: color.qty ? parseInt(color.qty) : null,
            hasSize: editedProduct.has_size,
            sizes: editedProduct.has_size
              ? color.sizes.map((size) => ({
                  id: size.id, // Include the size ID if it exists
                  name: size.name,
                  price: parseFloat(size.price),
                  qty: parseInt(size.qty),
                  images: size.images,
                }))
              : [],
            images: color.images,
          }))
        : [],
      sizes:
        editedProduct.has_size && !editedProduct.has_color
          ? editedProduct.sizes.map((size) => ({
              id: size.id, // Include the size ID if it exists
              name: size.name,
              price: parseFloat(size.price),
              qty: parseInt(size.qty),
              images: size.images,
            }))
          : [],
      price: editedProduct.price ? parseFloat(editedProduct.price) : null,
      qty: editedProduct.qty ? parseInt(editedProduct.qty) : null,
      images: editedProduct.images,
    };
    const token = getToken();

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

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

      const updatedProduct = await response.json();
      console.log("Product updated:", updatedProduct);
      toast.success("Product updated successfully!");
      onClose();
    } catch (error) {
      console.error("Error updating product:", error);
      toast.error("Failed to update product. Please try again.");
    }
  };

  if (!isOpen) return null;

  return (
    <div className="fixed inset-0 z-[99999999] flex h-screen transform items-center justify-center overflow-y-scroll bg-black bg-opacity-50">
      <div className="relative h-screen w-full max-w-2xl overflow-y-scroll rounded-lg bg-white p-8">
        <button
          onClick={onClose}
          className="absolute right-4 top-4 text-gray-500 hover:text-gray-700"
        >
          <X size={24} />
        </button>

        <h2 className="mb-6 text-2xl font-bold">Edit Product</h2>

        <form onSubmit={handleSubmit} className="space-y-4">
          {/* Product Name */}
          <div>
            <label className="mb-2 block font-bold" htmlFor="name">
              Product Name
            </label>
            <input
              type="text"
              id="name"
              name="name"
              value={editedProduct.name}
              onChange={handleInputChange}
              className="w-full rounded-md border p-2"
              required
            />
          </div>

          {/* Description */}
          <div>
            <label className="mb-2 block font-bold" htmlFor="description">
              Description
            </label>
            <textarea
              id="description"
              name="description"
              value={editedProduct.description}
              onChange={handleInputChange}
              className="w-full rounded-md border p-2"
              style={{ direction: "rtl" }}
              required
            />
          </div>

          {/* Categories */}
          <div>
            <label className="mb-2 block font-bold">Categories</label>
            <div className="flex flex-wrap gap-2">
              {categories.map((category) => (
                <button
                  key={category.id}
                  type="button"
                  onClick={() => handleCategoryToggle(category.id)}
                  className={`rounded-full px-3 py-1 text-sm ${
                    editedProduct.categories.some(
                      // @ts-ignore
                      (cat) => cat.id === category.id,
                    )
                      ? "bg-blue-500 text-white"
                      : "bg-gray-200 text-gray-700"
                  }`}
                >
                  {category.name}
                </button>
              ))}
            </div>
          </div>

          {/* Brand */}
          <div>
            <label className="mb-2 block font-bold" htmlFor="brand">
              Brand
            </label>
            <select
              id="brand"
              name="brand"
              value={editedProduct.brand_id}
              onChange={handleBrandChange}
              className="w-full rounded-md border p-2"
              required
            >
              <option value="">Select a brand</option>
              {brands.map((brand) => (
                <option key={brand.id} value={brand.id}>
                  {brand.name}
                </option>
              ))}
            </select>
          </div>

          {/* Has Color */}
          <div>
            <label className="flex items-center">
              <input
                type="checkbox"
                checked={editedProduct.has_color}
                onChange={handleColorToggle}
                className="mr-2"
              />
              <span className="font-bold">Has Color?</span>
            </label>
          </div>

          {/* Colors */}
          {editedProduct.has_color && (
            <div>
              <label className="mb-2 block font-bold">Colors</label>
              <div className="space-y-4">
                {editedProduct.colors.map((color, colorIndex) => (
                  <div key={colorIndex} className="rounded-md border p-4">
                    <div className="mb-2 flex items-center justify-between">
                      <input
                        type="text"
                        value={color.name}
                        onChange={(e) =>
                          handleColorChange(colorIndex, "name", e.target.value)
                        }
                        className="mr-2 flex-grow rounded-md border p-2"
                        placeholder="Color name"
                      />
                      <button
                        type="button"
                        onClick={() => handleDeleteColor(colorIndex)}
                        className="text-red-500 hover:text-red-700"
                      >
                        <Trash2 size={20} />
                      </button>
                    </div>

                    <div className="mt-2 space-y-2">
                      <div className="flex space-x-2">
                        <input
                          type="number"
                          // @ts-ignore
                          value={color.price}
                          onChange={(e) =>
                            handleColorChange(
                              colorIndex,
                              "price",
                              e.target.value,
                            )
                          }
                          className="w-1/2 rounded-md border p-2"
                          placeholder="Price"
                        />
                        <input
                          type="number"
                          // @ts-ignore
                          value={color.qty}
                          onChange={(e) =>
                            handleColorChange(colorIndex, "qty", e.target.value)
                          }
                          className="w-1/2 rounded-md border p-2"
                          placeholder="Quantity"
                        />
                      </div>
                      <MultipartFileUploader
                        onUploadSuccess={(fileIds) =>
                          // @ts-ignore
                          handleImageUpload(fileIds, "color", colorIndex)
                        }
                        // @ts-ignore
                        existingImages={color.images}
                      />
                    </div>
                  </div>
                ))}
              </div>
              <button
                type="button"
                onClick={handleAddColor}
                className="mt-2 rounded-md bg-blue-500 px-4 py-2 text-white hover:bg-blue-600"
              >
                <Plus className="mr-1 inline-block" size={16} />
                Add Color
              </button>
            </div>
          )}

          {/* Has Size */}
          <div>
            <label className="flex items-center">
              <input
                type="checkbox"
                checked={editedProduct.has_size}
                onChange={handleSizeToggle}
                className="mr-2"
              />
              <span className="font-bold">Has Size?</span>
            </label>
          </div>

          {/* Sizes */}
          {editedProduct.has_size && (
            <div>
              <label className="mb-2 block font-bold">Sizes</label>
              <div className="space-y-2">
                {editedProduct.sizes.map((size, index) => (
                  <div key={index} className="space-y-2 rounded-md border p-2">
                    <div className="flex items-center justify-between">
                      <input
                        type="text"
                        value={size.name}
                        onChange={(e) =>
                          handleSizeChange(-1, index, "name", e.target.value)
                        }
                        className="mr-2 w-full rounded-md border p-2"
                        placeholder="Size name"
                      />
                      <button
                        type="button"
                        onClick={() => handleDeleteSize(-1, index)}
                        className="text-red-500 hover:text-red-700"
                      >
                        <Trash2 size={20} />
                      </button>
                    </div>
                    <div className="flex space-x-2">
                      <input
                        type="number"
                        value={size.price}
                        onChange={(e) =>
                          handleSizeChange(-1, index, "price", e.target.value)
                        }
                        className="w-1/2 rounded-md border p-2"
                        placeholder="Price"
                      />
                      <input
                        type="number"
                        value={size.qty}
                        onChange={(e) =>
                          handleSizeChange(-1, index, "qty", e.target.value)
                        }
                        className="w-1/2 rounded-md border p-2"
                        placeholder="Quantity"
                      />
                    </div>
                    {index > 0 && (
                      <label className="flex items-center">
                        <input
                          type="checkbox"
                          checked={size.inheritImages}
                          onChange={() =>
                            handleInheritImagesChange("size", -1, index)
                          }
                          className="mr-1"
                        />
                        <span>Inherit images</span>
                      </label>
                    )}
                    {!size.inheritImages && (
                      <MultipartFileUploader
                        onUploadSuccess={(fileIds) =>
                          handleImageUpload(fileIds, "size", -1, index)
                        }
                      />
                    )}
                  </div>
                ))}
                <button
                  type="button"
                  onClick={() => handleAddSize(-1)}
                  className="rounded-md bg-blue-500 px-4 py-2 text-white hover:bg-blue-600"
                >
                  <Plus className="mr-1 inline-block" size={16} />
                  Add Size
                </button>
              </div>
            </div>
          )}

          {/* Product Details (when no color and no size) */}
          {!product.has_color && !product.has_size && (
            <div>
              <label className="mb-2 block font-bold">Product Details</label>
              <div className="flex items-center space-x-2">
                <input
                  type="number"
                  // @ts-ignore
                  value={product.price}
                  onChange={(e) =>
                    handleInputChange({
                      target: { name: "price", value: e.target.value },
                    })
                  }
                  className="rounded-md border p-2"
                  placeholder="Price"
                />
                <input
                  type="number"
                  // @ts-ignore
                  value={product.qty}
                  onChange={(e) =>
                    handleInputChange({
                      target: { name: "qty", value: e.target.value },
                    })
                  }
                  className="rounded-md border p-2"
                  placeholder="Quantity"
                />
              </div>
              <div className="mt-2">
                <MultipartFileUploader
                  onUploadSuccess={(fileIds) =>
                    // @ts-ignore
                    handleImageUpload(fileIds, "product")
                  }
                />
              </div>
            </div>
          )}

          <div className="flex justify-end">
            <button
              type="submit"
              className="rounded-md bg-green-500 px-4 py-2 text-white hover:bg-green-600"
            >
              Edit Product
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}
AddProduct:
"use client";
import React, { useState, useEffect } from "react";
import { X, Plus } from "lucide-react";
import { MultipartFileUploader } from "@/components/MultipartFileUploader";
import { toast } from "react-toastify";
import { getToken } from "@/app/auth";

export default function AddProductDialog({ isOpen, onClose }) {
  const [product, setProduct] = useState({
    name: "",
    description: "",
    category: "",
    subcategory: "",
    brand: "",
    hasColor: false,
    colors: [],
    hasSize: false,
    sizes: [],
    categories: [],
    price: "",
    qty: "",
    images: [],
  });

  const [categories, setCategories] = useState([]);
  const [brands, setBrands] = useState([]);

  useEffect(() => {
    fetchCategories();
    fetchBrands();
  }, []);

  const fetchCategories = async () => {
    try {
      const token = getToken(); // Retrieve the token from localStorage

      if (!token) {
        toast.error("You must be logged in to add a product.");
        return;
      }
      const response = await fetch(
        "http://localhost:4000/subcategories/non-brands",
        {
          headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${token}`, // Include the token here
          },
        },
      );
      const data = await response.json();
      setCategories(data);
    } catch (error) {
      console.error("Error fetching categories:", error);
    }
  };

  const fetchBrands = async () => {
    try {
      const token = getToken(); // Retrieve the token from localStorage

      if (!token) {
        toast.error("You must be logged in to add a product.");
        return;
      }
      const response = await fetch(
        "http://localhost:4000/subcategories/brands",
        {
          headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${token}`, // Include the token here
          },
        },
      );
      const data = await response.json();
      setBrands(data);
    } catch (error) {
      console.error("Error fetching brands:", error);
    }
  };

  const handleCategoryToggle = (categoryId) => {
    setProduct((prevProduct) => {
      const updatedCategories = prevProduct.categories.includes(categoryId)
        ? prevProduct.categories.filter((id) => id !== categoryId)
        : [...prevProduct.categories, categoryId];
      return { ...prevProduct, categories: updatedCategories };
    });
  };

  const handleInputChange = (e) => {
    const { name, value } = e.target;
    setProduct((prevProduct) => ({
      ...prevProduct,
      [name]: value,
    }));
  };
  useEffect(() => {
    console.log("Updated product state:", product);
  }, [product]);
  const handleColorToggle = () => {
    setProduct({ ...product, hasColor: !product.hasColor, colors: [] });
  };

  const handleBrandChange = (e) => {
    setProduct({ ...product, brand: e.target.value });
  };

  const handleSizeToggle = () => {
    setProduct({
      ...product,
      hasSize: !product.hasSize,
      sizes: !product.hasSize ? [] : product.sizes,
    });
  };
  const [isSubmitting, setIsSubmitting] = useState(false); // Start submission]
  const handleAddColor = () => {
    setProduct((prevProduct) => {
      const newColor = {
        name: "",
        hasSize: false,
        sizes: [],
        price: "",
        qty: "",
        images: [],
        inheritImages: false,
      };

      return {
        ...prevProduct,
        colors: [...prevProduct.colors, newColor],
      };
    });
  };

  const handleColorChange = (index, field, value) => {
    setProduct((prevProduct) => {
      const newColors = [...prevProduct.colors];
      newColors[index] = {
        ...newColors[index],
        [field]: value,
      };
      return { ...prevProduct, colors: newColors };
    });
  };

  const handleColorSizeToggle = (colorIndex) => {
    const newColors = [...product.colors];
    newColors[colorIndex].hasSize = !newColors[colorIndex].hasSize;
    newColors[colorIndex].sizes = [];
    setProduct({ ...product, colors: newColors });
  };

  const handleAddSize = (colorIndex) => {
    setProduct((prevProduct) => {
      if (colorIndex === -1) {
        const newSize = {
          name: "",
          images: [],
          price: "",
          qty: "",
          inheritImages: false,
        };
        return {
          ...prevProduct,
          sizes: [...prevProduct.sizes, newSize],
        };
      } else {
        const newColors = [...prevProduct.colors];
        const newSize = {
          name: "",
          images: [],
          price: "",
          qty: "",
          inheritImages: false,
        };
        newColors[colorIndex] = {
          ...newColors[colorIndex],
          sizes: [...newColors[colorIndex].sizes, newSize],
        };
        return {
          ...prevProduct,
          colors: newColors,
        };
      }
    });
  };

  const handleSizeChange = (colorIndex, sizeIndex, field, value) => {
    setProduct((prevProduct) => {
      if (colorIndex === -1) {
        const newSizes = [...prevProduct.sizes];
        newSizes[sizeIndex] = {
          ...newSizes[sizeIndex],
          [field]: value,
        };
        return { ...prevProduct, sizes: newSizes };
      } else {
        const newColors = [...prevProduct.colors];
        newColors[colorIndex].sizes[sizeIndex] = {
          ...newColors[colorIndex].sizes[sizeIndex],
          [field]: value,
        };
        return { ...prevProduct, colors: newColors };
      }
    });
  };

  const handleImageUpload = (fileIds, variantType, colorIndex, sizeIndex) => {
    const formattedImages = fileIds.map((url) => ({ url }));

    setProduct((prevProduct) => {
      let updatedProduct = { ...prevProduct };

      if (variantType === "color") {
        updatedProduct.colors[colorIndex].images = formattedImages;
      } else if (variantType === "size") {
        if (colorIndex === -1) {
          updatedProduct.sizes[sizeIndex].images = formattedImages;
        } else {
          updatedProduct.colors[colorIndex].sizes[sizeIndex].images =
            formattedImages;
        }
      } else {
        updatedProduct.images = formattedImages;
      }

      return updatedProduct;
    });
  };
  const handleInheritImagesChange = (variantType, colorIndex, sizeIndex) => {
    setProduct((prevProduct) => {
      let updatedProduct = JSON.parse(JSON.stringify(prevProduct)); // Deep clone

      if (variantType === "color") {
        updatedProduct.colors[colorIndex].inheritImages =
          !updatedProduct.colors[colorIndex].inheritImages;

        if (updatedProduct.colors[colorIndex].inheritImages && colorIndex > 0) {
          const prevColor = updatedProduct.colors[colorIndex - 1];
          updatedProduct.colors[colorIndex].images = [...prevColor.images];
        }
      } else if (variantType === "size") {
        if (colorIndex === -1) {
          updatedProduct.sizes[sizeIndex].inheritImages =
            !updatedProduct.sizes[sizeIndex].inheritImages;

          if (updatedProduct.sizes[sizeIndex].inheritImages && sizeIndex > 0) {
            const prevSize = updatedProduct.sizes[sizeIndex - 1];
            updatedProduct.sizes[sizeIndex].images = [...prevSize.images];
          }
        } else {
          updatedProduct.colors[colorIndex].sizes[sizeIndex].inheritImages =
            !updatedProduct.colors[colorIndex].sizes[sizeIndex].inheritImages;

          if (
            updatedProduct.colors[colorIndex].sizes[sizeIndex].inheritImages &&
            sizeIndex > 0
          ) {
            const prevSize =
              updatedProduct.colors[colorIndex].sizes[sizeIndex - 1];
            updatedProduct.colors[colorIndex].sizes[sizeIndex].images = [
              ...prevSize.images,
            ];
          }
        }
      }

      return updatedProduct;
    });
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    setIsSubmitting(true);
    // Determine if any color has sizes
    const colorsHaveSizes =
      product.hasColor &&
      product.colors.some((color) => color.hasSize && color.sizes.length > 0);

    // Determine productType based on the presence of colors and sizes
    let productType;
    if (colorsHaveSizes) {
      productType = "color_size";
    } else if (product.hasColor) {
      productType = "color";
    } else if (product.hasSize) {
      productType = "size";
    } else {
      productType = "simple";
    }

    // Construct productData without using ||
    const productData = {
      name: product.name,
      description: product.description,
      brand_id: parseInt(product.brand, 10),
      has_color: product.hasColor,
      has_size: product.hasSize,
      product_type: productType,
      category_ids: product.categories,
      colors: product.colors.map((color) => ({
        name: color.name,
        images: color.images,
        has_size: color.hasSize,
        sizes: color.hasSize
          ? color.sizes.map((size) => ({
              name: size.name,
              price: parseFloat(size.price),
              qty: parseInt(size.qty, 10) || 0,
              images: size.images,
            }))
          : [],
        price: parseFloat(color.price),
        qty: parseInt(color.qty, 10) || 0,
      })),
      sizes: !product.hasColor
        ? product.sizes.map((size) => ({
            name: size.name,
            price: parseFloat(size.price),
            qty: parseInt(size.qty, 10) || 0,
            images: size.images,
          }))
        : [],
      price: parseFloat(product.price),
      qty: parseInt(product.qty, 10) || 0,
      images: product.images,
    };
    console.log(productData);
    try {
      const token = getToken(); // Retrieve the token from localStorage

      if (!token) {
        setIsSubmitting(true); // Start submission
        toast.error("You must be logged in to add a product.");
        return;
      }

      const response = await fetch("http://localhost:4000/products", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${token}`, // Include the token here
        },
        body: JSON.stringify(productData),
      });

      if (!response.ok) {
        setIsSubmitting(true); // Start submission
        const errorData = await response.json();
        throw new Error(errorData.message || "Failed to create product");
      }

      // Reset the form after successful submission
      setProduct({
        name: "",
        description: "",
        category: "",
        subcategory: "",
        brand: "",
        hasColor: false,
        colors: [],
        hasSize: false,
        sizes: [],
        categories: [],
        price: "",
        qty: "",
        images: [],
      });

      toast.success("Product added successfully!");
      onClose();
    } catch (error) {
      console.error("Error creating product:", error);
      setIsSubmitting(true); // Start submission
      toast.error("Failed to add product. Please try again.");
    }
  };

  if (!isOpen) return null;

  return (
    <div className="fixed inset-0 z-[99999999] flex h-screen transform items-center justify-center overflow-y-scroll bg-black bg-opacity-50">
      <div className="relative h-screen w-full max-w-2xl overflow-y-scroll rounded-lg bg-white p-8">
        <button
          onClick={onClose}
          className="absolute right-4 top-4 text-gray-500 hover:text-gray-700"
        >
          <X size={24} />
        </button>

        <h2 className="mb-6 text-2xl font-bold">Add New Product</h2>

        <form onSubmit={handleSubmit} className="space-y-4">
          {/* Product Name */}
          <div>
            <label className="mb-2 block font-bold" htmlFor="name">
              Product Name
            </label>
            <input
              type="text"
              id="name"
              name="name"
              value={product.name}
              onChange={handleInputChange}
              className="w-full rounded-md border p-2"
              required
            />
          </div>

          {/* Description */}
          <div>
            <label className="mb-2 block font-bold" htmlFor="description">
              Description
            </label>
            <textarea
              id="description"
              name="description"
              value={product.description}
              onChange={handleInputChange}
              className="w-full rounded-md border p-2"
              style={{ direction: "rtl" }}
              required
            />
          </div>

          {/* Categories */}
          <div>
            <label className="mb-2 block font-bold">Categories</label>
            <div className="flex flex-wrap gap-2">
              {categories.map((category) => (
                <button
                  key={category.id}
                  type="button"
                  onClick={() => handleCategoryToggle(category.id)}
                  className={`rounded-full px-3 py-1 text-sm ${
                    product.categories.includes(category.id)
                      ? "bg-blue-500 text-white"
                      : "bg-gray-200 text-gray-700"
                  }`}
                >
                  {category.name}
                </button>
              ))}
            </div>
          </div>

          {/* Brand */}
          <div>
            <label className="mb-2 block font-bold" htmlFor="brand">
              Brand
            </label>
            <select
              id="brand"
              name="brand"
              value={product.brand}
              onChange={handleBrandChange}
              className="w-full rounded-md border p-2"
              required
            >
              <option value="">Select a brand</option>
              {brands.map((brand) => (
                <option key={brand.id} value={brand.id}>
                  {brand.name}
                </option>
              ))}
            </select>
          </div>

          {/* Has Color */}
          <div>
            <label className="flex items-center">
              <input
                type="checkbox"
                checked={product.hasColor}
                onChange={handleColorToggle}
                className="mr-2"
              />
              <span className="font-bold">Has Color?</span>
            </label>
          </div>

          {/* Colors */}
          {product.hasColor && (
            <div>
              <label className="mb-2 block font-bold">Colors</label>
              <div className="space-y-4">
                {product.colors.map((color, colorIndex) => (
                  <div key={colorIndex} className="rounded-md border p-4">
                    <input
                      type="text"
                      value={color.name}
                      onChange={(e) =>
                        handleColorChange(colorIndex, "name", e.target.value)
                      }
                      className="mb-2 rounded-md border p-2"
                      placeholder="Color name"
                    />

                    <label className="ml-2 flex items-center">
                      <input
                        type="checkbox"
                        checked={color.hasSize}
                        onChange={() => handleColorSizeToggle(colorIndex)}
                        className="mr-1"
                      />
                      <span>Has Size?</span>
                    </label>

                    {colorIndex > 0 && (
                      <label className="ml-2 flex items-center">
                        <input
                          type="checkbox"
                          checked={color.inheritImages}
                          onChange={() =>
                            handleInheritImagesChange("color", colorIndex)
                          }
                          className="mr-1"
                        />
                        <span>Inherit images</span>
                      </label>
                    )}

                    {color.hasSize ? (
                      <div className="mt-2 space-y-2">
                        {color.sizes.map((size, sizeIndex) => (
                          <div
                            key={sizeIndex}
                            className="space-y-2 rounded-md border p-2"
                          >
                            <input
                              type="text"
                              value={size.name}
                              onChange={(e) =>
                                handleSizeChange(
                                  colorIndex,
                                  sizeIndex,
                                  "name",
                                  e.target.value,
                                )
                              }
                              className="w-full rounded-md border p-2"
                              placeholder="Size name"
                            />
                            <div className="flex space-x-2">
                              <input
                                type="number"
                                value={size.price}
                                onChange={(e) =>
                                  handleSizeChange(
                                    colorIndex,
                                    sizeIndex,
                                    "price",
                                    e.target.value,
                                  )
                                }
                                className="w-1/2 rounded-md border p-2"
                                placeholder="Price"
                              />
                              <input
                                type="number"
                                value={size.qty}
                                onChange={(e) =>
                                  handleSizeChange(
                                    colorIndex,
                                    sizeIndex,
                                    "qty",
                                    e.target.value,
                                  )
                                }
                                className="w-1/2 rounded-md border p-2"
                                placeholder="Quantity"
                              />
                            </div>
                            {sizeIndex > 0 && (
                              <label className="flex items-center">
                                <input
                                  type="checkbox"
                                  checked={size.inheritImages}
                                  onChange={() =>
                                    handleInheritImagesChange(
                                      "size",
                                      colorIndex,
                                      sizeIndex,
                                    )
                                  }
                                  className="mr-1"
                                />
                                <span>Inherit images</span>
                              </label>
                            )}
                            {!size.inheritImages && (
                              <MultipartFileUploader
                                onUploadSuccess={(fileIds) =>
                                  handleImageUpload(
                                    fileIds,
                                    "size",
                                    colorIndex,
                                    sizeIndex,
                                  )
                                }
                              />
                            )}
                          </div>
                        ))}
                        <button
                          type="button"
                          onClick={() => handleAddSize(colorIndex)}
                          className="mt-2 rounded-md bg-blue-500 px-2 py-1 text-white hover:bg-blue-600"
                        >
                          Add Size
                        </button>
                      </div>
                    ) : (
                      <div className="mt-2 space-y-2">
                        <div className="flex space-x-2">
                          <input
                            type="number"
                            value={color.price}
                            onChange={(e) =>
                              handleColorChange(
                                colorIndex,
                                "price",
                                e.target.value,
                              )
                            }
                            className="w-1/2 rounded-md border p-2"
                            placeholder="Price"
                          />
                          <input
                            type="number"
                            value={color.qty}
                            onChange={(e) =>
                              handleColorChange(
                                colorIndex,
                                "qty",
                                e.target.value,
                              )
                            }
                            className="w-1/2 rounded-md border p-2"
                            placeholder="Quantity"
                          />
                        </div>
                        {!color.inheritImages && (
                          <MultipartFileUploader
                            onUploadSuccess={(fileIds) =>
                              handleImageUpload(fileIds, "color", colorIndex)
                            }
                          />
                        )}
                      </div>
                    )}
                  </div>
                ))}
              </div>
              <button
                type="button"
                onClick={handleAddColor}
                className="mt-2 rounded-md bg-blue-500 px-4 py-2 text-white hover:bg-blue-600"
              >
                <Plus className="mr-1 inline-block" size={16} />
                Add Color
              </button>
            </div>
          )}

          {/* Has Size (when no color) */}
          {!product.hasColor && (
            <div>
              <label className="flex items-center">
                <input
                  type="checkbox"
                  checked={product.hasSize}
                  onChange={handleSizeToggle}
                  className="mr-2"
                />
                <span className="font-bold">Has Size?</span>
              </label>
            </div>
          )}

          {/* Sizes (when no color) */}
          {!product.hasColor && product.hasSize && (
            <div>
              <label className="mb-2 block font-bold">Sizes</label>
              <div className="space-y-2">
                {product.sizes.map((size, index) => (
                  <div key={index} className="space-y-2 rounded-md border p-2">
                    <input
                      type="text"
                      value={size.name}
                      onChange={(e) =>
                        handleSizeChange(-1, index, "name", e.target.value)
                      }
                      className="w-full rounded-md border p-2"
                      placeholder="Size name"
                    />
                    <div className="flex space-x-2">
                      <input
                        type="number"
                        value={size.price}
                        onChange={(e) =>
                          handleSizeChange(-1, index, "price", e.target.value)
                        }
                        className="w-1/2 rounded-md border p-2"
                        placeholder="Price"
                      />
                      <input
                        type="number"
                        value={size.qty}
                        onChange={(e) =>
                          handleSizeChange(-1, index, "qty", e.target.value)
                        }
                        className="w-1/2 rounded-md border p-2"
                        placeholder="Quantity"
                      />
                    </div>
                    {index > 0 && (
                      <label className="flex items-center">
                        <input
                          type="checkbox"
                          checked={size.inheritImages}
                          onChange={() =>
                            handleInheritImagesChange("size", -1, index)
                          }
                          className="mr-1"
                        />
                        <span>Inherit images</span>
                      </label>
                    )}
                    {!size.inheritImages && (
                      <MultipartFileUploader
                        onUploadSuccess={(fileIds) =>
                          handleImageUpload(fileIds, "size", -1, index)
                        }
                      />
                    )}
                  </div>
                ))}
                <button
                  type="button"
                  onClick={() => handleAddSize(-1)}
                  className="rounded-md bg-blue-500 px-4 py-2 text-white hover:bg-blue-600"
                >
                  <Plus className="mr-1 inline-block" size={16} />
                  Add Size
                </button>
              </div>
            </div>
          )}

          {/* Product Details (when no color and no size) */}
          {!product.hasColor && !product.hasSize && (
            <div>
              <label className="mb-2 block font-bold">Product Details</label>
              <div className="flex items-center space-x-2">
                <input
                  type="number"
                  value={product.price}
                  onChange={(e) =>
                    handleInputChange({
                      target: { name: "price", value: e.target.value },
                    })
                  }
                  className="rounded-md border p-2"
                  placeholder="Price"
                />
                <input
                  type="number"
                  value={product.qty}
                  onChange={(e) =>
                    handleInputChange({
                      target: { name: "qty", value: e.target.value },
                    })
                  }
                  className="rounded-md border p-2"
                  placeholder="Quantity"
                />
              </div>
              <div className="mt-2">
                <MultipartFileUploader
                  onUploadSuccess={(fileIds) =>
                    handleImageUpload(fileIds, "product")
                  }
                />
              </div>
            </div>
          )}

          <div className="flex justify-end">
            <button
              disabled={isSubmitting}
              type="submit"
              className="rounded-md bg-green-500 px-4 py-2 text-white hover:bg-green-600"
            >
              Add Product
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

types.ts:
// types.ts
export interface Size {
  id: number;
  name: string;
  price: number;
  qty: number;
  sold: number;
  color_id: number | null;
  images: string[];
}

export interface Color {
  id: number;
  name: string;
  price: number | null;
  qty: number | null;
  sold: number;
  sizes: Size[];
  images: string;
}

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

export interface Category {
  id: number;
  name: string;
  main_category_id: number;
  main_category_name: string;
}

export interface Product {
  id: number;
  name: string;
  description: string;
  brand_id: number;
  has_color: boolean;
  has_size: boolean;
  product_type: string;
  price: number;
  qty: number;
  sold: number;
  created_at: string;
  updated_at: string;
  categories: Category[];
  colors: Color[];
  sizes: Size[];
  images: ImageType[];
}

export interface ApiResponse {
  products: Product[];
  total: number;
  page: number;
  itemsPerPage: number;
  totalPages: number;
  hasMore: boolean;
}

export interface Brand {
  id: number;
  name: string;
}

consider your solution deeply and make sure it is flewless...