All files / src/components/features/cart/CartSidebarModal index.tsx

16.12% Statements 20/124
100% Branches 0/0
0% Functions 0/1
16.12% Lines 20/124

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 1251x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                                                                                                                                                                                                                 1x 1x  
"use client";
import React, { useEffect } from "react";
import { usePathname } from "next/navigation";
 
import { useCartModalContext } from "@/contexts";
import {
  removeItemFromCart,
  selectTotalPrice } from "@/redux/features/cartSlice";
import { useAppSelector } from "@/redux/store";
import { useSelector } from "react-redux";
import SingleItem from "./SingleItem";
import Link from "next/link";
import EmptyCart from "./EmptyCart";
import { Icon } from "@/components/ui/icons";
import { Button } from "@/components/ui";
import { formatCurrency } from "@/lib/core";
 
const CartSidebarModal = () => {
  const { isCartModalOpen, closeCartModal } = useCartModalContext();
  const cartItems = useAppSelector((state) => state.cartReducer.items);
  const pathname = usePathname();

  const totalPrice = useSelector(selectTotalPrice);

  // Close modal on route change
  useEffect(() => {
    if (isCartModalOpen) {
      closeCartModal();
    }
  }, [pathname]); // eslint-disable-line react-hooks/exhaustive-deps

  useEffect(() => {
    // closing modal while clicking outside
    function handleClickOutside(event: MouseEvent) {
      if (event.target && !(event.target as HTMLElement).closest(".modal-content")) {
        closeCartModal();
      }
    }

    if (isCartModalOpen) {
      document.addEventListener("mousedown", handleClickOutside);
    }

    return () => {
      document.removeEventListener("mousedown", handleClickOutside);
    };
  }, [isCartModalOpen, closeCartModal]);

  return (
    <div
      className={`fixed top-0 left-0 z-99999 overflow-y-auto no-scrollbar w-full h-screen bg-dark/70 ease-linear duration-300 ${
        isCartModalOpen ? "translate-x-0" : "translate-x-full"
      }`}
      role="dialog"
      aria-modal="true"
      aria-label="Shopping cart"
      data-testid="cart-sidebar"
    >
      <div className="flex items-center justify-end">
        <div className="w-full max-w-[500px] shadow-1 bg-white dark:bg-gray-800 px-4 sm:px-7.5 lg:px-11 relative modal-content">
          <div className="sticky top-0 z-10 bg-white dark:bg-gray-800 flex items-center justify-between pb-7 pt-4 sm:pt-7.5 lg:pt-11 border-b border-gray-3 dark:border-gray-700 mb-7.5">
            <h2 className="font-medium text-dark dark:text-gray-100 text-lg sm:text-2xl">
              Cart View
            </h2>
            <Button
              onClick={() => closeCartModal()}
              aria-label="Close cart"
              variant="ghost"
              size="sm"
              className="flex items-center justify-center ease-in duration-150 bg-meta text-dark-5 dark:text-gray-400 hover:text-dark dark:hover:text-gray-200"
            >
              <Icon name="x-circle" size={30} />
            </Button>
          </div>

          <div className="h-[66vh] overflow-y-auto no-scrollbar">
            <div className="flex flex-col">
              {/* <!-- cart item --> */}
              {cartItems.length > 0 ? (
                cartItems.map((item, key) => (
                  <SingleItem
                    key={key}
                    item={item}
                    removeItemFromCart={removeItemFromCart}
                  />
                ))
              ) : (
                <EmptyCart />
              )}
            </div>
          </div>

          <div className="border-t border-gray-3 dark:border-gray-700 bg-white dark:bg-gray-800 pt-5 pb-4 sm:pb-7.5 lg:pb-11 mt-7.5 sticky bottom-0 z-10">
            <div className="flex items-center justify-between gap-5 mb-6">
              <p className="font-medium text-xl text-dark dark:text-gray-100">Subtotal:</p>

              <p className="font-medium text-xl text-dark dark:text-gray-100">{formatCurrency(totalPrice)}</p>
            </div>

            <div className="flex items-center gap-4">
              <Link
                onClick={() => closeCartModal()}
                href="/cart"
                className="w-full flex justify-center font-medium text-white bg-blue py-[13px] px-6 rounded-md ease-out duration-200 hover:bg-blue-dark"
              >
                View Cart
              </Link>

              <Link
                onClick={() => closeCartModal()}
                href="/checkout"
                className="w-full flex justify-center font-medium text-white bg-dark py-[13px] px-6 rounded-md ease-out duration-200 hover:bg-opacity-95"
              >
                Checkout
              </Link>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};
 
export default CartSidebarModal;