diff options
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/auth/components/Menu.jsx | 99 | ||||
| -rw-r--r-- | src/lib/brand/components/BrandCard.jsx | 2 | ||||
| -rw-r--r-- | src/lib/flashSale/components/FlashSale.jsx | 2 | ||||
| -rw-r--r-- | src/lib/home/components/BannerSection.jsx | 1 | ||||
| -rw-r--r-- | src/lib/home/components/CategoryDynamic.jsx | 178 | ||||
| -rw-r--r-- | src/lib/home/components/CategoryDynamicMobile.jsx | 2 | ||||
| -rw-r--r-- | src/lib/home/components/PromotionProgram.jsx | 59 | ||||
| -rw-r--r-- | src/lib/home/components/ServiceList.jsx | 4 | ||||
| -rw-r--r-- | src/lib/product/components/Product/ProductDesktop.jsx | 1 | ||||
| -rw-r--r-- | src/lib/product/components/Product/ProductMobile.jsx | 1 | ||||
| -rw-r--r-- | src/lib/product/components/ProductCard.jsx | 30 | ||||
| -rw-r--r-- | src/lib/product/components/ProductSlider.jsx | 2 | ||||
| -rw-r--r-- | src/lib/transaction/api/checkoutPoApi.js | 19 | ||||
| -rw-r--r-- | src/lib/transaction/components/Transaction.jsx | 132 | ||||
| -rw-r--r-- | src/lib/treckingAwb/component/Manifest.jsx | 1 |
15 files changed, 362 insertions, 171 deletions
diff --git a/src/lib/auth/components/Menu.jsx b/src/lib/auth/components/Menu.jsx index f475db1f..9cd10ab4 100644 --- a/src/lib/auth/components/Menu.jsx +++ b/src/lib/auth/components/Menu.jsx @@ -1,76 +1,129 @@ -import Link from '@/core/components/elements/Link/Link' -import { useRouter } from 'next/router' -import ImageNext from 'next/image' -import whatsappUrl from '@/core/utils/whatsappUrl' - +import Link from '@/core/components/elements/Link/Link'; +import { useRouter } from 'next/router'; +import ImageNext from 'next/image'; +import whatsappUrl from '@/core/utils/whatsappUrl'; +import { deleteAuth } from '@/core/utils/auth'; const Menu = () => { - const router = useRouter() + const router = useRouter(); + + const routeStartWith = (route) => router.pathname.startsWith(route); - const routeStartWith = (route) => router.pathname.startsWith(route) + const logout = async () => { + deleteAuth().then(() => { + router.push('/login'); + }); + }; return ( <div className='grid grid-cols-1 bg-white border border-gray_r-6 rounded py-2 px-4 sticky top-48'> <div className='mt-4 mb-1 font-medium'>Menu</div> <LinkItem href='/my/quotations' active={routeStartWith('/my/quotations')}> <div className='flex gap-x-3 items-center'> - <ImageNext src='/images/icon/icon_daftar_quotation.svg' width={18} height={20} /> + <ImageNext + src='/images/icon/icon_daftar_quotation.svg' + width={18} + height={20} + /> <p>Daftar Quotation</p> </div> </LinkItem> - <LinkItem href='/my/transactions' active={routeStartWith('/my/transactions')}> + <LinkItem + href='/my/transactions' + active={routeStartWith('/my/transactions')} + > <div className='flex gap-x-3 items-center'> - <ImageNext src='/images/icon/icon_daftar_transaksi.svg' width={18} height={20} /> + <ImageNext + src='/images/icon/icon_daftar_transaksi.svg' + width={18} + height={20} + /> <p>Daftar Transaksi</p> </div> </LinkItem> <LinkItem href='/my/shipments' active={routeStartWith('/my/shipments')}> <div className='flex gap-x-3 items-center'> - <ImageNext src='/images/icon/icon_pengiriman.svg' width={18} height={20} /> + <ImageNext + src='/images/icon/icon_pengiriman.svg' + width={18} + height={20} + /> <p>Daftar Pengiriman</p> </div> </LinkItem> <LinkItem href='/my/invoices' active={routeStartWith('/my/invoices')}> <div className='flex gap-x-3 items-center'> - <ImageNext src='/images/icon/icon_invoice.svg' width={18} height={20} /> + <ImageNext + src='/images/icon/icon_invoice.svg' + width={18} + height={20} + /> <p>Invoice & Faktur Pajak</p> </div> </LinkItem> <LinkItem href='/my/wishlist' active={routeStartWith('/my/wishlist')}> <div className='flex gap-x-3 items-center'> - <ImageNext src='/images/icon/icon_wishlist.svg' width={18} height={20} /> + <ImageNext + src='/images/icon/icon_wishlist.svg' + width={18} + height={20} + /> <p>Wishlist</p> </div> </LinkItem> <div className='mt-4 mb-1 font-medium'>Pusat Bantuan</div> - <LinkItem href={whatsappUrl('', '', '')} rel='noopener noreferrer' target='_blank'> + <LinkItem + href={whatsappUrl('', '', '')} + rel='noopener noreferrer' + target='_blank' + > <div className='flex gap-x-3 items-center'> - <ImageNext src='/images/icon/icon_layanan_pelanggan.svg' width={18} height={20} /> + <ImageNext + src='/images/icon/icon_layanan_pelanggan.svg' + width={18} + height={20} + /> <p>Layanan Pelanggan</p> </div> </LinkItem> <div className='mt-4 mb-1 font-medium'>Pengaturan Akun</div> <LinkItem href='/my/address' active={routeStartWith('/my/address')}> <div className='flex gap-x-3 items-center'> - <ImageNext src='/images/icon/icon_daftar_alamat.svg' width={18} height={20} /> + <ImageNext + src='/images/icon/icon_daftar_alamat.svg' + width={18} + height={20} + /> <p>Daftar Alamat</p> </div> </LinkItem> <LinkItem href='/my/profile' active={routeStartWith('/my/profile')}> <div className='flex gap-x-3 items-center'> - <ImageNext src='/images/icon/icon_profile.svg' width={18} height={20} /> + <ImageNext + src='/images/icon/icon_profile.svg' + width={18} + height={20} + /> <p>Profil Saya</p> </div> </LinkItem> - <button type='button' className='text-gray_r-12/80 p-2 text-left'> + <button + type='button' + onClick={logout} + className='text-gray_r-12/80 p-2 text-left' + > <div className='flex gap-x-3 items-center'> - <ImageNext src='/images/icon/icon_logout.svg' width={18} height={20} /> + <ImageNext + src='/images/icon/icon_logout.svg' + width={18} + height={20} + /> <p>Keluar Akun</p> </div> </button> </div> - ) -} + ); +}; const LinkItem = ({ children, ...props }) => ( <Link @@ -81,6 +134,6 @@ const LinkItem = ({ children, ...props }) => ( > {children} </Link> -) +); -export default Menu +export default Menu; diff --git a/src/lib/brand/components/BrandCard.jsx b/src/lib/brand/components/BrandCard.jsx index ebd41a67..dff61b24 100644 --- a/src/lib/brand/components/BrandCard.jsx +++ b/src/lib/brand/components/BrandCard.jsx @@ -11,6 +11,7 @@ const BrandCard = ({ brand }) => { className={`py-1 px-2 border-gray_r-6 flex justify-center items-center hover:scale-110 transition duration-500 ease-in-out ${ isMobile ? 'h-16' : 'h-24' }`} + aria-label={brand.name} > {brand.logo && ( <NextImage @@ -20,6 +21,7 @@ const BrandCard = ({ brand }) => { height={500} quality={85} className='h-full w-[122px] object-contain object-center' + loading='eager' /> )} {!brand.logo && ( diff --git a/src/lib/flashSale/components/FlashSale.jsx b/src/lib/flashSale/components/FlashSale.jsx index 6d90cad7..f4be279e 100644 --- a/src/lib/flashSale/components/FlashSale.jsx +++ b/src/lib/flashSale/components/FlashSale.jsx @@ -47,6 +47,7 @@ const FlashSale = () => { width={1080} height={192} className='w-full rounded mb-4 hidden sm:block' + loading='eager' /> <Image src={flashSale.bannerMobile} @@ -54,6 +55,7 @@ const FlashSale = () => { width={256} height={48} className='w-full rounded mb-4 block sm:hidden' + loading='eager' /> <FlashSaleProduct flashSaleId={flashSale.pricelistId} diff --git a/src/lib/home/components/BannerSection.jsx b/src/lib/home/components/BannerSection.jsx index 303b5c4b..898f1bf5 100644 --- a/src/lib/home/components/BannerSection.jsx +++ b/src/lib/home/components/BannerSection.jsx @@ -51,6 +51,7 @@ const BannerSection = () => { src={banner.image} alt={banner.name} className='h-auto w-full rounded' + loading='eager' /> </Link> ))} diff --git a/src/lib/home/components/CategoryDynamic.jsx b/src/lib/home/components/CategoryDynamic.jsx index cc4f42b7..b6994f60 100644 --- a/src/lib/home/components/CategoryDynamic.jsx +++ b/src/lib/home/components/CategoryDynamic.jsx @@ -9,6 +9,7 @@ import 'swiper/css'; import 'swiper/css/navigation'; import 'swiper/css/pagination'; import { Pagination } from 'swiper'; +import { LazyLoadComponent } from 'react-lazy-load-image-component'; const CategoryDynamic = () => { const [categoryManagement, setCategoryManagement] = useState([]); @@ -22,12 +23,17 @@ const CategoryDynamic = () => { if (data) { setCategoryManagement(data); } - setIsLoading(false); }; fetchCategoryData(); }, []); + useEffect(() => { + if (categoryManagement?.length > 0) { + setIsLoading(false); + } + }, [categoryManagement]); + const swiperBanner = { modules: [Pagination], classNames: 'mySwiper', @@ -44,95 +50,105 @@ const CategoryDynamic = () => { {categoryManagement && categoryManagement.map((category) => ( <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'> - <h1 className='font-semibold text-[14px] sm:text-h-lg mr-2'> - {category.name} - </h1> - <Link - href={createSlug( - '/shop/category/', - category?.name, - category?.category_id - )} - className='!text-red-500 font-semibold' - > - Lihat Semua - </Link> - </div> + <LazyLoadComponent key={category.id}> + <div key={category.id}> + <div className='bagian-judul flex flex-row justify-start items-center gap-3 mb-4 mt-4'> + <h1 className='font-semibold text-[14px] sm:text-h-lg mr-2'> + {category.name} + </h1> + <Link + href={createSlug( + '/shop/category/', + category?.name, + category?.category_id + )} + className='!text-red-500 font-semibold' + > + Lihat Semua + </Link> + </div> - <Swiper {...swiperBanner}> - {category?.categories?.map((subCategory) => ( - <SwiperSlide key={subCategory.id}> - <div 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 p-4' - /> - <div className='bagian-judul flex flex-col justify-center items-start gap-2 ml-2'> - <h2 className='font-semibold text-lg mr-2'> - {subCategory?.name} - </h2> - <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.child_frontend_id_i.map( - (childCategory) => ( - <div key={childCategory.id} className=''> + <Swiper {...swiperBanner}> + {category?.categories?.map((subCategory) => ( + <LazyLoadComponent key={subCategory.id}> + <SwiperSlide key={subCategory.id}> + <div 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 p-4' + loading='eager' + /> + <div className='bagian-judul flex flex-col justify-center items-start gap-2 ml-2'> + <h2 className='font-semibold text-lg mr-2'> + {subCategory?.name} + </h2> <Link href={createSlug( '/shop/category/', - childCategory?.name, - childCategory?.id_level_3 + subCategory?.name, + subCategory?.id_level_2 )} - className='flex flex-row gap-2 border rounded group hover:border-red-500' + className='!text-red-500 font-semibold' > - <NextImage - src={ - childCategory.image - ? childCategory.image - : '/images/noimage.jpeg' - } - alt={childCategory.name} - className='p-2 ml-1' - 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'> - <h3 className='font-semibold line-clamp-2 group-hover:text-red-500 text-sm mr-2'> - {childCategory.name} - </h3> - </div> + 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.child_frontend_id_i.map( + (childCategory) => ( + <LazyLoadComponent key={childCategory.id}> + <div key={childCategory.id} className=''> + <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} + className='p-2 ml-1' + width={40} + height={40} + placeholder='blur' + blurDataURL='/icon.jpg' + loading='eager' + /> + <div className='bagian-judul flex flex-col justify-center items-center gap-2 break-words line-clamp-2 group-hover:text-red-500'> + <h3 className='font-semibold line-clamp-2 group-hover:text-red-500 text-sm mr-2'> + {childCategory.name} + </h3> + </div> + </Link> + </div> + </LazyLoadComponent> + ) + )} + </div> + </div> </div> - </div> - </div> - </SwiperSlide> - ))} - </Swiper> - </div> + </SwiperSlide> + </LazyLoadComponent> + ))} + </Swiper> + </div> + </LazyLoadComponent> </Skeleton> ))} </div> diff --git a/src/lib/home/components/CategoryDynamicMobile.jsx b/src/lib/home/components/CategoryDynamicMobile.jsx index 67ae6f5f..5d9e872c 100644 --- a/src/lib/home/components/CategoryDynamicMobile.jsx +++ b/src/lib/home/components/CategoryDynamicMobile.jsx @@ -90,6 +90,7 @@ const CategoryDynamicMobile = () => { width={30} height={30} className='' + loading='eager' /> <div className='bagian-judul flex flex-col justify-center items-start gap-1 ml-2'> <h2 className='font-semibold text-[10px] line-clamp-1'> @@ -123,6 +124,7 @@ const CategoryDynamicMobile = () => { width={40} height={40} className='p-2' + loading='eager' /> <div className='bagian-judul flex flex-col justify-center items-start gap-1 break-words line-clamp-2 group-hover:text-red-500'> <h3 className='font-semibold line-clamp-2 group-hover:text-red-500 text-[10px]'> diff --git a/src/lib/home/components/PromotionProgram.jsx b/src/lib/home/components/PromotionProgram.jsx index 562fa138..d8bf3edb 100644 --- a/src/lib/home/components/PromotionProgram.jsx +++ b/src/lib/home/components/PromotionProgram.jsx @@ -4,56 +4,35 @@ import { bannerApi } from '@/api/bannerApi'; import useDevice from '@/core/hooks/useDevice'; import { Swiper, SwiperSlide } from 'swiper/react'; import BannerPromoSkeleton from '../components/Skeleton/BannerPromoSkeleton'; + import { useEffect, useState } from 'react'; const { useQuery } = require('react-query'); const BannerSection = () => { const { isMobile, isDesktop } = useDevice(); const [data, setData] = useState(null); const [shouldFetch, setShouldFetch] = useState(false); + const [ isLoading, setIsLoading] = useState(true); useEffect(() => { const fetchData = async () => { - const res = await fetch(`/api/hero-banner?type=banner-promotion`); - const { data } = await res.json(); - if (data) { - setData(data); + try { + const res = await fetch(`/api/hero-banner?type=banner-promotion`); + const { data } = await res.json(); + if (data) { + setData(data); + } + } catch (e) { + console.log(e); + } finally { + setIsLoading(false); } }; fetchData(); }, []); - // useEffect(() => { - // const localData = localStorage.getItem('Homepage_promotionProgram'); - // if (localData) { - // setData(JSON.parse(localData)); - // } else { - // setShouldFetch(true); - // } - // }, []); - - // const getPromotionProgram = useQuery( - // 'promotionProgram', - // bannerApi({ type: 'banner-promotion' }), - // { - // enabled: shouldFetch, - // onSuccess: (data) => { - // if (data) { - // localStorage.setItem( - // 'Homepage_promotionProgram', - // JSON.stringify(data) - // ); - // setData(data); - // } - // }, - // } - // ); - const promotionProgram = data; - // if (getPromotionProgram?.isLoading && !data) { - // return <BannerPromoSkeleton />; - // } - if (!data) { + if (isLoading) { return <BannerPromoSkeleton />; } @@ -90,7 +69,8 @@ const BannerSection = () => { quality={85} src={banner.image} alt={banner.name} - className='h-auto w-full rounded hover:scale-105 transition duration-500 ease-in-out' + className='rounded hover:scale-105 transition duration-500 ease-in-out' + loading='eager' /> </Link> ))} @@ -103,12 +83,13 @@ const BannerSection = () => { <SwiperSlide key={banner.id}> <Link key={banner.id} href={banner.url}> <Image - width={439} - height={150} - quality={85} + width={350} + height={100} + quality={70} src={banner.image} alt={banner.name} - className='h-auto w-full rounded ' + className='rounded ' + loading='eager' /> </Link> </SwiperSlide> diff --git a/src/lib/home/components/ServiceList.jsx b/src/lib/home/components/ServiceList.jsx index b3cc8fe5..6d03a587 100644 --- a/src/lib/home/components/ServiceList.jsx +++ b/src/lib/home/components/ServiceList.jsx @@ -18,6 +18,7 @@ const ServiceList = () => { src='/images/icon_service/ONE-STOP-SOLUTIONS.svg' alt='' className='h-20 w-20 rounded' + loading='eager' /> </div> <div className=''> @@ -43,6 +44,7 @@ const ServiceList = () => { src='/images/icon_service/WARRANTY.svg' alt='' className='h-20 w-20 rounded' + loading='eager' /> </div> <div> @@ -68,6 +70,7 @@ const ServiceList = () => { src='/images/icon_service/DUE-PAYMENT.svg' alt='' className='h-20 w-20 rounded' + loading='eager' /> </div> <div> @@ -93,6 +96,7 @@ const ServiceList = () => { src='/images/icon_service/TAX.svg' alt='' className='h-20 w-20 rounded' + loading='eager' /> </div> <div> diff --git a/src/lib/product/components/Product/ProductDesktop.jsx b/src/lib/product/components/Product/ProductDesktop.jsx index 444ddd8e..19e76a2b 100644 --- a/src/lib/product/components/Product/ProductDesktop.jsx +++ b/src/lib/product/components/Product/ProductDesktop.jsx @@ -255,6 +255,7 @@ const ProductDesktop = ({ products, wishlist, toggleWishlist }) => { > <ImageNext src='/images/ICON_FLASH_SALE_WEBSITE_INDOTEKNIK.svg' + alt='Flash Sale' width={17} height={10} /> diff --git a/src/lib/product/components/Product/ProductMobile.jsx b/src/lib/product/components/Product/ProductMobile.jsx index 113a1e42..4cfd3755 100644 --- a/src/lib/product/components/Product/ProductMobile.jsx +++ b/src/lib/product/components/Product/ProductMobile.jsx @@ -219,6 +219,7 @@ const ProductMobile = ({ product, wishlist, toggleWishlist }) => { > <ImageNext src='/images/ICON_FLASH_SALE_WEBSITE_INDOTEKNIK.svg' + alt='Flash Sale' width={17} height={10} /> diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx index 3e6a6913..a8ed90a4 100644 --- a/src/lib/product/components/ProductCard.jsx +++ b/src/lib/product/components/ProductCard.jsx @@ -18,7 +18,9 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { const [discount, setDiscount] = useState(0); const { isDesktop, isMobile } = useDevice(); let voucherPastiHemat = 0; - voucherPastiHemat = product?.newVoucherPastiHemat[0]; + voucherPastiHemat = product?.newVoucherPastiHemat[0] + ? product?.newVoucherPastiHemat[0] + : product?.newVoucherPastiHemat; const callForPriceWhatsapp = whatsappUrl('product', { name: product.name, @@ -72,7 +74,7 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { if (variant == 'vertical') { return ( <div className='rounded shadow-sm border border-gray_r-4 bg-white h-[330px] md:h-[380px]'> - <Link href={URL.product} className='border-b border-gray_r-4 relative'> + <Link href={URL.product} className='border-b border-gray_r-4 relative' aria-label='Produk'> <div className='relative'> <Image src={image} @@ -88,6 +90,7 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { className='w-4 h-5 object-contain object-top sm:h-6' width={50} height={50} + loading='eager' /> )} </div> @@ -99,6 +102,7 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { className='w-11 h-6 object-contain object-top ml-1 mr-1 sm:h-6' width={50} height={50} + loading='eager' /> )} </div> @@ -113,6 +117,7 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { className='h-full' width={1000} height={100} + loading='eager' /> </div> <div className='relative'> @@ -125,8 +130,10 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { <div className='bg-red-600 border border-solid border-yellow-400 p-2 rounded-full h-6 flex w-fit items-center justify-center gap-x-2'> <ImageNext src='/images/ICON_FLASH_SALE_WEBSITE_INDOTEKNIK.svg' + alt='flash sale' width={13} height={5} + loading='eager' /> <span className='text-white text-[9px] md:text-[10px] font-semibold'> {product?.flashSale?.tag != 'false' || @@ -148,26 +155,28 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { <div className='p-2 sm:p-3 pb-3 text-caption-2 sm:text-body-2 leading-5'> <div className='flex justify-between '> {product?.manufacture?.name ? ( - <Link href={URL.manufacture} className='mb-1 mt-1 truncate'> + <Link href={URL.manufacture} className='mb-1 mt-1 truncate' aria-label={product.manufacture.name}> {product.manufacture.name} </Link> ) : ( <div>-</div> )} {product?.isInBu && ( - <Link href='/panduan-pick-up-service' className='group'> + <Link href='/panduan-pick-up-service' className='group' aria-label='pickup now'> <Image src='/images/PICKUP-NOW.png' className='group-hover:scale-105 transition-transform duration-200' alt='pickup now' width={90} height={12} + loading='eager' /> </Link> )} </div> <Link href={URL.product} + aria-label={product?.name} className={`mb-2 !text-gray_r-12 leading-6 block line-clamp-3 h-[64px]`} title={product?.name} > @@ -192,6 +201,7 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { rel='noopener noreferrer' target='_blank' href={callForPriceWhatsapp} + aria-label='Call for Inquiry' > Call for Inquiry </a> @@ -215,6 +225,7 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { rel='noopener noreferrer' target='_blank' href={callForPriceWhatsapp} + aria-label='Call for Inquiry' > Call for Inquiry </a> @@ -249,7 +260,7 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { return ( <div className='flex bg-white'> <div className='w-4/12'> - <Link href={URL.product} className='relative'> + <Link href={URL.product} className='relative' aria-label={product?.name}> <div className='relative'> <Image src={image} @@ -265,6 +276,7 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { className='w-4 h-5 object-contain object-top sm:h-6' width={50} height={50} + loading='eager' /> )} </div> @@ -276,6 +288,7 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { className='w-11 h-6 object-contain object-top ml-1 sm:h-6' width={50} height={50} + loading='eager' /> )} </div> @@ -293,8 +306,10 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { <div className='bg-red-600 rounded-full mb-1 p-2 pl-3 pr-3 flex w-fit items-center gap-x-1'> <ImageNext src='/images/ICON_FLASH_SALE_WEBSITE_INDOTEKNIK.svg' + alt='flash sae' width={15} height={10} + loading='eager' /> <span className='text-white text-xs font-semibold'> {' '} @@ -306,7 +321,7 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { )} {product?.manufacture?.name ? ( <div className='flex justify-between'> - <Link href={URL.manufacture} className='mb-1'> + <Link href={URL.manufacture} className='mb-1' aria-label={product?.manufacture.name}> {product.manufacture.name} </Link> {/* {product?.is_in_bu && ( @@ -322,6 +337,7 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { )} <Link href={URL.product} + aria-label={product?.name} className={`mb-3 !text-gray_r-12 leading-6 line-clamp-3`} > {product?.name} @@ -348,6 +364,7 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { rel='noopener noreferrer' target='_blank' href={callForPriceWhatsapp} + aria-label='Call for Inquiry' > Call for Inquiry </a> @@ -371,6 +388,7 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { rel='noopener noreferrer' target='_blank' href={callForPriceWhatsapp} + aria-label='Call for Inquiry' > Call for Inquiry </a> diff --git a/src/lib/product/components/ProductSlider.jsx b/src/lib/product/components/ProductSlider.jsx index 54f209cc..91d199a6 100644 --- a/src/lib/product/components/ProductSlider.jsx +++ b/src/lib/product/components/ProductSlider.jsx @@ -35,7 +35,7 @@ const ProductSlider = ({ products, simpleTitle = false, bannerMode = false }) => <> {bannerMode && ( <SwiperSlide> - <Link href={products.banner.url} className='w-full h-full block'></Link> + <Link href={products.banner.url} className='w-full h-full block' aria-label={products.banner.name}></Link> </SwiperSlide> )} {products?.products?.map((product, index) => ( diff --git a/src/lib/transaction/api/checkoutPoApi.js b/src/lib/transaction/api/checkoutPoApi.js index 04421368..3376e773 100644 --- a/src/lib/transaction/api/checkoutPoApi.js +++ b/src/lib/transaction/api/checkoutPoApi.js @@ -1,13 +1,14 @@ -import odooApi from '@/core/api/odooApi' -import { getAuth } from '@/core/utils/auth' +import odooApi from '@/core/api/odooApi'; +import { getAuth } from '@/core/utils/auth'; -const checkoutPoApi = async ({ id }) => { - const auth = getAuth() +const checkoutPoApi = async ({ id, status }) => { + const auth = getAuth(); const dataCheckout = await odooApi( 'POST', - `/api/v1/partner/${auth?.partnerId}/sale_order/${id}/checkout` - ) - return dataCheckout -} + `/api/v1/partner/${auth?.partnerId}/sale_order/${id}/checkout`, + { status } + ); + return dataCheckout; +}; -export default checkoutPoApi +export default checkoutPoApi; diff --git a/src/lib/transaction/components/Transaction.jsx b/src/lib/transaction/components/Transaction.jsx index d001c7f4..f5dc507a 100644 --- a/src/lib/transaction/components/Transaction.jsx +++ b/src/lib/transaction/components/Transaction.jsx @@ -38,7 +38,9 @@ import aprpoveApi from '../api/approveApi'; import rejectApi from '../api/rejectApi'; import rejectProductApi from '../api/rejectProductApi'; import { useRouter } from 'next/router'; - +import { gtagPurchase } from '@/core/utils/googleTag'; +import { deleteItemCart } from '@/core/utils/cart'; +import axios from 'axios'; const Transaction = ({ id }) => { const router = useRouter(); const [isModalOpen, setIsModalOpen] = useState(false); @@ -46,9 +48,8 @@ const Transaction = ({ id }) => { const [reason, setReason] = useState(''); const auth = useAuth(); const { transaction } = useTransaction({ id }); - const statusApprovalWeb = transaction.data?.approvalStep; - + const [isLoading, setIsLoading] = useState(false); const { queryAirwayBill } = useAirwayBill({ orderId: id }); const [airwayBillPopup, setAirwayBillPopup] = useState(null); @@ -84,8 +85,26 @@ const Transaction = ({ id }) => { }; const [cancelTransaction, setCancelTransaction] = useState(false); + const [continueNoPo, setContinueNoPo] = useState(false); + const [continueTransaction, setContinueTransaction] = useState(false); const openCancelTransaction = () => setCancelTransaction(true); + const openContinueTransaction = () => { + if (auth.partnerTempo) { + checkout(); + } else { + if (!transaction.data?.purchaseOrderFile) { + setContinueTransaction(true); + } else { + checkoutNoPO(); + } + } + }; + // const ContinueTransaction = () => { + // setContinueNoPo(true); + // checkoutNoPO(); + // }; const closeCancelTransaction = () => setCancelTransaction(false); + const closeContinueTransaction = () => setContinueTransaction(false); const [rejectTransaction, setRejectTransaction] = useState(false); @@ -101,15 +120,70 @@ const Transaction = ({ id }) => { } closeCancelTransaction(); }; - const checkout = async () => { if (!transaction.data?.purchaseOrderFile) { toast.error('Mohon upload dokumen PO anda sebelum melanjutkan pesanan'); return; } - await checkoutPoApi({ id }); + await checkoutPoApi({ id, status: true }); + toast.success('Berhasil melanjutkan pesanan'); + transaction.refetch(); + }; + + const checkoutNoPO = async () => { + setIsLoading(true); + gtagPurchase( + transaction.data.products, + transaction.data.deliveryAmount, + transaction.data.name + ); + + gtag('event', 'conversion', { + send_to: 'AW-954540379/nDymCL3BhaQYENvClMcD', + value: + transaction.data?.amountTotal + + Math.round(parseInt(transaction.data.deliveryAmount * 1.1) / 1000) * + 1000, + currency: 'IDR', + transaction_id: transaction.data.id, + }); + + for (const product of transaction.data.products) + deleteItemCart({ productId: product.id }); + if (transaction.data?.amountTotal > 0) { + const payment = await axios.post( + `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/midtrans-payment?transactionId=${transaction.data.id}` + ); + setIsLoading(false); + window.location.href = payment.data.redirectUrl; + } else { + window.location.href = `${ + process.env.NEXT_PUBLIC_SELF_HOST + }/shop/checkout/success?order_id=${transaction.data.name.replace( + /\//g, + '-' + )}`; + } toast.success('Berhasil melanjutkan pesanan'); transaction.refetch(); + + /* const midtrans = async () => { + for (const product of products) deleteItemCart({ productId: product.id }); + if (grandTotal > 0) { + const payment = await axios.post( + `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/midtrans-payment?transactionId=${isCheckouted.id}` + ); + setIsLoading(false); + window.location.href = payment.data.redirectUrl; + } else { + window.location.href = `${ + process.env.NEXT_PUBLIC_SELF_HOST + }/shop/checkout/success?order_id=${isCheckouted.name.replace( + /\//g, + '-' + )}`; + } + };*/ }; const handleApproval = async () => { @@ -208,6 +282,32 @@ const Transaction = ({ id }) => { transaction.data?.name && ( <> <BottomPopup + active={continueTransaction} + close={closeContinueTransaction} + title='Lanjutkan Transaksi' + > + <div className='leading-7 text-gray_r-12/80'> + Apakah anda yakin melanjutkan tanpa upload PO?{' '} + <span className='underline'>{transaction.data?.name}</span>? + </div> + <div className='flex justify-end mt-6 gap-x-4'> + <button + className='btn-solid-red w-full md:w-fit' + type='button' + onClick={checkoutNoPO} + > + Ya, Lanjutkan + </button> + <button + className='btn-light w-full md:w-fit' + type='button' + onClick={closeContinueTransaction} + > + Batal + </button> + </div> + </BottomPopup> + <BottomPopup active={cancelTransaction} close={closeCancelTransaction} title='Batalkan Transaksi' @@ -469,7 +569,10 @@ const Transaction = ({ id }) => { )} {transaction.data?.status == 'draft' && !auth?.feature?.soApproval && ( - <button className='btn-yellow w-full mt-4' onClick={checkout}> + <button + className='btn-yellow w-full mt-4' + onClick={openContinueTransaction} + > Lanjutkan Transaksi </button> )} @@ -563,7 +666,10 @@ const Transaction = ({ id }) => { )} {transaction.data?.status == 'draft' && !auth?.feature.soApproval && ( - <button className='btn-yellow' onClick={checkout}> + <button + className='btn-yellow' + onClick={openContinueTransaction} + > Lanjutkan Transaksi </button> )} @@ -778,10 +884,14 @@ const Transaction = ({ id }) => { ? `| ${product?.attributes.join(', ')}` : ''} </div> - <div className='text-[10px] text-red-500 italic mt-2'> - {product.availableQuantity} barang ini bisa di - pickup maksimal pukul 16.00 - </div> + {product.soQty && product.reservedStockQty && ( + <div className='text-[10px] text-red-500 italic mt-2'> + {product.soQty !== product.reservedStockQty + ? 'Barang sedang disiapkan' + : `${product.reservedStockQty} barang bisa di + kirim/pickup`} + </div> + )} </div> </td> {/* <td> diff --git a/src/lib/treckingAwb/component/Manifest.jsx b/src/lib/treckingAwb/component/Manifest.jsx index 02d0bc7a..87e01e38 100644 --- a/src/lib/treckingAwb/component/Manifest.jsx +++ b/src/lib/treckingAwb/component/Manifest.jsx @@ -10,7 +10,6 @@ import { list } from 'postcss'; const Manifest = ({ idAWB, closePopup }) => { const [manifests, setManifests] = useState(null); const [isLoading, setIsLoading] = useState(false); - console.log('manifests', manifests); const formatCustomDate = (date) => { const months = [ 'Jan', |
