Make the search more stable...
improve pagination to include latest page as well... (improve its overall design as well)
include the total product with good ui...
Ensures good ui/ux practices are applied throughout the page...
improve font family, font size and colors...
you can use libraries if u want to... I'm using nextjs app router 14 and tailwind css.
Finally, make the background like this animation:
css:
@tailwind base;
@tailwind components;
@tailwind utilities;

/*Start Animations*/
@-webkit-keyframes animatetop {
	from {
		top: -300px;
		opacity: 0;
	}
	to {
		top: 0;
		opacity: 1;
	}
}
@keyframes animatetop {
	from {
		top: -300px;
		opacity: 0;
	}
	to {
		top: 0;
		opacity: 1;
	}
}
@-webkit-keyframes zoomIn {
	0% {
		opacity: 0;
		-webkit-transform: scale3d(0.3, 0.3, 0.3);
		transform: scale3d(0.3, 0.3, 0.3);
	}
	50% {
		opacity: 1;
	}
}
@keyframes zoomIn {
	0% {
		opacity: 0;
		-webkit-transform: scale3d(0.3, 0.3, 0.3);
		transform: scale3d(0.3, 0.3, 0.3);
	}
	50% {
		opacity: 1;
	}
}
/*End Animations*/
/*
-- Start BackGround Animation 
*/
.area {
	background: #4e54c8;
	background: -webkit-linear-gradient(to left, #8f94fb, #4e54c8);
	width: 100%;
	height: 100vh;
	position: absolute;
	z-index: -1;
}

.circles {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 96%;
	overflow: hidden;
}

.circles li {
	position: absolute;
	display: block;
	list-style: none;
	width: 20px;
	height: 20px;
	background: rgba(255, 255, 255, 0.2);
	animation: animate 25s linear infinite;
	bottom: -150px;
}

.circles li:nth-child(1) {
	left: 25%;
	width: 80px;
	height: 80px;
	animation-delay: 0s;
}

.circles li:nth-child(2) {
	left: 10%;
	width: 20px;
	height: 20px;
	animation-delay: 2s;
	animation-duration: 12s;
}

.circles li:nth-child(3) {
	left: 70%;
	width: 20px;
	height: 20px;
	animation-delay: 4s;
}

.circles li:nth-child(4) {
	left: 40%;
	width: 60px;
	height: 60px;
	animation-delay: 0s;
	animation-duration: 18s;
}

.circles li:nth-child(5) {
	left: 65%;
	width: 20px;
	height: 20px;
	animation-delay: 0s;
}

.circles li:nth-child(6) {
	left: 75%;
	width: 110px;
	height: 110px;
	animation-delay: 3s;
}

.circles li:nth-child(7) {
	left: 35%;
	width: 150px;
	height: 150px;
	animation-delay: 7s;
}

.circles li:nth-child(8) {
	left: 50%;
	width: 25px;
	height: 25px;
	animation-delay: 15s;
	animation-duration: 45s;
}

.circles li:nth-child(9) {
	left: 20%;
	width: 15px;
	height: 15px;
	animation-delay: 2s;
	animation-duration: 35s;
}

.circles li:nth-child(10) {
	left: 85%;
	width: 150px;
	height: 150px;
	animation-delay: 0s;
	animation-duration: 11s;
}

@keyframes animate {
	0% {
		transform: translateY(0) rotate(0deg);
		opacity: 1;
		border-radius: 0;
	}

	100% {
		transform: translateY(-1000px) rotate(720deg);
		opacity: 0;
		border-radius: 50%;
	}
}
/*
-- End BackGround Animation 
*/
html:
	<!--Start Background Animation Body-->
		<div class="area">
			<ul class="circles">
				<li></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
			</ul>
		</div>
		<!--End Background Animation Body-->

I don't care how you do it, but I just want the same animation as above.
ProductsPage.jsx:
// 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 } 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" });
  }, []);

  // @ts-ignore
  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)}
        />
      )}

      {/* Edit Product Dialog */}
      {isEditProductDialogOpen && productToEdit && (
        <EditProduct
          isOpen={isEditProductDialogOpen}
          onClose={() => {
            setIsEditProductDialogOpen(false);
            setProductToEdit(null);
            fetchProducts(); // Refresh the product list after editing
          }}
          // @ts-ignore
          product={productToEdit}
        />
      )}

      {/* 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);

layout.js:
"use client";
import "jsvectormap/dist/jsvectormap.css";
import "flatpickr/dist/flatpickr.min.css";
import "@/css/satoshi.css";
import "@/css/style.css";
import React, { useEffect, useState } from "react";
import Loader from "@/components/common/Loader";
import AdminOnly from "@/components/AdminOnly";

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  const [sidebarOpen, setSidebarOpen] = useState(false);
  const [loading, setLoading] = useState<boolean>(true);

  useEffect(() => {
    setTimeout(() => setLoading(false), 1000);
  }, []);

  return (
    <html lang="en">
      <body suppressHydrationWarning={true}>
        <div className="dark:bg-boxdark-2 dark:text-bodydark">
          <AdminOnly />
          {loading ? <Loader /> : children}
        </div>
      </body>
    </html>
  );
}

DefaultLayout.tsx:
"use client";
import React, { useState } from "react";
import Sidebar from "@/components/Sidebar";
import Header from "@/components/Header";

export default function DefaultLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  const [sidebarOpen, setSidebarOpen] = useState(false);

  return (
    <>
      {/* <!-- ===== Page Wrapper Start ===== --> */}
      <div className="flex">
        {/* <!-- ===== Sidebar Start ===== --> */}
        <Sidebar sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
        {/* <!-- ===== Sidebar End ===== --> */}

        {/* <!-- ===== Content Area Start ===== --> */}
        <div className="relative flex flex-1 flex-col lg:ml-72.5">
          {/* <!-- ===== Header Start ===== --> */}
          <Header sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
          {/* <!-- ===== Header End ===== --> */}

          {/* <!-- ===== Main Content Start ===== --> */}
          <main>
            <div className="mx-auto max-w-screen-2xl p-4 md:p-6 2xl:p-10">
              {children}
            </div>
          </main>
          {/* <!-- ===== Main Content End ===== --> */}
        </div>
        {/* <!-- ===== Content Area End ===== --> */}
      </div>
      {/* <!-- ===== Page Wrapper End ===== --> */}
    </>
  );
}
style.css:
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap");

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
    body {
        @apply relative z-1 bg-whiten font-satoshi text-base font-normal text-body;
    }
}

@layer components {
}

@layer utilities {
    /* Chrome, Safari and Opera */
    .no-scrollbar::-webkit-scrollbar {
        display: none;
    }

    .no-scrollbar {
        -ms-overflow-style: none; /* IE and Edge */
        scrollbar-width: none; /* Firefox */
    }

    .chat-height {
        @apply h-[calc(100vh_-_8.125rem)] lg:h-[calc(100vh_-_5.625rem)];
    }

    .inbox-height {
        @apply h-[calc(100vh_-_8.125rem)] lg:h-[calc(100vh_-_5.625rem)];
    }
}

/* third-party libraries CSS */

.tableCheckbox:checked ~ div span {
    @apply opacity-100;
}

.tableCheckbox:checked ~ div {
    @apply border-primary bg-primary;
}

.apexcharts-legend-text {
    @apply !text-body dark:!text-bodydark;
}

.apexcharts-text {
    @apply !fill-body dark:!fill-bodydark;
}

.apexcharts-xcrosshairs {
    @apply !fill-stroke dark:!fill-strokedark;
}

.apexcharts-gridline {
    @apply !stroke-stroke dark:!stroke-strokedark;
}

.apexcharts-series.apexcharts-pie-series path {
    @apply dark:!stroke-transparent;
}

.apexcharts-legend-series {
    @apply !inline-flex gap-1.5;
}

.apexcharts-tooltip.apexcharts-theme-light {
    @apply dark:!border-strokedark dark:!bg-boxdark;
}

.apexcharts-tooltip.apexcharts-theme-light .apexcharts-tooltip-title {
    @apply dark:!border-strokedark dark:!bg-meta-4;
}

.apexcharts-xaxistooltip,
.apexcharts-yaxistooltip {
    @apply dark:!border-meta-4 dark:!bg-meta-4 dark:!text-bodydark1;
}







.flatpickr-wrapper {
    @apply w-full;
}

.flatpickr-months .flatpickr-prev-month:hover svg,
.flatpickr-months .flatpickr-next-month:hover svg {
    @apply !fill-primary;
}

.flatpickr-calendar.arrowTop:before {
    @apply dark:!border-b-boxdark;
}

.flatpickr-calendar.arrowTop:after {
    @apply dark:!border-b-boxdark;
}

.flatpickr-calendar {
    @apply !p-6 dark:!bg-boxdark dark:!text-bodydark dark:!shadow-8 2xsm:!w-auto;
}

.flatpickr-day {
    @apply dark:!text-bodydark dark:hover:!border-meta-4 dark:hover:!bg-meta-4;
}

.flatpickr-months .flatpickr-prev-month,
.flatpickr-months .flatpickr-next-month {
    @apply !top-7 dark:!fill-white dark:!text-white;
}

.flatpickr-months .flatpickr-prev-month.flatpickr-prev-month,
.flatpickr-months .flatpickr-next-month.flatpickr-prev-month {
    @apply !left-7;
}

.flatpickr-months .flatpickr-prev-month.flatpickr-next-month,
.flatpickr-months .flatpickr-next-month.flatpickr-next-month {
    @apply !right-7;
}

span.flatpickr-weekday,
.flatpickr-months .flatpickr-month {
    @apply dark:!fill-white dark:!text-white;
}

.flatpickr-day.inRange {
    box-shadow: -5px 0 0 #f3f4f6, 5px 0 0 #f3f4f6 !important;
    @apply dark:!shadow-7;
}

.flatpickr-day.inRange,
.flatpickr-day.prevMonthDay.inRange,
.flatpickr-day.nextMonthDay.inRange,
.flatpickr-day.today.inRange,
.flatpickr-day.prevMonthDay.today.inRange,
.flatpickr-day.nextMonthDay.today.inRange,
.flatpickr-day:hover,
.flatpickr-day.prevMonthDay:hover,
.flatpickr-day.nextMonthDay:hover,
.flatpickr-day:focus,
.flatpickr-day.prevMonthDay:focus,
.flatpickr-day.nextMonthDay:focus {
    @apply !border-[#F3F4F6] !bg-[#F3F4F6] dark:!border-meta-4 dark:!bg-meta-4;
}

.flatpickr-day.selected,
.flatpickr-day.startRange,
.flatpickr-day.selected,
.flatpickr-day.endRange {
    @apply dark:!text-white;
}

.flatpickr-day.selected,
.flatpickr-day.startRange,
.flatpickr-day.endRange,
.flatpickr-day.selected.inRange,
.flatpickr-day.startRange.inRange,
.flatpickr-day.endRange.inRange,
.flatpickr-day.selected:focus,
.flatpickr-day.startRange:focus,
.flatpickr-day.endRange:focus,
.flatpickr-day.selected:hover,
.flatpickr-day.startRange:hover,
.flatpickr-day.endRange:hover,
.flatpickr-day.selected.prevMonthDay,
.flatpickr-day.startRange.prevMonthDay,
.flatpickr-day.endRange.prevMonthDay,
.flatpickr-day.selected.nextMonthDay,
.flatpickr-day.startRange.nextMonthDay,
.flatpickr-day.endRange.nextMonthDay {
    background: #3c50e0;
    @apply !border-primary !bg-primary hover:!border-primary hover:!bg-primary;
}

.flatpickr-day.selected.startRange + .endRange:not(:nth-child(7n + 1)),
.flatpickr-day.startRange.startRange + .endRange:not(:nth-child(7n + 1)),
.flatpickr-day.endRange.startRange + .endRange:not(:nth-child(7n + 1)) {
    box-shadow: -10px 0 0 #3c50e0;
}

.map-btn .jvm-zoom-btn {
    @apply flex h-7.5 w-7.5 items-center justify-center rounded border border-stroke bg-white px-0 pb-0.5 pt-0 text-2xl leading-none text-body hover:border-primary hover:bg-primary hover:text-white dark:border-strokedark dark:bg-meta-4 dark:text-bodydark dark:hover:border-primary dark:hover:bg-primary dark:hover:text-white;
}

.mapOne .jvm-zoom-btn {
    @apply !bottom-0 !left-auto !top-auto;
}

.mapOne .jvm-zoom-btn.jvm-zoomin {
    @apply !right-10;
}

.mapOne .jvm-zoom-btn.jvm-zoomout {
    @apply !right-0;
}

.taskCheckbox:checked ~ .box span {
    @apply opacity-100;
}

.taskCheckbox:checked ~ p {
    @apply line-through;
}

.taskCheckbox:checked ~ .box {
    @apply border-primary bg-primary dark:border-primary;
}

.custom-input-date::-webkit-calendar-picker-indicator {
    background: transparent;
}

input[type="search"]::-webkit-search-cancel-button {
    @apply appearance-none;
}

.custom-input-date::-webkit-calendar-picker-indicator {
    background-position: center;
    background-repeat: no-repeat;
    background-size: 20px;
}

[x-cloak] {
    display: none !important;
}