diff options
Diffstat (limited to 'src/lib/product')
| -rw-r--r-- | src/lib/product/components/LobSectionCategory.jsx | 1 | ||||
| -rw-r--r-- | src/lib/product/components/ProductCard.jsx | 124 | ||||
| -rw-r--r-- | src/lib/product/components/ProductFilterDesktop.jsx | 1 | ||||
| -rw-r--r-- | src/lib/product/components/ProductFilterDesktopPromotion.jsx | 132 | ||||
| -rw-r--r-- | src/lib/product/components/ProductSearch.jsx | 1 |
5 files changed, 246 insertions, 13 deletions
diff --git a/src/lib/product/components/LobSectionCategory.jsx b/src/lib/product/components/LobSectionCategory.jsx index 03d6e8c0..5cd467e9 100644 --- a/src/lib/product/components/LobSectionCategory.jsx +++ b/src/lib/product/components/LobSectionCategory.jsx @@ -24,7 +24,6 @@ const LobSectionCategory = ({ categories }) => { }; const displayedCategories = categories[0]?.categoryIds; - return ( <section> {isDesktop && ( diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx index 38ed35f8..35e2a665 100644 --- a/src/lib/product/components/ProductCard.jsx +++ b/src/lib/product/components/ProductCard.jsx @@ -1,7 +1,7 @@ import clsx from 'clsx'; import ImageNext from 'next/image'; import { useRouter } from 'next/router'; -import { useMemo } from 'react'; +import { useMemo, useEffect, useState } from 'react'; import Image from '@/core/components/elements/Image/Image'; import Link from '@/core/components/elements/Link/Link'; @@ -14,6 +14,15 @@ import useUtmSource from '~/hooks/useUtmSource'; const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { const router = useRouter(); const utmSource = useUtmSource(); + const [discount, setDiscount] = useState(0); + + let voucherPastiHemat = 0; + + if (product?.voucherPastiHemat ? product?.voucherPastiHemat.length : voucherPastiHemat > 0) { + const stringVoucher = product?.voucherPastiHemat[0]; + const validJsonString = stringVoucher.replace(/'/g, '"'); + voucherPastiHemat = JSON.parse(validJsonString); + } const callForPriceWhatsapp = whatsappUrl('product', { name: product.name, @@ -37,15 +46,65 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { ), }; + const hitungDiscountVoucher = () => { + let countDiscount = 0; + if (voucherPastiHemat.discount_type === 'percentage') { + countDiscount = + product?.lowestPrice.priceDiscount * + (voucherPastiHemat.discount_amount / 100); + if ( + voucherPastiHemat.max_discount > 0 && + countDiscount > voucherPastiHemat.max_discount + ) { + countDiscount = voucherPastiHemat.max_discount; + } + } else { + countDiscount = voucherPastiHemat.discount_amount; + } + + setDiscount(countDiscount); + }; + + useEffect(() => { + hitungDiscountVoucher(); + }, []); + if (variant == 'vertical') { return ( - <div className='rounded shadow-sm border border-gray_r-4 bg-white h-[300px] md:h-[350px]'> + <div className='rounded shadow-sm border border-gray_r-4 bg-white h-[330px] md:h-[380px]'> <Link href={URL.product} className='border-b border-gray_r-4 relative'> - <Image - src={image} - alt={product?.name} - className='w-full object-contain object-center h-36 sm:h-48' - /> + <div className='relative'> + <Image + src={image} + alt={product?.name} + className='gambarA w-full object-contain object-center h-36 sm:h-48' + /> + <div className='absolute top-0 right-0 flex mt-3'> + <div className='gambarB '> + {product?.isSni && ( + <ImageNext + src='/images/sni-logo.png' + alt='SNI Logo' + className='w-4 h-5 object-contain object-top sm:h-6' + width={50} + height={50} + /> + )} + </div> + <div className='gambarC '> + {product?.isTkdn && ( + <ImageNext + src='/images/TKDN.png' + alt='TKDN' + className='w-11 h-6 object-contain object-top ml-1 mr-1 sm:h-6' + width={50} + height={50} + /> + )} + </div> + </div> + </div> + {router.pathname != '/' && product?.flashSale?.id > 0 && ( <div className='absolute bottom-0 w-full grid'> <div className='absolute bottom-0 w-full h-full'> @@ -149,6 +208,13 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { )} </div> )} + {discount > 0 && product?.flashSale?.id < 1 && ( + <div className='flex gap-x-1 mb-1 text-sm'> + <div className='inline-flex items-center rounded-md bg-green-50 px-2 py-1 text-xs font-medium text-green-700 ring-1 ring-inset ring-green-600/20'> + Voucher : {currencyFormat(discount)} + </div> + </div> + )} <div className='flex w-full items-center gap-x-1 '> {product?.stockTotal > 0 && ( @@ -171,11 +237,37 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { <div className='flex bg-white'> <div className='w-4/12'> <Link href={URL.product} className='relative'> - <Image - src={image} - alt={product?.name} - className='w-full object-contain object-center h-36' - /> + <div className='relative'> + <Image + src={image} + alt={product?.name} + className='gambarA w-full object-contain object-center h-36 sm:h-48' + /> + <div className='absolute top-0 right-0 flex mt-3'> + <div className='gambarB '> + {product?.isSni && ( + <ImageNext + src='/images/sni-logo.png' + alt='SNI Logo' + className='w-4 h-5 object-contain object-top sm:h-6' + width={50} + height={50} + /> + )} + </div> + <div className='gambarC '> + {product?.isTkdn && ( + <ImageNext + src='/images/TKDN.png' + alt='TKDN' + className='w-11 h-6 object-contain object-top ml-1 sm:h-6' + width={50} + height={50} + /> + )} + </div> + </div> + </div> {product.variantTotal > 1 && ( <div className='absolute badge-gray bottom-1.5 left-1.5'> {product.variantTotal} Varian @@ -264,6 +356,14 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { </div> )} + {discount > 0 && product?.flashSale?.id < 1 && ( + <div className='flex gap-x-1 mb-1 text-sm'> + <div className='inline-flex items-center rounded-md bg-green-50 px-2 py-1 text-xs font-medium text-green-700 ring-1 ring-inset ring-green-600/20'> + Voucher : {currencyFormat(discount)} + </div> + </div> + )} + <div className='flex w-full items-center gap-x-1 '> {product?.stockTotal > 0 && ( <div className='badge-solid-red'>Ready Stock</div> diff --git a/src/lib/product/components/ProductFilterDesktop.jsx b/src/lib/product/components/ProductFilterDesktop.jsx index 1933c5f0..73fecab5 100644 --- a/src/lib/product/components/ProductFilterDesktop.jsx +++ b/src/lib/product/components/ProductFilterDesktop.jsx @@ -22,6 +22,7 @@ import { formatCurrency } from '@/core/utils/formatValue' const ProductFilterDesktop = ({ brands, categories, prefixUrl, defaultBrand = null }) => { + const router = useRouter() const { query } = router const [order, setOrder] = useState(query?.orderBy) diff --git a/src/lib/product/components/ProductFilterDesktopPromotion.jsx b/src/lib/product/components/ProductFilterDesktopPromotion.jsx new file mode 100644 index 00000000..0815b881 --- /dev/null +++ b/src/lib/product/components/ProductFilterDesktopPromotion.jsx @@ -0,0 +1,132 @@ +import { useRouter } from 'next/router'; +import { useEffect, useState } from 'react'; +import _ from 'lodash'; +import { toQuery } from 'lodash-contrib'; +import { Button } from '@chakra-ui/react'; +import { MultiSelect } from 'react-multi-select-component'; + +const ProductFilterDesktop = ({ brands, categories, prefixUrl }) => { + const router = useRouter(); + const { query } = router; + const [order, setOrder] = useState(query?.orderBy); + const [brandValues, setBrand] = useState([]); + const [categoryValues, setCategory] = useState([]); + const [priceFrom, setPriceFrom] = useState(query?.priceFrom); + const [priceTo, setPriceTo] = useState(query?.priceTo); + const [stock, setStock] = useState(query?.stock); + const [activeRange, setActiveRange] = useState(null); + const [isBrandDropdownClicked, setIsBrandDropdownClicked] = useState(false); + const [isCategoryDropdownClicked, setIsCategoryDropdownClicked] = useState(false); + + // Effect to set brandValues from query parameter 'brand' + useEffect(() => { + const brandParam = query?.brand; + if (brandParam) { + const brandsArray = brandParam.split(',').map((b) => ({ + label: b, + value: b, + })); + setBrand(brandsArray); + } + + }, [query.brand]); // Trigger effect whenever query.brand changes + + useEffect(() => { + const categoryParam = query?.category; + if (categoryParam) { + const categoriesArray = categoryParam.split(',').map((c) => ({ + label: c, + value: c, + })); + setCategory(categoriesArray); + } + }, [query.category]); // Trigger effect whenever query.category changes + + const handleSubmit = () => { + let params = { + q: router.query.q, + orderBy: order, + brand: brandValues.map((b) => b.value).join(','), + category: categoryValues.map((c) => c.value).join(','), + priceFrom, + priceTo, + stock: stock, + }; + params = _.pickBy(params, _.identity); + params = toQuery(params); + + const slug = Array.isArray(router.query.slug) + ? router.query.slug[0] + : router.query.slug; + + if (slug) { + router.push(`${prefixUrl}/${slug}?${params}`); + } else { + router.push(`${prefixUrl}?${params}`); + } + }; + + + const brandOptions = brands.map((brand) => ({ + label: `${brand.brand} (${brand.qty})`, + value: brand.brand, + })); + + const categoryOptions = categories.map((category) => ({ + label: `${category.name} (${category.qty})`, + value: category.name, + })); + + return ( + <> + <div className='flex h-full w-[100%] justify-end '> + {/* Brand MultiSelect */} + <div className='mb-[20px] mr-4 w-64 h-full flex justify-start '> + <div className='relative'> + <label>Brand</label> + <div className='h-auto z-50 w-64 '> + <MultiSelect + options={brandOptions} + value={brandValues} + onChange={setBrand} + labelledBy='Select Brand' + onMenuToggle={(isOpen) => setIsBrandDropdownClicked(isOpen)} + hasSelectAll={false} + /> + </div> + </div> + </div> + + {/* Category MultiSelect */} + <div className='mb-[20px] mr-4 w-64 h-full flex justify-start '> + <div className='relative'> + <label>Kategori</label> + <div className=' h-auto w-64'> + <MultiSelect + options={categoryOptions} + value={categoryValues} + onChange={setCategory} + labelledBy='Select Kategori' + onMenuToggle={() => + setIsCategoryDropdownClicked(!isCategoryDropdownClicked) + } + hasSelectAll={false} + /> + </div> + </div> + </div> + + {/* Apply Button */} + <div className='TOMBOL mb-1 h-24 flex justify-center items-center w-24'> + <div className=' bottom-1 pb-1 left-0 right-0 flex justify-center rounded' > + <Button colorScheme='red' width={"full"} onClick={handleSubmit}> + Terapkan + </Button> + </div> + </div> + </div> + </> + ); +}; + +export default ProductFilterDesktop; diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index 09534a5d..9f19aced 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -267,6 +267,7 @@ const ProductSearch = ({ const orderOptions = [ + { value: '', label: 'Pilih Filter' }, { value: 'price-asc', label: 'Harga Terendah' }, { value: 'price-desc', label: 'Harga Tertinggi' }, { value: 'popular', label: 'Populer' }, |
