diff options
| author | IT Fixcomart <it@fixcomart.co.id> | 2024-09-25 01:53:07 +0000 |
|---|---|---|
| committer | IT Fixcomart <it@fixcomart.co.id> | 2024-09-25 01:53:07 +0000 |
| commit | ad952b397b1cebcf85b66877da8e949e7e7a891f (patch) | |
| tree | c174d9dabd75a97544884f47b513f5b4b58443a0 /src-migrate | |
| parent | 1e834e45f9a11911036496151b71f99de480862e (diff) | |
| parent | a66b690ad0445452816f3ac8f8e98dba2e53ca31 (diff) | |
Merged in perapihan-tag (pull request #331)
Perapihan tag
Approved-by: trisusilo
Diffstat (limited to 'src-migrate')
| -rw-r--r-- | src-migrate/modules/page-content/index.tsx | 61 | ||||
| -rw-r--r-- | src-migrate/modules/product-promo/components/Item.tsx | 37 | ||||
| -rw-r--r-- | src-migrate/modules/promo/components/Hero.tsx | 103 | ||||
| -rw-r--r-- | src-migrate/modules/promo/components/PromotinProgram.jsx | 223 | ||||
| -rw-r--r-- | src-migrate/modules/promo/components/Voucher.tsx | 65 | ||||
| -rw-r--r-- | src-migrate/modules/register/components/FormBisnis.tsx | 2 | ||||
| -rw-r--r-- | src-migrate/pages/shop/cart/index.tsx | 146 |
7 files changed, 368 insertions, 269 deletions
diff --git a/src-migrate/modules/page-content/index.tsx b/src-migrate/modules/page-content/index.tsx index 547b1957..af597641 100644 --- a/src-migrate/modules/page-content/index.tsx +++ b/src-migrate/modules/page-content/index.tsx @@ -1,44 +1,45 @@ -import { useMemo } from "react" -import { useQuery } from "react-query" -import { PageContentProps } from "~/types/pageContent" -import { getPageContent } from "~/services/pageContent" +import { useMemo } from 'react'; +import { useQuery } from 'react-query'; +import { PageContentProps } from '~/types/pageContent'; +import { getPageContent } from '~/services/pageContent'; type Props = { - path: string -} + path: string; +}; const PageContent = ({ path }: Props) => { - const { data, isLoading } = useQuery<PageContentProps>(`page-content:${path}`, async () => await getPageContent({ path })) + const { data, isLoading } = useQuery<PageContentProps>( + `page-content:${path}`, + async () => await getPageContent({ path }) + ); const parsedContent = useMemo<string>(() => { - if (!data) return '' + if (!data) return ''; return data.content.replaceAll( 'src="/web/image', `src="${process.env.NEXT_PUBLIC_ODOO_API_HOST}/web/image` - ) - }, [data]) + ); + }, [data]); + console.log('parsedContent', parsedContent); + if (isLoading) return <PageContentSkeleton />; - if (isLoading) return <PageContentSkeleton /> - - return ( - <div dangerouslySetInnerHTML={{ __html: parsedContent || '' }}></div> - ) -} + return <div dangerouslySetInnerHTML={{ __html: parsedContent || '' }}></div>; +}; const PageContentSkeleton = () => ( - <div className="animate-pulse grid gap-y-4"> - <div className="w-full h-10 bg-gray-300 rounded" /> - <div className="h-2" /> - <div className="w-full h-4 bg-gray-300 rounded" /> - <div className="w-full h-4 bg-gray-300 rounded" /> - <div className="w-full h-4 bg-gray-300 rounded" /> - <div className="w-8/12 h-4 bg-gray-300 rounded" /> - <div className="h-2" /> - <div className="w-full h-4 bg-gray-300 rounded" /> - <div className="w-full h-4 bg-gray-300 rounded" /> - <div className="w-full h-4 bg-gray-300 rounded" /> - <div className="w-1/2 h-4 bg-gray-300 rounded" /> + <div className='animate-pulse grid gap-y-4'> + <div className='w-full h-10 bg-gray-300 rounded' /> + <div className='h-2' /> + <div className='w-full h-4 bg-gray-300 rounded' /> + <div className='w-full h-4 bg-gray-300 rounded' /> + <div className='w-full h-4 bg-gray-300 rounded' /> + <div className='w-8/12 h-4 bg-gray-300 rounded' /> + <div className='h-2' /> + <div className='w-full h-4 bg-gray-300 rounded' /> + <div className='w-full h-4 bg-gray-300 rounded' /> + <div className='w-full h-4 bg-gray-300 rounded' /> + <div className='w-1/2 h-4 bg-gray-300 rounded' /> </div> -) +); -export default PageContent
\ No newline at end of file +export default PageContent; diff --git a/src-migrate/modules/product-promo/components/Item.tsx b/src-migrate/modules/product-promo/components/Item.tsx index b396160f..4b345654 100644 --- a/src-migrate/modules/product-promo/components/Item.tsx +++ b/src-migrate/modules/product-promo/components/Item.tsx @@ -1,34 +1,35 @@ -import style from '../styles/item.module.css' +import style from '../styles/item.module.css'; -import { Tooltip } from '@chakra-ui/react' +import { Tooltip } from '@chakra-ui/react'; -import Image from '~/components/ui/image' -import { IProductVariantPromo } from '~/types/promotion' +import Image from '~/components/ui/image'; +import { IProductVariantPromo } from '~/types/promotion'; type Props = { - variant: IProductVariantPromo, - isFree?: boolean -} + variant: IProductVariantPromo; + isFree?: boolean; +}; -const ProductPromoItem = ({ - variant, - isFree = false -}: Props) => { +const ProductPromoItem = ({ variant, isFree = false }: Props) => { return ( <div className={style.item}> <div className={style.image}> - <Image src={variant.image || '/images/noimage.jpeg'} alt={variant.display_name} width={120} height={120} quality={100} /> + <Image + src={variant.image || '/images/noimage.jpeg'} + alt={variant.display_name} + width={120} + height={120} + quality={85} + /> <div className={style.quantity}> {variant.qty} pcs {isFree ? '(free)' : ''} </div> </div> <Tooltip label={variant.display_name} placement='top' fontSize='sm'> - <div className={style.name}> - {variant.name} - </div> + <div className={style.name}>{variant.name}</div> </Tooltip> </div> - ) -} + ); +}; -export default ProductPromoItem
\ No newline at end of file +export default ProductPromoItem; diff --git a/src-migrate/modules/promo/components/Hero.tsx b/src-migrate/modules/promo/components/Hero.tsx index 97cbe0b7..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/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 510fe746..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,23 +111,26 @@ 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 && ( <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> )} @@ -134,17 +140,36 @@ const VoucherComponent = () => { {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; diff --git a/src-migrate/modules/register/components/FormBisnis.tsx b/src-migrate/modules/register/components/FormBisnis.tsx index 5ee19e58..e4cf3442 100644 --- a/src-migrate/modules/register/components/FormBisnis.tsx +++ b/src-migrate/modules/register/components/FormBisnis.tsx @@ -325,7 +325,7 @@ const form: React.FC<FormProps> = ({ className='w-full h-full ' width={800} height={800} - quality={100} + quality={85} /> </div> </BottomPopup> diff --git a/src-migrate/pages/shop/cart/index.tsx b/src-migrate/pages/shop/cart/index.tsx index 4768f62d..c5386c91 100644 --- a/src-migrate/pages/shop/cart/index.tsx +++ b/src-migrate/pages/shop/cart/index.tsx @@ -14,10 +14,10 @@ import clsxm from '~/libs/clsxm'; import useDevice from '@/core/hooks/useDevice'; import CartSummaryMobile from '~/modules/cart/components/CartSummaryMobile'; import Image from '~/components/ui/image'; -import { CartItem } from '~/types/cart' -import { deleteUserCart ,upsertUserCart } from '~/services/cart' +import { CartItem } from '~/types/cart'; +import { deleteUserCart, upsertUserCart } from '~/services/cart'; import { Trash2Icon } from 'lucide-react'; -import { useProductCartContext } from '@/contexts/ProductCartContext' +import { useProductCartContext } from '@/contexts/ProductCartContext'; const CartPage = () => { const router = useRouter(); @@ -26,11 +26,11 @@ const CartPage = () => { const [isSelectedAll, setIsSelectedAll] = useState(false); const [isButtonChek, setIsButtonChek] = useState(false); const [buttonSelectNow, setButtonSelectNow] = useState(true); - const [isLoad, setIsLoad] = useState<boolean>(false) - const [isLoadDelete, setIsLoadDelete] = useState<boolean>(false) + const [isLoad, setIsLoad] = useState<boolean>(false); + const [isLoadDelete, setIsLoadDelete] = useState<boolean>(false); const { loadCart, cart, summary, updateCartItem } = useCartStore(); const useDivvice = useDevice(); - const { setRefreshCart } = useProductCartContext() + const { setRefreshCart } = useProductCartContext(); const [isTop, setIsTop] = useState(true); const [hasChanged, setHasChanged] = useState(false); const prevCartRef = useRef<CartItem[] | null>(null); @@ -64,18 +64,19 @@ const CartPage = () => { const hasSelectedChanged = () => { if (prevCartRef.current && cart) { const prevCart = prevCartRef.current; - return cart.products.some((item, index) => - prevCart[index] && prevCart[index].selected !== item.selected + return cart.products.some( + (item, index) => + prevCart[index] && prevCart[index].selected !== item.selected ); } return false; }; if (hasSelectedChanged()) { - setHasChanged(true) + setHasChanged(true); // Perform necessary actions here if selection has changed - }else{ - setHasChanged(false) + } else { + setHasChanged(false); } prevCartRef.current = cart ? [...cart.products] : null; @@ -83,35 +84,38 @@ const CartPage = () => { const hasSelectedPromo = useMemo(() => { if (!cart) return false; - return cart.products.some(item => item.cart_type === 'promotion' && item.selected); + return cart.products.some( + (item) => item.cart_type === 'promotion' && item.selected + ); }, [cart]); const hasSelected = useMemo(() => { if (!cart) return false; - return cart.products.some(item => item.selected); + return cart.products.some((item) => item.selected); }, [cart]); const hasSelectNoPrice = useMemo(() => { if (!cart) return false; - return cart.products.some(item => item.selected && item.price.price_discount === 0); + return cart.products.some( + (item) => item.selected && item.price.price_discount === 0 + ); }, [cart]); const hasSelectedAll = useMemo(() => { if (!cart || !Array.isArray(cart.products)) return false; - return cart.products.every(item => item.selected); + return cart.products.every((item) => item.selected); }, [cart]); - useEffect(() => { const updateCartItems = async () => { if (typeof auth === 'object' && cart) { - const upsertPromises = cart.products.map(item => + const upsertPromises = cart.products.map((item) => upsertUserCart({ userId: auth.id, type: item.cart_type, id: item.id, qty: item.quantity, - selected: item.selected + selected: item.selected, }) ); try { @@ -128,7 +132,7 @@ const CartPage = () => { const handleCheckout = () => { router.push('/shop/checkout'); - } + }; const handleQuotation = () => { if (hasSelectedPromo || !hasSelected) { @@ -136,54 +140,53 @@ const CartPage = () => { } else { router.push('/shop/quotation'); } - } + }; const handleChange = async (e: React.ChangeEvent<HTMLInputElement>) => { - - if (cart) { const updatedCart = { ...cart, - products: cart.products.map(item => ({ + products: cart.products.map((item) => ({ ...item, - selected: !hasSelectedAll - })) + selected: !hasSelectedAll, + })), }; - - updateCartItem(updatedCart); - if(hasSelectedAll){ + + updateCartItem(updatedCart); + if (hasSelectedAll) { setIsSelectedAll(false); - }else{ + } else { setIsSelectedAll(true); } } }; - const handleDelete = async () => { if (typeof auth !== 'object' || !cart) return; - setIsLoadDelete(true) + setIsLoadDelete(true); for (const item of cart.products) { - if(item.selected === true){ - await deleteUserCart(auth.id, [item.cart_id]) - await loadCart(auth.id) + if (item.selected === true) { + await deleteUserCart(auth.id, [item.cart_id]); + await loadCart(auth.id); } } - setIsLoadDelete(false) - setRefreshCart(true) - } + setIsLoadDelete(false); + setRefreshCart(true); + }; return ( <> - <div className={`${isTop ? 'border-b-[0px]' : 'border-b-[1px]'} sticky md:top-[157px] flex-col bg-white py-4 border-gray-300 z-50 sm:w-full md:w-3/4`}> - <div className={`${style['title']}`}>Keranjang Belanja</div> + <div + className={`${ + isTop ? 'border-b-[0px]' : 'border-b-[1px]' + } sticky md:top-[157px] flex-col bg-white py-4 border-gray-300 z-50 sm:w-full md:w-3/4`} + > + <h1 className={`${style['title']}`}>Keranjang Belanja</h1> <div className='h-2' /> <div className={`flex items-center object-center justify-between `}> <div className='flex items-center object-center'> - {isLoad && ( - <Spinner className='my-auto' size='sm' /> - )} + {isLoad && <Spinner className='my-auto' size='sm' />} {!isLoad && ( <Checkbox borderColor='gray.600' @@ -193,34 +196,31 @@ const CartPage = () => { onChange={handleChange} /> )} - <p className='p-2 text-caption-2'> - {hasSelectedAll ? "Uncheck all" : "Select all"} - </p> + <p className='p-2 text-caption-2'> + {hasSelectedAll ? 'Uncheck all' : 'Select all'} + </p> + </div> + <div className='delate all flex items-center object-center'> + <Tooltip + label={clsxm({ + 'Tidak ada item yang dipilih': !hasSelected, + })} + > + <Button + bg='#fadede' + variant='outline' + colorScheme='red' + w='full' + isDisabled={!hasSelected} + onClick={handleDelete} + > + {isLoadDelete && <Spinner size='xs' />} + {!isLoadDelete && <Trash2Icon size={16} />} + <p className='text-sm ml-2'>Hapus Barang</p> + </Button> + </Tooltip> </div> - <div className='delate all flex items-center object-center'> - <Tooltip - label={clsxm({ - 'Tidak ada item yang dipilih': !hasSelected, - })} - > - <Button - bg='#fadede' - variant='outline' - colorScheme='red' - w='full' - isDisabled={!hasSelected} - onClick={handleDelete} - > - {isLoadDelete && <Spinner size='xs' />} - {!isLoadDelete && <Trash2Icon size={16} />} - <p className='text-sm ml-2'> - Hapus Barang - </p> - </Button> - </Tooltip> - </div> </div> - </div> <div className={style['content']}> @@ -274,7 +274,13 @@ const CartPage = () => { <CartSummary {...summary} isLoaded={!!cart} /> )} - <div className={isStepApproval ? style['summary-buttons-step-approval'] : style['summary-buttons']}> + <div + className={ + isStepApproval + ? style['summary-buttons-step-approval'] + : style['summary-buttons'] + } + > <Tooltip label={ hasSelectedPromo && @@ -315,4 +321,4 @@ const CartPage = () => { ); }; -export default CartPage;
\ No newline at end of file +export default CartPage; |
