diff options
| author | it-fixcomart <it@fixcomart.co.id> | 2024-07-29 15:23:01 +0700 |
|---|---|---|
| committer | it-fixcomart <it@fixcomart.co.id> | 2024-07-29 15:23:01 +0700 |
| commit | a59ed6e73a599a82d6ef248c57ad29f2ab9cb15d (patch) | |
| tree | d87d37a5dafda05e44123be8a0cf1791d086e3ae /src/lib/product | |
| parent | b951ed0de4285076a71f57a0e440b5e68d4a44bd (diff) | |
<iman> Merge branch 'Feature/category-management' into development
Diffstat (limited to 'src/lib/product')
| -rw-r--r-- | src/lib/product/components/CategorySection.jsx | 11 | ||||
| -rw-r--r-- | src/lib/product/components/LobSectionCategory.jsx | 82 | ||||
| -rw-r--r-- | src/lib/product/components/ProductSearch.jsx | 123 |
3 files changed, 196 insertions, 20 deletions
diff --git a/src/lib/product/components/CategorySection.jsx b/src/lib/product/components/CategorySection.jsx index 14a39e7e..2af3db10 100644 --- a/src/lib/product/components/CategorySection.jsx +++ b/src/lib/product/components/CategorySection.jsx @@ -13,23 +13,16 @@ import { HeartIcon, } from '@heroicons/react/24/outline'; import { useState } from 'react'; // Import useState +import { getIdFromSlug } from '@/core/utils/slug' const CategorySection = ({ categories }) => { const { isDesktop, isMobile } = useDevice(); - const router = useRouter(); const [isOpenCategory, setIsOpenCategory] = useState(false); // State to manage category visibility - let teks = router.query.slug; - let hasil = teks?.match(/(\d+)$/)[0]; - - const breadcrumbs = useQuery( - `category-breadcrumbs/${hasil}`, - async () => await odooApi('GET', `/api/v1/category/${hasil}/category-breadcrumb`) - ); - const handleToggleCategories = () => { setIsOpenCategory(!isOpenCategory); }; + const displayedCategories = isOpenCategory ? categories : categories.slice(0, 10); diff --git a/src/lib/product/components/LobSectionCategory.jsx b/src/lib/product/components/LobSectionCategory.jsx new file mode 100644 index 00000000..34a09e46 --- /dev/null +++ b/src/lib/product/components/LobSectionCategory.jsx @@ -0,0 +1,82 @@ +import Image from "next/image"; +import Link from 'next/link'; +import { createSlug } from '@/core/utils/slug'; +import useDevice from '@/core/hooks/useDevice'; +import { Swiper, SwiperSlide } from 'swiper/react'; +import 'swiper/css'; +import { useQuery } from 'react-query'; +import { useRouter } from 'next/router'; +import { + ChevronDownIcon, + ChevronUpIcon, // Import ChevronUpIcon for toggling + DocumentCheckIcon, + HeartIcon, +} from '@heroicons/react/24/outline'; +import { useState } from 'react'; // Import useState +import { getIdFromSlug } from '@/core/utils/slug' + +const LobSectionCategory = ({ categories }) => { + const { isDesktop, isMobile } = useDevice(); + const [isOpenCategory, setIsOpenCategory] = useState(false); // State to manage category visibility + + const handleToggleCategories = () => { + setIsOpenCategory(!isOpenCategory); + }; + console.log("categories",categories[0]?.categoryIds) + + const displayedCategories = categories[0]?.categoryIds; + + return ( + <section> + {isDesktop && ( + <div className="group/item grid grid-flow-col gap-y-2 gap-x-4 w-full h-full"> + {displayedCategories?.map((category) => ( + <Link + href={createSlug('/shop/category/', category?.name, category?.id)} + key={category?.id} + passHref + className="block hover:scale-105 transition-transform duration-300 bg-cover bg-center h-[144px]" + style={{ + backgroundImage: `url('${category?.image ? category?.image : 'https://erp.indoteknik.com/web/image?model=x_banner.banner&id=5&field=x_banner_image&unique=09202023100557'}')`, + }} + > + </Link> + ))} + </div> + )} + + {isMobile && ( + <div className="py-4"> + <Swiper slidesPerView={1.2} spaceBetween={10}> + {displayedCategories?.map((category) => ( + <SwiperSlide key={category?.id}> + <Link + href={createSlug('/shop/category/', category?.name, category?.id)} + key={category?.id} + passHref + className="block bg-cover bg-center h-[144px]" + style={{ + backgroundImage: `url('${category?.image ? category?.image : 'https://erp.indoteknik.com/web/image?model=x_banner.banner&id=5&field=x_banner_image&unique=09202023100557'}')`, + }} + > + </Link> + </SwiperSlide> + ))} + </Swiper> + {categories.length > 10 && ( + <div className="w-full flex justify-end mt-4"> + <button + onClick={handleToggleCategories} + className="flex justify-end mt-4 bg-red-500 text-white text-sm px-4 py-2 rounded" + > + {isOpenCategory ? 'Sembunyikan Semua' : 'Lihat Semua'} + </button> + </div> + )} + </div> + )} + </section> + ) +} + +export default LobSectionCategory diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index 34018ffe..4d510c5b 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -27,7 +27,9 @@ import ProductSearchSkeleton from './Skeleton/ProductSearchSkeleton'; import SideBanner from '~/modules/side-banner'; import FooterBanner from '~/modules/footer-banner'; import CategorySection from './CategorySection'; +import LobSectionCategory from './LobSectionCategory'; import { getIdFromSlug } from '@/core/utils/slug' +import { data } from 'autoprefixer'; const ProductSearch = ({ query, @@ -36,14 +38,105 @@ const ProductSearch = ({ 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'); + const [finalQuery, setFinalQuery] = useState({}); + const [queryFinal, setQueryFinal] = useState({}); + const [dataCategoriesProduct, setDataCategoriesProduct] = useState([]) + const [dataCategoriesLob, setDataCategoriesLob] = useState([]) + const categoryId = getIdFromSlug(prefixUrl) + const [data, setData] = useState([]) + const [dataLob, setDataLob] = useState([]); if (defaultBrand) query.brand = defaultBrand.toLowerCase(); + const dataIdCategories = [] + useEffect(() => { + if(prefixUrl.includes('category')){ + const loadProduct = async () => { + const getCategoriesId = await odooApi('GET', `/api/v1/category/numFound?parent_id=${categoryId}`); + if (getCategoriesId) { + setDataCategoriesProduct(getCategoriesId); + } + }; + loadProduct(); + }else if(prefixUrl.includes('lob')){ + const loadProduct = async () => { + const lobData = await odooApi('GET', `/api/v1/lob_homepage/${categoryId}/category_id`); + + if (lobData) { + setDataLob(lobData); + } + }; + loadProduct(); + + } + }, [categoryId]); + + const collectIds = (category) => { + const ids = []; + function recurse(cat) { + if (cat && cat.id) { + ids.push(cat.id); + } + if (Array.isArray(cat.children)) { + cat.children.forEach(recurse); + } + } + recurse(category); + return ids; + }; + + useEffect(() => { + if(prefixUrl.includes('category')){ + const ids = collectIds(dataCategoriesProduct); + const newQuery = { + fq: `category_id_ids:(${ids.join(' OR ')})`, + page, + brand : router.query.brand? router.query.brand : '', + category : router.query.category? router.query.category : '', + }; + setFinalQuery(newQuery); + } else if (prefixUrl.includes('lob')){ + + const fetchCategoryData = async () => { + if (dataLob[0]?.categoryIds) { + + for (const cate of dataLob[0].categoryIds) { + + dataIdCategories.push(cate.childId) + } + + + const mergedArray = dataIdCategories.flat(); + + const newQuery = { + fq: `category_id_ids:(${mergedArray.join(' OR ')})`, + page, + brand : router.query.brand? router.query.brand : '', + category : router.query.category? router.query.category : '', + }; + + setFinalQuery(newQuery); + + } + }; + fetchCategoryData(); + } + }, [dataCategoriesProduct, dataLob]); + + useEffect(() => { + if (prefixUrl.includes('category') || prefixUrl.includes('lob')) { + setQueryFinal({ ...finalQuery, q, limit, orderBy }); + } else { + setQueryFinal({ ...query, q, limit, orderBy }); + } + }, [prefixUrl,dataCategoriesProduct, query, finalQuery]); + const { productSearch } = useProductSearch({ - query: { ...query, q, limit, orderBy }, + query: queryFinal, operation: 'AND', }); const [products, setProducts] = useState(null); @@ -63,6 +156,7 @@ const ProductSearch = ({ const [categoryValues, setCategory] = useState( query?.category?.split(',') || [] ); + const [priceFrom, setPriceFrom] = useState(query?.priceFrom || null); const [priceTo, setPriceTo] = useState(query?.priceTo || null); @@ -71,9 +165,7 @@ const ProductSearch = ({ const productRows = limit; const productFound = productSearch.data?.response.numFound; const [dataCategories, setDataCategories] = useState([]) - - const categoryId = getIdFromSlug(prefixUrl) - + useEffect(() => { if (productFound == 0 && query.q && !spellings) { searchSpellApi({ query: query.q }).then((response) => { @@ -103,7 +195,7 @@ const ProductSearch = ({ }); } }, [productFound, query, spellings]); - + let id = [] useEffect(() => { const checkIfBrand = async () => { const brand = await axios( @@ -122,15 +214,20 @@ const ProductSearch = ({ }, [q]); useEffect(() => { - const loadCategories = async () => { - const getCategories = await odooApi('GET', `/api/v1/category/child?parent_id=${categoryId}`) - if(getCategories){ - setDataCategories(getCategories) - } + if(prefixUrl.includes('category')){ + const loadCategories = async () => { + const getCategories = await odooApi('GET', `/api/v1/category/child?parent_id=${categoryId}`) + if(getCategories){ + setDataCategories(getCategories) + } + } + loadCategories() } - loadCategories() }, []) + + + const brands = []; for ( let i = 0; @@ -277,6 +374,8 @@ const ProductSearch = ({ }; const isNotReadyStockPage = router.asPath !== '/shop/search?orderBy=stock'; + + console.log("finalQuery",finalQuery) return ( <> @@ -338,6 +437,7 @@ const ProductSearch = ({ SpellingComponent )} </div> + <LobSectionCategory categories={dataLob}/> <CategorySection categories={dataCategories}/> {productFound > 0 && ( @@ -429,6 +529,7 @@ const ProductSearch = ({ </div> <div className='w-9/12 pl-6'> + <LobSectionCategory categories={dataLob}/> <CategorySection categories={dataCategories}/> {bannerPromotionHeader && bannerPromotionHeader?.image && ( <div className='mb-3'> |
