diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/components/elements/Sidebar/Sidebar.jsx | 193 | ||||
| -rw-r--r-- | src/lib/home/api/categoryManagementApi.js | 61 | ||||
| -rw-r--r-- | src/lib/home/components/CategoryDynamic.jsx | 38 | ||||
| -rw-r--r-- | src/lib/home/components/CategoryDynamicMobile.jsx | 45 | ||||
| -rw-r--r-- | src/lib/home/hooks/useCategoryManagement.js | 13 | ||||
| -rw-r--r-- | src/lib/product/components/CategorySection.jsx | 7 | ||||
| -rw-r--r-- | src/pages/api/shop/promo.js | 2 | ||||
| -rw-r--r-- | src/pages/shop/brands/[slug].jsx | 7 |
8 files changed, 185 insertions, 181 deletions
diff --git a/src/core/components/elements/Sidebar/Sidebar.jsx b/src/core/components/elements/Sidebar/Sidebar.jsx index 55838890..ddae3e20 100644 --- a/src/core/components/elements/Sidebar/Sidebar.jsx +++ b/src/core/components/elements/Sidebar/Sidebar.jsx @@ -5,6 +5,8 @@ import { AnimatePresence, motion } from 'framer-motion' import { ChevronDownIcon, ChevronUpIcon, CogIcon, UserIcon } from '@heroicons/react/24/outline' import { Fragment, useEffect, useState } from 'react' import odooApi from '@/core/api/odooApi' +import { createSlug } from '@/core/utils/slug' +import Image from 'next/image' const Sidebar = ({ active, close }) => { const auth = useAuth() @@ -79,7 +81,7 @@ const Sidebar = ({ active, close }) => { exit={{ left: '-80%' }} transition={transition} > - <div className='divide-y divide-gray_r-6'> + <div className='divide-y divide-gray_r-6 h-full flex flex-col'> <div className='p-4 flex gap-x-3'> {!auth && ( <> @@ -112,104 +114,115 @@ const Sidebar = ({ active, close }) => { href='/my/menu' className='!text-gray_r-11 ml-auto my-auto' > - <UserIcon class='h-6 w-6 text-gray-500' /> + <UserIcon className='h-6 w-6 text-gray-500' /> </Link> </> )} </div> - <SidebarLink className={itemClassName} href='/shop/promo'> - Semua Promo - </SidebarLink> - <SidebarLink className={itemClassName} href='/shop/brands'> - Semua Brand - </SidebarLink> - <SidebarLink - className={itemClassName} - href='https://blog.indoteknik.com/' - target='_blank' - rel='noreferrer noopener' - > - Blog Indoteknik - </SidebarLink> - {/* <SidebarLink className={itemClassName} href='/video'> - Indoteknik TV - </SidebarLink> */} - <SidebarLink className={itemClassName} href='/tentang-kami'> - Tentang Indoteknik - </SidebarLink> - <SidebarLink className={itemClassName} href='/contact-us'> - Hubungi Kami - </SidebarLink> - <button - className={`${itemClassName} w-full text-left flex`} - onClick={() => setOpenCategory(!isOpenCategory)} - > - Kategori - <div className='ml-auto'> - {!isOpenCategory && <ChevronDownIcon className='text-gray_r-12 w-5' />} - {isOpenCategory && <ChevronUpIcon className='text-gray_r-12 w-5' />} - </div> - </button> - {isOpenCategory && - categories.map((category) => ( - <Fragment key={category.id}> - <div className='flex w-full text-gray_r-11 border-b border-gray_r-6 px-4 pl-8 items-center'> - <Link - href={`/shop/search?category=${category.name}`} - className='flex-1 font-normal !text-gray_r-11 py-4' - > - {category.name} - </Link> - <div - className='ml-4 h-full py-4' - onClick={() => toggleCategories(category.id)} - > - {!category.isOpen && <ChevronDownIcon className='text-gray_r-11 w-5' />} - {category.isOpen && <ChevronUpIcon className='text-gray_r-11 w-5' />} + <div className='overflow-y-auto flex-1'> + <SidebarLink className={itemClassName} href='/shop/promo'> + Semua Promo + </SidebarLink> + <SidebarLink className={itemClassName} href='/shop/brands'> + Semua Brand + </SidebarLink> + <SidebarLink + className={itemClassName} + href='https://blog.indoteknik.com/' + target='_blank' + rel='noreferrer noopener' + > + Blog Indoteknik + </SidebarLink> + {/* <SidebarLink className={itemClassName} href='/video'> + Indoteknik TV + </SidebarLink> */} + <SidebarLink className={itemClassName} href='/tentang-kami'> + Tentang Indoteknik + </SidebarLink> + <SidebarLink className={itemClassName} href='/contact-us'> + Hubungi Kami + </SidebarLink> + <button + className={`${itemClassName} w-full text-left flex`} + onClick={() => setOpenCategory(!isOpenCategory)} + > + Kategori + <div className='ml-auto'> + {!isOpenCategory && <ChevronDownIcon className='text-gray_r-12 w-5' />} + {isOpenCategory && <ChevronUpIcon className='text-gray_r-12 w-5' />} + </div> + </button> + {isOpenCategory && + categories.map((category) => ( + <Fragment key={category.id}> + <div className='flex w-full text-gray_r-11 border-b border-gray_r-6 px-4 pl-8 items-center'> + <Link + href={createSlug('/shop/category/', category.name, category.id)} + className='flex-1 font-normal !text-gray_r-11 py-4 flex items-center flex-row' + > + <div className='mr-2 flex justify-center items-center'> + <Image src={category.image} alt='' width={25} height={25} /> + </div> + {category.name} + </Link> + <div + className='ml-4 h-full py-4' + onClick={() => toggleCategories(category.id)} + > + {!category.isOpen && <ChevronDownIcon className='text-gray_r-11 w-5' />} + {category.isOpen && <ChevronUpIcon className='text-gray_r-11 w-5' />} + </div> </div> - </div> - {category.isOpen && - category.childs.map((child1Category) => ( - <Fragment key={child1Category.id}> - <div - className={`flex w-full !text-gray_r-11 border-b border-gray_r-6 p-4 pl-12 ${ - category.isOpen ? 'bg-gray_r-2' : '' - }`} - > - <Link - href={`/shop/search?category=${child1Category.name}`} - className='flex-1 font-normal !text-gray_r-11' + {category.isOpen && + category.childs.map((child1Category) => ( + <Fragment key={child1Category.id}> + <div + className={`flex w-full !text-gray_r-11 border-b border-gray_r-6 p-4 pl-12 ${ + category.isOpen ? 'bg-gray_r-2' : '' + }`} > - {child1Category.name} - </Link> - {child1Category.childs.length > 0 && ( - <div - className='ml-4 h-full' - onClick={() => toggleCategories(child1Category.id)} - > - {!child1Category.isOpen && ( - <ChevronDownIcon className='text-gray_r-11 w-5' /> - )} - {child1Category.isOpen && ( - <ChevronUpIcon className='text-gray_r-11 w-5' /> - )} - </div> - )} - </div> - {child1Category.isOpen && - child1Category.childs.map((child2Category) => ( <Link - key={child2Category.id} - href={`/shop/search?category=${child2Category.name}`} - className='flex w-full font-normal !text-gray_r-11 border-b border-gray_r-6 p-4 pl-16' + href={createSlug('/shop/category/', child1Category.name, child1Category.id)} + className='flex-1 font-normal !text-gray_r-11 flex flex-row items-center' > - {child2Category.name} + <div className='mr-2 flex justify-center items-center'> + <Image src={`https://erp.indoteknik.com/api/image/product.public.category/image_1920/${child1Category.id}`} alt='' width={25} height={25} /> + </div> + {child1Category.name} </Link> - ))} - </Fragment> - ))} - </Fragment> - ))} + {child1Category.childs.length > 0 && ( + <div + className='ml-4 h-full' + onClick={() => toggleCategories(child1Category.id)} + > + {!child1Category.isOpen && ( + <ChevronDownIcon className='text-gray_r-11 w-5' /> + )} + {child1Category.isOpen && ( + <ChevronUpIcon className='text-gray_r-11 w-5' /> + )} + </div> + )} + </div> + {child1Category.isOpen && + child1Category.childs.map((child2Category) => ( + <Link + key={child2Category.id} + href={createSlug('/shop/category/', child2Category.name, child2Category.id)} + className='flex w-full font-normal !text-gray_r-11 border-b border-gray_r-6 p-4 pl-16 flex-row' + > + <div className='mr-2 flex justify-center items-center'> + <Image src={`https://erp.indoteknik.com/api/image/product.public.category/image_1920/${child2Category.id}`} alt='' width={25} height={25} /> + </div> + {child2Category.name} + </Link> + ))} + </Fragment> + ))} + </Fragment> + ))} + </div> </div> </motion.div> </> diff --git a/src/lib/home/api/categoryManagementApi.js b/src/lib/home/api/categoryManagementApi.js index 63edd629..0aeb2aac 100644 --- a/src/lib/home/api/categoryManagementApi.js +++ b/src/lib/home/api/categoryManagementApi.js @@ -1,43 +1,40 @@ -// import odooApi from '@/core/api/odooApi' - -// const categoryManagementApi = async () => { -// const dataCategoryManagement = await odooApi('GET', '/api/v1/categories_management') -// return dataCategoryManagement -// } - -// export default categoryManagementApi - - - -export const fetchPopulerProductSolr = async (category_id_ids) => { - let sort ='sort=qty_sold_f desc'; +export const fetchCategoryManagementSolr = async () => { + let sort ='sort=sequence_i asc'; try { - const queryParams = new URLSearchParams({ q: category_id_ids }); - const response = await fetch(`/solr/category_management/query?q=*:*&q.op=OR&indent=true`); + const response = await fetch(`/solr/category_management/query?q=*:*&q.op=OR&indent=true&${sort}&&rows=20`); if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); + throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); - const promotions = await map(data.response.docs); - return promotions; - } catch (error) { - console.error("Error fetching promotion data:", error); - return []; - } - }; - - const map = async (promotions) => { - const result = []; - for (const promotion of promotions) { - const data = { + const promotions = await map(data.response.docs); + return promotions; + } catch (error) { + console.error("Error fetching promotion data:", error); + return []; + } + }; + + const map = async (promotions) => { + return promotions.map((promotion) =>{ + let parsedCategories = promotion.categories.map(category => { + // Parse string JSON utama + let parsedCategory = JSON.parse(category); + + // Parse setiap elemen di child_frontend_id_i jika ada + if (parsedCategory.child_frontend_id_i) { + parsedCategory.child_frontend_id_i = parsedCategory.child_frontend_id_i.map(child => JSON.parse(child)); + } + + return parsedCategory; + }); + let productMapped = { id: promotion.id, name: promotion.name_s, image: promotion.image_s, sequence: promotion.sequence_i, numFound: promotion.numFound_i, - categories_level_2:promotion.categories_level_2 + categories: parsedCategories }; - result.push(data); - } - return result; + return productMapped; + }) };
\ No newline at end of file diff --git a/src/lib/home/components/CategoryDynamic.jsx b/src/lib/home/components/CategoryDynamic.jsx index 11a15d6d..ca104ada 100644 --- a/src/lib/home/components/CategoryDynamic.jsx +++ b/src/lib/home/components/CategoryDynamic.jsx @@ -1,6 +1,5 @@ import React, { useEffect, useState, useCallback } from 'react'; -import useCategoryManagement from '../hooks/useCategoryManagement'; -import {fetchPopulerProductSolr} from '../api/categoryManagementApi' +import {fetchCategoryManagementSolr} from '../api/categoryManagementApi' import NextImage from 'next/image'; import Link from "next/link"; import { createSlug } from '@/core/utils/slug'; @@ -14,28 +13,20 @@ import { Navigation, Pagination, Autoplay } from 'swiper'; const CategoryDynamic = () => { - const [manufactures, setManufactures] = useState([]) + const [categoryManagement, setCategoryManagement] = useState([]) + const [isLoading, setIsLoading] = useState(false) const loadBrand = useCallback(async () => { - // setIsLoading(true) - //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 items = await fetchPopulerProductSolr(); - - console.log("items",items) + setIsLoading(true) + const items = await fetchCategoryManagementSolr(); - // setIsLoading(false) - // setManufactures((manufactures) => [...result.data]) + setIsLoading(false) + setCategoryManagement(items) }, []) useEffect(() => { loadBrand() }, [loadBrand]) - const { categoryManagement } = useCategoryManagement(); + // const [categoryData, setCategoryData] = useState({}); // const [subCategoryData, setSubCategoryData] = useState({}); @@ -76,18 +67,17 @@ const CategoryDynamic = () => { return ( <div> - {categoryManagement && categoryManagement.data?.map((category) => { + {categoryManagement && categoryManagement?.map((category) => { // const countLevel1 = categoryData[category.categoryIdI] || 0; - return ( - <Skeleton key={category.id} isLoaded={categoryManagement}> + <Skeleton key={category.id} isLoaded={!isLoading}> <div key={category.id}> <div className='bagian-judul flex flex-row justify-start items-center gap-3 mb-4 mt-4'> <div className='font-semibold sm:text-h-lg mr-2'>{category.name}</div> {/* <Skeleton isLoaded={countLevel1 != 0}> <p className={`text-gray_r-10 text-sm`}>{countLevel1} Produk tersedia</p> </Skeleton> */} - <Link href={createSlug('/shop/category/', category?.name, category?.categoryIdI)} className="!text-red-500 font-semibold">Lihat Semua</Link> + <Link href={createSlug('/shop/category/', category?.name, category?.id)} className="!text-red-500 font-semibold">Lihat Semua</Link> </div> {/* Swiper for SubCategories */} @@ -115,13 +105,13 @@ const CategoryDynamic = () => { {countLevel2} Produk tersedia </p> </Skeleton> */} - <Link href={createSlug('/shop/category/', subCategory?.name, subCategory?.idLevel2)} className="!text-red-500 font-semibold">Lihat Semua</Link> + <Link href={createSlug('/shop/category/', subCategory?.name, subCategory?.id_level_2)} className="!text-red-500 font-semibold">Lihat Semua</Link> </div> </div> <div className='grid grid-cols-2 gap-2 overflow-y-auto max-h-[240px] min-h-[240px] content-start'> - {subCategory.childFrontendIdI.map((childCategory) => ( + {subCategory.child_frontend_id_i.map((childCategory) => ( <div key={childCategory.id} className=''> - <Link href={createSlug('/shop/category/', childCategory?.name, childCategory?.idLevel3)} className="flex flex-row gap-2 border rounded group hover:border-red-500"> + <Link href={createSlug('/shop/category/', childCategory?.name, childCategory?.id_level_3)} className="flex flex-row gap-2 border rounded group hover:border-red-500"> <NextImage src={childCategory.image ? childCategory.image : "/images/noimage.jpeg"} alt={childCategory.name} diff --git a/src/lib/home/components/CategoryDynamicMobile.jsx b/src/lib/home/components/CategoryDynamicMobile.jsx index 2877a5a7..1061f3e4 100644 --- a/src/lib/home/components/CategoryDynamicMobile.jsx +++ b/src/lib/home/components/CategoryDynamicMobile.jsx @@ -1,22 +1,35 @@ -import React, { useEffect, useState } from 'react'; -import useCategoryManagement from '../hooks/useCategoryManagement'; +import React, { useEffect, useState, useCallback } from 'react'; import NextImage from 'next/image'; import Link from "next/link"; import { createSlug } from '@/core/utils/slug'; import { Swiper, SwiperSlide } from 'swiper/react'; import 'swiper/css'; +import {fetchCategoryManagementSolr} from '../api/categoryManagementApi' const CategoryDynamicMobile = () => { - const { categoryManagement } = useCategoryManagement() const [selectedCategory, setSelectedCategory] = useState({}); + const [categoryManagement, setCategoryManagement] = useState([]) + const [isLoading, setIsLoading] = useState(false) + + const loadBrand = useCallback(async () => { + setIsLoading(true) + const items = await fetchCategoryManagementSolr(); + + setIsLoading(false) + setCategoryManagement(items) + }, []) + + useEffect(() => { + loadBrand() + }, [loadBrand]) useEffect(() => { const loadPromo = async () => { try { - if (categoryManagement.data?.length > 0) { - const initialSelections = categoryManagement.data.reduce((acc, category) => { + if (categoryManagement?.length > 0) { + const initialSelections = categoryManagement.reduce((acc, category) => { if (category.categories.length > 0) { - acc[category.id] = category.categories[0].idLevel2; + acc[category.id] = category.categories[0].id_level_2; } return acc; }, {}); @@ -28,7 +41,7 @@ const CategoryDynamicMobile = () => { }; loadPromo(); - }, [categoryManagement.data]); + }, [categoryManagement]); const handleCategoryLevel2Click = (categoryIdI, idLevel2) => { setSelectedCategory(prev => ({ @@ -39,18 +52,18 @@ const CategoryDynamicMobile = () => { return ( <div className='p-4'> - {categoryManagement.data && categoryManagement.data.map((category) => ( + {categoryManagement && categoryManagement?.map((category) => ( <div key={category.id}> <div className='bagian-judul flex flex-row justify-between items-center gap-3 mb-4 mt-4'> - <div className='font-semibold sm:text-h-sm mr-2'>{category.name}</div> - <Link href={createSlug('/shop/category/', category?.name, category?.categoryIdI)} className="!text-red-500 font-semibold text-sm">Lihat Semua</Link> + <div className='font-semibold sm:text-h-sm mr-2'>{category?.name}</div> + <Link href={createSlug('/shop/category/', category?.name, category?.id)} className="!text-red-500 font-semibold text-sm">Lihat Semua</Link> </div> <Swiper slidesPerView={2.3} spaceBetween={10}> {category.categories.map((index) => ( <SwiperSlide key={index.id}> <div - onClick={() => handleCategoryLevel2Click(category.id, index?.idLevel2)} - className={`border flex justify-start items-center max-w-48 max-h-16 rounded ${selectedCategory[category.id] === index?.idLevel2 ? 'bg-red-50 border-red-500 text-red-500' : 'border-gray-200 text-gray-900'}`} + onClick={() => handleCategoryLevel2Click(category.id, index?.id_level_2)} + className={`border flex justify-start items-center max-w-48 max-h-16 rounded ${selectedCategory[category.id] === index?.id_level_2 ? 'bg-red-50 border-red-500 text-red-500' : 'border-gray-200 text-gray-900'}`} > <div className='p-1 flex justify-start items-center'> <div className='flex flex-row justify-center items-center'> @@ -62,7 +75,7 @@ const CategoryDynamicMobile = () => { className='' /> <div className='bagian-judul flex flex-col justify-center items-start gap-1 ml-2'> - <div className='font-semibold text-[10px] line-clamp-1'>{index.name}</div> + <div className='font-semibold text-[10px] line-clamp-1'>{index?.name}</div> </div> </div> </div> @@ -73,9 +86,9 @@ const CategoryDynamicMobile = () => { <div className='p-3 mt-2 border'> <div className='grid grid-cols-2 gap-2 overflow-y-auto max-h-[240px]'> {category.categories.map((index) => ( - selectedCategory[category.id] === index?.idLevel2 && index.childFrontendIdI.map((x) => ( + selectedCategory[category.id] === index?.id_level_2 && index?.child_frontend_id_i.map((x) => ( <div key={x.id}> - <Link href={createSlug('/shop/category/', x?.name, x?.idLevel3)} className="flex flex-row gap-1 border rounded group hover:border-red-500"> + <Link href={createSlug('/shop/category/', x?.name, x?.id_level_3)} className="flex flex-row gap-1 border rounded group hover:border-red-500"> <NextImage src={x.image ? x.image : "/images/noimage.jpeg"} alt={x.name} @@ -84,7 +97,7 @@ const CategoryDynamicMobile = () => { className='p-2' /> <div className='bagian-judul flex flex-col justify-center items-start gap-1 break-words line-clamp-2 group-hover:text-red-500'> - <div className='font-semibold line-clamp-2 group-hover:text-red-500 text-[10px]'>{x.name}</div> + <div className='font-semibold line-clamp-2 group-hover:text-red-500 text-[10px]'>{x?.name}</div> </div> </Link> </div> diff --git a/src/lib/home/hooks/useCategoryManagement.js b/src/lib/home/hooks/useCategoryManagement.js deleted file mode 100644 index c1dda585..00000000 --- a/src/lib/home/hooks/useCategoryManagement.js +++ /dev/null @@ -1,13 +0,0 @@ -import categoryManagementApi from '../api/categoryManagementApi' -import { useQuery } from 'react-query' - -const useCategoryManagement = () => { - const fetchCategoryManagement = async () => await categoryManagementApi() - const { isLoading, data } = useQuery('categoryManagementApi', fetchCategoryManagement) - - return { - categoryManagement: { data, isLoading } - } -} - -export default useCategoryManagement
\ No newline at end of file diff --git a/src/lib/product/components/CategorySection.jsx b/src/lib/product/components/CategorySection.jsx index e8ebb095..a287fa78 100644 --- a/src/lib/product/components/CategorySection.jsx +++ b/src/lib/product/components/CategorySection.jsx @@ -63,7 +63,7 @@ const CategorySection = ({ categories }) => { {isMobile && ( <div className="py-4"> <Swiper slidesPerView={2.3} spaceBetween={10}> - {displayedCategories.map((category) => ( + {categories.map((category) => ( <SwiperSlide key={category?.id}> <Link href={createSlug('/shop/category/', category?.name, category?.id)} passHref> <div className="group transition-colors duration-300"> @@ -74,6 +74,7 @@ const CategorySection = ({ categories }) => { width={56} height={48} alt={category?.name} + className="p-3" /> <h2 className="text-gray-700 group-hover:text-[#E20613] line-clamp-2 content-center h-fit w-60 px-1 font-semibold text-sm text-start"> {category?.name} @@ -85,7 +86,7 @@ const CategorySection = ({ categories }) => { </SwiperSlide> ))} </Swiper> - {categories.length > 10 && ( + {/* {categories.length > 10 && ( <div className="w-full flex justify-end mt-4"> <button onClick={handleToggleCategories} @@ -94,7 +95,7 @@ const CategorySection = ({ categories }) => { {isOpenCategory ? 'Sembunyikan Semua' : 'Lihat Semua'} </button> </div> - )} + )} */} </div> )} </section> diff --git a/src/pages/api/shop/promo.js b/src/pages/api/shop/promo.js index 221a9adb..f90c8559 100644 --- a/src/pages/api/shop/promo.js +++ b/src/pages/api/shop/promo.js @@ -52,6 +52,7 @@ export default async function handler(req, res) { 'facet.field=category_name', 'facet=true', 'indent=true', + `facet.limit=-1`, // `facet.query=${escapeSolrQuery(q)}`, `q.op=${operation}`, `q=${q}`, @@ -60,6 +61,7 @@ export default async function handler(req, res) { `rows=${limit}`, `sort=${paramOrderBy}`, `fq=product_ids:[* TO *]`, + `fq=active_b:true`, ]; if (priceFrom > 0 || priceTo > 0) { diff --git a/src/pages/shop/brands/[slug].jsx b/src/pages/shop/brands/[slug].jsx index 88e9b302..ed6724ea 100644 --- a/src/pages/shop/brands/[slug].jsx +++ b/src/pages/shop/brands/[slug].jsx @@ -18,9 +18,10 @@ export default function BrandDetail() { const brandName = getNameFromSlug(slug) const id = getIdFromSlug(slug) const {brand} = useBrand({id}) - if ( !brand.isLoading && _.isEmpty(brand.data)) { - return <PageNotFound />; - } + // if ( !brand.isLoading && _.isEmpty(brand.data)) { + // console.log('ini masuk pak') + // return <PageNotFound />; + // } return ( <BasicLayout> <Seo |
