From 70591a6a132d25656e4404d78d6364e21949e81a Mon Sep 17 00:00:00 2001 From: "HATEC\\SPVDEV001" Date: Fri, 20 Oct 2023 09:29:48 +0700 Subject: filter choices --- src/core/utils/formatValue.js | 11 ++- .../product/components/ProductFilterDesktop.jsx | 10 +- src/lib/product/components/ProductSearch.jsx | 109 ++++++++++++++++++++- 3 files changed, 119 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/core/utils/formatValue.js b/src/core/utils/formatValue.js index f2c17769..f0f65c69 100644 --- a/src/core/utils/formatValue.js +++ b/src/core/utils/formatValue.js @@ -7,4 +7,13 @@ const sellingProductFormat = (value) => { } } -export { sellingProductFormat } +const formatCurrency = (value) => { + if (value >= 1000) { + const thousands = Math.floor(value / 1000) // Menghitung ribuan + return `Rp${thousands}k` + } else { + return `Rp${value}` + } +} + +export { sellingProductFormat, formatCurrency} diff --git a/src/lib/product/components/ProductFilterDesktop.jsx b/src/lib/product/components/ProductFilterDesktop.jsx index 6118ed6b..e4a62abb 100644 --- a/src/lib/product/components/ProductFilterDesktop.jsx +++ b/src/lib/product/components/ProductFilterDesktop.jsx @@ -18,6 +18,7 @@ import { VStack } from '@chakra-ui/react' import Image from '@/core/components/elements/Image/Image' +import { formatCurrency } from '@/core/utils/formatValue' const ProductFilterDesktop = ({ brands, categories, prefixUrl, defaultBrand = null }) => { const router = useRouter() @@ -104,14 +105,7 @@ const ProductFilterDesktop = ({ brands, categories, prefixUrl, defaultBrand = nu router.push(`${prefixUrl}?${params}`) } - const formatCurrency = (value) => { - if (value >= 1000) { - const thousands = Math.floor(value / 1000) // Menghitung ribuan - return `Rp${thousands}k` - } else { - return `Rp${value}` - } - } + /*const handleIndexAccordion = async () => { if (brandValues) { diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index 9d59b305..bc69c9dd 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -15,8 +15,9 @@ import { useRouter } from 'next/router' import searchSpellApi from '@/core/api/searchSpellApi' import Link from '@/core/components/elements/Link/Link' import whatsappUrl from '@/core/utils/whatsappUrl' -import { Image } from '@chakra-ui/react' +import { HStack, Image, Tag, TagCloseButton, TagLabel } from '@chakra-ui/react' import odooApi from '@/core/api/odooApi' +import { formatCurrency } from '@/core/utils/formatValue' const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { const router = useRouter() @@ -32,6 +33,10 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { const [bannerPromotionFooter, setBannerPromotionFooter] = useState(null) const popup = useActive() const numRows = [30, 50, 80, 100] + const [brandValues, setBrand] = useState(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 @@ -98,7 +103,7 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { categories.push({ name, qty }) } } - + /*const categories = productSearch.data?.facetCounts?.facetFields?.categoryName?.filter( (value, index) => { if (index % 2 === 0) { @@ -166,12 +171,62 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { ) }, [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}`) + } + return ( <> {productSearch.isLoading && }

Produk

+
{!spellings ? ( @@ -271,6 +326,13 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { )}

Hasil Pencarian

+
{!spellings ? ( @@ -388,3 +450,46 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { } 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 ? ( + + + + ) : ( + '' + )} + +
+) -- cgit v1.2.3 From b8f5507cda2ede25ebc5433439168a8dadc71ddc Mon Sep 17 00:00:00 2001 From: "HATEC\\SPVDEV001" Date: Fri, 20 Oct 2023 10:26:15 +0700 Subject: fixing serach --- src/lib/product/components/ProductSearch.jsx | 9 +++++++-- src/lib/product/hooks/useProductSearch.js | 4 ++-- src/pages/api/shop/search.js | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index bc69c9dd..af3d881f 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -26,18 +26,22 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { 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 } }) + const { productSearch } = useProductSearch({ query: { ...query, q, limit, orderBy } , operation : router?.pathname?.includes('brands') ? 'OR' : 'AND' }) const [products, setProducts] = useState(null) const [spellings, setSpellings] = useState(null) const [bannerPromotionHeader, setBannerPromotionHeader] = useState(null) const [bannerPromotionFooter, setBannerPromotionFooter] = useState(null) const popup = useActive() const numRows = [30, 50, 80, 100] - const [brandValues, setBrand] = useState(query?.brand?.split(',') || []) + 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) + console.log('ini roiute', router.pathname.includes('brands')) + const pageCount = Math.ceil(productSearch.data?.response.numFound / limit) const productStart = productSearch.data?.responseHeader.params.start const productRows = limit @@ -466,6 +470,7 @@ const FilterChoicesComponent = ({ handleDeleteFilter('brands', value)} /> ))} + {categoryValues.map((value, index) => ( {value} diff --git a/src/lib/product/hooks/useProductSearch.js b/src/lib/product/hooks/useProductSearch.js index 4c9272f1..f3b7530a 100644 --- a/src/lib/product/hooks/useProductSearch.js +++ b/src/lib/product/hooks/useProductSearch.js @@ -2,9 +2,9 @@ import { useQuery } from 'react-query' import productSearchApi from '../api/productSearchApi' import _ from 'lodash-contrib' -const useProductSearch = ({ query }) => { +const useProductSearch = ({ query, operation }) => { const queryString = _.toQuery(query) - const fetchProductSearch = async () => await productSearchApi({ query: queryString }) + const fetchProductSearch = async () => await productSearchApi({ query: queryString , operation : operation}) const productSearch = useQuery(`productSearch-${queryString}`, fetchProductSearch) return { diff --git a/src/pages/api/shop/search.js b/src/pages/api/shop/search.js index b4d67c5d..883bb8df 100644 --- a/src/pages/api/shop/search.js +++ b/src/pages/api/shop/search.js @@ -67,7 +67,7 @@ export default async function handler(req, res) { } if (brand) parameter.push(`fq=manufacture_name:${brand.replace(/,/g, ' OR ')}`) - if (category) parameter.push(`fq=category_name:${category}`) + if (category) parameter.push(`fq=category_name:${category.replace(/,/g, ' OR ')}`) if (stock) parameter.push(`fq=stock_total_f:{1 TO *}`) // Single fq in url params -- cgit v1.2.3 From 40c30c5ea9a61ce39e6faf72504a141afa2d1505 Mon Sep 17 00:00:00 2001 From: "HATEC\\SPVDEV001" Date: Fri, 20 Oct 2023 11:11:58 +0700 Subject: items center untuk filter urutan dan page limit --- src/lib/product/components/ProductSearch.jsx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index af3d881f..a4e3d872 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -40,8 +40,6 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { const [priceFrom, setPriceFrom] = useState(query?.priceFrom || null) const [priceTo, setPriceTo] = useState(query?.priceTo || null) - console.log('ini roiute', router.pathname.includes('brands')) - const pageCount = Math.ceil(productSearch.data?.response.numFound / limit) const productStart = productSearch.data?.responseHeader.params.start const productRows = limit @@ -337,8 +335,8 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { priceTo={priceTo} handleDeleteFilter={handleDeleteFilter} /> -
-
+
+
{!spellings ? ( <> Menampilkan  @@ -369,7 +367,7 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => {
handleLimit(e)} > -- cgit v1.2.3 From 85e0a7e47db518fb5fb2531b2ea7c6d50408875f Mon Sep 17 00:00:00 2001 From: "HATEC\\SPVDEV001" Date: Fri, 20 Oct 2023 14:02:51 +0700 Subject: logo brand di page brand --- src/lib/brand/components/Brand.jsx | 24 +++------------- src/lib/product/components/ProductSearch.jsx | 41 ++++++++++++++-------------- src/pages/shop/brands/[slug].jsx | 6 +++- 3 files changed, 30 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/lib/brand/components/Brand.jsx b/src/lib/brand/components/Brand.jsx index 4afbcb3e..78a9d5bd 100644 --- a/src/lib/brand/components/Brand.jsx +++ b/src/lib/brand/components/Brand.jsx @@ -20,8 +20,8 @@ const swiperBanner = { modules: [Pagination, Autoplay] } -const Brand = ({ id }) => { - const { brand } = useBrand({ id }) +const Brand = ({ brand }) => { + // const { brand } = useBrand({ id }) return ( <> @@ -91,7 +91,7 @@ const Brand = ({ id }) => { -
+
{ ))} -
-
Produk dari brand:
- {brand?.data?.logo && ( - {brand?.data?.name} - )} - {!brand?.data?.logo && ( -
- {brand?.data?.name} -
- )} -
+ )}
diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index a4e3d872..630e3a74 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -19,14 +19,17 @@ import { HStack, Image, Tag, TagCloseButton, TagLabel } from '@chakra-ui/react' import odooApi from '@/core/api/odooApi' import { formatCurrency } from '@/core/utils/formatValue' -const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { +const ProductSearch = ({ query, prefixUrl, defaultBrand = null, brand = null }) => { const router = useRouter() const { page = 1 } = query const [q, setQ] = 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 : router?.pathname?.includes('brands') ? 'OR' : 'AND' }) + const { productSearch } = useProductSearch({ + query: { ...query, q, limit, orderBy }, + operation: router?.pathname?.includes('brands') ? 'OR' : 'AND' + }) const [products, setProducts] = useState(null) const [spellings, setSpellings] = useState(null) const [bannerPromotionHeader, setBannerPromotionHeader] = useState(null) @@ -34,7 +37,7 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { const popup = useActive() const numRows = [30, 50, 80, 100] const [brandValues, setBrand] = useState( - !router.pathname.includes('brands') ? query.brand ? query.brand.split(',') : [] : [] + !router.pathname.includes('brands') ? (query.brand ? query.brand.split(',') : []) : [] ) const [categoryValues, setCategory] = useState(query?.category?.split(',') || []) const [priceFrom, setPriceFrom] = useState(query?.priceFrom || null) @@ -87,15 +90,6 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { brands.push({ brand, qty }) } } - /*const brandsList = productSearch.data?.facetCounts?.facetFields?.manufactureName?.filter( - (value, index) => { - if (index % 2 === 0) { - const brand = value - const qty = index + 1 - brands.push({ brand, qty }) - } - } - )*/ const categories = [] for (let i = 0; i < productSearch.data?.facetCounts?.facetFields?.categoryName.length; i += 2) { @@ -106,14 +100,6 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { } } - /*const categories = productSearch.data?.facetCounts?.facetFields?.categoryName?.filter( - (value, index) => { - if (index % 2 === 0) { - return true - } - } - )*/ - const orderOptions = [ { value: 'price-asc', label: 'Harga Terendah' }, { value: 'price-desc', label: 'Harga Tertinggi' }, @@ -309,6 +295,21 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => {
+
+
Produk dari brand:
+ {brand?.data?.logo && ( + {brand?.data?.name} + )} + {!brand?.data?.logo && ( +
+ {brand?.data?.name} +
+ )} +
import('@/core/components/layouts/BasicLayout')) const ProductSearch = dynamic(() => import('@/lib/product/components/ProductSearch')) @@ -14,6 +15,8 @@ export default function BrandDetail() { const { slug = '' } = router.query const brandName = getNameFromSlug(slug) + const id = getIdFromSlug(slug) + const {brand} = useBrand({id}) return ( - + {!_.isEmpty(router.query) && ( )} -- cgit v1.2.3 From 4310c68248520d265879fbc0a2fc094f7f3e3b52 Mon Sep 17 00:00:00 2001 From: "HATEC\\SPVDEV001" Date: Fri, 20 Oct 2023 15:06:08 +0700 Subject: feedback testing - filter by brand (ada brand lain yang ikut) --- src/lib/product/components/ProductSearch.jsx | 35 +++++++++++++++------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index 630e3a74..d094a25b 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -28,7 +28,7 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null, brand = null }) if (defaultBrand) query.brand = defaultBrand.toLowerCase() const { productSearch } = useProductSearch({ query: { ...query, q, limit, orderBy }, - operation: router?.pathname?.includes('brands') ? 'OR' : 'AND' + operation: 'OR' }) const [products, setProducts] = useState(null) const [spellings, setSpellings] = useState(null) @@ -295,21 +295,24 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null, brand = null })
-
-
Produk dari brand:
- {brand?.data?.logo && ( - {brand?.data?.name} - )} - {!brand?.data?.logo && ( -
- {brand?.data?.name} -
- )} -
+ {brand && ( +
+
Produk dari brand:
+ {brand?.data?.logo && ( + {brand?.data?.name} + )} + {!brand?.data?.logo && ( +
+ {brand?.data?.name} +
+ )} +
+ )} + Date: Mon, 23 Oct 2023 15:40:04 +0700 Subject: bugs fix query solr filter brand dan category --- src/lib/product/components/ProductSearch.jsx | 2 +- src/pages/api/shop/search.js | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index d094a25b..79df93f4 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -28,7 +28,7 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null, brand = null }) if (defaultBrand) query.brand = defaultBrand.toLowerCase() const { productSearch } = useProductSearch({ query: { ...query, q, limit, orderBy }, - operation: 'OR' + operation: 'AND' }) const [products, setProducts] = useState(null) const [spellings, setSpellings] = useState(null) diff --git a/src/pages/api/shop/search.js b/src/pages/api/shop/search.js index 883bb8df..576d028a 100644 --- a/src/pages/api/shop/search.js +++ b/src/pages/api/shop/search.js @@ -66,8 +66,9 @@ export default async function handler(req, res) { ) } - if (brand) parameter.push(`fq=manufacture_name:${brand.replace(/,/g, ' OR ')}`) - if (category) parameter.push(`fq=category_name:${category.replace(/,/g, ' OR ')}`) + if (brand) parameter.push(`fq=${brand.split(',').map(manufacturer => `manufacture_name:"${manufacturer}"`).join(" OR ")}`) + if (category) parameter.push(`fq=${category.split(',').map(cat => `category_name:"${cat}"`).join(' OR ')}`) + // if (category) parameter.push(`fq=category_name:${capitalizeFirstLetter(category.replace(/,/g, ' OR '))}`) if (stock) parameter.push(`fq=stock_total_f:{1 TO *}`) // Single fq in url params -- cgit v1.2.3 From 84d81890283155056c26058df65939f4837b14b4 Mon Sep 17 00:00:00 2001 From: "HATEC\\SPVDEV001" Date: Mon, 23 Oct 2023 15:48:06 +0700 Subject: CR UI - change label if product not found --- src/lib/product/components/ProductSearch.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index 79df93f4..5fc75930 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -28,7 +28,7 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null, brand = null }) if (defaultBrand) query.brand = defaultBrand.toLowerCase() const { productSearch } = useProductSearch({ query: { ...query, q, limit, orderBy }, - operation: 'AND' + operation: 'AND' }) const [products, setProducts] = useState(null) const [spellings, setSpellings] = useState(null) @@ -148,7 +148,7 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null, brand = null }) const SpellingComponent = useMemo(() => { return ( <> - Mungkin yang anda cari{' '} + {spellings?.length > 0 ? <>Mungkin yang anda cari : <>Produk yang anda tidak ada} {spellings?.map((spelling, i) => ( {spelling} -- cgit v1.2.3 From 7c08e60acc68f4fbd3ff6af756aeae7c1e7b866c Mon Sep 17 00:00:00 2001 From: "HATEC\\SPVDEV001" Date: Tue, 24 Oct 2023 10:02:44 +0700 Subject: change label --- src/lib/product/components/ProductSearch.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index 5fc75930..3740d264 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -148,7 +148,7 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null, brand = null }) const SpellingComponent = useMemo(() => { return ( <> - {spellings?.length > 0 ? <>Mungkin yang anda cari : <>Produk yang anda tidak ada} + {spellings?.length > 0 ? <>Mungkin yang anda cari : <>Produk yang cari anda tidak ada} {spellings?.map((spelling, i) => ( {spelling} -- cgit v1.2.3