diff options
Diffstat (limited to 'src-migrate/modules/promo/components')
| -rw-r--r-- | src-migrate/modules/promo/components/FlashSaleNonDisplay.tsx | 33 | ||||
| -rw-r--r-- | src-migrate/modules/promo/components/Hero.tsx | 103 | ||||
| -rw-r--r-- | src-migrate/modules/promo/components/HeroDiskon.tsx | 22 | ||||
| -rw-r--r-- | src-migrate/modules/promo/components/PromoList.tsx | 79 | ||||
| -rw-r--r-- | src-migrate/modules/promo/components/PromotinProgram.jsx | 223 | ||||
| -rw-r--r-- | src-migrate/modules/promo/components/Voucher.tsx | 69 |
6 files changed, 312 insertions, 217 deletions
diff --git a/src-migrate/modules/promo/components/FlashSaleNonDisplay.tsx b/src-migrate/modules/promo/components/FlashSaleNonDisplay.tsx index 1c5cc86d..5685b83a 100644 --- a/src-migrate/modules/promo/components/FlashSaleNonDisplay.tsx +++ b/src-migrate/modules/promo/components/FlashSaleNonDisplay.tsx @@ -1,20 +1,17 @@ -import dynamic from "next/dynamic"; -import React from "react"; -import { FlashSaleSkeleton } from "@/lib/flashSale/skeleton/FlashSaleSkeleton"; - +import dynamic from 'next/dynamic'; +import React from 'react'; +import { FlashSaleSkeleton } from '@/lib/flashSale/skeleton/FlashSaleSkeleton'; const FlashSaleNonDisplay = dynamic( - () => import('@/lib/flashSale/components/FlashSaleNonDisplay'), - { - loading: () => <FlashSaleSkeleton />, - } - ); - - const FlashSalePromo = ()=> { - return( - <> - <FlashSaleNonDisplay/> - </> - ) + () => import('@/lib/flashSale/components/FlashSaleNonDisplay'), + { + loading: () => <FlashSaleSkeleton />, } - - export default FlashSalePromo
\ No newline at end of file +); +const FlashSalePromo = () => { + return ( + <> + <FlashSaleNonDisplay /> + </> + ); +}; +export default FlashSalePromo; diff --git a/src-migrate/modules/promo/components/Hero.tsx b/src-migrate/modules/promo/components/Hero.tsx index c5f0afad..7d0aad11 100644 --- a/src-migrate/modules/promo/components/Hero.tsx +++ b/src-migrate/modules/promo/components/Hero.tsx @@ -3,34 +3,34 @@ import 'swiper/css'; import Image from 'next/image'; import { useEffect, useMemo } from 'react'; import { useQuery } from 'react-query'; -import { Swiper, SwiperProps, SwiperSlide } from 'swiper/react'; +import { Swiper, SwiperProps, SwiperSlide } from 'swiper/react'; import style from '../styles/hero.module.css'; import 'swiper/css/navigation'; import 'swiper/css/pagination'; -import { Navigation, Pagination, Autoplay } from 'swiper'; +import { Navigation, Pagination, Autoplay } from 'swiper'; import MobileView from '../../../../src/core/components/views/MobileView'; import DesktopView from '@/core/components/views/DesktopView'; -import {bannerApi} from '../../../../src/api/bannerApi' +import { bannerApi } from '../../../../src/api/bannerApi'; interface IPromotionProgram { headlineBanner: string; descriptionBanner: string; - image: string ; + image: string; name: string; } const swiperBanner: SwiperProps = { - modules:[Navigation, Pagination, Autoplay], + modules: [Navigation, Pagination, Autoplay], autoplay: { delay: 6000, - disableOnInteraction: false + disableOnInteraction: false, }, loop: true, className: 'h-[400px] w-full', slidesPerView: 1, spaceBetween: 10, - pagination:true, -} + pagination: true, +}; const swiperBannerMob = { autoplay: { delay: 6000, @@ -43,7 +43,10 @@ const swiperBannerMob = { }; const Hero = () => { - const heroBanner = useQuery('allPromo', bannerApi({ type: 'banner-semua-promo' })); + const heroBanner = useQuery( + 'allPromo', + bannerApi({ type: 'banner-semua-promo' }) + ); const banners: IPromotionProgram[] = useMemo( () => heroBanner?.data || [], @@ -54,52 +57,60 @@ const Hero = () => { ...swiperBannerMob, pagination: { dynamicBullets: false, clickable: true }, }; - + return ( <> <DesktopView> <div className={style['wrapper']}> - <Swiper {...swiperBanner}> - {banners.map((banner, index) => ( - <SwiperSlide key={index} className='flex flex-row'> - <div className={style['desc-section']}> - <div className={style['title']}>{banner.headlineBanner? banner.headlineBanner : "Pasti Hemat & Untung Selama Belanja di Indoteknik.com!"}</div> - <div className='h-4' /> - <div className={style['subtitle']}>{banner.descriptionBanner? banner.descriptionBanner : "Cari paket yang kami sediakan dengan penawaran harga & Nikmati kemudahan dalam setiap transaksi dengan fitur lengkap Pembayaran hingga barang sampai!"}</div> + <Swiper {...swiperBanner}> + {banners?.map((banner, index) => ( + <SwiperSlide key={index} className='flex flex-row'> + <div className={style['desc-section']}> + <div className={style['title']}> + {banner?.headlineBanner + ? banner?.headlineBanner + : 'Pasti Hemat & Untung Selama Belanja di Indoteknik.com!'} </div> - <div className={style['banner-section']}> - <Image - src={banner.image} - alt={banner.name} - width={666} - height={450} - quality={90} - className='w-full h-full object-fit object-center rounded-2xl' /> + <div className='h-4' /> + <div className={style['subtitle']}> + {banner?.descriptionBanner + ? banner?.descriptionBanner + : 'Cari paket yang kami sediakan dengan penawaran harga & Nikmati kemudahan dalam setiap transaksi dengan fitur lengkap Pembayaran hingga barang sampai!'} </div> - </SwiperSlide> - ))} - </Swiper> - </div> - </DesktopView> - <MobileView> - <Swiper {...swiperBannerMobile}> - {banners?.map((banner, index) => ( - <SwiperSlide key={index}> - <Image - width={439} - height={150} - quality={100} - src={banner.image} - alt={banner.name} - className='w-full h-full object-cover object-center rounded-2xl' - /> + </div> + <div className={style['banner-section']}> + <Image + src={banner.image} + alt={banner.name} + width={666} + height={450} + quality={85} + className='w-full h-full object-fit object-center rounded-2xl' + /> + </div> </SwiperSlide> ))} </Swiper> - + </div> + </DesktopView> + <MobileView> + <Swiper {...swiperBannerMobile}> + {banners?.map((banner, index) => ( + <SwiperSlide key={index}> + <Image + width={439} + height={150} + quality={85} + src={banner?.image} + alt={banner?.name} + className='w-full h-full object-cover object-center rounded-2xl' + /> + </SwiperSlide> + ))} + </Swiper> </MobileView> </> - ) -} + ); +}; -export default Hero
\ No newline at end of file +export default Hero; diff --git a/src-migrate/modules/promo/components/HeroDiskon.tsx b/src-migrate/modules/promo/components/HeroDiskon.tsx index 6d38c763..8b8edcc0 100644 --- a/src-migrate/modules/promo/components/HeroDiskon.tsx +++ b/src-migrate/modules/promo/components/HeroDiskon.tsx @@ -39,7 +39,7 @@ const Hero = () => { queryFn: () => getBanner({ type: 'banner-promotion' }) }) - const banners = useMemo(() => bannerQuery.data || [], [bannerQuery.data]); + const banners = useMemo(() => bannerQuery?.data || [], [bannerQuery?.data]); useEffect(() => { if (banners.length > 1) { @@ -56,8 +56,8 @@ const Hero = () => { {banners.map((banner, index) => ( <SwiperSlide key={index}> <Image - src={banner.image} - alt={banner.name} + src={banner?.image} + alt={banner?.name} width={666} height={480} className='w-[446px] h-[446px] object-fill object-center rounded-2xl' @@ -71,8 +71,8 @@ const Hero = () => { {banners.map((banner, index) => ( <SwiperSlide key={index}> <Image - src={banner.image} - alt={banner.name} + src={banner?.image} + alt={banner?.name} width={666} height={450} className='w-[400px] h-[217px] object-cover object-center rounded-2xl ' @@ -86,8 +86,8 @@ const Hero = () => { {banners.map((banner, index) => ( <SwiperSlide key={index}> <Image - src={banner.image} - alt={banner.name} + src={banner?.image} + alt={banner?.name} width={666} height={450} className='w-[400px] h-[217px] object-cover object-center rounded-2xl' @@ -101,8 +101,8 @@ const Hero = () => { {banners.map((banner, index) => ( <SwiperSlide key={index}> <Image - src={banner.image} - alt={banner.name} + src={banner?.image} + alt={banner?.name} width={666} height={450} className='w-[400px] h-[217px] object-cover object-center rounded-2xl' @@ -116,8 +116,8 @@ const Hero = () => { {banners.map((banner, index) => ( <SwiperSlide key={index}> <Image - src={banner.image} - alt={banner.name} + src={banner?.image} + alt={banner?.name} width={666} height={450} className='w-[400px] h-[217px] object-cover object-center rounded-2xl' diff --git a/src-migrate/modules/promo/components/PromoList.tsx b/src-migrate/modules/promo/components/PromoList.tsx index be74fc93..9f808718 100644 --- a/src-migrate/modules/promo/components/PromoList.tsx +++ b/src-migrate/modules/promo/components/PromoList.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useState } from 'react'; -import { Button, Skeleton } from '@chakra-ui/react' -import clsxm from "~/libs/clsxm" +import { Button, Skeleton } from '@chakra-ui/react'; +import clsxm from '~/libs/clsxm'; import ProductPromoCard from '../../product-promo/components/Card'; import { fetchPromoItemsSolr } from '../../../../src/api/promoApi'; import { Swiper, SwiperSlide } from 'swiper/react'; @@ -8,7 +8,7 @@ import SwiperCore, { Navigation, Pagination } from 'swiper'; import useDevice from '@/core/hooks/useDevice'; import LogoSpinner from '../../../../src/core/components/elements/Spinner/LogoSpinner'; import usePromoStore from './promoStore'; -import Link from "next/link" +import Link from 'next/link'; import { IPromotion } from '~/types/promotion'; interface PromoListProps { selectedPromo: string; // Tipe selectedPromo ditetapkan sebagai string @@ -35,8 +35,8 @@ const PromoList: React.FC<PromoListProps> = ({ selectedPromo }) => { className: 'h-full w-full', slidesPerView: isMobile ? 1.1 : 3.25, spaceBetween: 10, - navigation:isMobile? true : false, - allowTouchMove:isMobile? false : true, + navigation: isMobile ? true : false, + allowTouchMove: isMobile ? false : true, }; useEffect(() => { @@ -56,10 +56,10 @@ const PromoList: React.FC<PromoListProps> = ({ selectedPromo }) => { const fetchPromotions = async () => { setIsLoading(true); try { - const items = await fetchPromoItemsSolr(`type_value_s:${slug}`, 0, 10); + const items = await fetchPromoItemsSolr(`type_value_s:${slug}`, 0, 10); setPromoItems(items); - const promoDataPromises = items.map(async (item) => { + const promoDataPromises = items?.map(async (item) => { try { const response = await fetchPromoItemsSolr(`id:${item.id}`, 0, 10); return response; @@ -69,9 +69,11 @@ const PromoList: React.FC<PromoListProps> = ({ selectedPromo }) => { }); const promoDataArray = await Promise.all(promoDataPromises); - const mergedPromoData = promoDataArray.reduce((accumulator, currentValue) => accumulator.concat(currentValue), []); + const mergedPromoData = promoDataArray?.reduce( + (accumulator, currentValue) => accumulator.concat(currentValue), + [] + ); setPromoData(mergedPromoData); - } catch (error) { console.error('Error fetching promo items:', error); } finally { @@ -92,44 +94,49 @@ const PromoList: React.FC<PromoListProps> = ({ selectedPromo }) => { <div className='flex justify-between items-center'> <h1 className='text-h-sm md:text-h-lg font-semibold py-4'>{title}</h1> <div> - <Link href={`/shop/promo/${slug}`} className='!text-red-500 font-semibold'> + <Link + href={`/shop/promo/${slug}`} + className='!text-red-500 font-semibold' + > Lihat Semua </Link> </div> </div> {isLoading ? ( - <div className="loading-spinner flex justify-center"> + <div className='loading-spinner flex justify-center'> <LogoSpinner width={48} height={48} /> </div> ) : ( <Skeleton - isLoaded={!isLoading} - className={clsxm( - "flex gap-x-4 overflow-x-auto px-4 md:px-0", { - "min-h-[340px]": promoData[0] && promoData?.length > 0 - })} - > - {isDesktop && ( - <Swiper {...swiperBanner}> - {promoData?.map((promotion: IPromotion) => ( - <SwiperSlide key={promotion.id}> - <div className="min-w-36 max-w-[400px] mb-[20px] sm:w-full md:w-full lg:w-full xl:w-full"> - <ProductPromoCard promotion={promotion} /> - </div> - </SwiperSlide> - ))} - </Swiper> - )} - {isMobile && (promoData?.map((promotion: IPromotion) => ( - <div key={promotion.id} className="min-w-[400px] max-w-[400px]"> - <ProductPromoCard promotion={promotion} /> - </div> - )))} - - </Skeleton> + isLoaded={!isLoading} + className={clsxm('flex gap-x-4 overflow-x-auto px-4 md:px-0', { + 'min-h-[340px]': promoData[0] && promoData?.length > 0, + })} + > + {isDesktop && ( + <Swiper {...swiperBanner}> + {promoData?.map((promotion: IPromotion) => ( + <SwiperSlide key={promotion.id}> + <div className='min-w-36 max-w-[400px] mb-[20px] sm:w-full md:w-full lg:w-full xl:w-full'> + <ProductPromoCard + product={promoItems} + promotion={promotion} + /> + </div> + </SwiperSlide> + ))} + </Swiper> + )} + {isMobile && + promoData?.map((promotion: IPromotion) => ( + <div key={promotion.id} className='min-w-[400px] max-w-[400px]'> + <ProductPromoCard product={promoItems} promotion={promotion} /> + </div> + ))} + </Skeleton> )} </div> ); }; -export default PromoList;
\ No newline at end of file +export default PromoList; diff --git a/src-migrate/modules/promo/components/PromotinProgram.jsx b/src-migrate/modules/promo/components/PromotinProgram.jsx index 33839944..43e4eedf 100644 --- a/src-migrate/modules/promo/components/PromotinProgram.jsx +++ b/src-migrate/modules/promo/components/PromotinProgram.jsx @@ -1,9 +1,7 @@ import React from 'react'; import Image from 'next/image'; -import { InfoIcon } from "lucide-react"; -import MobileView from '../../../../src/core/components/views/MobileView'; -import DesktopView from '@/core/components/views/DesktopView'; -import { Swiper, SwiperProps, SwiperSlide } from 'swiper/react'; +import { InfoIcon } from 'lucide-react'; +import { Swiper, SwiperProps, SwiperSlide } from 'swiper/react'; import 'swiper/css'; import useDevice from '@/core/hooks/useDevice'; @@ -11,9 +9,12 @@ const PromotionProgram = ({ selectedPromo, onSelectPromo }) => { const { isMobile } = useDevice(); return ( <> - <div className="text-h-sm md:text-h-lg font-semibold py-4">Serba Serbi Promo</div> + <h1 className='text-h-sm md:text-h-lg font-semibold py-4'> + {' '} + Serba Serbi Promo + </h1> <div className='px-4 sm:px-0'> - {/* <div className='w-full h-full '> + {/* <div className='w-full h-full '> <div onClick={() => onSelectPromo('Diskon')} className={`border p-2 flex items-center gap-x-2 rounded-lg cursor-pointer ${selectedPromo === 'Diskon' ? 'bg-red-50 border-red-500 text-red-500' : 'border-gray-200 text-gray-900'}`} @@ -39,93 +40,147 @@ const PromotionProgram = ({ selectedPromo, onSelectPromo }) => { </div> </div> </div> */} - - <Swiper slidesPerView={isMobile ? 1.3 : 3} spaceBetween={10}> - <SwiperSlide> - <div className='w-full h-full '> - <div - onClick={() => onSelectPromo('Bundling')} - className={`border h-full p-1 flex items-center gap-x-2 rounded-lg cursor-pointer ${selectedPromo === 'Bundling' ? 'bg-red-50 border-red-500 text-red-500' : 'border-gray-200 text-gray-900'}`} - > - <div> - <Image - width={24} - height={24} - quality={100} - src='/images/icon_promo/silat.svg' - alt='' - className='h-12 w-12 rounded' - /> - </div> - <div > - <div className='flex w-full flex-row items-center justify-start'> - <h1 className={`mr-1 font-semibold text-base ${selectedPromo === 'Bundling' ? 'text-red-500' : 'text-gray-900'}`}>Paket Silat</h1> - <InfoIcon className='mt-[1px] text-red-500' size={14} /> - </div> - <p className={`text-xs md:text-sm ${selectedPromo === 'Bundling' ? 'text-red-500' : 'text-gray-500'}`}> - Pilihan bundling barang kombinasi Silat. - </p> + + <Swiper slidesPerView={isMobile ? 1.3 : 3} spaceBetween={10}> + <SwiperSlide> + <div className='w-full h-full '> + <div + onClick={() => onSelectPromo('Bundling')} + className={`border h-full p-1 flex items-center gap-x-2 rounded-lg cursor-pointer ${ + selectedPromo === 'Bundling' + ? 'bg-red-50 border-red-500 text-red-500' + : 'border-gray-200 text-gray-900' + }`} + > + <div> + <Image + width={24} + height={24} + quality={85} + src='/images/icon_promo/silat.svg' + alt='' + className='h-12 w-12 rounded' + /> + </div> + <div> + <div className='flex w-full flex-row items-center justify-start'> + <h1 + className={`mr-1 font-semibold text-base ${ + selectedPromo === 'Bundling' + ? 'text-red-500' + : 'text-gray-900' + }`} + > + Paket Silat + </h1> + <InfoIcon className='mt-[1px] text-red-500' size={14} /> </div> + <p + className={`text-xs md:text-sm ${ + selectedPromo === 'Bundling' + ? 'text-red-500' + : 'text-gray-500' + }`} + > + Pilihan bundling barang kombinasi Silat. + </p> </div> </div> - </SwiperSlide> - <SwiperSlide> - <div className='w-full h-full '> - <div - onClick={() => onSelectPromo('Loading')} - className={`border p-2 h-full flex items-center gap-x-2 rounded-lg cursor-pointer ${selectedPromo === 'Loading' ? 'bg-red-50 border-red-500 text-red-500' : 'border-gray-200 text-gray-900'}`} - > - <div> - <Image - width={24} - height={24} - quality={100} - src='/images/icon_promo/barong.svg' - alt='' - className='h-12 w-12 rounded' - /> - </div> - <div> - <div className='flex w-full flex-row items-center justify-start'> - <h1 className={`mr-1 font-semibold text-base ${selectedPromo === 'Loading' ? 'text-red-500' : 'text-gray-900'}`}>Paket Barong</h1> - <InfoIcon className='mt-[1px] text-red-500' size={14} /> - </div> - <p className={`text-xs md:text-sm ${selectedPromo === 'Loading' ? 'text-red-500' : 'text-gray-500'}`}> - Beli banyak barang/partai barang borong. - </p> + </div> + </SwiperSlide> + <SwiperSlide> + <div className='w-full h-full '> + <div + onClick={() => onSelectPromo('Loading')} + className={`border p-2 h-full flex items-center gap-x-2 rounded-lg cursor-pointer ${ + selectedPromo === 'Loading' + ? 'bg-red-50 border-red-500 text-red-500' + : 'border-gray-200 text-gray-900' + }`} + > + <div> + <Image + width={24} + height={24} + quality={85} + src='/images/icon_promo/barong.svg' + alt='' + className='h-12 w-12 rounded' + /> + </div> + <div> + <div className='flex w-full flex-row items-center justify-start'> + <h1 + className={`mr-1 font-semibold text-base ${ + selectedPromo === 'Loading' + ? 'text-red-500' + : 'text-gray-900' + }`} + > + Paket Barong + </h1> + <InfoIcon className='mt-[1px] text-red-500' size={14} /> </div> + <p + className={`text-xs md:text-sm ${ + selectedPromo === 'Loading' + ? 'text-red-500' + : 'text-gray-500' + }`} + > + Beli banyak barang/partai barang borong. + </p> </div> </div> - </SwiperSlide> - <SwiperSlide> - <div className='w-full h-full '> - <div - onClick={() => onSelectPromo('Merchandise')} - className={`border p-2 h-full flex items-center gap-x-2 rounded-lg cursor-pointer ${selectedPromo === 'Merchandise' ? 'bg-red-50 border-red-500 text-red-500' : 'border-gray-200 text-gray-900'}`} - > - <div> - <Image - width={24} - height={24} - quality={100} - src='/images/icon_promo/angklung.svg' - alt='' - className='h-12 w-12 rounded' - /> - </div> - <div > - <div className='flex w-full flex-row items-center justify-start '> - <h1 className={`mr-1 font-semibold text-base ${selectedPromo === 'Merchandise' ? 'text-red-500' : 'text-gray-900'}`}>Paket Angklung</h1> - <InfoIcon className='mt-[1px] text-red-500' size={14} /> - </div> - <p className={` m1 text-xs md:text-sm ${selectedPromo === 'Merchandise' ? 'text-red-500' : 'text-gray-500'}`}> - Gratis barang promosi/merchandise menang langsung. - </p> + </div> + </SwiperSlide> + <SwiperSlide> + <div className='w-full h-full '> + <div + onClick={() => onSelectPromo('Merchandise')} + className={`border p-2 h-full flex items-center gap-x-2 rounded-lg cursor-pointer ${ + selectedPromo === 'Merchandise' + ? 'bg-red-50 border-red-500 text-red-500' + : 'border-gray-200 text-gray-900' + }`} + > + <div> + <Image + width={24} + height={24} + quality={85} + src='/images/icon_promo/angklung.svg' + alt='' + className='h-12 w-12 rounded' + /> + </div> + <div> + <div className='flex w-full flex-row items-center justify-start '> + <h1 + className={`mr-1 font-semibold text-base ${ + selectedPromo === 'Merchandise' + ? 'text-red-500' + : 'text-gray-900' + }`} + > + Paket Angklung + </h1> + <InfoIcon className='mt-[1px] text-red-500' size={14} /> </div> + <p + className={` m1 text-xs md:text-sm ${ + selectedPromo === 'Merchandise' + ? 'text-red-500' + : 'text-gray-500' + }`} + > + Gratis barang promosi/merchandise menang langsung. + </p> </div> </div> - </SwiperSlide> - </Swiper> + </div> + </SwiperSlide> + </Swiper> </div> </> ); diff --git a/src-migrate/modules/promo/components/Voucher.tsx b/src-migrate/modules/promo/components/Voucher.tsx index e5877e51..034d13e9 100644 --- a/src-migrate/modules/promo/components/Voucher.tsx +++ b/src-migrate/modules/promo/components/Voucher.tsx @@ -55,15 +55,18 @@ const VoucherComponent = () => { slidesPerView: isMobile ? 1.2 : 3.2, spaceBetween: 2, }; - - const dataVouchers = useMemo(() => voucherQuery.data || [], [voucherQuery.data]); - const vouchers = auth?.id? listVouchers : dataVouchers; + const dataVouchers = useMemo( + () => voucherQuery?.data || [], + [voucherQuery?.data] + ); + const vouchers = auth?.id ? listVouchers : dataVouchers; const copyText = (text: string) => { if (navigator.clipboard && navigator.clipboard.writeText) { - navigator.clipboard.writeText(text) + navigator.clipboard + .writeText(text) .then(() => { toast({ title: 'Salin ke papan klip', @@ -72,7 +75,7 @@ const VoucherComponent = () => { duration: 3000, isClosable: true, position: 'top', - }) + }); }) .catch(() => { fallbackCopyTextToClipboard(text); @@ -80,10 +83,10 @@ const VoucherComponent = () => { } else { fallbackCopyTextToClipboard(text); } - } + }; const fallbackCopyTextToClipboard = (text: string) => { - const textArea = document.createElement("textarea"); + const textArea = document.createElement('textarea'); textArea.value = text; // Tambahkan style untuk menyembunyikan textArea secara visual textArea.style.position = 'fixed'; @@ -108,43 +111,65 @@ const VoucherComponent = () => { duration: 3000, isClosable: true, position: 'top', - }) + }); } catch (err) { console.error('Fallback: Oops, unable to copy', err); } document.body.removeChild(textArea); - } + }; return ( <> - <div className={style['title']}>Pakai Voucher Belanja</div> + <h1 className={style['title']}>Pakai Voucher Belanja</h1> <div className='h-6' /> - {voucherQuery.isLoading && ( + {voucherQuery?.isLoading && ( <div className='grid grid-cols-3 gap-x-4 animate-pulse'> {Array.from({ length: 3 }).map((_, index) => ( - <div key={index} className='w-full h-[160px] bg-gray-200 rounded-xl' /> + <div + key={index} + className='w-full h-[160px] bg-gray-200 rounded-xl' + /> ))} </div> )} - {!voucherQuery.isLoading && ( + {!voucherQuery?.isLoading && ( <div className={style['voucher-section']}> <Swiper {...swiperVoucher}> {vouchers?.map((voucher) => ( <SwiperSlide key={voucher.id} className='pb-2'> <div className={style['voucher-card']}> - <Image src={voucher.image} alt={voucher.name} width={128} height={128} className={style['voucher-image']} /> + <Image + src={voucher?.image} + alt={voucher?.name} + width={128} + height={128} + className={style['voucher-image']} + /> <div className={style['voucher-content']}> - <div className={style['voucher-title']}>{voucher.name}</div> - <div className={style['voucher-desc']}>{voucher.description}</div> + <div className={style['voucher-title']}> + {voucher?.name} + </div> + <div className={style['voucher-desc']}> + {voucher?.description} + </div> <div className={style['voucher-bottom']}> <div> - <div className={style['voucher-code-desc']}>Kode Promo</div> - <div className={style['voucher-code']}>{voucher.code}</div> + <div className={style['voucher-code-desc']}> + Kode Promo + </div> + <div className={style['voucher-code']}> + {voucher?.code} + </div> </div> - <button className={style['voucher-copy']} onClick={() => copyText(voucher.code)}>Salin</button> + <button + className={style['voucher-copy']} + onClick={() => copyText(voucher?.code)} + > + Salin + </button> </div> </div> </div> @@ -154,7 +179,7 @@ const VoucherComponent = () => { </div> )} </> - ) -} + ); +}; -export default VoucherComponent +export default VoucherComponent; |
