diff options
Diffstat (limited to 'src/lib/home/components')
| -rw-r--r-- | src/lib/home/components/CategoryDynamic.jsx | 108 | ||||
| -rw-r--r-- | src/lib/home/components/CategoryDynamicMobile.jsx | 101 | ||||
| -rw-r--r-- | src/lib/home/components/CategoryPilihan.jsx | 120 | ||||
| -rw-r--r-- | src/lib/home/components/PreferredBrand.jsx | 46 | ||||
| -rw-r--r-- | src/lib/home/components/PromotionProgram.jsx | 5 | ||||
| -rw-r--r-- | src/lib/home/components/Skeleton/BannerPromoSkeleton.jsx | 16 |
6 files changed, 16 insertions, 380 deletions
diff --git a/src/lib/home/components/CategoryDynamic.jsx b/src/lib/home/components/CategoryDynamic.jsx deleted file mode 100644 index 0cc43d91..00000000 --- a/src/lib/home/components/CategoryDynamic.jsx +++ /dev/null @@ -1,108 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import useCategoryManagement from '../hooks/useCategoryManagement'; -import NextImage from 'next/image'; -import Link from "next/link"; -import { createSlug } from '@/core/utils/slug'; -import odooApi from '@/core/api/odooApi'; -import { Skeleton} from '@chakra-ui/react' - -const CategoryDynamic = () => { - const { categoryManagement } = useCategoryManagement(); - const [categoryData, setCategoryData] = useState({}); - const [subCategoryData, setSubCategoryData] = useState({}); - - useEffect(() => { - const fetchCategoryData = async () => { - if (categoryManagement && categoryManagement.data) { - const updatedCategoryData = {}; - const updatedSubCategoryData = {}; - - for (const category of categoryManagement.data) { - const countLevel1 = await odooApi('GET', `/api/v1/category/numFound?parent_id=${category.categoryIdI}`); - - updatedCategoryData[category.categoryIdI] = countLevel1?.numFound; - - for (const subCategory of countLevel1.children) { - updatedSubCategoryData[subCategory.id] = subCategory.numFound; - } - } - - setCategoryData(updatedCategoryData); - setSubCategoryData(updatedSubCategoryData); - } - }; - - fetchCategoryData(); - }, [categoryManagement.isLoading]); - - return ( - <div> - {categoryManagement && categoryManagement.data?.map((category) => { - const countLevel1 = categoryData[category.categoryIdI] || 0; - - return ( - <Skeleton key={category.id} isLoaded={categoryManagement}> - <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> - </div> - <div className='grid grid-cols-3 gap-2'> - {category.categories.map((subCategory) => { - const countLevel2 = subCategoryData[subCategory.idLevel2] || 0; - - return ( - <div key={subCategory.id} className='border rounded justify-start items-start'> - <div className='p-3'> - <div className='flex flex-row border rounded mb-2 justify-start items-center'> - <NextImage - src={subCategory.image ? subCategory.image : "/images/noimage.jpeg"} - alt={subCategory.name} - width={90} - height={30} - className='object-fit' - /> - <div className='bagian-judul flex flex-col justify-center items-start gap-2 ml-2'> - <div className='font-semibold text-lg mr-2'>{subCategory.name}</div> - <Skeleton isLoaded={countLevel2 != 0}> - <p className={`text-gray_r-10 text-sm`}> - {countLevel2} Produk tersedia - </p> - </Skeleton> - <Link href={createSlug('/shop/category/', subCategory?.name, subCategory?.idLevel2)} 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]'> - {subCategory.childFrontendIdI.map((childCategory) => ( - <div key={childCategory.id}> - <Link href={createSlug('/shop/category/', childCategory?.name, childCategory?.idLevel3)} 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} - width={40} - height={40} - /> - <div className='bagian-judul flex flex-col justify-center items-center gap-2 break-words line-clamp-2 group-hover:text-red-500'> - <div className='font-semibold line-clamp-2 group-hover:text-red-500 text-sm mr-2'>{childCategory.name}</div> - </div> - </Link> - </div> - ))} - </div> - </div> - </div> - ); - })} - </div> - </div> - </Skeleton> - ); - })} - </div> - ); -}; - -export default CategoryDynamic; diff --git a/src/lib/home/components/CategoryDynamicMobile.jsx b/src/lib/home/components/CategoryDynamicMobile.jsx deleted file mode 100644 index c1433a2d..00000000 --- a/src/lib/home/components/CategoryDynamicMobile.jsx +++ /dev/null @@ -1,101 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import useCategoryManagement from '../hooks/useCategoryManagement'; -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'; - -const CategoryDynamicMobile = () => { - const { categoryManagement } = useCategoryManagement() - const [selectedCategory, setSelectedCategory] = useState({}); - - useEffect(() => { - const loadPromo = async () => { - try { - if (categoryManagement.data?.length > 0) { - const initialSelections = categoryManagement.data.reduce((acc, category) => { - if (category.categories.length > 0) { - acc[category.id] = category.categories[0].idLevel2; - } - return acc; - }, {}); - setSelectedCategory(initialSelections); - } - } catch (loadError) { - // console.error("Error loading promo items:", loadError); - } - }; - - loadPromo(); - }, [categoryManagement.data]); - - const handleCategoryLevel2Click = (categoryIdI, idLevel2) => { - setSelectedCategory(prev => ({ - ...prev, - [categoryIdI]: idLevel2 - })); - }; - - return ( - <div className='p-4'> - {categoryManagement.data && categoryManagement.data.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> - <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'}`} - > - <div className='p-1 flex justify-start items-center'> - <div className='flex flex-row justify-center items-center'> - <NextImage - src={index.image ? index.image : "/images/noimage.jpeg"} - alt={index.name} - width={30} - height={30} - className='object-' - /> - <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> - <p className='text-gray_r-10 text-[10px]'>999 rb+ Produk</p> - </div> - </div> - </div> - </div> - </SwiperSlide> - ))} - </Swiper> - <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) => ( - <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"> - <NextImage - src={x.image ? x.image : "/images/noimage.jpeg"} - alt={x.name} - width={40} - height={40} - /> - <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> - </Link> - </div> - )) - ))} - </div> - </div> - </div> - ))} - </div> - ); -}; - -export default CategoryDynamicMobile; diff --git a/src/lib/home/components/CategoryPilihan.jsx b/src/lib/home/components/CategoryPilihan.jsx deleted file mode 100644 index 6568621c..00000000 --- a/src/lib/home/components/CategoryPilihan.jsx +++ /dev/null @@ -1,120 +0,0 @@ -import Image from 'next/image' -import useCategoryHome from '../hooks/useCategoryHome' -import Link from '@/core/components/elements/Link/Link' -import { createSlug } from '@/core/utils/slug' -import { useEffect, useState } from 'react'; -import { bannerApi } from '../../../api/bannerApi'; -const { useQuery } = require('react-query') -import { HeroBannerSkeleton } from '../../../components/skeleton/BannerSkeleton'; -import useCategoryPilihan from '../hooks/useCategoryPilihan'; -import useDevice from '@/core/hooks/useDevice' -import { Swiper, SwiperSlide } from 'swiper/react'; -import 'swiper/css'; - -const CategoryPilihan = ({ id, categories }) => { - const { isDesktop, isMobile } = useDevice() - const { categoryPilihan } = useCategoryPilihan(); - const heroBanner = useQuery('categoryPilihan', bannerApi({ type: 'banner-category-list' })); - return ( - <section> - {isDesktop && ( - <div> - <div className='flex flex-row items-center mb-4'> - <div className='font-semibold sm:text-h-lg mr-2'>LOB Kategori Pilihan</div> - <p className='text-gray_r-10 text-sm'>200 Rb+ Produk Unggulan & 800+ Brand Rekomendasi tersedia!</p> - </div> - {heroBanner.data && - heroBanner.data?.length > 0 && ( - <div className='flex w-full h-full justify-center mb-4 bg-cover bg-center'> - <Link key={heroBanner.data[0].id} href={heroBanner.data[0].url}> - <Image - width={1260} - height={170} - quality={100} - src={heroBanner.data[0].image} - alt={heroBanner.data[0].name} - className='h-full object-cover w-full' - /> - </Link> - </div> - )} - <div className="group/item grid grid-cols-6 gap-y-2 w-full h-full col-span-2 "> - {categoryPilihan?.data?.map((category) => ( - <div key={category.id} className="KartuInti h-48 w-60 max-w-sm lg:max-w-full flex flex-col border-[1px] border-gray-200 relative group"> - <div className='KartuB absolute h-48 w-60 inset-0 flex items-center justify-center '> - <div className="group/edit flex items-center justify-end h-48 w-60 flex-col group-hover/item:visible"> - <div className=' h-36 flex justify-end items-end'> - <Image className='group-hover:scale-105 transition-transform duration-300 ' src={category?.image? category?.image : '/images/noimage.jpeg'} width={120} height={120} alt={category?.name} /> - </div> - <h2 className="text-gray-700 content-center h-12 border-t-[1px] px-1 w-60 border-gray-200 font-normal text-sm text-center">{category?.industries}</h2> - </div> - </div> - <div className='KartuA relative inset-0 flex h-36 w-60 items-center justify-center opacity-0 group-hover:opacity-75 group-hover:bg-[#E20613] transition-opacity '> - <Link - href={createSlug('/shop/lob/', category?.industries, category?.id)} - className='category-mega-box__parent text-white rounded-lg' - > - Lihat semua - </Link> - </div> - </div> - ))} - </div> - </div> - )} - {isMobile && ( - <div className='p-4'> - <div className='flex flex-row items-center mb-4'> - <div className='font-semibold sm:text-h-md mr-2'>LOB Kategori Pilihan</div> - {/* <p className='text-gray_r-10 text-sm'>200 Rb+ Produk Unggulan & 800+ Brand Rekomendasi tersedia!</p> */} - </div> - <div className='flex'> - {heroBanner.data && - heroBanner.data?.length > 0 && ( - <div className=' object-fill '> - <Link key={heroBanner.data[0].id} href={heroBanner.data[0].url}> - <Image - width={439} - height={150} - quality={100} - src={heroBanner.data[0].image} - alt={heroBanner.data[0].name} - className='object-cover' - /> - </Link> - </div> - )} - </div> - <Swiper slidesPerView={2.1} spaceBetween={10}> - {categoryPilihan?.data?.map((category) => ( - <SwiperSlide key={category.id}> - <div key={category.id} className="KartuInti mt-2 h-48 w-48 max-w-sm lg:max-w-full flex flex-col border-[1px] border-gray-200 relative group"> - <div className='KartuB absolute h-48 w-48 inset-0 flex items-center justify-center '> - <div className="group/edit flex items-center justify-end h-48 w-48 flex-col group-hover/item:visible"> - <div className=' h-36 flex justify-end items-end'> - <Image className='group-hover:scale-105 transition-transform duration-300 ' src={category?.image? category?.image : '/images/noimage.jpeg'} width={120} height={120} alt={category?.name} /> - </div> - <h2 className="text-gray-700 content-center h-12 border-t-[1px] px-1 w-48 border-gray-200 font-normal text-sm text-center">{category?.industries}</h2> - </div> - </div> - <div className='KartuA relative inset-0 flex h-36 w-48 items-center justify-center opacity-0 group-hover:opacity-75 group-hover:bg-[#E20613] transition-opacity '> - <Link - href={createSlug('/shop/lob/', category?.industries, category?.id)} - className='category-mega-box__parent text-white rounded-lg' - > - Lihat semua - </Link> - </div> - </div> - </SwiperSlide> - ))} - - </Swiper> - - </div> - )} - </section> - ) -} - -export default CategoryPilihan diff --git a/src/lib/home/components/PreferredBrand.jsx b/src/lib/home/components/PreferredBrand.jsx index ae12505d..6b64a444 100644 --- a/src/lib/home/components/PreferredBrand.jsx +++ b/src/lib/home/components/PreferredBrand.jsx @@ -1,5 +1,4 @@ import { Swiper, SwiperSlide } from 'swiper/react' -import { Navigation, Pagination, Autoplay } from 'swiper'; import { useCallback, useEffect, useState } from 'react' import usePreferredBrand from '../hooks/usePreferredBrand' import PreferredBrandSkeleton from './Skeleton/PreferredBrandSkeleton' @@ -39,23 +38,7 @@ const PreferredBrand = () => { const { preferredBrands } = usePreferredBrand(query) const { isMobile, isDesktop } = useDevice() - const swiperBanner = { - modules:[Navigation, Pagination, Autoplay], - autoplay: { - delay: 4000, - disableOnInteraction: false - }, - loop: true, - className: 'h-[70px] md:h-[100px] w-full', - slidesPerView: isMobile ? 4 : 8, - spaceBetween: isMobile ? 12 : 0, - pagination: { - dynamicBullets: true, - dynamicMainBullets: isMobile ? 6 : 8, - clickable: true, - } - } - const preferredBrandsData = manufactures ? manufactures.slice(0, 20) : [] + return ( <div className='px-4 sm:px-0'> <div className='flex justify-between items-center mb-4'> @@ -65,21 +48,24 @@ const PreferredBrand = () => { Lihat Semua </Link> )} - </div> - <div className='border rounded border-gray_r-6'> - {manufactures.isLoading && <PreferredBrandSkeleton />} - {!manufactures.isLoading && ( - <Swiper {...swiperBanner}> - {preferredBrandsData.map((manufacture) => ( - <SwiperSlide key={manufacture.id}> - <BrandCard brand={manufacture} /> - </SwiperSlide> - ))} - </Swiper> + {isMobile && ( + <Link href='/shop/brands' className='!text-red-500 font-semibold sm:text-h-sm'> + Lihat Semua + </Link> )} </div> + {manufactures.isLoading && <PreferredBrandSkeleton />} + {!manufactures.isLoading && ( + <Swiper slidesPerView={isMobile ? 3.5 : 7.5} spaceBetween={isMobile ? 12 : 24} freeMode> + {manufactures.map((manufacture) => ( + <SwiperSlide key={manufacture.id}> + <BrandCard brand={manufacture} /> + </SwiperSlide> + ))} + </Swiper> + )} </div> ) } -export default PreferredBrand
\ No newline at end of file +export default PreferredBrand diff --git a/src/lib/home/components/PromotionProgram.jsx b/src/lib/home/components/PromotionProgram.jsx index c2f76069..99258d94 100644 --- a/src/lib/home/components/PromotionProgram.jsx +++ b/src/lib/home/components/PromotionProgram.jsx @@ -3,16 +3,11 @@ import Image from 'next/image' import { bannerApi } from '@/api/bannerApi'; import useDevice from '@/core/hooks/useDevice' import { Swiper, SwiperSlide } from 'swiper/react'; -import BannerPromoSkeleton from '../components/Skeleton/BannerPromoSkeleton'; const { useQuery } = require('react-query') const BannerSection = () => { const promotionProgram = useQuery('promotionProgram', bannerApi({ type: 'banner-promotion' })); const { isMobile, isDesktop } = useDevice() - if (promotionProgram.isLoading) { - return <BannerPromoSkeleton />; - } - return ( <div className='px-4 sm:px-0'> <div className='flex justify-between items-center mb-4 '> diff --git a/src/lib/home/components/Skeleton/BannerPromoSkeleton.jsx b/src/lib/home/components/Skeleton/BannerPromoSkeleton.jsx deleted file mode 100644 index c5f39f19..00000000 --- a/src/lib/home/components/Skeleton/BannerPromoSkeleton.jsx +++ /dev/null @@ -1,16 +0,0 @@ -import useDevice from '@/core/hooks/useDevice' -import Skeleton from 'react-loading-skeleton' - -const BannerPromoSkeleton = () => { - const { isDesktop } = useDevice() - - return ( - <div className='grid grid-cols-1 md:grid-cols-3 gap-x-3'> - {Array.from({ length: isDesktop ? 3 : 1.2 }, (_, index) => ( - <Skeleton count={1} height={isDesktop ? 60 : 36} key={index} /> - ))} - </div> - ) -} - -export default BannerPromoSkeleton |
