diff options
| -rw-r--r-- | src/core/components/elements/Navbar/TopBanner.jsx | 2 | ||||
| -rw-r--r-- | src/lib/category/components/Category.jsx | 2 | ||||
| -rw-r--r-- | src/lib/product/components/Product/ColumnsSLA.jsx | 81 | ||||
| -rw-r--r-- | src/lib/product/components/Product/ProductDesktop.jsx | 81 | ||||
| -rw-r--r-- | src/lib/product/components/Product/ProductMobile.jsx | 59 | ||||
| -rw-r--r-- | src/lib/product/components/ProductCard.jsx | 20 | ||||
| -rw-r--r-- | src/pages/shop/product/[slug].jsx | 10 |
7 files changed, 136 insertions, 119 deletions
diff --git a/src/core/components/elements/Navbar/TopBanner.jsx b/src/core/components/elements/Navbar/TopBanner.jsx index dca2e930..a757c260 100644 --- a/src/core/components/elements/Navbar/TopBanner.jsx +++ b/src/core/components/elements/Navbar/TopBanner.jsx @@ -6,7 +6,7 @@ import { TopBannerSkeleton } from '../Skeleton/TopBannerSkeleton' const TopBanner = () => { const fetchTopBanner = async () => await odooApi('GET', '/api/v1/banner?type=top-banner') - const topBanner = useQuery('topBanner', fetchTopBanner) + const topBanner = useQuery('topBanner', fetchTopBanner, { refetchOnWindowFocus: false }) if (topBanner.isLoading) { return <TopBannerSkeleton /> diff --git a/src/lib/category/components/Category.jsx b/src/lib/category/components/Category.jsx index 884a871f..af696d42 100644 --- a/src/lib/category/components/Category.jsx +++ b/src/lib/category/components/Category.jsx @@ -10,7 +10,7 @@ const Category = () => { useEffect(() => { const loadCategories = async () => { let dataCategories = await odooApi('GET', '/api/v1/category/tree') - dataCategories = dataCategories.map((category) => { + dataCategories = dataCategories?.map((category) => { category.childs = category.childs.map((child1Category) => { return { ...child1Category, diff --git a/src/lib/product/components/Product/ColumnsSLA.jsx b/src/lib/product/components/Product/ColumnsSLA.jsx new file mode 100644 index 00000000..33da703a --- /dev/null +++ b/src/lib/product/components/Product/ColumnsSLA.jsx @@ -0,0 +1,81 @@ +import odooApi from '@/core/api/odooApi' +import { createSlug } from '@/core/utils/slug' +import whatsappUrl from '@/core/utils/whatsappUrl' +import { Button, Spinner } from 'flowbite-react' +import { memo, useEffect, useState } from 'react' +import { useQuery } from 'react-query' + +const ColumnSLA = ({ variant, product }) => { + const fetchSLA = async () => await odooApi('GET', `/api/v1/product_variant/${variant.id}/stock`) + const dataSLA = useQuery(`VariantSLA-${variant.id}`, fetchSLA, { refetchOnWindowFocus: false }) + + return ( + <> + <td> + {dataSLA.isFetching ? ( + <div className='text-center'> + <Spinner aria-label='Center-aligned spinner example' /> + </div> + ) : dataSLA?.data?.qty > 0 ? ( + dataSLA?.data?.qty + ) : ( + <a + href={whatsappUrl('product', { + name: variant.name, + manufacture: product.manufacture?.name, + url: createSlug('/shop/product/', product.name, product.id, true) + })} + className='text-danger-500 font-medium' + target='_blank' + rel='noreferrer noopener' + > + Tanya Admin + </a> + )} + </td> + <td className='flex justify-center'> + {dataSLA.isFetching ? ( + <Button color='gray'> + <Spinner aria-label='Alternate spinner button example' /> + <span className='pl-3'>Loading...</span> + </Button> + ) : dataSLA?.data?.slaDate != '-' ? ( + <button + type='button' + title={`Masa Persiapan Barang ${dataSLA?.data?.slaDate}`} + className={`flex gap-x-1 items-center p-2 rounded-lg w-full ${ + dataSLA?.data?.slaDate === 'indent' ? 'bg-indigo-900' : 'btn-light' + }`} + > + <div + className={`flex-1 text-caption-1 ${ + dataSLA?.data?.slaDate === 'indent' ? 'text-white' : '' + }`} + > + {dataSLA?.data?.slaDate} + </div> + <div className='flex-end'> + <svg + aria-hidden='true' + fill='none' + stroke='currentColor' + stroke-width='1.5' + className={`w-7 h-7 ${dataSLA?.data?.slaDate === 'indent' ? 'text-white' : ''}`} + > + <path + d='M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z' + stroke-linecap='round' + stroke-linejoin='round' + ></path> + </svg> + </div> + </button> + ) : ( + '-' + )} + </td> + </> + ) +} + +export default memo(ColumnSLA) diff --git a/src/lib/product/components/Product/ProductDesktop.jsx b/src/lib/product/components/Product/ProductDesktop.jsx index 618c35f5..937f2746 100644 --- a/src/lib/product/components/Product/ProductDesktop.jsx +++ b/src/lib/product/components/Product/ProductDesktop.jsx @@ -20,7 +20,8 @@ import PromotionType from '@/lib/promotinProgram/components/PromotionType' import useAuth from '@/core/hooks/useAuth' import ImageNext from 'next/image' import CountDown2 from '@/core/components/elements/CountDown/CountDown2' -import CountDown from '@/core/components/elements/CountDown/CountDown' +import { LazyLoadComponent } from 'react-lazy-load-image-component' +import ColumnsSLA from './ColumnsSLA' const ProductDesktop = ({ products, wishlist, toggleWishlist }) => { const router = useRouter() @@ -184,7 +185,7 @@ const ProductDesktop = ({ products, wishlist, toggleWishlist }) => { setIsLoadingSLA(false) } - fetchData() + if (product.variantTotal == 1) fetchData() }, [product]) return ( @@ -219,7 +220,9 @@ const ProductDesktop = ({ products, wishlist, toggleWishlist }) => { height={10} /> <span className='text-white text-lg font-semibold'> - {product.flashSale.tag || 'FLASH SALE'} + {product?.flashSale?.tag != 'false' || product?.flashSale?.tag + ? product?.flashSale?.tag + : 'FLASH SALE'} </span> </div> <div> @@ -450,7 +453,9 @@ const ProductDesktop = ({ products, wishlist, toggleWishlist }) => { height={10} /> <span className='text-white text-xs font-semibold'> - {product.flashSale.tag || 'FLASH SALE'} + {product?.flashSale?.tag != 'false' || product?.flashSale?.tag + ? product?.flashSale?.tag + : 'FLASH SALE'} </span> </div> )} @@ -564,71 +569,9 @@ const ProductDesktop = ({ products, wishlist, toggleWishlist }) => { {variant.code} </td> <td>{variant.attributes.join(', ') || '-'}</td> - <td> - {isLoadingSLA ? ( - <div className='text-center'> - <Spinner aria-label='Center-aligned spinner example' /> - </div> - ) : variant?.sla?.qty > 0 ? ( - variant?.sla?.qty - ) : ( - <a - href={whatsappUrl('product', { - name: variant.name, - manufacture: product.manufacture?.name, - url: createSlug('/shop/product/', product.name, product.id, true) - })} - className='text-danger-500 font-medium' - target='_blank' - rel='noreferrer noopener' - > - Tanya Admin - </a> - )} - </td> - <td className='flex justify-center'> - {isLoadingSLA ? ( - <Button color='gray'> - <Spinner aria-label='Alternate spinner button example' /> - <span className='pl-3'>Loading...</span> - </Button> - ) : variant?.sla?.slaDate != '-' ? ( - <button - type='button' - title={`Masa Persiapan Barang ${variant?.sla?.slaDate}`} - className={`flex gap-x-1 items-center p-2 rounded-lg w-full ${ - variant?.sla?.slaDate === 'indent' ? 'bg-indigo-900' : 'btn-light' - }`} - > - <div - className={`flex-1 text-caption-1 ${ - variant?.sla?.slaDate === 'indent' ? 'text-white' : '' - }`} - > - {variant?.sla?.slaDate} - </div> - <div className='flex-end'> - <svg - aria-hidden='true' - fill='none' - stroke='currentColor' - stroke-width='1.5' - className={`w-7 h-7 ${ - variant?.sla?.slaDate === 'indent' ? 'text-white' : '' - }`} - > - <path - d='M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z' - stroke-linecap='round' - stroke-linejoin='round' - ></path> - </svg> - </div> - </button> - ) : ( - '-' - )} - </td> + <LazyLoadComponent> + <ColumnsSLA variant={variant} product={product} /> + </LazyLoadComponent> <td> {variant.price.discountPercentage > 0 && variant.price.priceDiscount > 0 && ( diff --git a/src/lib/product/components/Product/ProductMobile.jsx b/src/lib/product/components/Product/ProductMobile.jsx index 56f20aac..6b0b27a5 100644 --- a/src/lib/product/components/Product/ProductMobile.jsx +++ b/src/lib/product/components/Product/ProductMobile.jsx @@ -83,35 +83,6 @@ const ProductMobile = ({ product, wishlist, toggleWishlist }) => { }) useEffect(() => { - const fetchData = async () => { - const promises = product.variants.map(async (variant) => { - const dataSLA = await odooApi('GET', `/api/v1/product_variant/${variant.id}/stock`) - return { - ...variant, - sla: dataSLA - } - }) - const variantData = await Promise.all(promises) - product.variants = variantData - - setIsLoadingSLA(false) - if (product.variants.length === 1) { - setActiveVariant({ - id: product.variants[0].id, - code: product.variants[0].code, - name: product.variants[0].parent.name, - price: product.variants[0].price, - stock: product.variants[0].stock, - weight: product.variants[0].weight, - sla: product.variants[0].sla, - hasProgram: product.variants[0].hasProgram - }) - } - } - fetchData() - }, [product]) - - useEffect(() => { if (!selectedVariant && variantOptions.length == 1) { setSelectedVariant(variantOptions[0]) } @@ -123,16 +94,23 @@ const ProductMobile = ({ product, wishlist, toggleWishlist }) => { const variantAttributes = variant.attributes.length > 0 ? ' - ' + variant.attributes.join(', ') : '' - setActiveVariant({ + const newActiveVariant = { id: variant.id, code: variant.code, name: variant.parent.name + variantAttributes, price: variant.price, stock: variant.stock, weight: variant.weight, - sla: variant.sla, hasProgram: variant.hasProgram - }) + } + + setActiveVariant(newActiveVariant) + + const fetchSLA = async () => { + const dataSLA = await odooApi('GET', `/api/v1/product_variant/${variant.id}/stock`) + setActiveVariant({ ...newActiveVariant, sla: dataSLA }) + } + fetchSLA() } }, [selectedVariant, product]) @@ -208,7 +186,9 @@ const ProductMobile = ({ product, wishlist, toggleWishlist }) => { height={10} /> <span className='text-white text-lg font-semibold'> - {product.flashSale.tag || 'FLASH SALE'} + {product?.flashSale?.tag != 'false' || product?.flashSale?.tag + ? product?.flashSale?.tag + : 'FLASH SALE'} </span> </div> <div> @@ -353,12 +333,7 @@ const ProductMobile = ({ product, wishlist, toggleWishlist }) => { > <SpecificationContent label='Ketersediaan'> <span> - {isLoadingSLA ? ( - <Button color='gray'> - <Spinner aria-label='Alternate spinner button example' /> - <span className='pl-3'>Loading...</span> - </Button> - ) : selectedVariant ? ( + {selectedVariant ? ( activeVariant?.sla?.slaDate != '-' ? ( <button type='button' @@ -410,13 +385,13 @@ const ProductMobile = ({ product, wishlist, toggleWishlist }) => { <span>{activeVariant?.code || '-'}</span> </SpecificationContent> <SpecificationContent label='Stok'> - {activeVariant?.stock > 0 && ( + {activeVariant?.sla?.qty > 0 && ( <span className='flex gap-x-1.5'> <div className='badge-solid-red'>Ready Stock</div> - <div className='badge-gray'>{activeVariant?.stock > 5 ? '> 5' : '< 5'}</div> + <div className='badge-gray'>{activeVariant?.sla?.qty}</div> </span> )} - {activeVariant?.stock == 0 && ( + {activeVariant?.sla?.qty == 0 && ( <a href={whatsappUrl('product', { name: product.name, diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx index abf462a1..10ffdaec 100644 --- a/src/lib/product/components/ProductCard.jsx +++ b/src/lib/product/components/ProductCard.jsx @@ -8,7 +8,7 @@ import { useRouter } from 'next/router' const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { const router = useRouter() - + const callForPriceWhatsapp = whatsappUrl('product', { name: product.name, url: createSlug('/shop/product/', product.name, product.id, true) @@ -29,7 +29,12 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { {router.pathname != '/' && product?.flashSale?.id > 0 && ( <div className='absolute bottom-0 w-full grid'> <div className='absolute bottom-0 w-full h-full'> - <ImageNext src='/images/GAMBAR-BG-FLASH-SALE.jpg' className='h-full' width={1000} height={100} /> + <ImageNext + src='/images/GAMBAR-BG-FLASH-SALE.jpg' + className='h-full' + width={1000} + height={100} + /> </div> <div className='relative'> <div className='flex gap-x-1 items-center p-2 justify-center'> @@ -45,7 +50,9 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { height={5} /> <span className='text-white text-[9px] md:text-[10px] font-semibold'> - {product?.flashSale?.tag != "false" || product?.flashSale?.tag != product?.flashSale?.tag ? product?.flashSale?.tag : 'FLASH SALE'} + {product?.flashSale?.tag != 'false' || product?.flashSale?.tag + ? product?.flashSale?.tag + : 'FLASH SALE'} </span> </div> </div> @@ -138,7 +145,12 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { width={15} height={10} /> - <span className='text-white text-xs font-semibold'>{product?.flashSale?.tag != "false" || product?.flashSale?.tag != product?.flashSale?.tag ? product?.flashSale?.tag : 'FLASH SALE'}</span> + <span className='text-white text-xs font-semibold'> + {' '} + {product?.flashSale?.tag != 'false' || product?.flashSale?.tag + ? product?.flashSale?.tag + : 'FLASH SALE'} + </span> </div> )} {product?.manufacture?.name ? ( diff --git a/src/pages/shop/product/[slug].jsx b/src/pages/shop/product/[slug].jsx index 5d706dec..af20413f 100644 --- a/src/pages/shop/product/[slug].jsx +++ b/src/pages/shop/product/[slug].jsx @@ -6,6 +6,7 @@ import PageNotFound from '@/pages/404' import dynamic from 'next/dynamic' import { useRouter } from 'next/router' import cookie from 'cookie' +import axios from 'axios' const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout')) const Product = dynamic(() => import('@/lib/product/components/Product/Product')) @@ -17,7 +18,12 @@ export async function getServerSideProps(context) { const auth = cookieObj.auth ? JSON.parse(cookieObj.auth) : {} const authToken = auth?.token || '' - let product = await productApi({ id: getIdFromSlug(slug), headers: { Token: authToken } }) + let response = await axios( + `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/product-detail?id=`+getIdFromSlug(slug) + ) + let product = response.data + // let productSolr = await productApi({ id: getIdFromSlug(slug), headers: { Token: authToken } }) + // let productSolr = null if (product?.length == 1) { product = product[0] const regexHtmlTags = /(<([^>]+)>)/gi @@ -35,7 +41,7 @@ export async function getServerSideProps(context) { } } -export default function ProductDetail({ product }) { +export default function ProductDetail({ product}) { const router = useRouter() if (!product) return <PageNotFound /> |
