Viewing File: /home/ubuntu/misabloom-frontend-base/src/components/Product/SingleProductIndex.jsx

import React, { useState, useEffect } from "react";
import {
  Container,
  Image,
  Button,
  Row,
  Col,
  ProgressBar,
  Nav,
  Tab,
  Tooltip,
  OverlayTrigger,
} from "react-bootstrap";
import { Link, useParams, useNavigate } from "react-router-dom";
import "./Product.css";
import ImageGallery from "react-image-gallery";
import NumericInput from "react-numeric-input";
import TopSellingProductIndex from "./TopSellingProductIndex";
import { withTranslation, useTranslation } from "react-multi-lang";
import CustomerReviewIndex from "../landingPage/CustomerReviewIndex";
import WriteReviewModal from "./WriteReviewModal";
import { connect } from "react-redux";
import {
  fetchMoreProductReviewListStart,
  fetchProductListStart,
  fetchProductReviewListStart,
  fetchSingleProductStart,
  saveWishlistsStart,
} from "../store/actions/ProductAction";
import SomethingWrong from "../Helper/SomethingWrong";
import NoDataFound from "../Helper/NoDataFound";
import CommonCenterLoader from "../Helper/CommonCenterLoader";
import {
  saveCartDetailsStart,
  guestCartList,
} from "../store/actions/CartsAction";
import ReactStars from "react-rating-stars-component";
import Skeleton from "react-loading-skeleton";
import "react-loading-skeleton/dist/skeleton.css";
import NoReviewsFound from "../Helper/NoReviewsFound";
import ThcProgress from "./ThcProgress";
import CbdProgress from "./CbdProgress";
import Breadcrumb from 'react-bootstrap/Breadcrumb';

const SingleProductIndex = (props) => {
  const navigate = useNavigate();
  const t = useTranslation();
  const params = useParams();
  const { singleProduct, productReviews } = props;
  const [isCarted, setIsCarted] = useState(false);
  const [isWishlisted, setIsWishlisted] = useState(false);
  const [skipRender, setSkipRender] = useState(true);
  const [clamped, setClamped] = useState(true);
  const [showButton, setShowButton] = useState(true);
  const handleClick = () => setClamped(!clamped);
  useEffect(() => {
    window.scrollTo(0, 0);
    props.dispatch(
      fetchSingleProductStart({ product_unique_id: params.productUniqueId })
    );
    props.dispatch(
      fetchProductReviewListStart({
        product_unique_id: params.productUniqueId,
        skip: 0,
        take: 12,
      })
    );
    props.dispatch(
      fetchProductListStart({
        order_by: "newest",
        skip: 0,
        take: 9,
      })
    );
  }, [params.productUniqueId]);

  useEffect(() => {
    if (
      !skipRender &&
      !singleProduct.loading &&
      Object.keys(singleProduct.data).length > 0
    ) {
      setIsWishlisted(singleProduct.data.product.is_wishlisted ? true : false);
      if (
        props.guestCartList.filter(
          (product) =>
            product.product_id === singleProduct.data.product.product_id
        ).length > 0
      )
        setIsCarted(true);
    }
    setSkipRender(false);
  }, [singleProduct]);

  const [writeReview, setWriteReview] = useState(false);

  const closeWriteReviewModal = () => {
    setWriteReview(false);
  };

  const onCartClick = (e) => {
    e.preventDefault();
    //User Add to cart
    if (singleProduct.data.product.is_carted === 0) {
      props.dispatch(
        saveCartDetailsStart({
          product_id: singleProduct.data.product.product_id,
          quantity: 1,
        })
      );
    } else {
      navigate("/cart");
    }
  };

  const onGuestCartClick = (e) => {
    e.preventDefault();
    if (!isCarted) {
      const cartProduct = {
        product_id: singleProduct.data.product.product_id,
        quantity: 1,
      };
      let cartItems = [...props.guestCartList, cartProduct];
      localStorage.setItem("carts", JSON.stringify(cartItems));
      props.dispatch(guestCartList(cartItems));
      setIsCarted(true);
    } else {
      navigate("/cart");
    }
  };

  const wishListToggle = () => {
    if (Object.keys(props.profile.data).length > 0) {
      props.dispatch(
        saveWishlistsStart({
          product_unique_id: singleProduct.data.product.product_unique_id,
        })
      );
    } else {
      localStorage.setItem("product", params.productUniqueId);
      navigate("/login");
    }
  };

  const loadMoreReview = () => {
    props.dispatch(
      fetchMoreProductReviewListStart({
        product_unique_id: params.productUniqueId,
        skip: productReviews.data.reviews.length,
        take: 12,
      })
    );
  };

  return (
    <>
      {singleProduct.loading ? (
        <div className="single-product-sec">
          <Container>
            <Row>
              <Col md={6}>
                <Skeleton className="product-image-loader" />
              </Col>
              <Col md={6}>
                <Skeleton height={100} />
                <Skeleton count={2} width={300} />
                <Skeleton count={4} />
                <Skeleton height={200} />
              </Col>
            </Row>
          </Container>
        </div>
      ) : Object.keys(singleProduct.data).length > 0 &&
        singleProduct.data.product &&
        Object.keys(singleProduct.data.product).length > 0 ? (
        <>
          <div className="single-product-sec">
            <Container>
              <Row>
                <Breadcrumb>
                  <Link to="/" className="breadcrumb-item">Home</Link>
                  <Link to="/shop" className="breadcrumb-item">Shop</Link>
                  {/* <Link to={`/shop?category_id=${category.category_id}`} className="breadcrumb-item">
                    {singleProduct.data.product.category_name}
                  </Link> */}
                  <Link to="/" className="breadcrumb-item active">
                    {props.singleProduct.data.product.name}
                  </Link>
                </Breadcrumb>
                <Col md={6}>
                  <div className="single-product-full-img-sec">
                    <ImageGallery
                      items={singleProduct.data.product.product_files}
                    />
                  </div>
                </Col>
                <Col md={6}>
                  <div className="single-product-info-sec">
                    <div className="">
                      <h4>{props.singleProduct.data.product.name}</h4>
                    </div>
                    <div className="single-product-review-card">
                      <ReactStars
                        count={5}
                        value={props.singleProduct.data.product.review_stars}
                        size={24}
                        isHalf={true}
                        edit={false}
                        emptyIcon={<i className="far fa-star"></i>}
                        halfIcon={<i className="fa fa-star-half-alt"></i>}
                        fullIcon={<i className="fa fa-star"></i>}
                        activeColor="#ffd700"
                      />
                      <Link
                        to={localStorage.getItem("userId") ? "#" : "/login"}
                        className="write-review-link"
                        onClick={() => setWriteReview(true)}
                      >
                        <span>{t("write_review")}</span>
                        <Image
                          className="single-product-review-edit-icon"
                          src={
                            window.location.origin +
                            "/images/icons/edit-icon.svg"
                          }
                          type="image/png"
                        />
                      </Link>
                    </div>
                    <div className="single-product-thc-sec">
                      <div className="thc-left-sec">
                        <h3>
                          {singleProduct.data.product.selling_price_formatted}{" "}
                          {singleProduct.data.product.discount_tag ? (
                            <sub>
                              <del>
                                {
                                  singleProduct.data.product
                                    .original_price_formatted
                                }
                              </del>
                            </sub>
                          ) : null}
                        </h3>
                        <p>
                          {t("category")}{" "}
                          <span>
                            {singleProduct.data.product.category_name}
                          </span>
                        </p>
                        <span
                          className="add-wishlist-sec point"
                          onClick={wishListToggle}
                        >
                          {isWishlisted ? (
                            <>
                              <Image
                                src={
                                  window.location.origin +
                                  "/images/like-fill.svg"
                                }
                              />
                              {t("remove_from_wishlist")}
                            </>
                          ) : (
                            <>
                              <Image
                                src={
                                  window.location.origin + "/images/like-1.svg"
                                }
                              />
                              {t("add_to_wishlist")}
                            </>
                          )}
                        </span>
                      </div>
                      {singleProduct.data.product.thc_drug_content || singleProduct.data.product.cbd_drug_content ?
                        <div className="thc-details-right-sec">
                          <div className="product-percentage-sec">
                            {singleProduct.data.product.thc_drug_content ?
                              <div className="pack-icon-sec">
                                <ThcProgress percentage={singleProduct.data.product.thc_avg} />
                                <div className="pack-value">
                                  <h4>{singleProduct.data.product.thc_formatted ? singleProduct.data.product.thc_formatted : '0.00'}</h4>
                                  <h4>{singleProduct.data.product.thc_per_formatted ? singleProduct.data.product.thc_per_formatted : '0.00'}</h4>
                                </div>
                                <div className="pack-info">
                                  <OverlayTrigger
                                    placement="top"
                                    overlay={
                                      <Tooltip id="button-tooltip-2">
                                        THC is an active component in Fashion
                                        responsible for psychoactive, or
                                        intoxicating, effects such as changes in
                                        perception and mobility.
                                      </Tooltip>
                                    }
                                  >
                                    {({ ref, ...triggerHandler }) => (
                                      <Button {...triggerHandler}>
                                        <Image
                                          ref={ref}
                                          src={
                                            window.location.origin +
                                            "/images/additional-info.svg"
                                          }
                                          type="image/png"
                                        />
                                      </Button>
                                    )}
                                  </OverlayTrigger>
                                </div>
                              </div>
                              : null
                            }
                            {singleProduct.data.product.cbd_drug_content ?
                              <div className="pack-icon-sec">
                                <CbdProgress percentage={singleProduct.data.product.cbd_avg} />

                                <div className="pack-value">
                                  <h4>{singleProduct.data.product.cbd_formatted ? singleProduct.data.product.cbd_formatted : '0.00'}</h4>
                                  <h4>{singleProduct.data.product.cbd_per_formatted ? singleProduct.data.product.cbd_per_formatted : '0.00'}</h4>
                                </div>
                                <div className="pack-info">
                                  <OverlayTrigger
                                    placement="top"
                                    overlay={
                                      <Tooltip id="button-tooltip-2">
                                        CBD is an active, but non-intoxicating
                                        component in Fashion.
                                      </Tooltip>
                                    }
                                  >
                                    {({ ref, ...triggerHandler }) => (
                                      <Button {...triggerHandler}>
                                        <Image
                                          ref={ref}
                                          src={
                                            window.location.origin +
                                            "/images/additional-info.svg"
                                          }
                                          type="image/png"
                                        />
                                      </Button>
                                    )}
                                  </OverlayTrigger>
                                </div>
                              </div>
                              : null
                            }
                          </div>
                        </div>
                        : null}
                    </div>

                    <div className={`progress-bar-sec`}>
                      <h5
                        className={
                          singleProduct.data.product.stock_status === 0
                            ? "text-danger"
                            : ""
                        }
                      >
                        {singleProduct.data.product.stock_availablity_formatted}
                      </h5>
                      <ProgressBar
                        now={
                          (singleProduct.data.product.product_inventory
                            .remaining /
                            singleProduct.data.product.product_inventory
                              .total) *
                          100
                        }
                      />
                    </div>
                    {/* <div className="single-product-quantity-sec">
                      <p>
                        QTY
                        <span>
                          <NumericInput mobile className="form-control" />
                        </span>
                      </p>
                    </div> */}
                    {singleProduct.data.product.stock_status === 1 ? (
                      <div className="single-product-action-btn-sec default-btn-sec mt-0">
                        {localStorage.getItem("userId") &&
                          Object.keys(props.profile.data).length > 0 ? (
                          <Button
                            className="add-to-cart-btn"
                            onClick={onCartClick}
                          >
                            {singleProduct.data.product.is_carted === 0
                              ? t("add_to_cart")
                              : t("go_to_cart")}
                          </Button>
                        ) : (
                          <Button
                            className="add-to-cart-btn"
                            onClick={onGuestCartClick}
                          >
                            {!isCarted ? t("add_to_cart") : t("go_to_cart")}
                          </Button>
                        )}
                        {/* <Button className="default-btn">Buy It Now</Button> */}
                      </div>
                    ) : null}

                    {/* <div className="single-product-support-sec">
                      <div className="single-product-support-box">
                        <div className="single-product-support-card">
                          <Image
                            className="single-product-support-icon"
                            src={
                              window.location.origin +
                              "/images/product/24-hours-support.png"
                            }
                            type="image/png"
                          />
                          <span>{t("24x7_support")}</span>
                        </div>

                        <div className="single-product-support-card">
                          <Image
                            className="single-product-support-icon"
                            src={
                              window.location.origin +
                              "/images/product/shield.png"
                            }
                            type="image/png"
                          />
                          <span>100% {t("safe_products")}</span>
                        </div>
                      </div>
                      <div className="single-product-trusted-sec">
                        <Image
                          className="single-product-trusted-icon"
                          src={
                            window.location.origin +
                            "/images/product/trusted-img.png"
                          }
                          type="image/png"
                        />
                      </div>
                    </div> */}
                    <div className="single-about-product vis-hidden">
                      <div className="about-product-details">
                        <div className="single-product-detail-about">
                          <h4>Brand</h4>
                          <p>Canaca</p>
                        </div>
                        <div className="single-product-detail-about">
                          <h4>Potency</h4>
                          <p>Very Strong</p>
                        </div>
                        <div className="single-product-detail-about">
                          <h4>Plant Type</h4>
                          <p>{singleProduct.data.product.plant_type}</p>
                        </div>
                        <div className="single-product-detail-about">
                          <h4>Terpenes</h4>
                          <p>Terpenes May Vary</p>
                        </div>
                        <div className="single-product-detail-about">
                          <h4>Growing Province</h4>
                          <p>Ontario</p>
                        </div>
                      </div>
                    </div>
                  </div>
                </Col>
              </Row>
              {/* <div className="single-about-product margin-top-lg">
                <h4>About This product</h4>
                <div className="about-product-details">
                  <div className="single-product-detail-about">
                    <h4>Brand</h4>
                    <p>Canaca</p>
                  </div>
                  <div className="single-product-detail-about mt-4">
                    <h4>Potency</h4>
                    <p>Very Strong</p>
                  </div>
                  <div className="single-product-detail-about mt-4">
                    <h4>Plant Type</h4>
                    <p>Indica dominant</p>
                  </div>
                  <div className="single-product-detail-about mt-4">
                    <h4>Terpenes</h4>
                    <p>Terpenes May Vary</p>
                  </div>
                  <div className="single-product-detail-about mt-4">
                    <h4>Growing Province</h4>
                    <p>Ontario</p>
                  </div>
                </div>
              </div> */}
              <Row className="margin-top-lg">
                <Col md={12}>
                  <div className="single-product-description-review-sec">
                    <Tab.Container
                      id="left-tabs-example"
                      defaultActiveKey="description"
                    >
                      <Row>
                        <Col sm={12}>
                          <Nav variant="pills">
                            <Nav.Item>
                              <Nav.Link eventKey="description">
                                {t("description")}
                              </Nav.Link>
                            </Nav.Item>
                            <Nav.Item>
                              <Nav.Link eventKey="reviews">
                                {t("reviews")}
                              </Nav.Link>
                            </Nav.Item>
                          </Nav>
                        </Col>
                        <Col sm={12}>
                          <Tab.Content>
                            <Tab.Pane eventKey="description">
                              <div
                                className={`single-product-overflow-text ${clamped
                                  ? "single-product-description-sec"
                                  : ""
                                  }`}
                              >
                                {singleProduct.data.product
                                  .description_formatted ? (
                                  singleProduct.data.product
                                    .description_formatted
                                ) : (
                                  <NoDataFound />
                                )}
                              </div>
                              {/* {showButton && (
                                <Button
                                  className="read-more-btn"
                                  onClick={handleClick}
                                >
                                  {t("read")} {clamped ? t("more") : t("less")}
                                </Button>
                              )} */}
                            </Tab.Pane>
                            <Tab.Pane eventKey="reviews">
                              <div className="single-product-review-sec">
                                {productReviews.loading ? (
                                  <CommonCenterLoader />
                                ) : productReviews.data.reviews.length > 0 ? (
                                  <>
                                    <div className="single-product-review-box">
                                      {productReviews.data.reviews.map(
                                        (review, i) => (
                                          <div
                                            className="single-product-review-item"
                                            key={i}
                                          >
                                            <div className="single-product-review-left">
                                              <div className="single-product-review-user-img-sec">
                                                <Image
                                                  className="single-product-review-user-img"
                                                  src={
                                                    review.user
                                                      ? review.user.picture
                                                      : window.location.origin +
                                                      "/images/profile.png"
                                                  }
                                                  type="image/png"
                                                />
                                              </div>
                                              <div className="single-product-review-info">
                                                <h4>
                                                  {review.user
                                                    ? review.user.name
                                                    : t("na")}
                                                </h4>
                                                <p>{review.review}</p>
                                                <ReactStars
                                                  count={5}
                                                  value={review.star}
                                                  size={24}
                                                  isHalf={true}
                                                  edit={false}
                                                  emptyIcon={
                                                    <i className="far fa-star"></i>
                                                  }
                                                  halfIcon={
                                                    <i className="fa fa-star-half-alt"></i>
                                                  }
                                                  fullIcon={
                                                    <i className="fa fa-star"></i>
                                                  }
                                                  activeColor="#ffd700"
                                                />
                                              </div>
                                            </div>
                                          </div>
                                        )
                                      )}
                                    </div>
                                    <div className="text-center">
                                      {productReviews.data.reviews.length <
                                        productReviews.data.total_reviews ? (
                                        productReviews.loadMore ? (
                                          <CommonCenterLoader />
                                        ) : (
                                          <div className="default-btn-sec">
                                            {console.log(productReviews)}
                                            {console.log(
                                              productReviews.loadMore
                                            )}
                                            <Button
                                              className="default-btn"
                                              onClick={() => loadMoreReview()}
                                            >
                                              Load More
                                            </Button>
                                          </div>
                                        )
                                      ) : null}
                                    </div>
                                  </>
                                ) : (
                                  <NoReviewsFound />
                                )}
                              </div>
                            </Tab.Pane>
                          </Tab.Content>
                        </Col>
                      </Row>
                    </Tab.Container>
                  </div>
                </Col>
              </Row>
            </Container>
            {props.productList.loading ? (
              "Loading"
            ) : props.productList.data.products &&
              props.productList.data.products.length > 0 ? (
              <div className="top-selling-product-page">
                <Container>
                  <Row>
                    <Col md={12}>
                      <div className="section-title-sec">
                        <h3>{t("top_selling_products")}</h3>
                        <h2>
                          <span>{t("fabulous_products")}</span>
                        </h2>
                      </div>
                    </Col>
                  </Row>
                  <Row>
                    <Col md="12">
                      <TopSellingProductIndex
                        products={
                          props.productList.data.products
                            .filter(product => product.product_unique_id !== props.singleProduct.data.product.product_unique_id)
                            .slice(0, 8)
                        }
                      />
                    </Col>
                  </Row>
                </Container>
              </div>
            ) : null}
            <CustomerReviewIndex />
          </div>
          {writeReview && singleProduct.data.product && (
            <WriteReviewModal
              writeReview={writeReview}
              closeWriteReviewModal={closeWriteReviewModal}
              setWriteReview={setWriteReview}
              singleProduct={singleProduct.data.product}
            />
          )}
        </>
      ) : (
        <SomethingWrong />
      )}
    </>
  );
};

const mapStateToPros = (state) => ({
  singleProduct: state.product.singleProduct,
  productReviews: state.product.productReviews,
  profile: state.users.profile,
  guestCartList: state.carts.guestCartList,
  productList: state.product.productList,
  wishlistSave: state.product.wishlistSave,
});

function mapDispatchToProps(dispatch) {
  return { dispatch };
}

export default connect(
  mapStateToPros,
  mapDispatchToProps
)(withTranslation(SingleProductIndex));
Back to Directory File Manager