import NextImage from 'next/image'; import { useRouter } from 'next/router'; import { useEffect, useMemo, useState } from 'react'; import { HStack, Image, Tag, TagCloseButton, TagLabel } from '@chakra-ui/react'; import axios from 'axios'; import _ from 'lodash'; import { toQuery } from 'lodash-contrib'; import odooApi from '@/core/api/odooApi'; import searchSpellApi from '@/core/api/searchSpellApi'; import Link from '@/core/components/elements/Link/Link'; import Pagination from '@/core/components/elements/Pagination/Pagination'; import DesktopView from '@/core/components/views/DesktopView'; import MobileView from '@/core/components/views/MobileView'; import useActive from '@/core/hooks/useActive'; import { formatCurrency } from '@/core/utils/formatValue'; import { createSlug } from '@/core/utils/slug'; import whatsappUrl from '@/core/utils/whatsappUrl'; import useProductSearch from '../hooks/useProductSearch'; import ProductCard from './ProductCard'; import ProductFilter from './ProductFilter'; import ProductFilterDesktop from './ProductFilterDesktop'; import ProductSearchSkeleton from './Skeleton/ProductSearchSkeleton'; import SideBanner from '~/modules/side-banner'; import FooterBanner from '~/modules/footer-banner'; const ProductSearch = ({ query, prefixUrl, defaultBrand = null, brand = null, }) => { const router = useRouter(); const { page = 1 } = query; const [q, setQ] = useState(query?.q || '*'); const [search, setSearch] = useState(query?.q || '*'); const [limit, setLimit] = useState(query?.limit || 30); const [orderBy, setOrderBy] = useState(router.query?.orderBy || 'popular'); if (defaultBrand) query.brand = defaultBrand.toLowerCase(); const { productSearch } = useProductSearch({ query: { ...query, q, limit, orderBy }, operation: 'AND', }); const [products, setProducts] = useState(null); const [spellings, setSpellings] = useState(null); const [bannerPromotionHeader, setBannerPromotionHeader] = useState(null); const [bannerPromotionFooter, setBannerPromotionFooter] = useState(null); const [isBrand, setIsBrand] = useState(null); const popup = useActive(); const numRows = [30, 50, 80, 100]; const [brandValues, setBrand] = useState( !router.pathname.includes('brands') ? query.brand ? query.brand.split(',') : [] : [] ); const [categoryValues, setCategory] = useState( query?.category?.split(',') || [] ); const [priceFrom, setPriceFrom] = useState(query?.priceFrom || null); const [priceTo, setPriceTo] = useState(query?.priceTo || null); const pageCount = Math.ceil(productSearch.data?.response.numFound / limit); const productStart = productSearch.data?.responseHeader.params.start; const productRows = limit; const productFound = productSearch.data?.response.numFound; useEffect(() => { if (productFound == 0 && query.q && !spellings) { searchSpellApi({ query: query.q }).then((response) => { 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); }); curr.suggestion.forEach((s) => { if (!acc.includes(s.word)) acc.push(s.word); }); return acc; }, []); if (dataSpellings.length > 0) { setQ(dataSpellings[0]); } setSpellings(dataSpellings); }); } }, [productFound, query, spellings]); useEffect(() => { const checkIfBrand = async () => { const brand = await axios( `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/brands?params=search&q=${search}` ); if (brand.data.length > 0) { setIsBrand(brand?.data[0]); } else { setIsBrand(null); } }; if (router.pathname.includes('search') && q !== '*') { checkIfBrand(); } }, [q]); const brands = []; for ( let i = 0; i < productSearch.data?.facetCounts?.facetFields?.manufactureNameS.length; i += 2 ) { const brand = productSearch.data?.facetCounts?.facetFields?.manufactureNameS[i]; const qty = productSearch.data?.facetCounts?.facetFields?.manufactureNameS[i + 1]; if (qty > 0) { brands.push({ brand, qty }); } } const categories = []; for ( let i = 0; i < productSearch.data?.facetCounts?.facetFields?.categoryName.length; i += 2 ) { const name = productSearch.data?.facetCounts?.facetFields?.categoryName[i]; const qty = productSearch.data?.facetCounts?.facetFields?.categoryName[i + 1]; if (qty > 0) { categories.push({ name, qty }); } } const orderOptions = [ { value: 'price-asc', label: 'Harga Terendah' }, { value: 'price-desc', label: 'Harga Tertinggi' }, { value: 'popular', label: 'Populer' }, { value: 'stock', label: 'Ready Stock' }, ]; const handleOrderBy = (e) => { let params = { ...router.query, orderBy: e.target.value, }; params = _.pickBy(params, _.identity); params = toQuery(params); router.push(`${prefixUrl}?${params}`); }; const handleLimit = (e) => { let params = { ...router.query, limit: e.target.value, }; params = _.pickBy(params, _.identity); params = toQuery(params); router.push(`${prefixUrl}?${params}`); }; const getBanner = async () => { if (router.pathname.includes('search')) { const getBannerHeader = await odooApi( 'GET', '/api/v1/banner?type=promotion-header' ); const getBannerFooter = await odooApi( 'GET', '/api/v1/banner?type=promotion-footer' ); var randomIndex = Math.floor(Math.random() * getBannerHeader.length); var randomIndexFooter = Math.floor( Math.random() * getBannerFooter.length ); setBannerPromotionHeader(getBannerHeader[randomIndex]); setBannerPromotionFooter(getBannerFooter[randomIndexFooter]); } }; useEffect(() => { getBanner(); }, []); useEffect(() => { setProducts(productSearch.data?.response?.products); }, [productSearch]); const SpellingComponent = useMemo(() => { return ( <> {spellings?.length > 0 ? ( <>Mungkin yang anda cari ) : ( <>Produk yang cari anda tidak ada )} {spellings?.map((spelling, i) => ( {spelling} {i + 1 < spellings.length ? ', ' : ''} ))} ); }, [spellings]); const handleDeleteFilter = async (source, value) => { let params = { q: router.query.q, orderBy: orderBy, brand: brandValues.join(','), category: categoryValues.join(','), priceFrom, priceTo, }; let brands = brandValues; let catagories = categoryValues; switch (source) { case 'brands': brands = brandValues.filter((item) => item !== value); params.brand = brands.join(','); await setBrand(brands); break; case 'category': catagories = categoryValues.filter((item) => item !== value); params.category = catagories.join(','); await setCategory(catagories); break; case 'price': params.priceFrom = null; params.priceTo = null; break; case 'delete': params = { q: router.query.q, orderBy: orderBy, }; break; } handleSubmitFilter(params); }; const handleSubmitFilter = (params) => { params = _.pickBy(params, _.identity); params = toQuery(params); router.push(`${prefixUrl}?${params}`); }; const isNotReadyStockPage = router.asPath !== '/shop/search?orderBy=stock'; return ( <> {productSearch.isLoading && }
{isNotReadyStockPage && isBrand && isBrand.logo && (

Brand Pencarian {q}

)}

Produk

{!spellings ? ( <> Menampilkan  {pageCount > 1 ? ( <> {productStart + 1}- {parseInt(productStart) + parseInt(productRows) > productFound ? productFound : parseInt(productStart) + parseInt(productRows)}  dari  ) : ( '' )} {productFound}  produk{' '} {query.q && ( <> untuk pencarian{' '} {query.q} )} ) : ( SpellingComponent )}
{productFound > 0 && (
)}
{products && products.map((product) => ( ))}
{brand && (
Produk dari brand:
{brand?.data?.logo && ( {brand?.data?.name} )} {!brand?.data?.logo && (
{brand?.data?.name}
)}
)}
{bannerPromotionHeader && bannerPromotionHeader?.image && (
)} {isNotReadyStockPage && isBrand && isBrand.logo && (

Brand Pencarian {q}

)}

Hasil Pencarian

{!spellings ? ( <> Menampilkan  {pageCount > 1 ? ( <> {productStart + 1}- {parseInt(productStart) + parseInt(productRows) > productFound ? productFound : parseInt(productStart) + parseInt(productRows)}  dari  ) : ( '' )} {productFound}  produk{' '} {query.q && ( <> untuk pencarian{' '} {query.q} )} ) : ( SpellingComponent )}
{productSearch.isLoading && }
{products && products.map((product) => ( ))}
Barang yang anda cari tidak ada?{' '} Hubungi Kami
{bannerPromotionFooter && bannerPromotionFooter?.image && (
)}
); }; export default ProductSearch; const FilterChoicesComponent = ({ brandValues, categoryValues, priceFrom, priceTo, handleDeleteFilter, }) => (
{brandValues?.map((value, index) => ( {value} handleDeleteFilter('brands', value)} /> ))} {categoryValues?.map((value, index) => ( {value} handleDeleteFilter('category', value)} /> ))} {priceFrom && priceTo && ( {formatCurrency(priceFrom) + '-' + formatCurrency(priceTo)} handleDeleteFilter('price', priceFrom)} /> )} {brandValues?.length > 0 || categoryValues?.length > 0 || priceFrom || priceTo ? ( ) : ( '' )}
);