diff options
| author | Miqdad <ahmadmiqdad27@gmail.com> | 2025-10-24 12:15:25 +0700 |
|---|---|---|
| committer | Miqdad <ahmadmiqdad27@gmail.com> | 2025-10-24 12:15:25 +0700 |
| commit | 54dacd110fdbd0f40961c884ec02b1a37189b218 (patch) | |
| tree | f4ef28a76b6e4c2a37a6eef53a3a10bb1145f9d5 /src-migrate/modules | |
| parent | dd16b65c603420d3965edcb4ee5a4a8df0cfadfc (diff) | |
<MIqdad> try show voucher prod detail
Diffstat (limited to 'src-migrate/modules')
| -rw-r--r-- | src-migrate/modules/product-detail/components/ProductDetail.tsx | 93 |
1 files changed, 74 insertions, 19 deletions
diff --git a/src-migrate/modules/product-detail/components/ProductDetail.tsx b/src-migrate/modules/product-detail/components/ProductDetail.tsx index f32bb38e..cfc27ffd 100644 --- a/src-migrate/modules/product-detail/components/ProductDetail.tsx +++ b/src-migrate/modules/product-detail/components/ProductDetail.tsx @@ -22,16 +22,17 @@ import PriceAction from './PriceAction'; import SimilarBottom from './SimilarBottom'; import SimilarSide from './SimilarSide'; import dynamic from 'next/dynamic'; - +import { TicketIcon } from '@heroicons/react/24/solid'; import { gtagProductDetail } from '@/core/utils/googleTag'; +import currencyFormat from '@/core/utils/currencyFormat'; type Props = { product: IProductDetail; }; const RWebShare = dynamic( - () => import('react-web-share').then(m => m.RWebShare), + () => import('react-web-share').then((m) => m.RWebShare), { ssr: false } ); @@ -42,7 +43,9 @@ const ProductDetail = ({ product }: Props) => { const router = useRouter(); const [auth, setAuth] = useState<any>(null); useEffect(() => { - try { setAuth(getAuth() ?? null); } catch { } + try { + setAuth(getAuth() ?? null); + } catch {} }, []); const canShare = @@ -87,7 +90,6 @@ const ProductDetail = ({ product }: Props) => { setSelectedVariant(selectedVariant); }, []); - const allImages = (() => { const arr: string[] = []; if (product?.image) arr.push(product.image); @@ -95,7 +97,6 @@ const ProductDetail = ({ product }: Props) => { 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)) { @@ -110,13 +111,11 @@ const ProductDetail = ({ product }: Props) => { const [mainImage, setMainImage] = useState(allImages[0] || ''); useEffect(() => { - if (!allImages.includes(mainImage)) { setMainImage(allImages[0] || ''); } }, [allImages]); - const sliderRef = useRef<HTMLDivElement | null>(null); const [currentIdx, setCurrentIdx] = useState(0); @@ -137,7 +136,48 @@ const ProductDetail = ({ product }: Props) => { setCurrentIdx(i); setMainImage(allImages[i] || ''); }; + // ====== Ambil voucher & hitung potongan (persis seperti ProductCard) ====== + const voucherRaw = Array.isArray(product?.voucher_pasti_hemat) + ? product.voucher_pasti_hemat[0] + : product?.voucher_pasti_hemat; + + // kalau backend kadang kirim string JSON + let voucher: any = voucherRaw; + if (typeof voucherRaw === 'string') { + try { + voucher = JSON.parse(voucherRaw.replace(/'/g, '"')); + } catch { + voucher = null; + } + } + // normalisasi nama properti (camelCase vs snake_case) + const discountType = voucher?.discountType ?? voucher?.discount_type ?? ''; // 'percentage' atau 'fixed' + const discountAmount = Number( + voucher?.discountAmount ?? voucher?.discount_amount ?? 0 + ); + const maxDiscount = Number( + voucher?.maxDiscount ?? voucher?.max_discount ?? 0 + ); + + // base price -> samakan dengan ProductCard: pakai price_discount + const basePrice = + Number(product?.lowest_price?.price_discount ?? 0) || + Number(product?.lowest_price?.price ?? 0); + + let voucherDiscount = 0; + if (discountType === 'percentage') { + voucherDiscount = basePrice * (discountAmount / 100); + if (maxDiscount > 0 && voucherDiscount > maxDiscount) { + voucherDiscount = maxDiscount; + } + } else { + // fixed + voucherDiscount = discountAmount; + } + voucherDiscount = Math.max(0, Math.floor(voucherDiscount)); + + const priceAfterVoucher = Math.max(0, basePrice - voucherDiscount); return ( <> @@ -165,7 +205,6 @@ const ProductDetail = ({ product }: Props) => { > {allImages.length > 0 ? ( allImages.map((img, i) => ( - <div key={i} className='w-full flex-shrink-0 snap-center flex justify-center items-center' @@ -200,8 +239,9 @@ const ProductDetail = ({ product }: Props) => { <button key={i} aria-label={`Ke slide ${i + 1}`} - className={`w-2 h-2 rounded-full ${currentIdx === i ? 'bg-gray-800' : 'bg-gray-300' - }`} + className={`w-2 h-2 rounded-full ${ + currentIdx === i ? 'bg-gray-800' : 'bg-gray-300' + }`} onClick={() => scrollToIndex(i)} /> ))} @@ -220,10 +260,11 @@ const ProductDetail = ({ product }: Props) => { {allImages.map((img, index) => ( <div key={index} - className={`flex-shrink-0 w-16 h-16 cursor-pointer border-2 rounded-md transition-colors ${mainImage === img - ? 'border-red-500 ring-2 ring-red-200' - : 'border-gray-200 hover:border-gray-300' - }`} + className={`flex-shrink-0 w-16 h-16 cursor-pointer border-2 rounded-md transition-colors ${ + mainImage === img + ? 'border-red-500 ring-2 ring-red-200' + : 'border-gray-200 hover:border-gray-300' + }`} onClick={() => setMainImage(img)} > <img @@ -249,6 +290,15 @@ const ProductDetail = ({ product }: Props) => { {/* ===== Kolom kanan: info ===== */} <div className='md:w-8/12 px-4 md:pl-6'> <div className='h-6 md:h-0' /> + <div className='text text-sm'> + <TicketIcon className='inline text-yellow-300 w-5 h-5' /> + Pakai{' '} + <span className='text-green-600 font-extrabold'> + {' '} + Voucher belanja hemat {currencyFormat(voucherDiscount)} saat + checkout + </span> + </div> <h1 className={style['title']}>{product.name}</h1> <div className='h-3 md:h-0' /> <Information product={product} /> @@ -281,7 +331,8 @@ const ProductDetail = ({ product }: Props) => { className={style['description']} dangerouslySetInnerHTML={{ __html: - !product.description || product.description == '<p><br></p>' + !product.description || + product.description == '<p><br></p>' ? 'Belum ada deskripsi' : product.description, }} @@ -317,10 +368,16 @@ const ProductDetail = ({ product }: Props) => { data={{ text: 'Check out this product', title: `${product.name} - Indoteknik.com`, - url: (process.env.NEXT_PUBLIC_SELF_HOST || '') + (router?.asPath || '/'), + url: + (process.env.NEXT_PUBLIC_SELF_HOST || '') + + (router?.asPath || '/'), }} > - <Button variant='link' colorScheme='gray' leftIcon={<Share2Icon size={18} />}> + <Button + variant='link' + colorScheme='gray' + leftIcon={<Share2Icon size={18} />} + > Share </Button> </RWebShare> @@ -350,8 +407,6 @@ const ProductDetail = ({ product }: Props) => { </div> </> ); - - }; export default ProductDetail; |
