From 33ee63af39d27062a9d5f296640c88cf5ff74334 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Mon, 29 Sep 2025 10:09:22 +0700 Subject: try fix crawl --- .../product-detail/components/ProductDetail.tsx | 241 +++++++++++++++------ 1 file changed, 180 insertions(+), 61 deletions(-) diff --git a/src-migrate/modules/product-detail/components/ProductDetail.tsx b/src-migrate/modules/product-detail/components/ProductDetail.tsx index 39011620..f32bb38e 100644 --- a/src-migrate/modules/product-detail/components/ProductDetail.tsx +++ b/src-migrate/modules/product-detail/components/ProductDetail.tsx @@ -1,18 +1,13 @@ import style from '../styles/product-detail.module.css'; + import Link from 'next/link'; import { useRouter } from 'next/router'; -import { useEffect, useMemo, useState } from 'react'; -import dynamic from 'next/dynamic'; +import { useEffect, useRef, useState, UIEvent } from 'react'; import { Button } from '@chakra-ui/react'; import { MessageCircleIcon, Share2Icon } from 'lucide-react'; import { LazyLoadComponent } from 'react-lazy-load-image-component'; -const RWebShare = dynamic( - () => import('react-web-share').then(m => m.RWebShare), - { ssr: false } -); - import useDevice from '@/core/hooks/useDevice'; import { getAuth } from '~/libs/auth'; import { whatsappUrl } from '~/libs/whatsappUrl'; @@ -26,23 +21,34 @@ import Information from './Information'; import PriceAction from './PriceAction'; import SimilarBottom from './SimilarBottom'; import SimilarSide from './SimilarSide'; +import dynamic from 'next/dynamic'; + + import { gtagProductDetail } from '@/core/utils/googleTag'; -type Props = { product: IProductDetail }; +type Props = { + product: IProductDetail; +}; + +const RWebShare = dynamic( + () => import('react-web-share').then(m => m.RWebShare), + { ssr: false } +); -const SELF_HOST = process.env.NEXT_PUBLIC_SELF_HOST || ''; +const SELF_HOST = process.env.NEXT_PUBLIC_SELF_HOST; const ProductDetail = ({ product }: Props) => { const { isDesktop, isMobile } = useDevice(); const router = useRouter(); - const [auth, setAuth] = useState(null); useEffect(() => { - try { - setAuth(getAuth() ?? null); - } catch {} + try { setAuth(getAuth() ?? null); } catch { } }, []); + const canShare = + typeof navigator !== 'undefined' && + typeof (navigator as any).share === 'function'; + const { setAskAdminUrl, askAdminUrl, @@ -50,51 +56,88 @@ const ProductDetail = ({ product }: Props) => { setIsApproval, isApproval, setSelectedVariant, + setSla, } = useProductDetail(); useEffect(() => { - try { - gtagProductDetail(product); - } catch {} + gtagProductDetail(product); }, [product]); - const currentPath = router?.asPath || '/'; useEffect(() => { const createdAskUrl = whatsappUrl({ template: 'product', payload: { - manufacture: product.manufacture?.name ?? '', - productName: product.name ?? '', - url: SELF_HOST + currentPath, + manufacture: product.manufacture.name, + productName: product.name, + url: process.env.NEXT_PUBLIC_SELF_HOST + router.asPath, }, - fallbackUrl: currentPath, + fallbackUrl: router.asPath, }); + setAskAdminUrl(createdAskUrl); - }, [currentPath, product.manufacture?.name, product.name, setAskAdminUrl]); + }, [router.asPath, product.manufacture.name, product.name, setAskAdminUrl]); useEffect(() => { - if (auth && typeof auth === 'object') { - setIsApproval(!!auth?.feature?.soApproval); + if (typeof auth === 'object') { + setIsApproval(auth?.feature?.soApproval); } const selectedVariant = - product?.variants?.find(v => v.is_in_bu) || product?.variants?.[0] || null; + product?.variants?.find((variant) => variant.is_in_bu) || + product?.variants?.[0]; setSelectedVariant(selectedVariant); - }, [auth, product?.variants, setIsApproval, setSelectedVariant]); + }, []); + - const allImages = useMemo(() => { + const allImages = (() => { const arr: string[] = []; - if (Array.isArray(product?.image_carousel)) arr.push(...product.image_carousel); - if (product?.image) arr.unshift(product.image); + if (product?.image) arr.push(product.image); + if ( + Array.isArray(product?.image_carousel) && + product.image_carousel.length + ) { + + const set = new Set(arr); + for (const img of product.image_carousel) { + if (!set.has(img)) { + arr.push(img); + set.add(img); + } + } + } return arr; - }, [product?.image, product?.image_carousel]); + })(); const [mainImage, setMainImage] = useState(allImages[0] || ''); + useEffect(() => { - if (!allImages.includes(mainImage)) setMainImage(allImages[0] || ''); - }, [allImages, mainImage]); - const canShare = - typeof navigator !== 'undefined' && typeof (navigator as any).share === 'function'; + if (!allImages.includes(mainImage)) { + setMainImage(allImages[0] || ''); + } + }, [allImages]); + + + const sliderRef = useRef(null); + const [currentIdx, setCurrentIdx] = useState(0); + + const handleMobileScroll = (e: UIEvent) => { + const el = e.currentTarget; + if (!el) return; + const idx = Math.round(el.scrollLeft / el.clientWidth); + if (idx !== currentIdx) { + setCurrentIdx(idx); + setMainImage(allImages[idx] || ''); + } + }; + + const scrollToIndex = (i: number) => { + const el = sliderRef.current; + if (!el) return; + el.scrollTo({ left: i * el.clientWidth, behavior: 'smooth' }); + setCurrentIdx(i); + setMainImage(allImages[i] || ''); + }; + return ( <> @@ -105,38 +148,105 @@ const ProductDetail = ({ product }: Props) => {
+ {/* ===== Kolom kiri: gambar ===== */}
- - - {allImages.length > 0 && ( -
-
- {allImages.map((img, index) => ( -
setMainImage(img)} - > + {/* === MOBILE: Slider swipeable, tanpa thumbnail carousel === */} + {isMobile ? ( +
+
+ {allImages.length > 0 ? ( + allImages.map((img, i) => ( + +
+ {/* gambar diperkecil */} + {`Gambar { + (e.target as HTMLImageElement).src = + '/images/noimage.jpeg'; + }} + /> +
+ )) + ) : ( +
{`Thumbnail { - (e.target as HTMLImageElement).src = '/images/noimage.jpeg'; - }} + src={mainImage || '/images/noimage.jpeg'} + alt='Gambar produk' + className='w-[85%] aspect-square object-contain' />
- ))} + )}
+ + {/* Dots indicator */} + {allImages.length > 1 && ( +
+ {allImages.map((_, i) => ( +
+ )}
+ ) : ( + <> + {/* === DESKTOP: Tetap seperti sebelumnya === */} + + + {/* Carousel horizontal (thumbnail) – hanya desktop */} + {allImages.length > 0 && ( +
+
+ {allImages.map((img, index) => ( +
setMainImage(img)} + > + {`Thumbnail { + (e.target as HTMLImageElement).src = + '/images/noimage.jpeg'; + }} + /> +
+ ))} +
+
+ )} + )}
+ {/* <<=== TUTUP kolom kiri */} + {/* ===== Kolom kanan: info ===== */}

{product.name}

@@ -155,7 +265,10 @@ const ProductDetail = ({ product }: Props) => {
{!!activeVariantId && !isApproval && ( - + )}
@@ -168,7 +281,7 @@ const ProductDetail = ({ product }: Props) => { className={style['description']} dangerouslySetInnerHTML={{ __html: - !product.description || product.description === '


' + !product.description || product.description == '


' ? 'Belum ada deskripsi' : product.description, }} @@ -184,7 +297,7 @@ const ProductDetail = ({ product }: Props) => {