The cart api may contain colors and sizes inside colors as well...
{"carts":[{"id":385,"user_id":null,"status":"Pending","notes":"","full_name":"test","governorate":"baghdad","city":"test","address":"test","closest_point":"0","phone_number":"07752546762","type":"home","created_at":"2024-10-05T23:05:02.994Z","coupon_id":null,"updated_at":"2024-10-05T23:05:02.994Z","items":[{"id":6204,"cart_id":385,"product_id":6017,"size_id":6044,"color_id":13,"quantity":3},{"id":6205,"cart_id":385,"product_id":6017,"size_id":null,"color_id":14,"quantity":4}]},{"id":383,"user_id":null,"status":"Pending","notes":"","full_name":"فاطمة احمد","governorate":"maysan","city":"ميسان","address":"نهاوند- شارع عشرين","closest_point":"","phone_number":"07712521240","type":"","created_at":"2024-10-05T22:07:30.792Z","coupon_id":5,"updated_at":"2024-10-05T22:07:30.792Z","items":[{"id":6197,"cart_id":383,"product_id":631,"size_id":2,"color_id":null,"quantity":1},{"id":6198,"cart_id":383,"product_id":940,"size_id":2106,"color_id":null,"quantity":1},{"id":6199,"cart_id":383,"product_id":1239,"size_id":3016,"color_id":null,"quantity":1}]},{"id":382,"user_id":null,"status":"Pending","notes":"","full_name":"in.14i علي هاشم","governorate":"baghdad","city":"بغداد","address":"شعب/الجزائر/المثلث","closest_point":"سما بغداد","phone_number":"٠٧٧١١٣٣٦٥٦٤","type":"home","created_at":"2024-10-05T19:34:22.446Z","coupon_id":null,"updated_at":"2024-10-05T19:34:22.446Z","items":[{"id":6195,"cart_id":382,"product_id":878,"size_id":2039,"color_id":null,"quantity":1},{"id":6196,"cart_id":382,"product_id":8,"size_id":1429,"color_id":null,"quantity":1}]},{"id":381,"user_id":null,"status":"On Way","notes":"","full_name":"Haneen Jasim","governorate":"baghdad","city":"Baghdad","address":"Inner karada","closest_point":"Inner karada","phone_number":"07701830137","type":"home","created_at":"2024-10-05T19:02:24.128Z","coupon_id":5,"updated_at":"2024-10-05T19:07:35.499Z","items":[{"id":6189,"cart_id":381,"product_id":904,"size_id":2068,"color_id":null,"quantity":1},{"id":6190,"cart_id":381,"product_id":148,"size_id":1801,"color_id":null,"quantity":1},{"id":6191,"cart_id":381,"product_id":367,"size_id":1702,"color_id":null,"quantity":1},{"id":6192,"cart_id":381,"product_id":978,"size_id":2149,"color_id":null,"quantity":1},{"id":6193,"cart_id":381,"product_id":174,"size_id":1816,"color_id":null,"quantity":1},{"id":6194,"cart_id":381,"product_id":451,"size_id":1688,"color_id":null,"quantity":1}]},{"id":380,"user_id":null,"status":"On Way","notes":" ويفضل غداً اريده يوصل العصر ","full_name":"Wajal waleed ","governorate":"baghdad","city":"زيونة ","address":"شارع الربيعي ","closest_point":"مطعم فلافل لبنان ","phone_number":"07712241013","type":"home","created_at":"2024-10-05T18:45:33.498Z","coupon_id":5,"updated_at":"2024-10-05T19:02:53.108Z","items":[{"id":6185,"cart_id":380,"product_id":6008,"size_id":6035,"color_id":null,"quantity":1},{"id":6186,"cart_id":380,"product_id":1238,"size_id":3015,"color_id":null,"quantity":1},{"id":6187,"cart_id":380,"product_id":269,"size_id":344,"color_id":null,"quantity":1},{"id":6188,"cart_id":380,"product_id":933,"size_id":2097,"color_id":null,"quantity":2}]},{"id":379,"user_id":null,"status":"On Way","notes":"","full_name":"Baraa kh","governorate":"nineveh","city":"موصل ","address":"بعشيقه","closest_point":"سيطرة العزاوي","phone_number":"07507193378","type":"","created_at":"2024-10-05T18:31:42.814Z","coupon_id":null,"updated_at":"2024-10-05T18:42:19.431Z","items":[{"id":6182,"cart_id":379,"product_id":266,"size_id":1761,"color_id":null,"quantity":1},{"id":6183,"cart_id":379,"product_id":192,"size_id":1352,"color_id":null,"quantity":1},{"id":6184,"cart_id":379,"product_id":1241,"size_id":3018,"color_id":null,"quantity":1}]},{"id":378,"user_id":null,"status":"On Way","notes":"","full_name":"بتول","governorate":"basra","city":"البصره","address":"التنومه شارع ١٧","closest_point":"قرب مدرسه الصمود","phone_number":"٠٧٧٢١١٨٠٣١٧","type":"","created_at":"2024-10-05T15:49:51.969Z","coupon_id":null,"updated_at":"2024-10-05T17:11:24.673Z","items":[{"id":6180,"cart_id":378,"product_id":415,"size_id":1609,"color_id":null,"quantity":2},{"id":6181,"cart_id":378,"product_id":901,"size_id":2064,"color_id":null,"quantity":2}]},{"id":377,"user_id":null,"status":"On Way","notes":"","full_name":"Manar ","governorate":"baghdad","city":"الاعظمية","address":".","closest_point":"شارع عمر بن عبد العزيز قرب جامع احمد ياسين","phone_number":"07745196507","type":"home","created_at":"2024-10-05T13:50:55.992Z","coupon_id":5,"updated_at":"2024-10-05T14:55:04.078Z","items":[{"id":6176,"cart_id":377,"product_id":777,"size_id":1194,"color_id":null,"quantity":1},{"id":6177,"cart_id":377,"product_id":173,"size_id":1832,"color_id":null,"quantity":1},{"id":6178,"cart_id":377,"product_id":911,"size_id":2077,"color_id":null,"quantity":1},{"id":6179,"cart_id":377,"product_id":892,"size_id":2055,"color_id":null,"quantity":1}]},{"id":376,"user_id":null,"status":"On Way","notes":"","full_name":"مريم امين","governorate":"basra","city":"بصرة ","address":"بصرة حي الخضراء شارع المطاحن","closest_point":" الفرع الي قبل افران يوسف ","phone_number":"07826026951","type":"","created_at":"2024-10-05T13:25:36.002Z","coupon_id":5,"updated_at":"2024-10-05T15:02:16.113Z","items":[{"id":6171,"cart_id":376,"product_id":281,"size_id":1692,"color_id":null,"quantity":1},{"id":6172,"cart_id":376,"product_id":409,"size_id":1690,"color_id":null,"quantity":1},{"id":6173,"cart_id":376,"product_id":452,"size_id":1590,"color_id":null,"quantity":1},{"id":6174,"cart_id":376,"product_id":1239,"size_id":3016,"color_id":null,"quantity":1},{"id":6175,"cart_id":376,"product_id":326,"size_id":1612,"color_id":null,"quantity":1}]},{"id":375,"user_id":null,"status":"On Way","notes":"التوصيل ليلاً رجاءا","full_name":"يسر زهير","governorate":"baghdad","city":"شارع فلسطين","address":"حي المهندسين ","closest_point":"قرب حيدر ماركت","phone_number":"7857274710","type":"","created_at":"2024-10-05T13:22:56.741Z","coupon_id":null,"updated_at":"2024-10-05T15:13:54.412Z","items":[{"id":6167,"cart_id":375,"product_id":886,"size_id":2049,"color_id":null,"quantity":1},{"id":6168,"cart_id":375,"product_id":904,"size_id":2068,"color_id":null,"quantity":1},{"id":6169,"cart_id":375,"product_id":1016,"size_id":2186,"color_id":null,"quantity":1},{"id":6170,"cart_id":375,"product_id":1268,"size_id":3044,"color_id":null,"quantity":1}]}],"total":256,"page":1,"limit":10}
a product response may be:
{"products":[{"id":6016,"name":"test","description":"test","brand_id":86,"has_color":true,"has_size":false,"product_type":"color","price":0,"qty":0,"sold":0,"created_at":"2024-10-05T21:55:18.485Z","updated_at":"2024-10-05T21:55:18.485Z","categories":[{"id":178,"name":"Body Cleansers","main_category_id":2,"main_category_name":"Body Care"}],"colors":[{"id":12,"name":"red","price":30000,"qty":30,"sold":0,"has_size":false,"sizes":[],"images":[]}],"sizes":[],"images":[]}.
or like this:
{"product":{"id":6017,"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-10-05T22:04:30.971Z","updated_at":"2024-10-05T22:04:30.971Z","categories":[{"id":178,"name":"Body Cleansers","main_category_id":2,"main_category_name":"Body Care"}],"colors":[{"id":13,"name":"red","price":0,"qty":0,"sold":0,"has_size":true,"sizes":[{"id":6044,"name":"30ml","price":30000,"qty":30,"sold":0,"color_id":13,"images":[]}],"images":[]},{"id":14,"name":"green","price":50000,"qty":50,"sold":0,"has_size":false,"sizes":[],"images":[]}],"sizes":[],"images":[]}}
or like this:
{"product":{"id":6000,"name":"‏Shea Moisture Manuka Honey & Mafura Oil Intensive Hydration Hair Masque ","description":"ماسك الترطيب المكثف من شيا مويسجر.\nبخلاصة عسل المانوكا وزيت المافورا مع مستخلص التين الافريقي.\nماسك مليء بالمواد التي تغذي الشعر وترطبه بعمق لتجعل بصيلات الشعر اكثر صحةً و نعومة.\n-يمتلك عسل المانوكا خواص مهدئة ومرطبة لفروة الرأس.\n-اما زيت المافورا فهو يزود الشعر ب oleic acid الذي يعزز ترطيب الشعر.\n-والتين الافريقي يحتوي على فيتامين C و مضادات الاكسدة مما يمنح الشعر مظهراً حيوياً.","brand_id":248,"has_color":false,"has_size":true,"product_type":"size","price":0,"qty":0,"sold":0,"created_at":"2024-10-02T13:46:33.443Z","updated_at":"2024-10-05T17:18:49.183Z","categories":[{"id":5,"name":"Masks","main_category_id":3,"main_category_name":"Hair Care"}],"colors":[],"sizes":[{"id":6003,"name":"283 g","price":20000,"qty":34,"sold":0,"color_id":null,"images":[]}],"images":[{"id":6328,"url":"5033.jpeg","color_id":null,"size_id":null},{"id":6329,"url":"5034.jpeg","color_id":null,"size_id":null}]}}
or without colors or sizes...
Update orders page to handle colors and colors-sizes with their prices correctly...
// src/pages/orders/page.tsx

"use client";

import React, { useState, useEffect, useCallback, useRef } from "react";
import DefaultLayout from "@/components/Layouts/DefaultLayout";
import {
  Trash2,
  Search,
  ChevronDown,
  ChevronUp,
  ChevronLeft,
  ChevronRight,
  EyeOff,
  Eye,
} from "lucide-react";
import { toast, ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import Image from "next/image";
import { getToken } from "@/app/auth";
import LoadingSpinner from "@/components/LoadingSpinner";

// Base API URL
const API_BASE_URL = process.env.NEXT_PUBLIC_API;

// Interfaces

interface OrderItem {
  price: string;
  id: number;
  cart_id: number;
  product_id: number;
  size_id?: number | null;
  color_id?: number | null;
  quantity: number;
}

interface CartWithItems {
  id: number;
  user_id?: number | null;
  status: string;
  notes?: string;
  full_name?: string;
  governorate?: string;
  city?: string;
  address?: string;
  closest_point?: string;
  phone_number?: string;
  type?: string;
  created_at: string;
  coupon_id: number | null; // Added coupon_id
  coupon?: Coupon | null; // Optional coupon object
  updated_at: string;
  items: OrderItem[];
}

interface Product {
  id: number;
  name: string;
  description?: string;
  brand_id?: number;
  has_color: boolean;
  has_size: boolean;
  product_type: string;
  price: string;
  qty: number | null;
  created_at: string;
  updated_at: string;
  categories: Array<{ id: number; name: string }>;
  colors: Array<{ id: number; name: string }>;
  sizes: Array<{
    id: number;
    name: string;
    price: string;
    qty: number;
    color_id: number | null;
    images: string[];
  }>;
  images: Array<{
    id: number;
    url: string;
    color_id: number | null;
    size_id: number | null;
  }>;
}

interface Coupon {
  id: number;
  code: string;
  name: string;
  description: string;
  discount_amount: string | null;
  discount_percentage: string | null;
  start_date: string;
  end_date: string;
  usage_limit: number;
  min_purchase_amount: string;
  max_discount_amount: string | null;
  is_active: boolean;
  coupon_image: string;
  created_at: string;
  updated_at: string;
}

interface OrderDetails {
  totalPrice: number;
  discountedPrice: number;
  deliveryCost: number;
}

interface OrderDetailsProps {
  order: CartWithItems;
  onUpdateStatus: (orderId: number, newStatus: string) => void;
  onDeleteOrder: (orderId: number) => void;
  fetchProduct: (productId: number) => Promise<{ product: Product } | null>;
  fetchCoupon?: (couponId: number) => Promise<Coupon | null>;
  products: { [key: number]: Product };
  excludedItems: Set<number>; // Track excluded product IDs
  onToggleExclude: (orderId: number, productId: number) => void;
  isDeleting: boolean;
}

interface OrderItemProps {
  item: OrderItem;
  fetchProduct: (productId: number) => Promise<{ product: Product } | null>;
  product?: Product;
  isExcluded: boolean;
  onToggleExclude: () => void;
}

// Utility Functions

const formatPrice = (price: number) => {
  return `${price.toLocaleString()} IQD`;
};

const getStatusColor = (status: string) => {
  switch (status) {
    case "Pending":
      return "bg-orange-100 text-orange-800";
    case "On Way":
      return "bg-indigo-100 text-indigo-800";
    case "Ordered":
      return "bg-emerald-100 text-emerald-800";
    case "Rejected":
      return "bg-danger text-white"; // Retaining bg-danger as per user request
    default:
      return "bg-gray-100 text-gray-800";
  }
};

// Main Component

const OrdersPage: React.FC = () => {
  // State Variables
  const [orders, setOrders] = useState<CartWithItems[]>([]);
  const [products, setProducts] = useState<{ [key: number]: Product }>({});
  const productsRef = useRef<{ [key: number]: Product }>({});
  const [coupons, setCoupons] = useState<{ [key: number]: Coupon }>({});
  const [error, setError] = useState<string | null>(null);
  const [searchTerm, setSearchTerm] = useState("");
  const [currentPage, setCurrentPage] = useState(1);
  const ordersPerPage = 10;
  const [statusFilter, setStatusFilter] = useState<string>("all");
  const [sortOrder, setSortOrder] = useState<"asc" | "desc">("desc");
  const [isInitialLoading, setIsInitialLoading] = useState<boolean>(true);

  // Excluded Items State: { [orderId]: Set<productId> }
  const [excludedItems, setExcludedItems] = useState<{
    [key: number]: Set<number>;
  }>({});

  // Ref to track ongoing fetches to prevent duplicate requests
  const ongoingFetches = useRef<{
    [key: number]: Promise<{ product: Product } | null>;
  }>({});

  // State for pagination
  const [totalOrders, setTotalOrders] = useState(0);
  const totalPages = Math.ceil(totalOrders / ordersPerPage);

  // State to track deleting orders
  const [deletingOrders, setDeletingOrders] = useState<Set<number>>(new Set());

  // Sync productsRef with products state
  useEffect(() => {
    productsRef.current = products;
  }, [products]);

  // Fetch Coupon based on ID
  const fetchCoupon = useCallback(
    async (couponId: number): Promise<Coupon | null> => {
      try {
        const token = getToken(); // Retrieve the token from localStorage

        if (!token) {
          toast.error("You must be logged in.");
          return null;
        }

        const response = await fetch(`${API_BASE_URL}/coupons/${couponId}`, {
          headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${token}`, // Include the token here
          },
        });

        if (!response.ok) throw new Error("Failed to fetch coupon");
        const data: Coupon = await response.json();
        return data;
      } catch (error) {
        console.error(`Error fetching coupon ${couponId}:`, error);
        return null;
      }
    },
    [],
  );

  // Function to fetch all unique coupons
  const fetchAllCoupons = useCallback(
    async (couponIds: Set<number>) => {
      const fetchedCoupons: { [key: number]: Coupon } = {};

      await Promise.all(
        Array.from(couponIds).map(async (id) => {
          const coupon = await fetchCoupon(id);
          if (coupon) {
            fetchedCoupons[id] = coupon;
          }
        }),
      );

      setCoupons((prev) => ({ ...prev, ...fetchedCoupons }));
    },
    [fetchCoupon],
  );
  const fetchProduct = useCallback(
    async (productId: number): Promise<{ product: Product } | null> => {
      // Check if product is already fetched
      if (productsRef.current[productId]) {
        return { product: productsRef.current[productId] };
      }

      // Check if there's an ongoing fetch for this product
      if (await ongoingFetches.current[productId]) {
        return await ongoingFetches.current[productId];
      }

      // Start fetching the product and store the promise
      const fetchPromise = (async () => {
        try {
          const token = getToken();
          if (!token) {
            toast.error("You must be logged in.");
            return null;
          }
          const response = await fetch(
            `${API_BASE_URL}/products/${productId}`,
            {
              headers: {
                "Content-Type": "application/json",
                Authorization: `Bearer ${token}`,
              },
            },
          );
          if (!response.ok) throw new Error("Failed to fetch product");
          const data = await response.json();
          setProducts((prev) => ({
            ...prev,
            [productId]: data.product,
          }));
          return data;
        } catch (error) {
          console.error(`Error fetching product ${productId}:`, error);
          return null;
        } finally {
          // Remove the promise from ongoing fetches
          delete ongoingFetches.current[productId];
        }
      })();

      ongoingFetches.current[productId] = fetchPromise;
      return fetchPromise;
    },
    [],
  );

  // Fetch Orders with Pagination
  const fetchOrders = useCallback(async () => {
    try {
      const token = getToken(); // Retrieve the token from localStorage

      if (!token) {
        toast.error("You must be logged in.");
        setIsInitialLoading(false);
        return;
      }

      // Prepare query parameters
      const params = new URLSearchParams({
        page: currentPage.toString(),
        limit: ordersPerPage.toString(),
      });

      if (statusFilter !== "all") {
        params.append("status", statusFilter);
      }

      if (searchTerm) {
        params.append("search", searchTerm);
      }

      // Assuming the backend supports filtering and sorting via query params
      const response = await fetch(
        `${API_BASE_URL}/cart/all?${params.toString()}`,
        {
          headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${token}`, // Include the token here
          },
          cache: "no-cache",
        },
      );

      if (!response.ok) throw new Error("Failed to fetch orders");
      const data = await response.json();

      const { carts, total } = data as {
        carts: CartWithItems[];
        total: number;
      };

      setOrders(carts);
      setTotalOrders(total);

      // Extract unique coupon IDs
      const uniqueCouponIds = new Set<number>();
      carts.forEach((cart) => {
        if (cart.coupon_id !== null) {
          uniqueCouponIds.add(cart.coupon_id);
        }
      });

      // Fetch all unique coupons
      await fetchAllCoupons(uniqueCouponIds);

      setIsInitialLoading(false);
    } catch (error) {
      console.error("Error fetching orders:", error);
      setError("Failed to fetch orders. Please try again.");
      setIsInitialLoading(false);
    }
  }, [currentPage, ordersPerPage, statusFilter, searchTerm, fetchAllCoupons]);

  // Initial Fetch and Fetch on Dependency Changes
  useEffect(() => {
    setIsInitialLoading(true);
    fetchOrders();
  }, [fetchOrders]);

  // Fetch products for current orders (without duplications)
  useEffect(() => {
    const fetchProductsForCurrentOrders = async () => {
      const productIds = new Set(
        orders.flatMap((order) => order.items.map((item) => item.product_id)),
      );
      const fetchPromises: Promise<void>[] = [];

      productIds.forEach((productId) => {
        if (
          !productsRef.current[productId] &&
          !ongoingFetches.current[productId]
        ) {
          const promise = fetchProduct(productId).then(() => {});
          fetchPromises.push(promise);
        }
      });

      await Promise.all(fetchPromises);
    };

    fetchProductsForCurrentOrders();
  }, [orders, fetchProduct]);

  // Map coupons to orders
  useEffect(() => {
    setOrders((prevOrders) =>
      prevOrders.map((order) => ({
        ...order,
        coupon: order.coupon_id ? coupons[order.coupon_id] : null,
      })),
    );
  }, [coupons]);

  // Handle Reset Pagination on Filter/Search Change
  useEffect(() => {
    setCurrentPage(1);
  }, [searchTerm, statusFilter]);

  // Fetch Product based on ID

  // Update Order Status
  const handleUpdateStatus = useCallback(
    async (orderId: number, newStatus: string) => {
      const oldStatus =
        orders.find((order) => order.id === orderId)?.status || "";

      // Optimistically update the UI
      setOrders((prevOrders) =>
        prevOrders.map((order) =>
          order.id === orderId ? { ...order, status: newStatus } : order,
        ),
      );

      try {
        const token = getToken();
        if (!token) {
          toast.error("You must be logged in.");
          throw new Error("Not logged in");
        }

        const response = await fetch(`${API_BASE_URL}/cart/${orderId}`, {
          method: "PUT",
          headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${token}`,
          },
          body: JSON.stringify({ status: newStatus }),
        });

        const result = await response.json();
        if (!response.ok) {
          throw new Error(result.message);
        }

        toast.success(result.message);
      } catch (error) {
        console.error("Error updating order status:", error);
        // Revert the status if the update failed
        setOrders((prevOrders) =>
          prevOrders.map((order) =>
            order.id === orderId ? { ...order, status: oldStatus } : order,
          ),
        );
        toast.error("Failed to update order status. Please try again.");
      }
    },
    [orders],
  );

  // Optimistic Delete Order
  const handleDeleteOrder = useCallback(
    async (orderId: number) => {
      const isConfirmed = window.confirm(
        "Are you sure you want to delete this order?",
      );

      if (isConfirmed) {
        // Find the order to be deleted
        const orderToDelete = orders.find((order) => order.id === orderId);
        if (!orderToDelete) {
          toast.error("Order not found.");
          return;
        }

        // Optimistically remove the order from the UI
        setOrders((prevOrders) =>
          prevOrders.filter((order) => order.id !== orderId),
        );
        setTotalOrders((prevTotal) => prevTotal - 1);
        setDeletingOrders((prev) => new Set(prev).add(orderId));

        try {
          const token = getToken(); // Retrieve the token from localStorage
          if (!token) {
            throw new Error("You must be logged in.");
          }

          const response = await fetch(`${API_BASE_URL}/cart/${orderId}`, {
            method: "DELETE",
            headers: {
              "Content-Type": "application/json",
              Authorization: `Bearer ${token}`, // Include the token here
            },
          });
          const result = await response.json();
          if (!response.ok) {
            throw new Error(result.message || "Failed to delete order.");
          }

          // Optionally, display a success toast
          toast.success(result.message || "Order deleted successfully.");
        } catch (error) {
          console.error("Error deleting order:", error);
          // Restore the order in case of an error
          setOrders((prevOrders) => [orderToDelete, ...prevOrders]);
          setTotalOrders((prevTotal) => prevTotal + 1);
          toast.error(
            error instanceof Error
              ? error.message
              : "Failed to delete order. Please try again.",
          );
        } finally {
          setDeletingOrders((prev) => {
            const newSet = new Set(prev);
            newSet.delete(orderId);
            return newSet;
          });
        }
      }
    },
    [orders],
  );

  // Handler to toggle exclude for a product in an order
  const handleToggleExclude = useCallback(
    (orderId: number, productId: number) => {
      setExcludedItems((prev) => {
        const orderExcluded = new Set(prev[orderId] || []);
        if (orderExcluded.has(productId)) {
          orderExcluded.delete(productId);
        } else {
          orderExcluded.add(productId);
        }
        return { ...prev, [orderId]: orderExcluded };
      });
    },
    [],
  );

  // Pagination Controls
  const paginate = (pageNumber: number) => {
    setCurrentPage(Math.max(1, Math.min(pageNumber, totalPages)));
  };

  // Render
  return (
    <DefaultLayout>
      <div className="container mx-auto p-6">
        <h1 className="mb-6 text-3xl font-bold text-gray-800">Orders</h1>
        {/* Search and Filters */}
        <div className="mb-6 flex flex-col space-y-4 md:flex-row md:items-center md:justify-between md:space-y-0">
          <div className="flex items-center space-x-4">
            <div className="relative">
              <Search className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400" />
              <input
                type="text"
                placeholder="Search orders..."
                value={searchTerm}
                onChange={(e) => setSearchTerm(e.target.value)}
                className="w-64 rounded-md border border-gray-300 px-10 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-500"
              />
            </div>
            <select
              value={statusFilter}
              onChange={(e) => setStatusFilter(e.target.value)}
              className="rounded-md border border-gray-300 px-4 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-500"
            >
              <option value="all">All Statuses</option>
              <option value="Pending">Pending</option>
              <option value="On Way">On Way</option>
              <option value="Ordered">Ordered</option>
              <option value="Rejected">Rejected</option>
            </select>
            <select
              value={sortOrder}
              onChange={(e) => setSortOrder(e.target.value as "asc" | "desc")}
              className="rounded-md border border-gray-300 px-4 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-500"
            >
              <option value="desc">Newest First</option>
              <option value="asc">Oldest First</option>
            </select>
          </div>
        </div>

        {/* Orders List */}
        {isInitialLoading ? (
          <LoadingSpinner />
        ) : (
          <div className="space-y-6">
            {orders.length > 0 ? (
              orders.map((order) => (
                <OrderDetails
                  key={order.id}
                  order={order}
                  onUpdateStatus={handleUpdateStatus}
                  onDeleteOrder={handleDeleteOrder}
                  fetchProduct={fetchProduct}
                  products={products}
                  excludedItems={excludedItems[order.id] || new Set()}
                  onToggleExclude={handleToggleExclude}
                  isDeleting={deletingOrders.has(order.id)}
                />
              ))
            ) : (
              <p className="text-center text-gray-500">No orders found.</p>
            )}
          </div>
        )}

        {/* Pagination Controls */}
        {totalPages > 1 && !isInitialLoading && (
          <div className="mt-6 flex items-center justify-center space-x-2">
            <button
              onClick={() => paginate(currentPage - 1)}
              disabled={currentPage === 1}
              className={`rounded bg-gray-200 p-2 transition-colors hover:bg-gray-300 ${
                currentPage === 1 ? "cursor-not-allowed opacity-50" : ""
              }`}
            >
              <ChevronLeft size={20} />
            </button>
            <span className="text-gray-700">
              Page {currentPage} of {totalPages}
            </span>
            <button
              onClick={() => paginate(currentPage + 1)}
              disabled={currentPage === totalPages}
              className={`rounded bg-gray-200 p-2 transition-colors hover:bg-gray-300 ${
                currentPage === totalPages
                  ? "cursor-not-allowed opacity-50"
                  : ""
              }`}
            >
              <ChevronRight size={20} />
            </button>
          </div>
        )}
        <ToastContainer />
      </div>
    </DefaultLayout>
  );
};

// OrderDetails Component

const OrderDetails: React.FC<OrderDetailsProps> = React.memo(
  ({
    order,
    onUpdateStatus,
    onDeleteOrder,
    fetchProduct,
    products,
    excludedItems,
    onToggleExclude,
    isDeleting,
  }) => {
    const [isExpanded, setIsExpanded] = useState(false);
    const [orderDetails, setOrderDetails] = useState<OrderDetails>({
      totalPrice: 0,
      discountedPrice: 0,
      deliveryCost: 0,
    });

    useEffect(() => {
      const calculateOrderDetails = () => {
        let total = 0;
        for (const item of order.items) {
          if (excludedItems.has(item.product_id)) {
            continue; // Exclude this item
          }

          const product = products[item.product_id];
          if (!product) continue;

          const size = product.sizes.find((s) => s.id === item.size_id);
          const itemPrice = size
            ? parseFloat(size.price)
            : parseFloat(product.price);
          total += itemPrice * item.quantity;
        }

        let discountedPrice = total;

        if (order.coupon) {
          const minPurchase = parseFloat(order.coupon.min_purchase_amount);
          if (total >= minPurchase) {
            let discount = 0;
            if (order.coupon.discount_percentage) {
              const discountPerc = parseFloat(order.coupon.discount_percentage);
              if (!isNaN(discountPerc)) {
                discount = total * (discountPerc / 100);
              }
            } else if (order.coupon.discount_amount) {
              const discountAmt = parseFloat(order.coupon.discount_amount);
              if (!isNaN(discountAmt)) {
                discount = discountAmt;
              }
            }

            if (order.coupon.max_discount_amount) {
              const maxDiscount = parseFloat(order.coupon.max_discount_amount);
              if (!isNaN(maxDiscount)) {
                discount = Math.min(discount, maxDiscount);
              }
            }

            discountedPrice = total - discount;
          } else {
            // If total is less than min_purchase_amount, no discount
            discountedPrice = total;
          }
        }

        const deliveryCost =
          total >= 100000 ||
          (order.governorate && order.governorate.toLowerCase() === "karbala")
            ? 0
            : 5000;

        setOrderDetails({ totalPrice: total, discountedPrice, deliveryCost });
      };

      calculateOrderDetails();
    }, [order, products, excludedItems]);

    const finalTotal = orderDetails.discountedPrice + orderDetails.deliveryCost;

    const handleStatusChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
      const newStatus = e.target.value;
      onUpdateStatus(order.id, newStatus);
    };

    return (
      <div className="rounded-lg bg-white p-6 shadow-md transition-transform hover:scale-105">
        {/* Order Header */}
        <div className="mb-4 flex items-center justify-between">
          <h2 className="text-xl font-semibold">Order #{order.id}</h2>
          <div className="flex items-center space-x-2">
            <select
              value={order.status}
              onChange={handleStatusChange}
              className={`rounded px-2 py-1 text-sm ${getStatusColor(
                order.status,
              )}`}
              disabled={isDeleting}
            >
              <option value="Pending">Pending</option>
              <option value="On Way">On Way</option>
              <option value="Ordered">Ordered</option>
              <option value="Rejected">Rejected</option>
            </select>
            <button
              onClick={() => onDeleteOrder(order.id)}
              className={`rounded bg-red p-1 text-white transition-colors hover:bg-danger ${
                isDeleting ? "cursor-not-allowed opacity-50" : ""
              }`}
              disabled={isDeleting}
            >
              {isDeleting ? <LoadingSpinner /> : <Trash2 size={16} />}
            </button>
          </div>
        </div>

        {/* Order Information */}
        <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
          <div>
            <p className="text-gray-700">
              <strong>Customer Name:</strong> {order.full_name || "N/A"}
            </p>
            <p className="text-gray-700">
              <strong>Status:</strong>{" "}
              <span
                className={`rounded px-2 py-1 text-sm ${getStatusColor(
                  order.status,
                )}`}
              >
                {order.status}
              </span>
            </p>
            <p className="text-gray-700">
              <strong>Created At:</strong>{" "}
              {new Date(order.created_at).toLocaleString()}
            </p>
            {/* Additional Information */}
            <p className="capitalize text-gray-700">
              <strong>Place:</strong> {order.type || "N/A"}
            </p>
            <p className="text-gray-700">
              <strong>Delivery Instructions:</strong> {order.notes || "N/A"}
            </p>
          </div>
          <div>
            <p className="text-gray-700">
              <strong>Address:</strong> {order.address || "N/A"}
            </p>
            <p className="text-gray-700">
              <strong>Closest Point:</strong> {order.closest_point || "N/A"}
            </p>
            <p className="text-gray-700">
              <strong>Phone Number:</strong> {order.phone_number || "N/A"}
            </p>
            <p className="text-gray-700">
              <strong>Governorate:</strong> {order.governorate || "N/A"}
            </p>
          </div>
        </div>

        {/* Items Toggle */}
        <div className="mt-4">
          <button
            onClick={() => setIsExpanded(!isExpanded)}
            className="flex items-center text-blue-500 hover:text-blue-700 focus:outline-none"
          >
            <h3 className="mr-2 text-lg font-semibold">Items:</h3>
            {isExpanded ? <ChevronUp size={20} /> : <ChevronDown size={20} />}
          </button>
          {isExpanded && (
            <ul className="mt-2 space-y-4">
              {order.items.map((item) => (
                <OrderItem
                  key={item.id}
                  item={item}
                  fetchProduct={fetchProduct}
                  product={products[item.product_id]}
                  isExcluded={excludedItems.has(item.product_id)}
                  onToggleExclude={() =>
                    onToggleExclude(order.id, item.product_id)
                  }
                />
              ))}
            </ul>
          )}
        </div>

        {/* Pricing Summary */}
        <div className="mt-4 border-t border-gray-200 pt-4">
          <div className="flex justify-between text-gray-700">
            <span>Total Price:</span>
            <span>{formatPrice(orderDetails.totalPrice)}</span>
          </div>
          {order.coupon && (
            <div className="flex justify-between text-gray-700">
              <span>Coupon Applied:</span>
              <span>
                {order.coupon.code} ({order.coupon.name})
              </span>
            </div>
          )}
          <div className="flex justify-between text-gray-700">
            <span>Delivery Cost:</span>
            <span>
              {orderDetails.deliveryCost === 0
                ? "Free"
                : formatPrice(orderDetails.deliveryCost)}
            </span>
          </div>
          <div className="flex justify-between text-xl font-bold">
            <span>Final Total:</span>
            <span>{formatPrice(finalTotal)}</span>
          </div>
          {order.coupon &&
            orderDetails.discountedPrice !== orderDetails.totalPrice && (
              <div className="mt-2 flex justify-between text-green-600">
                <span>Discount Applied:</span>
                <span>
                  -
                  {formatPrice(
                    orderDetails.totalPrice - orderDetails.discountedPrice,
                  )}
                </span>
              </div>
            )}
          <div
            className={`mt-4 rounded bg-red p-4 text-white ${
              excludedItems.size > 0 ? "opacity-100" : "opacity-0"
            }`}
          >
            <p>
              <strong>Warning:</strong> You have excluded {excludedItems.size}{" "}
              product{excludedItems.size > 1 ? "s" : ""} from this order. The
              total price has been adjusted accordingly. You can re-include them
              if needed.
            </p>
          </div>
        </div>
      </div>
    );
  },
);

OrderDetails.displayName = "OrderDetails";

// OrderItem Component

const OrderItem: React.FC<OrderItemProps> = React.memo(
  ({
    item,
    fetchProduct,
    product: initialProduct,
    isExcluded,
    onToggleExclude,
  }) => {
    const product = initialProduct || null;
    const [isLoading, setIsLoading] = useState(!product);

    useEffect(() => {
      let isMounted = true;

      if (!product) {
        setIsLoading(true);
        fetchProduct(item.product_id).then((data) => {
          if (data && data.product && isMounted) {
            // Product is already added to the cache in fetchProduct
          }
          if (isMounted) setIsLoading(false);
        });
      }

      return () => {
        isMounted = false;
      };
    }, [item.product_id, fetchProduct, product]);

    if (isLoading) {
      return (
        <li className="flex animate-pulse items-center space-x-4 rounded-md bg-gray-50 p-4">
          <div className="h-16 w-16 flex-shrink-0 rounded-md bg-gray-200"></div>
          <div className="flex-grow space-y-2">
            <div className="h-4 w-3/4 rounded bg-gray-200"></div>
            <div className="h-3 w-1/2 rounded bg-gray-200"></div>
            <div className="h-3 w-1/3 rounded bg-gray-200"></div>
          </div>
          <button onClick={onToggleExclude} className="ml-4">
            <span className="sr-only">Toggle Exclude</span>
            {isExcluded ? (
              <Eye size={20} color="#d32f2f" /> // bg-danger color
            ) : (
              <EyeOff size={20} color="#d32f2f" />
            )}
          </button>
        </li>
      );
    }

    if (!product) {
      return <li className="text-red-500">Error loading product.</li>;
    }

    const size = product.sizes.find((s) => s.id === item.size_id);
    const color = product.colors.find((c) => c.id === item.color_id);
    const itemPrice = size ? parseFloat(size.price) : parseFloat(product.price);
    const totalItemPrice = itemPrice * item.quantity;

    const image =
      product.images.find(
        (img) =>
          (img.size_id === item.size_id || img.color_id === item.color_id) &&
          (img.size_id === null || img.color_id === null),
      ) || product.images[0];

    return (
      <li className="flex items-center space-x-4 rounded-md bg-gray-50 p-4">
        <div
          className={`h-16 w-16 flex-shrink-0 overflow-hidden rounded-md border ${
            isExcluded ? "border-red-400" : "border-gray-200"
          }`}
        >
          {image ? (
            <Image
              src={`https://storage.naayiq.com/resources/${image.url}`}
              alt={product.name}
              width={64}
              height={64}
              className={`h-full w-full object-cover object-center ${
                isExcluded ? "opacity-50 grayscale" : ""
              }`}
              loading="lazy"
            />
          ) : (
            <div className="flex h-full w-full items-center justify-center bg-gray-100 text-gray-400">
              No image
            </div>
          )}
        </div>
        <div className="flex-grow">
          <div className="flex items-center justify-between">
            <h4 className="font-medium text-gray-800">{product.name}</h4>
            <button onClick={onToggleExclude} className="ml-4">
              <span className="sr-only">Toggle Exclude</span>
              {isExcluded ? (
                <Eye size={20} color="#d32f2f" /> // bg-danger color
              ) : (
                <EyeOff size={20} color="#d32f2f" />
              )}
            </button>
          </div>
          <p className="text-sm text-gray-500">
            {size && `Size: ${size.name}`} {color && `| Color: ${color.name}`}
          </p>
          <p className="text-sm text-gray-600">
            {item.quantity} x {formatPrice(itemPrice)} ={" "}
            {formatPrice(totalItemPrice)}
          </p>
          {isExcluded && (
            <p className="text-red-500 text-xs italic">Excluded from total</p>
          )}
        </div>
      </li>
    );
  },
);

OrderItem.displayName = "OrderItem";

export default OrdersPage;