I want to display related products for a product that has been unpublished using the handle got from URL

92 Views Asked by At

I want to display in this skeleton a component that brings related product for a product that has been unpublished and up now i managed to get the handle of the product

I tried to call here the component that brings related products


const SkeletonProductPage = () => {
  const [product, setProduct] = useState<Product | null>(null)

  useEffect(() => {
    const url = window.location.href
    const urlParts = url.split("/")
    const handleWithParams = urlParts[urlParts.length - 1]
    const handle = handleWithParams.split("?")[0]
    const productHandle = handle

    const fetchProductByHandle = async (handle: string) => {
      try {
        // Fetch the product data from your backend API
        const response = await fetch(`/products/${handle}`)
        const data = await response.json()

        // Set the product data in the state
        setProduct(data)
      } catch (error) {
        console.error("Error fetching product data:", error)
      }
    }

    fetchProductByHandle(handle)
  }, [])

  return (
    <div>
      <div className="content-container flex flex-col small:flex-row small:items-start py-6 relative">
        <div className="flex flex-col gap-y-8 w-full">
          <div className="flex items-start relative">
            <div className="flex flex-col text-center flex-1 small:mx-16 gap-y-4 mt-10">
              Product is no longer available
            </div>
            {console.log("proddd", product)}
            <div className="my-16 px-8 small:px-8 content-container min-[1440px]:px-0">
              {product ? (
                <RelatedProducts product={product} classname={"w-full"} />
              ) : null}
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}

export default SkeletonProductPage

But all i can render until now is simply the text saying that the product is no longer available.

This is the source code for the component that brings related products



type RelatedProductsProps = {
  product: Product
  classname?: any
}

const RelatedProducts = ({ product, classname }: RelatedProductsProps) => {
  const { cart } = useCart()
  const { t } = useTranslation()
  const { client } = useMedusa()
  const carouselRef = useRef<Slider>(null)
  const [slidesToShow, setSlidesToShow] = useState(3)
  const [slidesToScroll, setSlidesToScroll] = useState(3)

  const handlePrev = () => {
    carouselRef.current?.slickPrev()
  }

  const handleNext = () => {
    carouselRef.current?.slickNext()
  }

  const settings = {
    slidesToShow: 3,
    slidesToScroll: 3,
    dots: true,
    infinite: true,
    speed: 500,
    adaptiveHeight: true,
    adaptiveWidth: true,
    responsive: [
      {
        breakpoint: 1024,
        settings: {
          slidesToShow: 3,
          slidesToScroll: 3,
          dots: true,
        },
      },
      {
        breakpoint: 780,
        settings: {
          slidesToShow: 2,
          slidesToScroll: 2,
          initialSlide: 2,
        },
      },
      {
        breakpoint: 680,
        settings: {
          slidesToShow: 1,
          slidesToScroll: 1,
        },
      },
    ],
    prevArrow: (
      <button
        className="slick-prev"
        onClick={handlePrev}
        style={{
          position: "absolute",
          top: "50%",
          transform: "translateY(-50%)",
          left: 0,
          zIndex: 1,
          backgroundColor: "#0000 !important",
          color: "#0000 !important",
          padding: "8px 16px",
          borderTopRightRadius: 0,
          borderBottomRightRadius: 0,
          transition: "background-color 0.2s",
        }}
      >
        Prev
      </button>
    ),
    nextArrow: (
      <button
        className="slick-next"
        onClick={handleNext}
        style={{
          position: "absolute",
          top: "50%",
          transform: "translateY(-50%)",
          right: 0,
          zIndex: 1,
          backgroundColor: "#0000 !important",
          color: "#0000 !important",
          padding: "8px 16px",
          borderTopLeftRadius: 0,
          borderBottomLeftRadius: 0,
          transition: "background-color 0.2s",
        }}
      >
        Next
      </button>
    ),
  }

  const queryParams: StoreGetProductsParams = useMemo(() => {
    const params: StoreGetProductsParams = {}

    if (cart?.id) {
      params.cart_id = cart.id
    }

    if (product.related_products && product.related_products.length > 0) {
      params.id = product.related_products.map((p) => p.related_product_id)
      return params
    }

    if (product.collection_id) {
      params.collection_id = [product.collection_id]
    }

    if (product.type) {
      params.type_id = [product.type.id]
    }

    if (product.tags) {
      params.tags = product.tags.map((t) => t.value)
    }

    params.is_giftcard = false

    return params
  }, [product, cart?.id])

  const { data, hasNextPage, fetchNextPage, isLoading, isFetchingNextPage } =
    useInfiniteQuery(
      [`infinite-products-${product.id}`, queryParams, cart],
      ({ pageParam }) =>
        fetchProductsList({ medusaClient: client, pageParam, queryParams }),
      {
        getNextPageParam: (lastPage) => lastPage.nextPage,
      }
    )

  const previews = usePreviews({ pages: data?.pages })
  const translatedPreviews = useEntityTranslation(
    previews
  ) as ProductPreviewType[]
  useEffect(() => {
    const handleResize = () => {
      const width = window.innerWidth
      let updatedSlidesToShow = 3
      let updatedSlidesToScroll = 3

      if (width >= 1024) {
        updatedSlidesToShow = 3
        updatedSlidesToScroll = 3
      } else if (width >= 780) {
        updatedSlidesToShow = 2
        updatedSlidesToScroll = 2
      } else {
        updatedSlidesToShow = 1
        updatedSlidesToScroll = 1
      }

      setSlidesToShow(updatedSlidesToShow)
      setSlidesToScroll(updatedSlidesToScroll)
    }

    handleResize()
    window.addEventListener("resize", handleResize)

    return () => window.removeEventListener("resize", handleResize)
  }, [])

  return (
    <div
      className={classname ? classname : "max-w-2xl product-page-constraint"}
    >
      <div className="overflow-x-hidden p-[25px]">
        <div className="flex flex-col items-center text-center mb-2">
          <span
            className={clsx(
              "text-[13px] leading-[20px] mb-[8px] tracking-[2%] uppercase font-medium",
              themeConfigs[THEME].secondaryFont,
              themeConfigs[THEME].primaryTextColor
            )}
          >
            {t("productDetails.common.relatedProducts")}
          </span>
          <p
            className={clsx(
              "max-w-lg",
              THEME === "FASHION"
                ? "text-[40px] leading-[48px]"
                : "text-[32px] leading-[40px] ",
              themeConfigs[THEME].primaryFont,
              themeConfigs[THEME].primaryTextColor
            )}
          >
            {t("productDetails.common.relatedProductsSubtitle")}
          </p>
        </div>
        {!isLoading && translatedPreviews.length === 0 ? (
          <div
            className={clsx(
              "text-[16px] leading-[24px] my-8 tracking-[2%] text-center",
              themeConfigs[THEME].secondaryFont
            )}
          >
            {t("productDetails.common.noRelatedProducts")}
          </div>
        ) : null}
        <Slider ref={carouselRef} {...settings}>
          {translatedPreviews.map((p, index) => (
            <div
              className="flex-none pr-5 w-fit-content"
              data-cy={`related-product-${index}`}
              key={p.id}
              style={{
                width: `fit-content`,
                flex: "0 0 auto",
                padding: "20px",
                marginRight: "14px",
                maxWidth: "100%",
              }}
            >
              <ProductPreview {...p} />
            </div>
          ))}
          {isLoading &&
            !translatedPreviews.length &&
            repeat(8).map((index) => (
              <div className="flex-none" key={index}>
                <SkeletonProductPreview />
              </div>
            ))}
          {isFetchingNextPage &&
            repeat(getNumberOfSkeletons(data?.pages)).map((index) => (
              <div className="flex-none" key={index}>
                <SkeletonProductPreview />
              </div>
            ))}
        </Slider>

        {hasNextPage && (
          <div
            className={clsx(
              "flex items-center justify-center mt-8",
              themeConfigs[THEME].secondaryFont
            )}
          >
            <Button
              isLoading={isLoading}
              onClick={() => fetchNextPage()}
              className="w-72"
            >
              {t("productDetails.common.loadMore")}
            </Button>
          </div>
        )}
      </div>
    </div>
  )
}

export default RelatedProducts

0

There are 0 best solutions below