diff options
| author | IT Fixcomart <it@fixcomart.co.id> | 2024-11-12 07:36:02 +0000 |
|---|---|---|
| committer | IT Fixcomart <it@fixcomart.co.id> | 2024-11-12 07:36:02 +0000 |
| commit | efc1ab22528dac05d3ad89a7506349eb3b553539 (patch) | |
| tree | 31a7b3583fd41058d75f46efb66fb40087347e3a /src | |
| parent | bf668785232e2d7abba1660dfdb6eb2746adc09a (diff) | |
| parent | 584e3fd7f4d33992046557ba18ee8eeac993e650 (diff) | |
Merged in CR/new_product_detail (pull request #378)
CR/new product detail
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/components/layouts/BasicLayout.jsx | 41 | ||||
| -rw-r--r-- | src/lib/checkout/components/Checkout.jsx | 1 | ||||
| -rw-r--r-- | src/lib/product/components/Product/ProductDesktopVariant.jsx | 395 | ||||
| -rw-r--r-- | src/lib/product/components/Product/ProductMobileVariant.jsx | 33 | ||||
| -rw-r--r-- | src/lib/quotation/components/Quotation.jsx | 5 | ||||
| -rw-r--r-- | src/lib/transaction/components/Transaction.jsx | 6 | ||||
| -rw-r--r-- | src/lib/variant/components/VariantCard.jsx | 22 | ||||
| -rw-r--r-- | src/pages/_app.jsx | 2 | ||||
| -rw-r--r-- | src/pages/api/shop/variant-detail.js | 31 | ||||
| -rw-r--r-- | src/pages/shop/product/variant/[slug].jsx | 7 | ||||
| -rw-r--r-- | src/utils/solrMapping.js | 2 |
11 files changed, 358 insertions, 187 deletions
diff --git a/src/core/components/layouts/BasicLayout.jsx b/src/core/components/layouts/BasicLayout.jsx index c4674344..1b62bf05 100644 --- a/src/core/components/layouts/BasicLayout.jsx +++ b/src/core/components/layouts/BasicLayout.jsx @@ -8,6 +8,7 @@ import odooApi from '@/core/api/odooApi'; import whatsappUrl from '@/core/utils/whatsappUrl'; import Navbar from '../elements/Navbar/Navbar'; import styles from './BasicLayout.module.css'; // Import modul CSS +import useDevice from '@/core/hooks/useDevice'; const AnimationLayout = dynamic(() => import('./AnimationLayout'), { ssr: false, @@ -23,6 +24,9 @@ const BasicLayout = ({ children }) => { const [highlight, setHighlight] = useState(false); const [buttonPosition, setButtonPosition] = useState(null); const [wobble, setWobble] = useState(false); + const [isProductPage, setIsProductPage] = useState(false); + + const { isDesktop, isMobile } = useDevice(); const router = useRouter(); const buttonRef = useRef(null); @@ -43,13 +47,16 @@ const BasicLayout = ({ children }) => { setUrlPath(router.asPath); } + if (router.pathname.includes('/shop/product/')) { + setIsProductPage(true); + } }, [product, router]); useEffect(() => { const handleMouseOut = (event) => { const rect = buttonRef.current.getBoundingClientRect(); if (event.clientY <= 0) { - setButtonPosition(rect) + setButtonPosition(rect); setHighlight(true); } else { setHighlight(false); @@ -92,13 +99,15 @@ const BasicLayout = ({ children }) => { return ( <> - {highlight && buttonPosition && ( + {highlight && buttonPosition && ( <div className={styles['overlay-highlight']} style={{ - '--button-x': `${buttonPosition.x + buttonPosition.width / 2}px`, + '--button-x': `${buttonPosition.x + buttonPosition.width / 2}px`, '--button-y': `${buttonPosition.y + buttonPosition.height / 2}px`, - '--button-radius': `${Math.max(buttonPosition.width, buttonPosition.height) / 2}px` + '--button-radius': `${ + Math.max(buttonPosition.width, buttonPosition.height) / 2 + }px`, }} onAnimationEnd={() => setHighlight(false)} /> @@ -106,11 +115,25 @@ const BasicLayout = ({ children }) => { <Navbar /> <AnimationLayout> {children} - <div className='fixed bottom-4 right-4 sm:bottom-14 sm:right-10 z-50'> - <div className='flex flex-row items-center'> - <a href={whatsappUrl(templateWA, payloadWA, urlPath)} className='flex flex-row items-center' rel='noopener noreferrer' target='_blank'> - <span className={`text-green-300 text-lg font-bold mr-4 ${wobble ? 'animate-wobble' : ''}`} onAnimationEnd={() => setWobble(false)}> - Whatsapp + <div + className={`fixed ${ + isMobile && isProductPage ? 'bottom-40' : 'bottom-16' + } right-4 sm:bottom-14 sm:right-10 z-50`} + > + <div className='flex flex-row items-center'> + <a + href={whatsappUrl(templateWA, payloadWA, urlPath)} + className='flex flex-row items-center' + rel='noopener noreferrer' + target='_blank' + > + <span + className={`text-green-300 text-lg font-bold mr-4 ${ + wobble ? 'animate-wobble' : '' + }`} + onAnimationEnd={() => setWobble(false)} + > + {isDesktop && 'Whatsapp'} </span> </a> <a diff --git a/src/lib/checkout/components/Checkout.jsx b/src/lib/checkout/components/Checkout.jsx index 0e180d9c..e83e719c 100644 --- a/src/lib/checkout/components/Checkout.jsx +++ b/src/lib/checkout/components/Checkout.jsx @@ -442,6 +442,7 @@ const Checkout = () => { const productOrder = products.map((product) => ({ product_id: product.id, quantity: product.quantity, + available_quantity: product?.availableQuantity, })); let data = { // partner_shipping_id: auth.partnerId, diff --git a/src/lib/product/components/Product/ProductDesktopVariant.jsx b/src/lib/product/components/Product/ProductDesktopVariant.jsx index a4cc62dd..cca8ec5e 100644 --- a/src/lib/product/components/Product/ProductDesktopVariant.jsx +++ b/src/lib/product/components/Product/ProductDesktopVariant.jsx @@ -1,14 +1,12 @@ -import { Box, Skeleton, Tooltip } from '@chakra-ui/react'; +import { Box, Button, Skeleton, Tooltip } from '@chakra-ui/react'; import { HeartIcon } from '@heroicons/react/24/outline'; -import { Info } from 'lucide-react'; +import { Info, MessageCircleIcon, Share2Icon } from 'lucide-react'; import { useRouter } from 'next/router'; import { useCallback, useEffect, useRef, useState } from 'react'; import { toast } from 'react-hot-toast'; -import { MessageCircleIcon, Share2Icon } from 'lucide-react'; import AddToWishlist from '../../../../../src-migrate/modules/product-detail/components/AddToWishlist'; import { RWebShare } from 'react-web-share'; import LazyLoad from 'react-lazy-load'; -import { Button } from '@chakra-ui/react'; import { useProductCartContext } from '@/contexts/ProductCartContext'; import odooApi from '@/core/api/odooApi'; import Image from '@/core/components/elements/Image/Image'; @@ -21,11 +19,16 @@ import currencyFormat from '@/core/utils/currencyFormat'; import { createSlug } from '@/core/utils/slug'; import whatsappUrl from '@/core/utils/whatsappUrl'; import { getAuth } from '~/libs/auth'; -import SimilarBottom from '~/modules/product-detail/components/SimilarBottom'; + +import ImageNext from 'next/image'; import productSimilarApi from '../../api/productSimilarApi'; import ProductCard from '../ProductCard'; import ProductSimilar from '../ProductSimilar'; +import ProductPromoSection from '~/modules/product-promo/components/Section'; +import SimilarBottom from '~/modules/product-detail/components/SimilarBottom'; + const SELF_HOST = process.env.NEXT_PUBLIC_SELF_HOST; + const ProductDesktopVariant = ({ product, wishlist, @@ -44,25 +47,20 @@ const ProductDesktopVariant = ({ const { setRefreshCart } = useProductCartContext(); - useEffect(() => { - const createdAskUrl = whatsappUrl({ - template: 'product', - payload: { - manufacture: product.manufacture.name, - productName: product.name, - url: process.env.NEXT_PUBLIC_SELF_HOST + router.asPath, - }, - fallbackUrl: router.asPath, - }); + const [quantityInput, setQuantityInput] = useState(1); - setAskAdminUrl(createdAskUrl); - }, [router.asPath, product.manufacture.name, product.name, setAskAdminUrl]); + const createdAskUrl = whatsappUrl({ + template: 'product', + payload: { + manufacture: product.manufacture.name, + productName: product.name, + url: process.env.NEXT_PUBLIC_SELF_HOST + router.asPath, + }, + fallbackUrl: router.asPath, + }); const getLowestPrice = useCallback(() => { const lowest = product.price; - /* const lowest = prices.reduce((lowest, price) => { - return price.priceDiscount < lowest.priceDiscount ? price : lowest - }, prices[0])*/ return lowest; }, [product]); @@ -95,7 +93,7 @@ const ProductDesktopVariant = ({ router.push(`/login?next=/shop/product/${slug}?srsltid=${srsltid}`); return; } - const quantity = variantQuantityRefs.current[product.id].value; + const quantity = quantityInput; if (!validQuantity(quantity)) return; updateItemCart({ productId: product.id, @@ -149,6 +147,45 @@ const ProductDesktopVariant = ({ router.push(`/shop/checkout?source=buy`); }; + const handleButton = async (variant) => { + const quantity = quantityInput; + let isLoggedIn = typeof auth === 'object'; + + if (!isLoggedIn) { + const currentUrl = encodeURIComponent(router.asPath); + await router.push(`/login?next=${currentUrl}`); + + // Tunggu login berhasil, misalnya dengan memantau perubahan status auth. + const authCheckInterval = setInterval(() => { + const newAuth = getAuth(); + if (typeof newAuth === 'object') { + isLoggedIn = true; + auth = newAuth; // Update nilai auth setelah login + clearInterval(authCheckInterval); + } + }, 500); // Periksa status login setiap 500ms + + await new Promise((resolve) => { + const checkLogin = setInterval(() => { + if (isLoggedIn) { + clearInterval(checkLogin); + resolve(null); + } + }, 500); + }); + } + if (!validQuantity(quantity)) return; + + updateItemCart({ + productId: variant, + quantity, + programLineId: null, + selected: true, + source: 'buy', + }); + router.push('/shop/quotation?source=buy'); + }; + const variantSectionRef = useRef(null); const goToVariantSection = () => { if (variantSectionRef.current) { @@ -194,6 +231,7 @@ const ProductDesktopVariant = ({ }; fetchData(); }, [product]); + console.log('product', product); return ( <DesktopView> @@ -204,87 +242,39 @@ const ProductDesktopVariant = ({ <Image src={product.image + '?variant=True'} alt={product.name} - className='h-[430px] object-contain object-center w-full border border-gray_r-4' + className='w-full h-[350px]' /> </div> - <div className='w-7/12 px-4 py-4'> + <div className='w-7/12 px-6'> <h1 className='text-title-md leading-10 font-medium'> {product?.name} </h1> <div className='mt-10'> - <div className='flex p-3'> - <div className='w-4/12 text-gray_r-12/70'>Nomor SKU</div> - <div className='w-8/12'>SKU-{product.id}</div> - </div> <div className='flex p-3 bg-gray_r-4'> - <div className='w-4/12 text-gray_r-12/70'>Part Number</div> - <div className='w-8/12'>{product.code || '-'}</div> + <div className='w-4/12 text-gray_r-12/70'>Item Code</div> + <div className='w-8/12'>{product.code}</div> </div> - <div className='flex p-3'> + <div className='flex p-3 items-center '> <div className='w-4/12 text-gray_r-12/70'>Manufacture</div> <div className='w-8/12'> - {product.manufacture?.name ? ( - <Link - href={createSlug( - '/shop/brands/', - product.manufacture?.name, - product.manufacture?.id - )} - > - {product.manufacture?.name} - </Link> - ) : ( - <div>-</div> - )} - </div> - </div> - - <div className='flex p-3 items-center bg-gray_r-4'> - <div className='w-4/12 text-gray_r-12/70'> - Persiapan Barang - </div> - <div className='w-8/12'> - {!product?.sla && <Skeleton width='20%' height='16px' />} - {product?.sla && ( - <Tooltip - placement='top' - label={`Masa Persiapan Barang ${product?.sla?.slaDate}`} - > - <Box className='w-fit flex items-center gap-x-2'> - {product?.sla?.slaDate} - <Info size={16} /> - </Box> - </Tooltip> - )} + <Link + href={createSlug( + '/shop/brands/', + product.manufacture.name, + product.manufacture.id.toString() + )} + > + <Image + width={100} + src={product.manufacture.logo} + alt={product.manufacture.name} + /> + </Link> </div> </div> - <div className='flex p-3'> - <div className='w-4/12 text-gray_r-12/70'>Stock</div> - <div className='w-8/12'> - {!product?.sla && <Skeleton width='10%' height='16px' />} - {product?.sla?.qty > 0 && <span>{product?.sla?.qty}</span>} - {product?.sla?.qty == 0 && ( - <a - href={whatsappUrl('product', { - name: product.name, - manufacture: product?.manufacture?.name, - url: createSlug( - '/shop/product/', - product.name, - product.id, - true - ), - })} - className='text-danger-500 font-medium' - > - Tanya Admin - </a> - )} - </div> - </div> - <div className='flex p-3 bg-gray_r-4'> + <div className='flex p-3 bg-gray_r-4 '> <div className='w-4/12 text-gray_r-12/70'>Berat Barang</div> <div className='w-8/12'> {product?.weight > 0 && <span>{product?.weight} KG</span>} @@ -306,58 +296,55 @@ const ProductDesktopVariant = ({ )} </div> </div> - </div> - <div className='h-6' /> - <div className='flex gap-x-5'> - <Button - as={Link} - href={askAdminUrl} - variant='link' - target='_blank' - colorScheme='gray' - leftIcon={<MessageCircleIcon size={18} />} - > - Ask Admin - </Button> - - <AddToWishlist productId={product.id} /> + <div className='flex p-3 items-center '> + <div className='w-4/12 text-gray_r-12/70'>Terjual</div> + <div className='w-8/12'>-</div> + </div> - <RWebShare - data={{ - text: 'Check out this product', - title: `${product.name} - Indoteknik.com`, - url: SELF_HOST + router.asPath, - }} - > - <Button - variant='link' - colorScheme='gray' - leftIcon={<Share2Icon size={18} />} - > - Share - </Button> - </RWebShare> + <div className='flex p-3 items-center bg-gray_r-4 '> + <div className='w-4/12 text-gray_r-12/70'> + Persiapan Barang + </div> + <div className='w-8/12'> + {!product?.sla && <Skeleton width='20%' height='16px' />} + {product?.sla && ( + <Tooltip + placement='top' + label={`Masa Persiapan Barang ${product?.sla?.slaDate}`} + > + <Box className='w-fit flex items-center gap-x-2'> + {product?.sla?.slaDate} + <Info size={16} /> + </Box> + </Tooltip> + )} + </div> + </div> </div> </div> - <div className='py-4 md:p-6 md:bg-gray-50 rounded-xl w-[99%]'> - <h2 className='text-h-md md:text-h-lg font-medium'> - Informasi Produk - </h2> - <div className='h-4' /> - <div - className='leading-relaxed text-gray-700' - dangerouslySetInnerHTML={{ - __html: - !product.parent.description || - product.parent.description == '<p><br></p>' - ? 'Belum ada deskripsi' - : product.parent.description, - }} - /> + <div className='p-4 md:p-6 w-full'> + <ProductPromoSection product={product} productId={product.id} /> + + <div className='p-4 md:p-6 md:bg-gray-50 rounded-xl'> + <h2 className='text-h-md md:text-h-lg font-medium'> + Informasi Produk + </h2> + <div className='h-4' /> + <div + className='leading-relaxed text-gray-700' + dangerouslySetInnerHTML={{ + __html: + !product.parent.description || + product.parent.description == '<p><br></p>' + ? 'Belum ada deskripsi' + : product.parent.description, + }} + /> + </div> </div> </div> - <div className='w-[25%]'> + <div className='w-[33%]'> {product?.isFlashsale > 0 && product?.price?.discountPercentage > 0 ? ( <> @@ -415,27 +402,137 @@ const ProductDesktopVariant = ({ )} </h3> )} - <div className='flex gap-x-3 mt-4'> - <input - type='number' - className='form-input w-16 py-2 text-center bg-gray_r-1' - ref={setVariantQuantityRef(product.id)} - defaultValue={1} - /> - <button - type='button' + <div className='flex justify-between items-center py-5 px-3'> + <div className='relative flex items-center'> + <button + type='button' + className='absolute left-0 px-2 py-1 h-full text-gray-500' + onClick={() => + setQuantityInput( + String(Math.max(1, Number(quantityInput) - 1)) + ) + } + > + - + </button> + <input + type='number' + id='quantity' + min={1} + value={quantityInput} + onChange={(e) => setQuantityInput(e.target.value)} + className=' w-24 h-10 text-center border border-gray-300 rounded focus:outline-none' + /> + <button + type='button' + className='absolute right-0 px-2 py-1 h-full text-gray-500' + onClick={() => + setQuantityInput(String(Number(quantityInput) + 1)) + } + > + + + </button> + </div> + <div> + <Skeleton + isLoaded={sla} + h='21px' + // w={16} + className={ + product?.sla?.qty < 10 ? 'text-red-600 font-medium' : '' + } + > + Stock : {product?.sla?.qty}{' '} + </Skeleton> + </div> + <div> + {product?.sla?.qty > 0 && ( + <Link href='/panduan-pick-up-service' className='group'> + <Image + src='/images/PICKUP-NOW.png' + className='group-hover:scale-105 transition-transform duration-200 w-28' + alt='pickup now' + /> + </Link> + )} + </div> + </div> + <div className='flex gap-x-3'> + <Button onClick={() => handleAddToCart(product.id)} - className='flex-1 py-2 btn-yellow' + className='w-full' + colorScheme='yellow' > Keranjang - </button> - <button - type='button' + </Button> + <Button onClick={() => handleBuy(product.id)} - className='flex-1 py-2 btn-solid-red' + className='w-full' + colorScheme='red' > Beli - </button> + </Button> + </div> + <Button + onClick={() => handleButton(product.id)} + color={'red'} + colorScheme='white' + className='w-full border-2 p-2 gap-1 mt-2 hover:bg-slate-100 flex items-center' + > + <ImageNext + src='/images/writing.png' + alt='penawaran instan' + className='' + width={25} + height={25} + /> + Penawaran Harga Instan + </Button> + <div className='flex py-5'> + <div className='flex gap-x-5 items-center justify-center'> + <Button + as={Link} + href={createdAskUrl} + variant='link' + target='_blank' + colorScheme='gray' + leftIcon={<MessageCircleIcon size={18} />} + > + Ask Admin + </Button> + + <span>|</span> + + <button + className='flex items-center gap-x-1' + onClick={toggleWishlist} + > + {wishlist.data?.productTotal > 0 ? ( + <HeartIcon className='w-6 fill-danger-500 text-danger-500' /> + ) : ( + <HeartIcon className='w-6' /> + )} + Wishlist + </button> + + <span>|</span> + + <RWebShare + data={{ + text: 'Check out this product', + title: `${product.name} - Indoteknik.com`, + url: SELF_HOST + router.asPath, + }} + > + <Button + variant='link' + colorScheme='gray' + leftIcon={<Share2Icon size={18} />} + > + Share + </Button> + </RWebShare> + </div> </div> <div className='border border-gray_r-6 overflow-auto mt-4'> <div className='font-medium text-center p-4 bg-gray_r-1 border-b border-gray_r-6 sticky top-0 z-10'> diff --git a/src/lib/product/components/Product/ProductMobileVariant.jsx b/src/lib/product/components/Product/ProductMobileVariant.jsx index 790dbbe0..b87bcbc8 100644 --- a/src/lib/product/components/Product/ProductMobileVariant.jsx +++ b/src/lib/product/components/Product/ProductMobileVariant.jsx @@ -1,10 +1,10 @@ -import { Skeleton } from '@chakra-ui/react'; +import { Button, Skeleton } from '@chakra-ui/react'; import { HeartIcon } from '@heroicons/react/24/outline'; import { useRouter } from 'next/router'; import { useEffect, useState } from 'react'; import { toast } from 'react-hot-toast'; import LazyLoad from 'react-lazy-load'; - +import ImageNext from 'next/image'; import odooApi from '@/core/api/odooApi'; import Divider from '@/core/components/elements/Divider/Divider'; import Image from '@/core/components/elements/Image/Image'; @@ -133,6 +133,20 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => { router.push(`/shop/checkout?source=buy`); }; + const handleButton = (variant) => { + const quantity = quantityInput; + if (!validQuantity(quantity)) return; + + updateItemCart({ + productId: variant, + quantity, + programLineId: null, + selected: true, + source: 'buy', + }); + router.push('/shop/quotation?source=buy'); + }; + const productSimilarQuery = [ product?.name, `fq=-product_id_i:${product.id}`, @@ -272,6 +286,21 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => { Beli </button> </div> + <Button + onClick={() => handleButton(product.id)} + color={'red'} + colorScheme='white' + className='w-full border-2 p-2 gap-1 mt-2 hover:bg-slate-100 flex items-center' + > + <ImageNext + src='/images/writing.png' + alt='penawaran instan' + className='' + width={25} + height={25} + /> + Penawaran Harga Instan + </Button> </div> <Divider /> diff --git a/src/lib/quotation/components/Quotation.jsx b/src/lib/quotation/components/Quotation.jsx index cf0ad41f..5a2f63a5 100644 --- a/src/lib/quotation/components/Quotation.jsx +++ b/src/lib/quotation/components/Quotation.jsx @@ -39,9 +39,12 @@ const { getProductsCheckout } = require('@/lib/checkout/api/checkoutApi'); const Quotation = () => { const router = useRouter(); const auth = useAuth(); + const query = router.query.source ?? null; const { data: cartCheckout } = useQuery('cartCheckout', () => - getProductsCheckout() + getProductsCheckout({ + source: query, + }) ); const { setRefreshCart } = useProductCartContext(); diff --git a/src/lib/transaction/components/Transaction.jsx b/src/lib/transaction/components/Transaction.jsx index 4d401037..d001c7f4 100644 --- a/src/lib/transaction/components/Transaction.jsx +++ b/src/lib/transaction/components/Transaction.jsx @@ -778,6 +778,10 @@ 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> </div> </td> {/* <td> @@ -879,7 +883,7 @@ const Transaction = ({ id }) => { </div> </div> </div> - )} + )} {transaction?.data?.productsRejectLine.length > 0 && ( <div className='text-h-sm font-semibold mt-10 mb-4'> diff --git a/src/lib/variant/components/VariantCard.jsx b/src/lib/variant/components/VariantCard.jsx index 68cdf54f..08b7a97e 100644 --- a/src/lib/variant/components/VariantCard.jsx +++ b/src/lib/variant/components/VariantCard.jsx @@ -103,30 +103,42 @@ const VariantCard = ({ product, openOnClick = true, buyMore = false }) => { </div> </div> </div> - </div> <div className='w-8/12 flex flex-col'> - <p className='product-card__title wrap-line-ellipsis-2'>{product.parent.name}</p> + <p className='product-card__title wrap-line-ellipsis-2'> + {product.parent.name} + </p> <p className='text-caption-2 text-gray_r-11 mt-1'> {product.code || '-'} - {product.attributes.length > 0 ? ` ・ ${product.attributes.join(', ')}` : ''} + {product.attributes.length > 0 + ? ` ・ ${product.attributes.join(', ')}` + : ''} </p> <p className='text-caption-2 text-gray_r-11 mt-1'> Berat Item : {product?.weight} Kg x {product?.quantity} Barang </p> + <p className='text-[10px] text-red-500 italic mt-2'> + {product.availableQuantity} barang ini bisa di pickup maksimal pukul + 16.00 + </p> <div className='flex flex-wrap gap-x-1 items-center mt-auto'> {product.hasFlashsale && ( <> <p className='text-caption-2 text-gray_r-11 line-through'> {currencyFormat(product.price.price)} </p> - <span className='badge-red'>{product.price.discountPercentage}%</span> + <span className='badge-red'> + {product.price.discountPercentage}% + </span> </> )} </div> <p className='text-caption-2 text-gray_r-11 mt-1'> {product.price.priceDiscount > 0 - ? currencyFormat(product.price.priceDiscount) + ' × ' + product.quantity + ' Barang' + ? currencyFormat(product.price.priceDiscount) + + ' × ' + + product.quantity + + ' Barang' : ''} </p> <p className='text-caption-2 text-gray_r-12 font-bold mt-2'> diff --git a/src/pages/_app.jsx b/src/pages/_app.jsx index bcb41dd6..f52aa5f7 100644 --- a/src/pages/_app.jsx +++ b/src/pages/_app.jsx @@ -85,7 +85,7 @@ function MyApp({ Component, pageProps: { session, ...pageProps } }) { return ( <SessionProvider session={session}> <ScrollToTop /> - + <AnimatePresence> {animateLoader && ( <motion.div diff --git a/src/pages/api/shop/variant-detail.js b/src/pages/api/shop/variant-detail.js index 08ce75b8..af3525b3 100644 --- a/src/pages/api/shop/variant-detail.js +++ b/src/pages/api/shop/variant-detail.js @@ -1,21 +1,28 @@ -import { productMappingSolr, variantsMappingSolr } from '@/utils/solrMapping' -import axios from 'axios' +import { productMappingSolr, variantsMappingSolr } from '@/utils/solrMapping'; +import axios from 'axios'; export default async function handler(req, res) { try { let productVariants = await axios( process.env.SOLR_HOST + `/solr/variants/select?q=id:${req.query.id}&q.op=OR&indent=true` - ) - let auth = req.query.auth === 'false' ? JSON.parse(req.query.auth) : req.query.auth + ); + let template_id = productVariants.data.response.docs[0].template_id_i; + let auth = + req.query.auth === 'false' ? JSON.parse(req.query.auth) : req.query.auth; let productTemplate = await axios( - process.env.SOLR_HOST + `/solr/product/select?q=id:${req.query.id}&q.op=OR&indent=true` - ) - let result = variantsMappingSolr(productTemplate.data.response.docs, productVariants.data.response.docs, auth || false) - - res.status(200).json(result) + process.env.SOLR_HOST + + `/solr/product/select?q=id:${template_id}&q.op=OR&indent=true` + ); + let result = variantsMappingSolr( + productTemplate.data.response.docs, + productVariants.data.response.docs, + auth || false + ); + + res.status(200).json(result); } catch (error) { - console.error('Error fetching data from Solr:', error) - res.status(500).json({ error: 'Internal Server Error' }) + console.error('Error fetching data from Solr:', error); + res.status(500).json({ error: 'Internal Server Error' }); } -}
\ No newline at end of file +} diff --git a/src/pages/shop/product/variant/[slug].jsx b/src/pages/shop/product/variant/[slug].jsx index 42f38774..2c0dd64b 100644 --- a/src/pages/shop/product/variant/[slug].jsx +++ b/src/pages/shop/product/variant/[slug].jsx @@ -32,16 +32,9 @@ export async function getServerSideProps(context) { tier ); let product = response.data; - // let product = await variantApi({ id: getIdFromSlug(slug), headers: { Token: authToken } }) if (product?.length == 1) { product = product[0]; - /* const regexHtmlTags = /(<([^>]+)>)/gi - const regexHtmlTagsExceptP = /<\/?(?!p\b)[^>]*>/g - product.description = product.description - .replace(regexHtmlTagsExceptP, ' ') - .replace(regexHtmlTags, ' ') - .trim()*/ } else { product = null; } diff --git a/src/utils/solrMapping.js b/src/utils/solrMapping.js index f73e966a..f896a6a8 100644 --- a/src/utils/solrMapping.js +++ b/src/utils/solrMapping.js @@ -74,6 +74,7 @@ export const productMappingSolr = (products, pricelist) => { name: product.manufacture_name_s || '', imagePromotion1: product.image_promotion_1_s || '', imagePromotion2: product.image_promotion_2_s || '', + logo : product.x_logo_manufacture_s || '', }; } @@ -133,6 +134,7 @@ export const variantsMappingSolr = (parent, products, pricelist) => { productMapped.manufacture = { id: product.manufacture_id_i || '', name: product.manufacture_name_s || '', + logo : parent[0]?.x_logo_manufacture_s }; } productMapped.parent = { |
