summaryrefslogtreecommitdiff
path: root/src/lib/product/components/Product/ProductDesktopVariant.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/product/components/Product/ProductDesktopVariant.jsx')
-rw-r--r--src/lib/product/components/Product/ProductDesktopVariant.jsx348
1 files changed, 348 insertions, 0 deletions
diff --git a/src/lib/product/components/Product/ProductDesktopVariant.jsx b/src/lib/product/components/Product/ProductDesktopVariant.jsx
new file mode 100644
index 00000000..a98985c9
--- /dev/null
+++ b/src/lib/product/components/Product/ProductDesktopVariant.jsx
@@ -0,0 +1,348 @@
+import Image from '@/core/components/elements/Image/Image'
+import Link from '@/core/components/elements/Link/Link'
+import DesktopView from '@/core/components/views/DesktopView'
+import currencyFormat from '@/core/utils/currencyFormat'
+import { HeartIcon } from '@heroicons/react/24/outline'
+import { useCallback, useEffect, useRef, useState } from 'react'
+import LazyLoad from 'react-lazy-load'
+import ProductSimilar from '../ProductSimilar'
+import { toast } from 'react-hot-toast'
+import { updateItemCart } from '@/core/utils/cart'
+import { useRouter } from 'next/router'
+import { createSlug } from '@/core/utils/slug'
+import BottomPopup from '@/core/components/elements/Popup/BottomPopup'
+import ProductCard from '../ProductCard'
+import productSimilarApi from '../../api/productSimilarApi'
+import whatsappUrl from '@/core/utils/whatsappUrl'
+
+const ProductDesktopVariant = ({ product, wishlist, toggleWishlist, isVariant }) => {
+ const router = useRouter()
+
+ const [lowestPrice, setLowestPrice] = useState(null)
+
+ const [addCartAlert, setAddCartAlert] = useState(false)
+
+ const getLowestPrice = useCallback(() => {
+ const lowest = product.price
+ /* const lowest = prices.reduce((lowest, price) => {
+ return price.priceDiscount < lowest.priceDiscount ? price : lowest
+ }, prices[0])*/
+ return lowest
+ }, [product])
+
+ useEffect(() => {
+ const lowest = getLowestPrice()
+ setLowestPrice(lowest)
+ }, [getLowestPrice])
+
+ const [informationTab, setInformationTab] = useState(informationTabOptions[0].value)
+
+ const variantQuantityRefs = useRef([])
+
+ const setVariantQuantityRef = (variantId) => (element) => {
+ variantQuantityRefs.current[variantId] = element
+ }
+
+ const validQuantity = (quantity) => {
+ let isValid = true
+ if (!quantity || quantity < 1 || isNaN(parseInt(quantity))) {
+ toast.error('Jumlah barang minimal 1')
+ isValid = false
+ }
+ return isValid
+ }
+
+ const handleAddToCart = (variant) => {
+ const quantity = variantQuantityRefs.current[variant].value
+ if (!validQuantity(quantity)) return
+ updateItemCart({
+ productId: variant,
+ quantity,
+ selected: true
+ })
+ setAddCartAlert(true)
+ }
+
+ const handleBuy = (variant) => {
+ const quantity = variantQuantityRefs.current[variant].value
+ if (!validQuantity(quantity)) return
+ router.push(`/shop/checkout?productId=${variant}&quantity=${quantity}`)
+ }
+
+ const variantSectionRef = useRef(null)
+ const goToVariantSection = () => {
+ if (variantSectionRef.current) {
+ const position = variantSectionRef.current.getBoundingClientRect()
+ window.scrollTo({
+ top: position.top - 120 + window.pageYOffset,
+ behavior: 'smooth'
+ })
+ }
+ }
+
+ const productSimilarQuery = [
+ product?.name,
+ `fq=-product_id_i:${product.id}`,
+ `fq=-manufacture_id_i:${product.manufacture?.id || 0}`
+ ].join('&')
+
+ const [productSimilarInBrand, setProductSimilarInBrand] = useState(null)
+
+ useEffect(() => {
+ const loadProductSimilarInBrand = async () => {
+ const productSimilarQuery = [product?.name, `fq=-product_id_i:${product.id}`].join('&')
+ const dataProductSimilar = await productSimilarApi({ query: productSimilarQuery })
+ setProductSimilarInBrand(dataProductSimilar.products)
+ }
+ if (!productSimilarInBrand) loadProductSimilarInBrand()
+ }, [product, productSimilarInBrand])
+
+ return (
+ <DesktopView>
+ <div className='container mx-auto pt-10'>
+ <div className='flex'>
+ <div className='w-full flex flex-wrap'>
+ <div className='w-5/12'>
+ <Image
+ src={product.parent.image}
+ alt={product.name}
+ className='h-[430px] object-contain object-center w-full border border-gray_r-4'
+ />
+ </div>
+
+ <div className='w-7/12 px-4'>
+ <h1 className='text-title-md leading-10 font-medium'>{product?.name}</h1>
+ <div className='mt-10'>
+ <div className='flex p-3'>
+ <div className='w-1/4 text-gray_r-12/70'>Nomor SKU</div>
+ <div className='w-3/4'>SKU-{product.id}</div>
+ </div>
+ <div className='flex p-3 bg-gray_r-4'>
+ <div className='w-1/4 text-gray_r-12/70'>Part Number</div>
+ <div className='w-3/4'>{product.code || '-'}</div>
+ </div>
+ <div className='flex p-3'>
+ <div className='w-1/4 text-gray_r-12/70'>Manufacture</div>
+ <div className='w-3/4'>
+ {product.manufacture?.name ? (
+ <Link
+ href={createSlug(
+ '/shop/brands/',
+ product.manufacture?.name,
+ product.manufacture?.id
+ )}
+ >
+ {product.manufacture?.name}
+ </Link>
+ ) : (
+ <div>-</div>
+ )}
+ </div>
+ </div>
+ <div className='flex p-3 bg-gray_r-4'>
+ <div className='w-1/4 text-gray_r-12/70'>Berat Barang</div>
+ <div className='w-3/4'>
+ {product?.weight > 0 && <span>{product?.weight} KG</span>}
+ {product?.weight == 0 && (
+ <a
+ href={whatsappUrl('productWeight', {
+ name: product.name,
+ url: createSlug('/shop/product/', product.name, product.id, true)
+ })}
+ className='text-danger-500 font-medium'
+ >
+ Tanya Berat
+ </a>
+ )}
+ </div>
+ </div>
+ </div>
+ </div>
+
+ {/* <div className='w-full'>
+ <div className='mt-12'>
+ <div className='text-h-lg font-semibold'>Informasi Produk</div>
+ <div className='flex gap-x-4 mt-6 mb-4'>
+ {informationTabOptions.map((option) => (
+ <TabButton
+ value={option.value}
+ key={option.value}
+ active={informationTab == option.value}
+ onClick={() => setInformationTab(option.value)}
+ >
+ {option.label}
+ </TabButton>
+ ))}
+ </div>
+ <div className='flex'>
+ <div className='w-3/4 leading-7 product__description'>
+ <TabContent active={informationTab == 'description'}>
+ <span
+ dangerouslySetInnerHTML={{
+ __html:
+ product.description != ''
+ ? product.description
+ : 'Belum ada deskripsi produk.'
+ }}
+ />
+ </TabContent>
+
+ <TabContent active={informationTab == 'information'}>
+ Belum ada informasi.
+ </TabContent>
+ </div>
+ </div>
+ </div>
+ </div> */}
+ </div>
+
+ <div className='w-[25%]'>
+ {lowestPrice?.discountPercentage > 0 && (
+ <div className='flex gap-x-1 items-center mt-2'>
+ <div className='badge-solid-red text-caption-1'>
+ {lowestPrice?.discountPercentage}%
+ </div>
+ <div className='text-gray_r-11 line-through text-caption-1'>
+ {currencyFormat(lowestPrice?.price * 1.11)}
+ </div>
+ </div>
+ )}
+ <h3 className='font-semibold mt-1 text-title-sm'>
+ {currencyFormat(lowestPrice?.priceDiscount)}
+ </h3>
+ <h3 className='text-danger-500 font-semibold mt-1 text-title-md'>
+ {lowestPrice?.priceDiscount > 0 ? (
+ currencyFormat(lowestPrice?.priceDiscount * 1.11)
+ ) : (
+ <span className='text-gray_r-12/90 font-normal text-h-sm'>
+ Hubungi kami untuk dapatkan harga terbaik,&nbsp;
+ <a
+ href={whatsappUrl('product', {
+ name: product.name,
+ url: createSlug('/shop/product/', product.name, product.id, true)
+ })}
+ className='text-danger-500 underline'
+ >
+ klik disini
+ </a>
+ </span>
+ )}
+ {lowestPrice?.priceDiscount > 0 && (
+ <span className='text-sm text-gray_r-11'>*include PPN</span>
+ )}
+ </h3>
+
+ <div className='flex gap-x-3 mt-4'>
+ <input
+ type='number'
+ className='form-input w-16 py-2 text-center bg-gray_r-1'
+ ref={setVariantQuantityRef(product.id)}
+ defaultValue={1}
+ />
+ <button
+ type='button'
+ onClick={() => handleAddToCart(product.id)}
+ className='flex-1 py-2 btn-yellow'
+ >
+ Keranjang
+ </button>
+ <button
+ type='button'
+ onClick={() => handleBuy(product.id)}
+ className='flex-1 py-2 btn-solid-red'
+ >
+ Beli
+ </button>
+ </div>
+
+ <div className='flex mt-4'>
+ <button className='flex items-center gap-x-1' onClick={toggleWishlist}>
+ {wishlist.data?.productTotal > 0 ? (
+ <HeartIcon className='w-6 fill-danger-500 text-danger-500' />
+ ) : (
+ <HeartIcon className='w-6' />
+ )}
+ Wishlist
+ </button>
+ </div>
+
+ <div className='border border-gray_r-6 overflow-auto mt-4'>
+ <div className='font-medium text-center p-4 bg-gray_r-1 border-b border-gray_r-6 sticky top-0 z-10'>
+ Produk Serupa
+ </div>
+ <div className='h-full divide-y divide-gray_r-6 max-h-96'>
+ {productSimilarInBrand &&
+ productSimilarInBrand?.map((product) => (
+ <div className='py-2' key={product.id}>
+ <ProductCard product={product} variant='horizontal' />
+ </div>
+ ))}
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div className='my-12'>
+ <div className='text-h-lg font-semibold mb-6'>Kamu Mungkin Juga Suka</div>
+ <LazyLoad>
+ <ProductSimilar query={productSimilarQuery} />
+ </LazyLoad>
+ </div>
+
+ <BottomPopup
+ className='!container'
+ title='Berhasil Ditambahkan'
+ active={addCartAlert}
+ close={() => setAddCartAlert(false)}
+ >
+ <div className='flex mt-4'>
+ <div className='w-[10%]'>
+ <Image
+ src={product.image}
+ alt={product.name}
+ className='h-32 object-contain object-center w-full border border-gray_r-4'
+ />
+ </div>
+ <div className='ml-3 flex flex-1 items-center font-normal'>{product.name}</div>
+ <div className='ml-3 flex items-center font-normal'>
+ <Link href='/shop/cart' className='flex-1 py-2 text-gray_r-12 btn-yellow'>
+ Lihat Keranjang
+ </Link>
+ </div>
+ </div>
+
+ <div className='mt-8 mb-4'>
+ <div className='text-h-sm font-semibold mb-6'>Kamu Mungkin Juga Suka</div>
+ <LazyLoad>
+ <ProductSimilar query={productSimilarQuery} />
+ </LazyLoad>
+ </div>
+ </BottomPopup>
+ </div>
+ </DesktopView>
+ )
+}
+
+const informationTabOptions = [
+ { value: 'description', label: 'Deskripsi' },
+ { value: 'information', label: 'Info Penting' }
+]
+
+const TabButton = ({ children, active, ...props }) => {
+ const activeClassName = active
+ ? 'text-danger-500 underline underline-offset-4'
+ : 'text-gray_r-12/80'
+ return (
+ <button {...props} type='button' className={`font-medium ${activeClassName}`}>
+ {children}
+ </button>
+ )
+}
+
+const TabContent = ({ children, active, className = '', ...props }) => (
+ <div {...props} className={`${active ? 'block' : 'hidden'} ${className}`}>
+ {children}
+ </div>
+)
+
+export default ProductDesktopVariant