diff options
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/brand/components/Brands.jsx | 15 | ||||
| -rw-r--r-- | src/lib/cart/components/Cartheader.jsx | 12 | ||||
| -rw-r--r-- | src/lib/checkout/components/CheckoutOld.jsx | 1 | ||||
| -rw-r--r-- | src/lib/home/components/PreferredBrand.jsx | 6 | ||||
| -rw-r--r-- | src/lib/home/components/ServiceList.jsx | 105 | ||||
| -rw-r--r-- | src/lib/home/components/Skeleton/PopularProductSkeleton.jsx | 3 | ||||
| -rw-r--r-- | src/lib/home/hooks/usePreferredBrand.js | 13 | ||||
| -rw-r--r-- | src/lib/product/components/Product/ColumnsSLA.jsx | 89 | ||||
| -rw-r--r-- | src/lib/product/components/Product/ProductDesktop.jsx | 172 | ||||
| -rw-r--r-- | src/lib/product/components/Product/ProductDesktopVariant.jsx | 164 | ||||
| -rw-r--r-- | src/lib/product/components/Product/ProductMobile.jsx | 70 | ||||
| -rw-r--r-- | src/lib/product/components/Product/ProductMobileVariant.jsx | 84 | ||||
| -rw-r--r-- | src/lib/product/components/ProductCard.jsx | 89 | ||||
| -rw-r--r-- | src/lib/product/components/ProductFilterDesktop.jsx | 165 | ||||
| -rw-r--r-- | src/lib/product/components/ProductSearch.jsx | 8 | ||||
| -rw-r--r-- | src/lib/product/components/ProductSlider.jsx | 2 |
16 files changed, 577 insertions, 421 deletions
diff --git a/src/lib/brand/components/Brands.jsx b/src/lib/brand/components/Brands.jsx index c7483e40..f6cb4fbf 100644 --- a/src/lib/brand/components/Brands.jsx +++ b/src/lib/brand/components/Brands.jsx @@ -1,7 +1,7 @@ -import odooApi from '@/core/api/odooApi' import { useCallback, useEffect, useState } from 'react' import BrandCard from './BrandCard' import LogoSpinner from '@/core/components/elements/Spinner/LogoSpinner' +import axios from 'axios' const Brands = () => { const alpha = Array.from(Array(26)).map((e, i) => i + 65) @@ -13,13 +13,18 @@ const Brands = () => { const loadBrand = useCallback(async () => { setIsLoading(true) - const name = startWith ? `${startWith}%` : '' - const result = await odooApi( + const name = startWith ? `${startWith}*` : '' + //Get brand from odoo + /*const result = await odooApi( 'GET', `/api/v1/manufacture?limit=0&offset=${manufactures.length}&name=${name}` - ) + )*/ + + // Change get brands from solr + const result = await axios(`${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/brands?params=${name}`) + setIsLoading(false) - setManufactures((manufactures) => [...manufactures, ...result.manufactures]) + setManufactures((manufactures) => [...result.data]) }, [startWith]) const toggleStartWith = (alphabet) => { diff --git a/src/lib/cart/components/Cartheader.jsx b/src/lib/cart/components/Cartheader.jsx index dd6c276e..cbe7c7e1 100644 --- a/src/lib/cart/components/Cartheader.jsx +++ b/src/lib/cart/components/Cartheader.jsx @@ -48,7 +48,7 @@ const Cardheader = (cartCount) => { setProductCart(cart) setCountCart(cart.productTotal) setIsloading(false) - }, [setProductCart]) + }, [setProductCart, setIsloading]) useEffect(() => { if (!products) return @@ -158,14 +158,14 @@ const Cardheader = (cartCount) => { </div> </div> ))} - {products.length === 0 && !isLoading && ( + {auth && products.length === 0 && !isLoading && ( <div className='justify-center p-4'> <p className='text-gray-500 text-center '> Tidak Ada Produk di Keranjang Belanja Anda </p> </div> )} - {products.length > 0 && !isLoading && ( + {auth && products.length > 0 && !isLoading && ( <> <ul role='list' class='divide-y divide-gray-200 dark:divide-gray-700'> {products && @@ -251,11 +251,11 @@ const Cardheader = (cartCount) => { </> )} </div> - {products.length > 0 && !isLoading && ( + {auth && products.length > 0 && !isLoading && ( <> <div className='mt-3'> - <span className='text-gray-400 text-caption-2'>Sub Total Sebelum PPN : </span> - <span className='font-semibold text-red-600'>Rp. {currencyFormat(subTotal)}</span> + <span className='text-gray-400 text-caption-2'>Subtotal Sebelum PPN : </span> + <span className='font-semibold text-red-600'>{currencyFormat(subTotal)}</span> </div> <div className='mt-5 mb-2'> <button diff --git a/src/lib/checkout/components/CheckoutOld.jsx b/src/lib/checkout/components/CheckoutOld.jsx index 088b641b..6852059e 100644 --- a/src/lib/checkout/components/CheckoutOld.jsx +++ b/src/lib/checkout/components/CheckoutOld.jsx @@ -22,7 +22,6 @@ import DesktopView from '@/core/components/views/DesktopView' import ExpedisiList from '../api/ExpedisiList' import whatsappUrl from '@/core/utils/whatsappUrl' import { createSlug } from '@/core/utils/slug' -import { Button, Modal } from 'flowbite-react' import BottomPopup from '@/core/components/elements/Popup/BottomPopup' const SELF_PICKUP_ID = 32 diff --git a/src/lib/home/components/PreferredBrand.jsx b/src/lib/home/components/PreferredBrand.jsx index 55abe0b7..571c4745 100644 --- a/src/lib/home/components/PreferredBrand.jsx +++ b/src/lib/home/components/PreferredBrand.jsx @@ -6,7 +6,9 @@ import useDevice from '@/core/hooks/useDevice' import Link from '@/core/components/elements/Link/Link' const PreferredBrand = () => { - const { preferredBrands } = usePreferredBrand() + let query = 'level_s' + let params = 'prioritas' + const { preferredBrands } = usePreferredBrand(query) const { isMobile, isDesktop } = useDevice() return ( @@ -22,7 +24,7 @@ const PreferredBrand = () => { {preferredBrands.isLoading && <PreferredBrandSkeleton />} {!preferredBrands.isLoading && ( <Swiper slidesPerView={isMobile ? 3.5 : 7.5} spaceBetween={isMobile ? 12 : 24} freeMode> - {preferredBrands.data?.manufactures.map((brand) => ( + {preferredBrands.data?.data.map((brand) => ( <SwiperSlide key={brand.id}> <BrandCard brand={brand} /> </SwiperSlide> diff --git a/src/lib/home/components/ServiceList.jsx b/src/lib/home/components/ServiceList.jsx new file mode 100644 index 00000000..b8799d7d --- /dev/null +++ b/src/lib/home/components/ServiceList.jsx @@ -0,0 +1,105 @@ +import Image from 'next/image' +import Link from '@/core/components/elements/Link/Link' + +const ServiceList = () => { + return ( + <div className='px-4 sm:px-0'> + <div className='grid md:grid-cols-4 grid-cols-2 justify-between gap-2 items-center'> + <div className='w-full'> + <Link + href='/tentang-kami' + className='border border-gray-200 p-2 flex items-center gap-x-2 rounded-lg' + > + <div className=''> + <Image + width={24} + height={24} + quality={100} + src='/images/icon_service/ONE-STOP-SOLUTIONS.svg' + alt='' + className='h-20 w-20 rounded' + /> + </div> + <div className=''> + <h1 className='text-gray-900 font-semibold text-base'>One Stop Solution</h1> + <p className='text-xs md:text-sm text-gray-500'> + Temukan Solusi Lengkap Anda dalam Satu Tempat. + </p> + </div> + </Link> + </div> + <div className='w-full'> + <Link + href='/tentang-kami' + className='border border-gray-200 p-2 flex items-center gap-x-2 rounded-lg' + > + <div className=''> + <Image + width={24} + height={24} + quality={100} + src='/images/icon_service/WARRANTY.svg' + alt='' + className='h-20 w-20 rounded' + /> + </div> + <div> + <h1 className='text-gray-900 font-semibold text-base'>Garansi Resmi</h1> + <p className='text-xs md:text-sm text-gray-500'> + Garansi Keaslian Barang dan Jaminan Purna Jual. + </p> + </div> + </Link> + </div> + <div className='w-full '> + <Link + href='/tentang-kami' + className='border border-gray-200 p-2 flex items-center gap-x-2 rounded-lg' + > + <div className=''> + <Image + width={24} + height={24} + quality={100} + src='/images/icon_service/DUE-PAYMENT.svg' + alt='' + className='h-20 w-20 rounded' + /> + </div> + <div> + <h1 className='text-gray-900 font-semibold text-base'>Pembayaran Tempo</h1> + <p className='text-xs md:text-sm text-gray-500'> + Lebih mudah mengatur pembelian dengan pembayaran tempo. + </p> + </div> + </Link> + </div> + <div className='w-full'> + <Link + href='/tentang-kami' + className='border border-gray-200 p-2 flex items-center gap-x-2 rounded-lg' + > + <div className=''> + <Image + width={24} + height={24} + quality={100} + src='/images/icon_service/TAX.svg' + alt='' + className='h-20 w-20 rounded' + /> + </div> + <div> + <h1 className='text-gray-900 font-semibold text-base'>Faktur Pajak</h1> + <p className='text-xs md:text-sm text-gray-500'> + Dapat Faktur pajak untuk setiap transaksi dengan indoteknik.com + </p> + </div> + </Link> + </div> + </div> + </div> + ) +} + +export default ServiceList diff --git a/src/lib/home/components/Skeleton/PopularProductSkeleton.jsx b/src/lib/home/components/Skeleton/PopularProductSkeleton.jsx index 29fda966..754bdd57 100644 --- a/src/lib/home/components/Skeleton/PopularProductSkeleton.jsx +++ b/src/lib/home/components/Skeleton/PopularProductSkeleton.jsx @@ -11,7 +11,8 @@ const PopularProductSkeleton = () => ( </div> </MobileView> <DesktopView> - <div className='grid grid-cols-5 gap-x-3'> + <div className='grid grid-cols-6 gap-x-3'> + <ProductCardSkeleton /> <ProductCardSkeleton /> <ProductCardSkeleton /> <ProductCardSkeleton /> diff --git a/src/lib/home/hooks/usePreferredBrand.js b/src/lib/home/hooks/usePreferredBrand.js index e56d361f..b7d707e6 100644 --- a/src/lib/home/hooks/usePreferredBrand.js +++ b/src/lib/home/hooks/usePreferredBrand.js @@ -1,3 +1,4 @@ +import axios from 'axios' import preferredBrandApi from '../api/preferredBrandApi' import { useQuery } from 'react-query' @@ -10,4 +11,14 @@ const usePreferredBrand = () => { } } -export default usePreferredBrand +const GetBrands = (query) => { + const fetchingbrand = async () => + await axios(`${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/brands?params=` + query) + + const { data, isLoading } = useQuery('preferredBrand', fetchingbrand) + return { + preferredBrands: { data, isLoading } + } +} + +export default GetBrands diff --git a/src/lib/product/components/Product/ColumnsSLA.jsx b/src/lib/product/components/Product/ColumnsSLA.jsx index 33da703a..e5296f96 100644 --- a/src/lib/product/components/Product/ColumnsSLA.jsx +++ b/src/lib/product/components/Product/ColumnsSLA.jsx @@ -1,8 +1,9 @@ import odooApi from '@/core/api/odooApi' import { createSlug } from '@/core/utils/slug' import whatsappUrl from '@/core/utils/whatsappUrl' -import { Button, Spinner } from 'flowbite-react' -import { memo, useEffect, useState } from 'react' +import { Box, Skeleton, Tooltip } from '@chakra-ui/react' +import { Info } from 'lucide-react' +import { memo } from 'react' import { useQuery } from 'react-query' const ColumnSLA = ({ variant, product }) => { @@ -12,67 +13,35 @@ const ColumnSLA = ({ variant, product }) => { return ( <> <td> - {dataSLA.isFetching ? ( - <div className='text-center'> - <Spinner aria-label='Center-aligned spinner example' /> - </div> - ) : dataSLA?.data?.qty > 0 ? ( - dataSLA?.data?.qty - ) : ( - <a - href={whatsappUrl('product', { - name: variant.name, - manufacture: product.manufacture?.name, - url: createSlug('/shop/product/', product.name, product.id, true) - })} - className='text-danger-500 font-medium' - target='_blank' - rel='noreferrer noopener' - > - Tanya Admin - </a> - )} + <Skeleton isLoaded={!dataSLA.isFetching} w='full'> + {dataSLA?.data?.qty > 0 ? ( + dataSLA?.data?.qty + ) : ( + <a + href={whatsappUrl('product', { + name: variant.name, + manufacture: product.manufacture?.name, + url: createSlug('/shop/product/', product.name, product.id, true) + })} + className='text-danger-500 font-medium' + target='_blank' + rel='noreferrer noopener' + > + Tanya Admin + </a> + )} + </Skeleton> </td> + <td className='flex justify-center'> - {dataSLA.isFetching ? ( - <Button color='gray'> - <Spinner aria-label='Alternate spinner button example' /> - <span className='pl-3'>Loading...</span> - </Button> - ) : dataSLA?.data?.slaDate != '-' ? ( - <button - type='button' - title={`Masa Persiapan Barang ${dataSLA?.data?.slaDate}`} - className={`flex gap-x-1 items-center p-2 rounded-lg w-full ${ - dataSLA?.data?.slaDate === 'indent' ? 'bg-indigo-900' : 'btn-light' - }`} - > - <div - className={`flex-1 text-caption-1 ${ - dataSLA?.data?.slaDate === 'indent' ? 'text-white' : '' - }`} - > + <Skeleton isLoaded={!dataSLA.isFetching} w='75%'> + <Tooltip placement='top' label={`Masa Persiapan Barang ${dataSLA?.data?.slaDate}`}> + <Box className='border border-gray_r-7 rounded-md p-2 flex justify-center items-center gap-x-2'> {dataSLA?.data?.slaDate} - </div> - <div className='flex-end'> - <svg - aria-hidden='true' - fill='none' - stroke='currentColor' - stroke-width='1.5' - className={`w-7 h-7 ${dataSLA?.data?.slaDate === 'indent' ? 'text-white' : ''}`} - > - <path - d='M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z' - stroke-linecap='round' - stroke-linejoin='round' - ></path> - </svg> - </div> - </button> - ) : ( - '-' - )} + <Info size={16} /> + </Box> + </Tooltip> + </Skeleton> </td> </> ) diff --git a/src/lib/product/components/Product/ProductDesktop.jsx b/src/lib/product/components/Product/ProductDesktop.jsx index 6da289bc..0df60673 100644 --- a/src/lib/product/components/Product/ProductDesktop.jsx +++ b/src/lib/product/components/Product/ProductDesktop.jsx @@ -15,7 +15,6 @@ import ProductCard from '../ProductCard' import productSimilarApi from '../../api/productSimilarApi' import whatsappUrl from '@/core/utils/whatsappUrl' import odooApi from '@/core/api/odooApi' -import { Button, Spinner } from 'flowbite-react' import PromotionType from '@/lib/promotinProgram/components/PromotionType' import useAuth from '@/core/hooks/useAuth' import ImageNext from 'next/image' @@ -23,6 +22,8 @@ import CountDown2 from '@/core/components/elements/CountDown/CountDown2' import { LazyLoadComponent } from 'react-lazy-load-image-component' import ColumnsSLA from './ColumnsSLA' import { useProductCartContext } from '@/contexts/ProductCartContext' +import { Box, Skeleton, Tooltip } from '@chakra-ui/react' +import { Info } from 'lucide-react' const ProductDesktop = ({ products, wishlist, toggleWishlist }) => { const router = useRouter() @@ -40,7 +41,7 @@ const ProductDesktop = ({ products, wishlist, toggleWishlist }) => { const [selectVariantPromoActive, setSelectVariantPromoActive] = useState(null) const [backgorundFlashSale, setBackgorundFlashSale] = useState(null) - const {setRefreshCart , refreshCart} = useProductCartContext() + const { setRefreshCart, refreshCart } = useProductCartContext() const getLowestPrice = useCallback(() => { const prices = product.variants.map((variant) => variant.price) @@ -256,16 +257,16 @@ const ProductDesktop = ({ products, wishlist, toggleWishlist }) => { <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 className='w-4/12 text-gray_r-12/70'>Nomor SKU</div> + <div className='w-8/12'>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 className='w-4/12 text-gray_r-12/70'>Part Number</div> + <div className='w-8/12'>{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'> + <div className='w-4/12 text-gray_r-12/70'>Manufacture</div> + <div className='w-8/12'> {product.manufacture?.name ? ( <Link href={createSlug( @@ -282,9 +283,9 @@ const ProductDesktop = ({ products, wishlist, toggleWishlist }) => { </div> </div> <div className='flex p-3 items-center bg-gray_r-4'> - <div className='w-1/4 text-gray_r-12/70'>Persiapan Barang</div> - <div className='w-3/4'> - {product.variants.length > 1 ? ( + <div className='w-4/12 text-gray_r-12/70'>Persiapan Barang</div> + <div className='w-8/12'> + {product.variants.length > 1 && ( <button type='button' onClick={goToVariantSection} @@ -292,62 +293,32 @@ const ProductDesktop = ({ products, wishlist, toggleWishlist }) => { > <span className='text-red-600 text-sm'>Lihat Selengkapnya</span> </button> - ) : product.variants[0].sla ? ( - product.variants[0].sla?.slaDate != '-' ? ( - <button - type='button' - title={`Masa Persiapan Barang ${product.variants[0].sla?.slaDate}`} - className={`flex gap-x-1 items-center p-2 rounded-lg w-auto ${ - product.variants[0].sla?.slaDate === 'indent' - ? 'bg-indigo-900' - : 'btn-light' - }`} - > - <div - className={`flex-1 text-caption-1 ${ - product.variants[0].sla?.slaDate === 'indent' ? 'text-white' : '' - }`} + )} + + {product.variants.length === 1 && ( + <> + {!product.variants[0]?.sla && <Skeleton width='20%' height='16px' />} + {product.variants[0]?.sla && ( + <Tooltip + placement='top' + label={`Masa Persiapan Barang ${product.variants[0]?.sla?.slaDate}`} > - {product.variants[0].sla?.slaDate} - </div> - <div className='flex-end'> - <svg - aria-hidden='true' - fill='none' - stroke='currentColor' - stroke-width='1.5' - className={`w-7 h-7 ${ - product.variants[0].sla?.slaDate === 'indent' ? 'text-white' : '' - }`} - > - <path - d='M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z' - stroke-linecap='round' - stroke-linejoin='round' - ></path> - </svg> - </div> - </button> - ) : ( - '-' - ) - ) : ( - <Button color='gray'> - <Spinner aria-label='Alternate spinner button example' /> - <span className='pl-3'>Loading...</span> - </Button> + <Box className='w-fit flex items-center gap-x-2'> + {product.variants[0]?.sla?.slaDate} + <Info size={16} /> + </Box> + </Tooltip> + )} + </> )} </div> </div> + {product.variants.length === 1 && ( <div className='flex p-3 '> - <div className='w-1/4 text-gray_r-12/70'>Stock</div> - <div className='w-3/4'> - {isLoadingSLA && ( - <div className=''> - <Spinner aria-label='Center-aligned spinner example' /> - </div> - )} + <div className='w-4/12 text-gray_r-12/70'>Stock</div> + <div className='w-8/12'> + {!product.variants[0]?.sla && <Skeleton width='10%' height='16px' />} {product?.variants[0].sla?.qty > 0 && ( <span>{product?.variants[0].sla?.qty}</span> )} @@ -366,9 +337,10 @@ const ProductDesktop = ({ products, wishlist, toggleWishlist }) => { </div> </div> )} + <div className={`flex p-3 ${product.variants.length > 1 ? '' : 'bg-gray_r-4'} `}> - <div className='w-1/4 text-gray_r-12/70'>Berat Barang</div> - <div className='w-3/4'> + <div className='w-4/12 text-gray_r-12/70'>Berat Barang</div> + <div className='w-8/12'> {product?.weight > 0 && <span>{product?.weight} KG</span>} {product?.weight == 0 && ( <a @@ -441,13 +413,13 @@ const ProductDesktop = ({ products, wishlist, toggleWishlist }) => { <div className='text-gray_r-12/80'>Harga mulai dari: </div> )} - {lowestPrice?.discountPercentage > 0 && ( + {/* {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)} + <div className='text-gray_r-9 text-caption-1'> + Include PPN {currencyFormat(lowestPrice?.price * process.env.NEXT_PUBLIC_PPN)} </div> {product.flashSale.remainingTime > 0 && ( <div className='bg-red-600 rounded-full mb-1 p-2 pl-3 pr-3 flex w-fit items-center gap-x-1'> @@ -464,28 +436,54 @@ const ProductDesktop = ({ products, wishlist, toggleWishlist }) => { </div> )} </div> + )} */} + + {product?.flashSale?.remainingTime > 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-9 line-through text-caption-1'> + {currencyFormat(lowestPrice?.price)} + </div> + <div className='text-danger-500 font-semibold text-xl'> + {currencyFormat(lowestPrice?.priceDiscount)} + </div> + </div> + <div className='text-gray_r-9 text-base font-normal mt-1'> + Termasuk PPN: {currencyFormat(lowestPrice?.priceDiscount * process.env.NEXT_PUBLIC_PPN)} + </div> + </> + ) : ( + <h3 className='text-danger-500 font-semibold mt-1 text-title-md'> + {lowestPrice?.price > 0 ? ( + <> + {currencyFormat(lowestPrice?.price)} + <div className='text-gray_r-9 text-base font-normal mt-1'> + Termasuk PPN: {currencyFormat(lowestPrice?.price * process.env.NEXT_PUBLIC_PPN)} + </div> + </> + ) : ( + <span className='text-gray_r-12/90 font-normal text-h-sm'> + Hubungi kami untuk dapatkan harga terbaik, + <a + href={whatsappUrl('product', { + name: product.name, + manufacture: product.manufacture?.name, + url: createSlug('/shop/product/', product.name, product.id, true) + })} + className='text-danger-500 underline' + rel='noopener noreferrer' + target='_blank' + > + klik disini + </a> + </span> + )} + </h3> )} - <h3 className='text-danger-500 font-semibold mt-1 text-title-md'> - {lowestPrice?.priceDiscount > 0 ? ( - currencyFormat(lowestPrice?.priceDiscount) - ) : ( - <span className='text-gray_r-12/90 font-normal text-h-sm'> - Hubungi kami untuk dapatkan harga terbaik, - <a - href={whatsappUrl('product', { - name: product.name, - manufacture: product.manufacture?.name, - url: createSlug('/shop/product/', product.name, product.id, true) - })} - className='text-danger-500 underline' - rel='noopener noreferrer' - target='_blank' - > - klik disini - </a> - </span> - )} - </h3> + {product.variants.length > 1 ? ( <button type='button' diff --git a/src/lib/product/components/Product/ProductDesktopVariant.jsx b/src/lib/product/components/Product/ProductDesktopVariant.jsx index 940ba46f..51739bc9 100644 --- a/src/lib/product/components/Product/ProductDesktopVariant.jsx +++ b/src/lib/product/components/Product/ProductDesktopVariant.jsx @@ -16,7 +16,9 @@ import productSimilarApi from '../../api/productSimilarApi' import whatsappUrl from '@/core/utils/whatsappUrl' import useAuth from '@/core/hooks/useAuth' import odooApi from '@/core/api/odooApi' -import { Button, Spinner } from 'flowbite-react' +import { useProductCartContext } from '@/contexts/ProductCartContext' +import { Box, Skeleton, Tooltip } from '@chakra-ui/react' +import { Info } from 'lucide-react' const ProductDesktopVariant = ({ product, wishlist, toggleWishlist, isVariant }) => { const router = useRouter() @@ -28,6 +30,8 @@ const ProductDesktopVariant = ({ product, wishlist, toggleWishlist, isVariant }) const [addCartAlert, setAddCartAlert] = useState(false) const [isLoadingSLA, setIsLoadingSLA] = useState(true) + const { setRefreshCart } = useProductCartContext() + const getLowestPrice = useCallback(() => { const lowest = product.price /* const lowest = prices.reduce((lowest, price) => { @@ -71,6 +75,8 @@ const ProductDesktopVariant = ({ product, wishlist, toggleWishlist, isVariant }) programLineId: null, selected: true, source: null + }).then(() => { + setRefreshCart(true) }) setAddCartAlert(true) } @@ -144,16 +150,16 @@ const ProductDesktopVariant = ({ product, wishlist, toggleWishlist, isVariant }) <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 className='w-4/12 text-gray_r-12/70'>Nomor SKU</div> + <div className='w-8/12'>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 className='w-4/12 text-gray_r-12/70'>Part Number</div> + <div className='w-8/12'>{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'> + <div className='w-4/12 text-gray_r-12/70'>Manufacture</div> + <div className='w-8/12'> {product.manufacture?.name ? ( <Link href={createSlug( @@ -169,68 +175,36 @@ const ProductDesktopVariant = ({ product, wishlist, toggleWishlist, isVariant }) )} </div> </div> + <div className='flex p-3 items-center bg-gray_r-4'> - <div className='w-1/4 text-gray_r-12/70'>Persiapan Barang</div> - <div className='w-3/4'> - {product.sla ? ( - product.sla?.slaDate != '-' ? ( - <button - type='button' - title={`Masa Persiapan Barang ${product.sla?.slaDate}`} - className={`flex gap-x-1 items-center p-2 rounded-lg w-auto ${ - product.sla?.slaDate === 'indent' ? 'bg-indigo-900' : 'btn-light' - }`} - > - <div - className={`flex-1 text-caption-1 ${ - product.sla?.slaDate === 'indent' ? 'text-white' : '' - }`} - > - {product.sla?.slaDate} - </div> - <div className='flex-end'> - <svg - aria-hidden='true' - fill='none' - stroke='currentColor' - stroke-width='1.5' - className={`w-7 h-7 ${ - product.sla?.slaDate === 'indent' ? 'text-white' : '' - }`} - > - <path - d='M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z' - stroke-linecap='round' - stroke-linejoin='round' - ></path> - </svg> - </div> - </button> - ) : ( - '-' - ) - ) : ( - <Button color='gray'> - <Spinner aria-label='Alternate spinner button example' /> - <span className='pl-3'>Loading...</span> - </Button> + <div className='w-4/12 text-gray_r-12/70'>Persiapan Barang</div> + <div className='w-8/12'> + {!product?.sla && <Skeleton width='20%' height='16px' />} + {product?.sla && ( + <Tooltip + placement='top' + label={`Masa Persiapan Barang ${product?.sla?.slaDate}`} + > + <Box className='w-fit flex items-center gap-x-2'> + {product?.sla?.slaDate} + <Info size={16} /> + </Box> + </Tooltip> )} </div> </div> + <div className='flex p-3'> - <div className='w-1/4 text-gray_r-12/70'>Stock</div> - <div className='w-3/4'> - {isLoadingSLA && ( - <div className=''> - <Spinner aria-label='Center-aligned spinner example' /> - </div> - )} + <div className='w-4/12 text-gray_r-12/70'>Stock</div> + <div className='w-8/12'> + {!product?.sla && <Skeleton width='10%' height='16px' />} {product?.sla?.qty > 0 && <span>{product?.sla?.qty}</span>} {product?.sla?.qty == 0 && ( <a href={whatsappUrl('product', { name: product.name, - url: createSlug('/shop/product/variant/', product.name, product.id, true) + manufacture: product?.manufacture?.name, + url: createSlug('/shop/product/', product.name, product.id, true) })} className='text-danger-500 font-medium' > @@ -240,8 +214,8 @@ const ProductDesktopVariant = ({ product, wishlist, toggleWishlist, isVariant }) </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'> + <div className='w-4/12 text-gray_r-12/70'>Berat Barang</div> + <div className='w-8/12'> {product?.weight > 0 && <span>{product?.weight} KG</span>} {product?.weight == 0 && ( <a @@ -296,44 +270,52 @@ const ProductDesktopVariant = ({ product, wishlist, toggleWishlist, isVariant }) </div> */} </div> <div className='w-[25%]'> - {lowestPrice?.priceDiscount > 0 ? ( + {product?.flashSale?.remainingTime > 0 ? ( <> - <div className='flex gap-x-2 mb-3 items-center'> - <div className='flex'> - <span className='text-gray-400 text-md'>Harga Sebelum PPN : </span> - </div> - <div className='flex'> - <span className=' text-body-1 '> - {currencyFormat(lowestPrice?.priceDiscount)} - </span> - </div> - </div> - <span className='font-semibold'>Termasuk PPN :</span> - <div className='flex gap-x-1 items-center mt-2 '> + <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 className='text-gray_r-9 line-through text-caption-1'> + {currencyFormat(lowestPrice?.price)} + </div> + <div className='text-danger-500 font-semibold text-xl'> + {currencyFormat(lowestPrice?.priceDiscount)} </div> - <h3 className='text-danger-500 font-semibold text-title-sm'> - {currencyFormat(lowestPrice?.priceDiscount * 1.11)} - </h3> + </div> + <div className='text-gray_r-9 text-base font-normal mt-1'> + Termasuk PPN:{' '} + {currencyFormat(lowestPrice?.priceDiscount * process.env.NEXT_PUBLIC_PPN)} </div> </> ) : ( - <span className='text-gray_r-12/90 font-normal text-h-sm'> - Hubungi kami untuk dapatkan harga terbaik, - <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> + <h3 className='text-danger-500 font-semibold mt-1 text-title-md'> + {lowestPrice?.price > 0 ? ( + <> + {currencyFormat(lowestPrice?.price)} + <div className='text-gray_r-9 text-base font-normal mt-1'> + Termasuk PPN:{' '} + {currencyFormat(lowestPrice?.price * process.env.NEXT_PUBLIC_PPN)} + </div> + </> + ) : ( + <span className='text-gray_r-12/90 font-normal text-h-sm'> + Hubungi kami untuk dapatkan harga terbaik, + <a + href={whatsappUrl('product', { + name: product.name, + manufacture: product.manufacture?.name, + url: createSlug('/shop/product/', product.name, product.id, true) + })} + className='text-danger-500 underline' + rel='noopener noreferrer' + target='_blank' + > + klik disini + </a> + </span> + )} + </h3> )} <div className='flex gap-x-3 mt-4'> <input diff --git a/src/lib/product/components/Product/ProductMobile.jsx b/src/lib/product/components/Product/ProductMobile.jsx index 6b0b27a5..a9d34683 100644 --- a/src/lib/product/components/Product/ProductMobile.jsx +++ b/src/lib/product/components/Product/ProductMobile.jsx @@ -17,7 +17,6 @@ import whatsappUrl from '@/core/utils/whatsappUrl' import PromotionType from '@/lib/promotinProgram/components/PromotionType' import { gtagAddToCart } from '@/core/utils/googleTag' import odooApi from '@/core/api/odooApi' -import { Button, Spinner } from 'flowbite-react' import ImageNext from 'next/image' import CountDown2 from '@/core/components/elements/CountDown/CountDown2' @@ -101,7 +100,8 @@ const ProductMobile = ({ product, wishlist, toggleWishlist }) => { price: variant.price, stock: variant.stock, weight: variant.weight, - hasProgram: variant.hasProgram + hasProgram: variant.hasProgram, + isFlashsale: variant.isFlashsale } setActiveVariant(newActiveVariant) @@ -152,6 +152,8 @@ const ProductMobile = ({ product, wishlist, toggleWishlist }) => { router.push(`/shop/checkout?source=buy`) } + console.log('ini log', activeVariant) + const productSimilarQuery = [ product?.name, `fq=-product_id_i:${product.id}`, @@ -232,32 +234,48 @@ const ProductMobile = ({ product, wishlist, toggleWishlist }) => { <div className='text-gray_r-12/80 text-caption-2 mt-2 mb-1'>Harga mulai dari: </div> )} - {activeVariant?.price?.discountPercentage > 0 && ( - <div className='flex gap-x-1 items-center'> - <div className='text-gray_r-11 line-through text-caption-1'> - {currencyFormat(activeVariant?.price?.price)} + {activeVariant.isFlashsale ? ( + <> + <div className='flex gap-x-1 items-center'> + <div className='badge-solid-red'>{activeVariant?.price?.discountPercentage}%</div> + <div className='text-gray_r-11 line-through text-caption-1'> + {currencyFormat(activeVariant?.price?.price)} + </div> + <div className='text-danger-500 font-semibold'> + {currencyFormat(activeVariant?.price?.priceDiscount)} + </div> </div> - <div className='badge-solid-red'>{activeVariant?.price?.discountPercentage}%</div> - </div> + <div className='text-gray_r-9 text-base font-normal mt-1'> + Termasuk PPN:{' '} + {currencyFormat(activeVariant?.price.priceDiscount * process.env.NEXT_PUBLIC_PPN)} + </div> + </> + ) : ( + <h3 className='text-danger-500 font-semibold mt-1'> + {activeVariant?.price?.priceDiscount > 0 ? ( + <> + {currencyFormat(activeVariant?.price?.priceDiscount)} + <div className='text-gray_r-9 text-base font-normal mt-1'> + Termasuk PPN:{' '} + {currencyFormat(activeVariant?.price.priceDiscount * process.env.NEXT_PUBLIC_PPN)} + </div> + </> + ) : ( + <span className='text-gray_r-11 leading-6 font-normal'> + Hubungi kami untuk dapatkan harga terbaik, + <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> + )} + </h3> )} - <h3 className='text-danger-500 font-semibold mt-1'> - {activeVariant?.price?.priceDiscount > 0 ? ( - currencyFormat(activeVariant?.price?.priceDiscount) - ) : ( - <span className='text-gray_r-11 leading-6 font-normal'> - Hubungi kami untuk dapatkan harga terbaik, - <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> - )} - </h3> </div> <Divider /> diff --git a/src/lib/product/components/Product/ProductMobileVariant.jsx b/src/lib/product/components/Product/ProductMobileVariant.jsx index e0ba90c3..a7b1a543 100644 --- a/src/lib/product/components/Product/ProductMobileVariant.jsx +++ b/src/lib/product/components/Product/ProductMobileVariant.jsx @@ -16,7 +16,7 @@ import BottomPopup from '@/core/components/elements/Popup/BottomPopup' import whatsappUrl from '@/core/utils/whatsappUrl' import { gtagAddToCart } from '@/core/utils/googleTag' import odooApi from '@/core/api/odooApi' -import { Button, Spinner } from 'flowbite-react' +import { Skeleton } from '@chakra-ui/react' const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => { const router = useRouter() @@ -39,7 +39,8 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => { name: product.name, price: getLowestPrice(), stock: product.stockTotal, - weight: product.weight + weight: product.weight, + isFlashSale: product.isFlashsale }) useEffect(() => { @@ -50,7 +51,8 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => { name: product.name, price: product.price, stock: product.stock, - weight: product.weight + weight: product.weight, + isFlashSale: product.isFlashsale }) } }, [selectedVariant, product]) @@ -80,6 +82,7 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => { }) setAddCartAlert(true) } + console.log('ini log', activeVariant) const handleClickBuy = () => { if (!validAction()) return @@ -89,7 +92,7 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => { quantity, programLineId: null, selected: true, - source : 'buy' + source: 'buy' }) router.push(`/shop/checkout?source=buy`) } @@ -139,47 +142,47 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => { </div> <h1 className='leading-6 font-medium mb-3'>{activeVariant?.name}</h1> - {activeVariant?.price?.priceDiscount > 0 ? ( + {activeVariant.isFlashsale ? ( <> <div className='flex gap-x-1 items-center'> - <div className='text-gray_r-11 text-caption-1'>Harga Sebelum PPN :</div> - <div className='text-gray_r-12 line-through text-caption-1'> - {' '} + <div className='badge-solid-red'>{activeVariant?.price?.discountPercentage}%</div> + <div className='text-gray_r-11 line-through text-caption-1'> + {currencyFormat(activeVariant?.price?.price)} + </div> + <div className='text-danger-500 font-semibold'> {currencyFormat(activeVariant?.price?.priceDiscount)} </div> </div> - <div className='mt-2'> - <span className='font-semibold '>Termasuk PPN :</span> - <div className='flex gap-x-2 items-center mt-2'> - {activeVariant?.price?.discountPercentage > 0 && ( - <> - <div className='badge-solid-red'> - {activeVariant?.price?.discountPercentage}% - </div> - <div className='text-gray_r-11 line-through text-caption-1'> - {currencyFormat(activeVariant?.price?.price * 1.11)} - </div> - </> - )} - <h3 className='text-danger-500 font-semibold'> - {currencyFormat(activeVariant?.price?.priceDiscount * 1.11)} - </h3> - </div> + <div className='text-gray_r-9 text-base font-normal mt-1'> + Termasuk PPN:{' '} + {currencyFormat(activeVariant?.price.priceDiscount * process.env.NEXT_PUBLIC_PPN)} </div> </> ) : ( - <span className='text-gray_r-11 leading-6 font-normal'> - Hubungi kami untuk dapatkan harga terbaik, - <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> + <h3 className='text-danger-500 font-semibold mt-1'> + {activeVariant?.price?.priceDiscount > 0 ? ( + <> + {currencyFormat(activeVariant?.price?.priceDiscount)} + <div className='text-gray_r-9 text-base font-normal mt-1'> + Termasuk PPN:{' '} + {currencyFormat(activeVariant?.price.priceDiscount * process.env.NEXT_PUBLIC_PPN)} + </div> + </> + ) : ( + <span className='text-gray_r-11 leading-6 font-normal'> + Hubungi kami untuk dapatkan harga terbaik, + <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> + )} + </h3> )} </div> @@ -230,10 +233,7 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => { <SpecificationContent label='Ketersediaan'> <span> {isLoadingSLA ? ( - <Button color='gray'> - <Spinner aria-label='Alternate spinner button example' /> - <span className='pl-3'>Loading...</span> - </Button> + <Skeleton width='100px' height='full' /> ) : product?.sla?.slaDate != '-' ? ( <button type='button' @@ -267,7 +267,7 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => { </svg> </div> </button> - ): ( + ) : ( '-' )} </span> diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx index 10ffdaec..16c63c00 100644 --- a/src/lib/product/components/ProductCard.jsx +++ b/src/lib/product/components/ProductCard.jsx @@ -82,30 +82,47 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { )} <Link href={createSlug('/shop/product/', product?.name, product?.id)} - className={`mb-2 !text-gray_r-12 leading-6 block ${ + className={`mb-3 !text-gray_r-12 leading-6 block ${ simpleTitle ? 'line-clamp-2 h-12' : 'line-clamp-3 h-[64px]' }`} title={product?.name} > {product?.name} </Link> - {product?.lowestPrice.discountPercentage > 0 && ( - <div className='flex gap-x-1 mb-1 items-center'> - <div className='text-gray_r-11 line-through text-[11px] sm:text-caption-2'> - {currencyFormat(product.lowestPrice.price)} + {product?.flashSale?.id > 0 ? ( + <> + {product?.lowestPrice.discountPercentage > 0 && ( + <div className='flex gap-x-1 mb-1 items-center'> + <div className='text-gray_r-11 line-through text-[11px] sm:text-caption-2'> + {currencyFormat(product.lowestPrice.price)} + </div> + <div className='badge-solid-red'>{product?.lowestPrice.discountPercentage}%</div> + </div> + )} + + <div className='text-danger-500 font-semibold mb-2'> + {product?.lowestPrice.priceDiscount > 0 ? ( + currencyFormat(product?.lowestPrice.priceDiscount) + ) : ( + <a href={callForPriceWhatsapp}>Call for price</a> + )} </div> - <div className='badge-solid-red'>{product?.lowestPrice.discountPercentage}%</div> + </> + ) : ( + <div className='text-danger-500 font-semibold mb-2 min-h-[40px]'> + {product?.lowestPrice.price > 0 ? ( + <> + {currencyFormat(product?.lowestPrice.price)} + <div className='text-gray_r-9 text-[11px] font-normal sm:text-caption-2 mt-2'> + + PPN: {currencyFormat(product.lowestPrice.price * process.env.NEXT_PUBLIC_PPN)} + </div> + </> + ) : ( + <a href={callForPriceWhatsapp}>Call for price</a> + )} </div> )} - <div className='text-danger-500 font-semibold mb-2'> - {product?.lowestPrice.priceDiscount > 0 ? ( - currencyFormat(product?.lowestPrice.priceDiscount) - ) : ( - <a href={callForPriceWhatsapp}>Call for price</a> - )} - </div> - {product?.stockTotal > 0 && ( <div className='flex gap-x-1'> <div className='badge-solid-red'>Ready Stock</div> @@ -169,30 +186,46 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { )} <Link href={createSlug('/shop/product/', product?.name, product?.id)} - className={`mb-2 !text-gray_r-12 leading-6 ${ + className={`mb-3 !text-gray_r-12 leading-6 ${ simpleTitle ? 'line-clamp-2' : 'line-clamp-3' }`} > {product?.name} </Link> + {product?.flashSale?.id > 0 ? ( + <> + {product?.lowestPrice.discountPercentage > 0 && ( + <div className='flex gap-x-1 mb-1 items-center'> + <div className='badge-solid-red'>{product?.lowestPrice?.discountPercentage}%</div> + <div className='text-gray_r-11 line-through text-caption-2'> + {currencyFormat(product?.lowestPrice?.price)} + </div> + </div> + )} - {product?.lowestPrice?.discountPercentage > 0 && ( - <div className='flex gap-x-1 mb-1 items-center'> - <div className='badge-solid-red'>{product?.lowestPrice?.discountPercentage}%</div> - <div className='text-gray_r-11 line-through text-caption-2'> - {currencyFormat(product?.lowestPrice?.price)} + <div className='text-danger-500 font-semibold mb-2'> + {product?.lowestPrice?.priceDiscount > 0 ? ( + currencyFormat(product?.lowestPrice?.priceDiscount) + ) : ( + <a href={callForPriceWhatsapp}>Call for price</a> + )} </div> + </> + ) : ( + <div className='text-danger-500 font-semibold mb-2 min-h-[40px]'> + {product?.lowestPrice.price > 0 ? ( + <> + {currencyFormat(product?.lowestPrice.price)} + <div className='text-gray_r-9 text-[11px] sm:text-caption-2 font-normal mt-2'> + + PPN: {currencyFormat(product.lowestPrice.price * process.env.NEXT_PUBLIC_PPN)} + </div> + </> + ) : ( + <a href={callForPriceWhatsapp}>Call for price</a> + )} </div> )} - <div className='text-danger-500 font-semibold mb-2'> - {product?.lowestPrice?.priceDiscount > 0 ? ( - currencyFormat(product?.lowestPrice?.priceDiscount) - ) : ( - <a href={callForPriceWhatsapp}>Call for price</a> - )} - </div> - {product?.stockTotal > 0 && ( <div className='flex gap-x-1'> <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 ce6c12ed..b64349c7 100644 --- a/src/lib/product/components/ProductFilterDesktop.jsx +++ b/src/lib/product/components/ProductFilterDesktop.jsx @@ -2,7 +2,21 @@ import { useRouter } from 'next/router' import { useState } from 'react' import _ from 'lodash' import { toQuery } from 'lodash-contrib' -import { Accordion, Checkbox, Label, TextInput } from 'flowbite-react' +import { + Accordion, + AccordionButton, + AccordionIcon, + AccordionItem, + AccordionPanel, + Box, + Button, + Checkbox, + Input, + InputGroup, + InputLeftAddon, + Stack, + VStack +} from '@chakra-ui/react' const ProductFilterDesktop = ({ brands, categories, prefixUrl, defaultBrand = null }) => { const router = useRouter() @@ -13,7 +27,7 @@ const ProductFilterDesktop = ({ brands, categories, prefixUrl, defaultBrand = nu const [priceFrom, setPriceFrom] = useState(query?.priceFrom) const [priceTo, setPriceTo] = useState(query?.priceTo) - const handleCategorysChange = (event) => { + const handleCategoriesChange = (event) => { const value = event.target.value const isChecked = event.target.checked if (isChecked) { @@ -48,80 +62,95 @@ const ProductFilterDesktop = ({ brands, categories, prefixUrl, defaultBrand = nu return ( <> - <Accordion flush={true} alwaysOpen={true}> - <Accordion.Panel> - <Accordion.Title>Kategori</Accordion.Title> - <Accordion.Content className='overflow-auto max-h-[200px]'> - <div className='flex flex-col gap-4 scroll-snap' id='checkbox'> + <Accordion defaultIndex={[0]} allowMultiple> + <AccordionItem> + <AccordionButton padding={[2, 4]}> + <Box as='span' flex='1' textAlign='left' fontWeight='semibold'> + Brand + </Box> + <AccordionIcon /> + </AccordionButton> + + <AccordionPanel> + <Stack gap={3} direction='column' maxH={'240px'} overflow='auto'> + {brands.map((brand, index) => ( + <div className='flex items-center gap-2' key={index}> + <Checkbox + isChecked={brandValues.includes(brand)} + onChange={handleBrandsChange} + value={brand} + size='md' + > + {brand} + </Checkbox> + </div> + ))} + </Stack> + </AccordionPanel> + </AccordionItem> + + <AccordionItem> + <AccordionButton padding={[2, 4]}> + <Box as='span' flex='1' textAlign='left' fontWeight='semibold'> + Kategori + </Box> + <AccordionIcon /> + </AccordionButton> + + <AccordionPanel> + <Stack gap={3} direction='column' maxH={'240px'} overflow='auto'> {categories.map((category, index) => ( <div className='flex items-center gap-2' key={index}> <Checkbox - id={`categoryOption${index}`} - checked={categoryValues.includes(category)} - onChange={handleCategorysChange} + isChecked={categoryValues.includes(category)} + onChange={handleCategoriesChange} value={category} - /> - <Label htmlFor={`categoryOption${index}`} className='dark:text-gray_r-12/80'> + size='md' + > {category} - </Label> + </Checkbox> </div> ))} - </div> - </Accordion.Content> - </Accordion.Panel> - <Accordion.Panel> - {!defaultBrand && ( - <> - <Accordion.Title>Brand</Accordion.Title> - <Accordion.Content className='overflow-auto max-h-[200px]'> - <div className='flex flex-col gap-4 scroll-snap' id='checkbox'> - {brands.map((brand, index) => ( - <div className='flex items-center gap-2' key={index}> - <Checkbox - id={`brandOption${index}`} - checked={brandValues.includes(brand)} - onChange={handleBrandsChange} - value={brand} - /> - <Label htmlFor={`brandOption${index}`} className='dark:text-gray_r-12/80'> - {brand} - </Label> - </div> - ))} - </div> - </Accordion.Content> - </> - )} - </Accordion.Panel> - <Accordion.Panel> - <Accordion.Title>Harga</Accordion.Title> - <Accordion.Content> - <div className='mb-3'> - <TextInput - placeholder='Harga Minimum' - addon='Rp' - type='number' - value={priceFrom} - onChange={(e) => setPriceFrom(e.target.value)} - /> - </div> - <div className='mb-3'> - <TextInput - placeholder='Harga Maximum' - addon='Rp' - type='number' - value={priceTo} - onChange={(e) => setPriceTo(e.target.value)} - /> - </div> - </Accordion.Content> - </Accordion.Panel> + </Stack> + </AccordionPanel> + </AccordionItem> + + <AccordionItem> + <AccordionButton padding={[2, 4]}> + <Box as='span' flex='1' textAlign='left' fontWeight='semibold'> + Harga + </Box> + <AccordionIcon /> + </AccordionButton> + + <AccordionPanel paddingY={4}> + <VStack gap={4}> + <InputGroup> + <InputLeftAddon>Rp</InputLeftAddon> + <Input + type='number' + placeholder='Harga minimum' + value={priceFrom} + onChange={(e) => setPriceFrom(e.target.value)} + /> + </InputGroup> + <InputGroup> + <InputLeftAddon>Rp</InputLeftAddon> + <Input + type='number' + placeholder='Harga maximum' + value={priceTo} + onChange={(e) => setPriceTo(e.target.value)} + /> + </InputGroup> + </VStack> + </AccordionPanel> + </AccordionItem> </Accordion> - <div className='p-5'> - <button type='button' className='btn-solid-red w-full mt-6' onClick={handleSubmit}> - Terapkan - </button> - </div> + + <Button className='w-full mt-6' colorScheme='red' onClick={handleSubmit}> + Terapkan + </Button> </> ) } diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index ae9618d2..df9aa91b 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -39,9 +39,11 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { const oddIndexSuggestions = response.data.spellcheck.suggestions.filter( (_, index) => index % 2 === 1 ) + const oddIndexCollations = response.data.spellcheck.collations.filter( (_, index) => index % 2 === 1 ) + const dataSpellings = oddIndexSuggestions.reduce((acc, curr) => { oddIndexCollations.forEach((collation) => { acc.push(collation.collationQuery) @@ -52,7 +54,9 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { return acc }, []) - setQ(dataSpellings[0]) + if (dataSpellings.length > 0) { + setQ(dataSpellings[0]) + } setSpellings(dataSpellings) }) @@ -183,7 +187,7 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { defaultBrand={defaultBrand} /> </div> - <div className='w-9/12 p-3'> + <div className='w-9/12 pl-6'> <h1 className='text-2xl mb-2 font-semibold'>Hasil Pencarian</h1> <div className='flex justify-between items-center mb-2'> <div className='mb-2 leading-6 text-gray_r-11'> diff --git a/src/lib/product/components/ProductSlider.jsx b/src/lib/product/components/ProductSlider.jsx index dedbd6ab..54f209cc 100644 --- a/src/lib/product/components/ProductSlider.jsx +++ b/src/lib/product/components/ProductSlider.jsx @@ -10,7 +10,7 @@ import MobileView from '@/core/components/views/MobileView' import DesktopView from '@/core/components/views/DesktopView' const bannerClassName = - 'absolute rounded-r top-0 left-0 h-full w-auto md:w-[20%] idt-transition border border-gray_r-6' + 'absolute rounded-r top-0 left-0 h-full w-auto md:w-[20%] border border-gray_r-6' const ProductSlider = ({ products, simpleTitle = false, bannerMode = false }) => { const bannerRef = useRef('') |
