diff options
| author | trisusilo <tri.susilo@altama.co.id> | 2023-10-06 06:54:30 +0000 |
|---|---|---|
| committer | trisusilo <tri.susilo@altama.co.id> | 2023-10-06 06:54:30 +0000 |
| commit | 1203225f97f4371823ef82103b89bcddf2bce59c (patch) | |
| tree | 8c9fc18df252de1fd5afa57e64f13e005028f27a | |
| parent | 010cbf9ff08835ed0cf61e821ce4db79f744893c (diff) | |
| parent | 5d4cf836d098e9c351bce4d25f0e88e341646ccc (diff) | |
Merged in CR/Pricelist (pull request #92)
CR/Pricelist
| -rw-r--r-- | src/core/components/elements/Product/cartProductsList.jsx | 267 | ||||
| -rw-r--r-- | src/lib/cart/components/Cart.jsx | 257 | ||||
| -rw-r--r-- | src/lib/cart/components/Cartheader.jsx | 2 | ||||
| -rw-r--r-- | src/lib/checkout/components/Checkout.jsx | 42 | ||||
| -rw-r--r-- | src/lib/product/components/Product/ProductDesktop.jsx | 154 | ||||
| -rw-r--r-- | src/lib/product/components/Product/ProductDesktopVariant.jsx | 71 | ||||
| -rw-r--r-- | src/lib/product/components/Product/ProductMobile.jsx | 67 | ||||
| -rw-r--r-- | src/lib/product/components/Product/ProductMobileVariant.jsx | 72 | ||||
| -rw-r--r-- | src/lib/product/components/ProductCard.jsx | 89 | ||||
| -rw-r--r-- | src/lib/quotation/components/Quotation.jsx | 66 | ||||
| -rw-r--r-- | src/lib/variant/components/VariantCard.jsx | 2 | ||||
| -rw-r--r-- | src/lib/variant/components/VariantGroupCard.jsx | 1 | ||||
| -rw-r--r-- | src/pages/api/shop/product-detail.js | 32 | ||||
| -rw-r--r-- | src/pages/api/shop/search.js | 21 | ||||
| -rw-r--r-- | src/pages/shop/product/[slug].jsx | 3 | ||||
| -rw-r--r-- | src/utils/solrMapping.js | 113 |
16 files changed, 731 insertions, 528 deletions
diff --git a/src/core/components/elements/Product/cartProductsList.jsx b/src/core/components/elements/Product/cartProductsList.jsx new file mode 100644 index 00000000..5887b425 --- /dev/null +++ b/src/core/components/elements/Product/cartProductsList.jsx @@ -0,0 +1,267 @@ +import Link from '@/core/components/elements/Link/Link' +import Image from '@/core/components/elements/Image/Image' +import LogoSpinner from '../Spinner/LogoSpinner' +import { TrashIcon } from '@heroicons/react/24/outline' +import { useEffect } from 'react' +import { createSlug } from '@/core/utils/slug' +import currencyFormat from '@/core/utils/currencyFormat' + +const CardProdcuctsList = ({ + isLoading, + products, + source, + handlePopUpPromo = () => {}, + toggleSelected = () => {}, + updateQuantity = () => {}, + setDeleteConfirmation = () => {} +}) => { + + return ( + <table className='table-cart'> + <thead> + <tr> + <th colSpan={2}>Nama Produk</th> + <th>Jumlah</th> + <th>Harga</th> + <th>Subtotal</th> + {source == 'cart' && <th>Action</th>} + </tr> + </thead> + <tbody> + {isLoading && ( + <tr> + <td colSpan={6}> + <div className='container flex justify-center my-4'> + <LogoSpinner width={48} height={48} /> + </div> + </td> + </tr> + )} + {!isLoading && (!products || products?.length == 0) && ( + <tr> + <td colSpan={6}>Keranjang belanja anda masih kosong</td> + </tr> + )} + {products && + products?.map((product) => ( + <> + {product.hasProgram && ( + <tr className='!border-b-0 pb-0'> + <td colSpan={6}> + <div className='flex gap-x-2 bg-yellow-100 p-2 items-center'> + {product.program ? ( + <> + <div className='flex border border-solid border-red-600 rounded-md p-1'> + <span className='text-red-600'>{product.program.type.label}</span> + </div> + <div className='flex'> + {product.program.type.value == 'merchandise' ? ( + <>Selamat anda mendapatkan merchandise indoteknik.com</> + ) : ( + <> + Selamat! Pembelian anda lebih hemat + <span className='text-red-600 font-semibold ml-2'> + {' '} + {currencyFormat(product.program?.totalSavings)} + </span> + </> + )} + </div> + </> + ) : ( + <> + <div className='flex border border-solid border-red-600 rounded-md p-1'> + <span className='text-red-600'>Promo</span> + </div> + <div className='flex'>Pilih Promo Yang Tersedia Bisa lebih Hemat</div> + </> + )} + <div + onClick={() => + handlePopUpPromo(product.id, product.quantity, product.program?.id) + } + className='ml-auto text-red-500 flex gap-x-1 cursor-pointer' + > + <div className='font-semibold'> Cek Promo</div> + <div> + <svg + aria-hidden='true' + fill='none' + stroke='currentColor' + stroke-width='1.5' + viewBox='0 0 20 24' + className='h-5 w-5 font-semibold' + > + <path + d='M8.25 4.5l7.5 7.5-7.5 7.5' + stroke-linecap='round' + stroke-linejoin='round' + ></path> + </svg> + </div> + </div> + </div> + </td> + </tr> + )} + <tr + key={product.id} + className={`${product.hasProgram ? '!border-t-0 !border-b-0' : ''}`} + > + <td className='relative'> + {source == 'cart' && ( + <> + <ComponentCanBuy canBuy={product.canBuy} /> + <input + type='checkbox' + onClick={() => toggleSelected(product.id)} + checked={product?.selected} + className='accent-danger-500 w-4' + /> + </> + )} + </td> + <td className='flex relative'> + <ComponentCanBuy canBuy={product.canBuy} /> + <Link + href={createSlug('/shop/product/', product?.parent.name, product?.parent.id)} + className='w-[20%] flex-shrink-0' + > + <Image + src={product?.parent?.image} + alt={product?.name} + className='object-contain object-center border border-gray_r-6 h-28 w-full rounded-md' + /> + </Link> + <div className='px-2 text-left'> + <Link + href={createSlug('/shop/product/', product?.parent.name, product?.parent.id)} + className='line-clamp-2 leading-6 !text-gray_r-12 font-normal' + > + {product?.parent?.name} + </Link> + <div className='text-gray_r-11 mt-2'> + {product?.code}{' '} + {product?.attributes.length > 0 ? `| ${product?.attributes.join(', ')}` : ''} + </div> + <div className='text-gray_r-11 mt-2'>Berat item : {product?.weight} Kg</div> + </div> + </td> + <td className='relative'> + <ComponentCanBuy canBuy={product.canBuy} /> + <input + className='form-input w-16 py-2 text-center bg-gray_r-1' + type='number' + value={product?.quantity} + disabled={source === 'cart' ? false : true} + onChange={(e) => updateQuantity(e.target.value, product?.id)} + onBlur={(e) => updateQuantity(e.target.value, product?.id, 'BLUR')} + /> + </td> + <td className='relative'> + <ComponentCanBuy canBuy={product.canBuy} /> + {product?.hasFlashsale ? ( + <> + <div className='flex gap-x-1 items-center justify-center mt-3'> + <div className='text-gray_r-11 line-through text-caption-1'> + {currencyFormat(product?.price?.price)} + </div> + <div className='badge-solid-red'>{product?.price?.discountPercentage}%</div> + </div> + <div className='font-normal mt-1'> + {currencyFormat(product?.price?.priceDiscount)} + </div> + </> + ) : ( + <div className='font-normal mt-1'>{currencyFormat(product?.price?.price)}</div> + )} + </td> + <td className='relative'> + <ComponentCanBuy canBuy={product.canBuy} /> + <div className='text-danger-500 font-medium'> + {currencyFormat(product?.price?.priceDiscount * product?.quantity)} + </div> + </td> + {source == 'cart' && ( + <td> + <div className='flex justify-center items-center h-full'> + <button + className='btn-red p-1 ml-1' + onClick={() => setDeleteConfirmation(product)} + > + <TrashIcon className='w-4' /> + </button> + </div> + </td> + )} + </tr> + {/* Component for promotion program product */} + {product?.program?.items && ( + <tr key={product.program.id} className='!border-t-0'> + {product.program.items.map((item) => ( + <> + <td className='relative'> + <ComponentCanBuy canBuy={product.canBuy} /> + </td> + <td className='flex relative'> + <ComponentCanBuy canBuy={product.canBuy} /> + <div className='w-[20%] flex-shrink-0'> + <Image + src={item.parent.image} + alt={item.name} + className='object-contain object-center border border-gray_r-6 h-28 w-full rounded-md' + /> + </div> + <div className='px-2 text-left'> + <div className=''> + <span className='border border-solid border-red-600 rounded-md p-1 text-red-600'> + {product.program.type.label} + </span> + </div> + <div className='mt-2 line-clamp-2 leading-6'>{item.name}</div> + </div> + </td> + <td className='relative'> + <ComponentCanBuy canBuy={product.canBuy} /> + <input + className='form-input w-16 py-2 text-center bg-gray_r-1' + type='number' + value={1} + disabled + /> + </td> + <td className='relative'> + <ComponentCanBuy canBuy={product.canBuy} /> + {item?.price?.discountPercentage > 0 && ( + <div className='flex gap-x-1 items-center justify-center mt-3'> + <div className='text-gray_r-11 line-through text-caption-1'> + {currencyFormat(product?.price?.price)} + </div> + </div> + )} + <div className='font-normal mt-1'> + {item?.price.priceDiscount > 0 ? 'Gratis' : ''} + </div> + </td> + <td className='relative'> + <ComponentCanBuy canBuy={product.canBuy} /> + <div className='text-danger-500 font-medium'> + {item.price.priceDiscount > 0 ? 'Gratis' : ''} + </div> + </td> + <td></td> + </> + ))} + </tr> + )} + </> + ))} + </tbody> + </table> + ) +} + +const ComponentCanBuy = ({ canBuy }) => + !canBuy && <div className='absolute w-full h-full bg-gray_r-3/40 top-0 left-0' /> + +export default CardProdcuctsList diff --git a/src/lib/cart/components/Cart.jsx b/src/lib/cart/components/Cart.jsx index b5976a1b..c6aaa596 100644 --- a/src/lib/cart/components/Cart.jsx +++ b/src/lib/cart/components/Cart.jsx @@ -23,6 +23,8 @@ import { getPromotionProgram } from '@/lib/promotinProgram/api/homepageApi' import PromotionType from '@/lib/promotinProgram/components/PromotionType' import { gtagBeginCheckout } from '@/core/utils/googleTag' import { useProductCartContext } from '@/contexts/ProductCartContext' +import CardProdcuctsList from '@/core/components/elements/Product/cartProductsList' +// import cardProdcuctsList from '@/core/components/elements/Product/cartProductsList' const Cart = () => { const router = useRouter() @@ -32,7 +34,7 @@ const Cart = () => { const [cart, setCart] = useState(null) - const {setRefreshCart} = useProductCartContext() + const { setRefreshCart } = useProductCartContext() useEffect(() => { if (!auth) return @@ -115,7 +117,7 @@ const Cart = () => { selected: true }).then(() => { getCart().then(() => { - if(promotionActiveId){ + if (promotionActiveId) { setPromotionType(false) } }) @@ -438,7 +440,7 @@ const Cart = () => { product.program.items && product.program.items.map((item) => ( <div key={item.id} className='flex mx-4 relative'> - <ComponentCanBuy canBuy={product.canBuy} /> + <ComponentCanBuy canBuy={product.canBuy} /> <input className='mr-2 accent-danger-500 w-4' /> <Link href={createSlug( @@ -530,254 +532,7 @@ const Cart = () => { <div className='col-span-9 border border-gray_r-6 rounded bg-white p-4 pt-6'> <h1 className='text-title-sm font-semibold mb-6'>Keranjang</h1> - <table className='table-cart'> - <thead> - <tr> - <th colSpan={2}>Nama Produk</th> - <th>Jumlah</th> - <th>Harga</th> - <th>Subtotal</th> - <th>Action</th> - </tr> - </thead> - <tbody> - {isLoading && ( - <tr> - <td colSpan={6}> - <div className='container flex justify-center my-4'> - <LogoSpinner width={48} height={48} /> - </div> - </td> - </tr> - )} - {!isLoading && (!products || products?.length == 0) && ( - <tr> - <td colSpan={6}>Keranjang belanja anda masih kosong</td> - </tr> - )} - {products && - products?.map((product) => ( - <> - {product.hasProgram && ( - <tr className='!border-b-0 pb-0'> - <td colSpan={6}> - <div className='flex gap-x-2 bg-yellow-100 p-2 items-center'> - {product.program ? ( - <> - <div className='flex border border-solid border-red-600 rounded-md p-1'> - <span className='text-red-600'> - {product.program.type.label} - </span> - </div> - <div className='flex'> - {product.program.type.value == 'merchandise' ? ( - <>Selamat anda mendapatkan merchandise indoteknik.com</> - ) : ( - <> - Selamat! Pembelian anda lebih hemat - <span className='text-red-600 font-semibold ml-2'> - {' '} - {currencyFormat(product.program?.totalSavings)} - </span> - </> - )} - </div> - </> - ) : ( - <> - <div className='flex border border-solid border-red-600 rounded-md p-1'> - <span className='text-red-600'>Promo</span> - </div> - <div className='flex'> - Pilih Promo Yang Tersedia Bisa lebih Hemat - </div> - </> - )} - <div - onClick={() => - handlePopUpPromo( - product.id, - product.quantity, - product.program?.id - ) - } - className='ml-auto text-red-500 flex gap-x-1 cursor-pointer' - > - <div className='font-semibold'> Cek Promo</div> - <div> - <svg - aria-hidden='true' - fill='none' - stroke='currentColor' - stroke-width='1.5' - viewBox='0 0 20 24' - className='h-5 w-5 font-semibold' - > - <path - d='M8.25 4.5l7.5 7.5-7.5 7.5' - stroke-linecap='round' - stroke-linejoin='round' - ></path> - </svg> - </div> - </div> - </div> - </td> - </tr> - )} - <tr - key={product.id} - className={`${product.hasProgram ? '!border-t-0 !border-b-0' : ''}`} - > - <td className='relative'> - <ComponentCanBuy canBuy={product.canBuy} /> - <input - type='checkbox' - onClick={() => toggleSelected(product.id)} - checked={product?.selected} - className='accent-danger-500 w-4' - /> - </td> - <td className='flex relative'> - <ComponentCanBuy canBuy={product.canBuy} /> - <Link - href={createSlug( - '/shop/product/', - product?.parent.name, - product?.parent.id - )} - className='w-[20%] flex-shrink-0' - > - <Image - src={product?.parent?.image} - alt={product?.name} - className='object-contain object-center border border-gray_r-6 h-28 w-full rounded-md' - /> - </Link> - <div className='px-2 text-left'> - <Link - href={createSlug( - '/shop/product/', - product?.parent.name, - product?.parent.id - )} - className='line-clamp-2 leading-6 !text-gray_r-12 font-normal' - > - {product?.parent?.name} - </Link> - <div className='text-gray_r-11 mt-2'> - {product?.code}{' '} - {product?.attributes.length > 0 - ? `| ${product?.attributes.join(', ')}` - : ''} - </div> - </div> - </td> - <td className='relative'> - <ComponentCanBuy canBuy={product.canBuy} /> - <input - className='form-input w-16 py-2 text-center bg-gray_r-1' - type='number' - value={product?.quantity} - onChange={(e) => updateQuantity(e.target.value, product?.id)} - onBlur={(e) => updateQuantity(e.target.value, product?.id, 'BLUR')} - /> - </td> - <td className='relative'> - <ComponentCanBuy canBuy={product.canBuy} /> - {product?.price?.discountPercentage > 0 && ( - <div className='flex gap-x-1 items-center justify-center mt-3'> - <div className='text-gray_r-11 line-through text-caption-1'> - {currencyFormat(product?.price?.price)} - </div> - <div className='badge-solid-red'> - {product?.price?.discountPercentage}% - </div> - </div> - )} - <div className='font-normal mt-1'> - {currencyFormat(product?.price?.priceDiscount)} - </div> - </td> - <td className='relative'> - <ComponentCanBuy canBuy={product.canBuy} /> - <div className='text-danger-500 font-medium'> - {currencyFormat(product?.price?.priceDiscount * product?.quantity)} - </div> - </td> - <td> - <div className='flex justify-center items-center h-full'> - <button - className='btn-red p-1 ml-1' - onClick={() => setDeleteConfirmation(product)} - > - <TrashIcon className='w-4' /> - </button> - </div> - </td> - </tr> - {product?.program?.items && ( - <tr key={product.program.id} className='!border-t-0'> - {product.program.items.map((item) => ( - <> - <td className='relative'> - <ComponentCanBuy canBuy={product.canBuy} /> - </td> - <td className='flex relative'> - <ComponentCanBuy canBuy={product.canBuy} /> - <div className='w-[20%] flex-shrink-0'> - <Image - src={item.parent.image} - alt={item.name} - className='object-contain object-center border border-gray_r-6 h-28 w-full rounded-md' - /> - </div> - <div className='px-2 text-left'> - <div className=''> - <span className='border border-solid border-red-600 rounded-md p-1 text-red-600'> - {product.program.type.label} - </span> - </div> - <div className='mt-2 line-clamp-2 leading-6'>{item.name}</div> - </div> - </td> - <td className='relative'> - <ComponentCanBuy canBuy={product.canBuy} /> - <input - className='form-input w-16 py-2 text-center bg-gray_r-1' - type='number' - value={1} - disabled - /> - </td> - <td className='relative'> - <ComponentCanBuy canBuy={product.canBuy} /> - {item?.price?.discountPercentage > 0 && ( - <div className='flex gap-x-1 items-center justify-center mt-3'> - <div className='text-gray_r-11 line-through text-caption-1'> - {currencyFormat(product?.price?.price)} - </div> - </div> - )} - <div className='font-normal mt-1'> - {item?.price.priceDiscount > 0 ? 'Gratis' : ''} - </div> - </td> - <td className='relative'> - <ComponentCanBuy canBuy={product.canBuy} /> - <div className='text-danger-500 font-medium'> - {item.price.priceDiscount > 0 ? 'Gratis' : ''} - </div> - </td> - <td></td> - </> - ))} - </tr> - )} - </> - ))} - </tbody> - </table> + <CardProdcuctsList isLoading={isLoading} products={products} source='cart' handlePopUpPromo ={handlePopUpPromo} toggleSelected ={toggleSelected} updateQuantity ={updateQuantity} setDeleteConfirmation ={setDeleteConfirmation}/> <div className='pt-2 pb-6 flex items-center gap-x-3'> <NextImage diff --git a/src/lib/cart/components/Cartheader.jsx b/src/lib/cart/components/Cartheader.jsx index cbe7c7e1..901b1501 100644 --- a/src/lib/cart/components/Cartheader.jsx +++ b/src/lib/cart/components/Cartheader.jsx @@ -204,7 +204,7 @@ const Cardheader = (cartCount) => { </p> </Link> - {product?.price?.discountPercentage > 0 && ( + {product?.hasFlashsale && ( <div className='flex gap-x-1 items-center mb-2 mt-1'> <div className='badge-solid-red'> {product?.price?.discountPercentage}% diff --git a/src/lib/checkout/components/Checkout.jsx b/src/lib/checkout/components/Checkout.jsx index 6d2f62e0..e2c1a85b 100644 --- a/src/lib/checkout/components/Checkout.jsx +++ b/src/lib/checkout/components/Checkout.jsx @@ -32,6 +32,7 @@ import BottomPopup from '@/core/components/elements/Popup/BottomPopup' import { useQuery } from 'react-query' import { gtagPurchase } from '@/core/utils/googleTag' import { findVoucher, getVoucher } from '../api/getVoucher' +import CardProdcuctsList from '@/core/components/elements/Product/cartProductsList' const SELF_PICKUP_ID = 32 @@ -633,8 +634,11 @@ const Checkout = () => { Berakhir dalam{' '} <span className='text-red-600'>{item.remainingTime}</span> lagi,{' '} </div> - <div className='text-sm ml-2 text-red-600' onClick={() => handlingTnC(item)} > - Baca S&K + <div + className='text-sm ml-2 text-red-600' + onClick={() => handlingTnC(item)} + > + Baca S&K </div> </div> </div> @@ -985,7 +989,9 @@ const Checkout = () => { <div className='p-4'> <div className='font-medium'>Detail Pesanan</div> - <table className='table-checkout'> + <CardProdcuctsList isLoading={isLoading} products={products} /> + + {/* <table className='table-checkout'> <thead> <tr> <th>Nama Produk</th> @@ -1045,21 +1051,27 @@ const Checkout = () => { /> </td> <td> - {product?.price?.discountPercentage > 0 && ( - <div className='flex gap-x-1 items-center justify-center mt-3'> - <div className='text-gray_r-11 line-through text-caption-1'> - {currencyFormat(product?.price?.price)} + {product?.hasFlashsale ? ( + <> + <div className='flex gap-x-1 items-center justify-center mt-3'> + <div className='text-gray_r-11 line-through text-caption-1'> + {currencyFormat(product?.price?.price)} + </div> + <div className='badge-solid-red'> + {product?.price?.discountPercentage}% + </div> </div> - <div className='badge-solid-red'> - {product?.price?.discountPercentage}% + <div className='font-normal mt-1'> + {currencyFormat(product?.price?.priceDiscount)} </div> + </> + ) : ( + <div className='font-normal mt-1'> + {product.price.priceDiscount > 0 + ? currencyFormat(product?.price?.priceDiscount) + : 'Call For Price'} </div> )} - <div className='font-normal mt-1'> - {product.price.priceDiscount > 0 - ? currencyFormat(product?.price?.priceDiscount) - : 'Call For Price'} - </div> </td> <td> <div className='text-danger-500 font-medium'> @@ -1139,7 +1151,7 @@ const Checkout = () => { )) )} </tbody> - </table> + </table> */} </div> </div> <div className='w-1/4 pl-4'> diff --git a/src/lib/product/components/Product/ProductDesktop.jsx b/src/lib/product/components/Product/ProductDesktop.jsx index 5cc35df7..4c8c3ae9 100644 --- a/src/lib/product/components/Product/ProductDesktop.jsx +++ b/src/lib/product/components/Product/ProductDesktop.jsx @@ -44,7 +44,10 @@ const ProductDesktop = ({ products, wishlist, toggleWishlist }) => { const { setRefreshCart, refreshCart } = useProductCartContext() const getLowestPrice = useCallback(() => { - const prices = product.variants.map((variant) => variant.price) + const prices = product.variants.map((variant) => ({ + price: variant.price, + isFlashsale: variant.isFlashsale + })) const lowest = prices.reduce((lowest, price) => { return price.priceDiscount < lowest.priceDiscount ? price : lowest }, prices[0]) @@ -413,13 +416,13 @@ const ProductDesktop = ({ products, wishlist, toggleWishlist }) => { <div className='text-gray_r-12/80'>Harga mulai dari: </div> )} - {lowestPrice?.discountPercentage > 0 && ( + {/* {lowestPrice?.discountPercentage > 0 && ( <div className='flex gap-x-1 items-center mt-2'> <div className='badge-solid-red text-caption-1'> {lowestPrice?.discountPercentage}% </div> - <div className='text-gray_r-11 line-through text-caption-1'> - {currencyFormat(lowestPrice?.price)} + <div className='text-gray_r-9 text-caption-1'> + Include PPN {currencyFormat(lowestPrice?.price * process.env.NEXT_PUBLIC_PPN)} </div> {product.flashSale.remainingTime > 0 && ( <div className='bg-red-600 rounded-full mb-1 p-2 pl-3 pr-3 flex w-fit items-center gap-x-1'> @@ -436,28 +439,56 @@ const ProductDesktop = ({ products, wishlist, toggleWishlist }) => { </div> )} </div> + )} */} + + {lowestPrice?.isFlashsale ? ( + <> + <div className='flex gap-x-1 items-center mt-2'> + <div className='badge-solid-red text-caption-1'> + {lowestPrice?.price?.discountPercentage}% + </div> + <div className='text-gray_r-9 line-through text-caption-1'> + {currencyFormat(lowestPrice?.price?.price)} + </div> + <div className='text-danger-500 font-semibold text-xl'> + {currencyFormat(lowestPrice?.price?.priceDiscount)} + </div> + </div> + <div className='text-gray_r-9 text-base font-normal mt-1'> + Termasuk PPN:{' '} + {currencyFormat(lowestPrice?.price.priceDiscount * process.env.NEXT_PUBLIC_PPN)} + </div> + </> + ) : ( + <h3 className='text-danger-500 font-semibold mt-1 text-title-md'> + {lowestPrice?.price.price > 0 ? ( + <> + {currencyFormat(lowestPrice?.price.price)} + <div className='text-gray_r-9 text-base font-normal mt-1'> + Termasuk PPN:{' '} + {currencyFormat(lowestPrice?.price.price * process.env.NEXT_PUBLIC_PPN)} + </div> + </> + ) : ( + <span className='text-gray_r-12/90 font-normal text-h-sm'> + Hubungi kami untuk dapatkan harga terbaik, + <a + href={whatsappUrl('product', { + name: product.name, + manufacture: product.manufacture?.name, + url: createSlug('/shop/product/', product.name, product.id, true) + })} + className='text-danger-500 underline' + rel='noopener noreferrer' + target='_blank' + > + klik disini + </a> + </span> + )} + </h3> )} - <h3 className='text-danger-500 font-semibold mt-1 text-title-md'> - {lowestPrice?.priceDiscount > 0 ? ( - currencyFormat(lowestPrice?.priceDiscount) - ) : ( - <span className='text-gray_r-12/90 font-normal text-h-sm'> - Hubungi kami untuk dapatkan harga terbaik, - <a - href={whatsappUrl('product', { - name: product.name, - manufacture: product.manufacture?.name, - url: createSlug('/shop/product/', product.name, product.id, true) - })} - className='text-danger-500 underline' - rel='noopener noreferrer' - target='_blank' - > - klik disini - </a> - </span> - )} - </h3> + {product.variants.length > 1 ? ( <button type='button' @@ -549,32 +580,65 @@ const ProductDesktop = ({ products, wishlist, toggleWishlist }) => { <ColumnsSLA variant={variant} product={product} /> </LazyLoadComponent> <td> - {variant.price.discountPercentage > 0 && + {variant.isFlashsale ? ( + <> + <div className='flex items-center gap-x-1 justify-center'> + <div className='badge-solid-red text-caption-1'> + {variant?.price?.discountPercentage}% + </div> + <div className='line-through text-caption-1 text-gray_r-11'> + {currencyFormat(variant?.price?.price)} + </div>{' '} + <div className=' text-caption-1 text-red-600 font-semibold'> + {currencyFormat(variant?.price?.priceDiscount)} + </div>{' '} + </div> + <div className=' text-caption-1 text-gray_r-11 mb-1'> + Inc. PPN:{' '} + {currencyFormat( + variant.price.priceDiscount * process.env.NEXT_PUBLIC_PPN + )} + </div> + </> + ) : ( + <div> + {variant?.price?.price > 0 ? ( + <> + <div className=' text-caption-1 text-red-600 font-semibold'> + {currencyFormat(variant?.price?.price)} + </div>{' '} + <div className=' text-caption-1 text-gray_r-11 mb-1'> + Inc. PPN:{' '} + {currencyFormat( + variant?.price?.priceDiscount * process.env.NEXT_PUBLIC_PPN + )} + </div> + </> + ) : ( + <a + href={whatsappUrl('product', { + name: variant.name, + manufacture: product.manufacture?.name, + url: createSlug('/shop/product/', product.name, product.id, true) + })} + className='text-red_r-11' + rel='noopener noreferrer' + target='_blank' + > + Call for price + </a> + )} + </div> + )} + {/* {variant.price.discountPercentage > 0 && variant.price.priceDiscount > 0 && ( <> <div className='line-through text-caption-1 text-gray_r-11 mb-1'> {currencyFormat(variant.price.price)} </div>{' '} </> - )} - <div> - {variant.price.priceDiscount > 0 ? ( - currencyFormat(variant.price.priceDiscount) - ) : ( - <a - href={whatsappUrl('product', { - name: variant.name, - manufacture: product.manufacture?.name, - url: createSlug('/shop/product/', product.name, product.id, true) - })} - className='text-red_r-11' - rel='noopener noreferrer' - target='_blank' - > - Call for price - </a> - )} - </div> + )} */} + {/* <VariantPrice id={variant.id} /> */} </td> <td> diff --git a/src/lib/product/components/Product/ProductDesktopVariant.jsx b/src/lib/product/components/Product/ProductDesktopVariant.jsx index d64e70c2..51739bc9 100644 --- a/src/lib/product/components/Product/ProductDesktopVariant.jsx +++ b/src/lib/product/components/Product/ProductDesktopVariant.jsx @@ -203,7 +203,8 @@ const ProductDesktopVariant = ({ product, wishlist, toggleWishlist, isVariant }) <a href={whatsappUrl('product', { name: product.name, - url: createSlug('/shop/product/variant/', product.name, product.id, true) + manufacture: product?.manufacture?.name, + url: createSlug('/shop/product/', product.name, product.id, true) })} className='text-danger-500 font-medium' > @@ -269,44 +270,52 @@ const ProductDesktopVariant = ({ product, wishlist, toggleWishlist, isVariant }) </div> */} </div> <div className='w-[25%]'> - {lowestPrice?.priceDiscount > 0 ? ( + {product?.flashSale?.remainingTime > 0 ? ( <> - <div className='flex gap-x-2 mb-3 items-center'> - <div className='flex'> - <span className='text-gray-400 text-md'>Harga Sebelum PPN : </span> - </div> - <div className='flex'> - <span className=' text-body-1 '> - {currencyFormat(lowestPrice?.priceDiscount)} - </span> - </div> - </div> - <span className='font-semibold'>Termasuk PPN :</span> - <div className='flex gap-x-1 items-center mt-2 '> + <div className='flex gap-x-1 items-center mt-2'> <div className='badge-solid-red text-caption-1'> {lowestPrice?.discountPercentage}% </div> - <div className='text-gray_r-11 line-through text-caption-1'> - {currencyFormat(lowestPrice?.price * 1.11)} + <div className='text-gray_r-9 line-through text-caption-1'> + {currencyFormat(lowestPrice?.price)} </div> - <h3 className='text-danger-500 font-semibold text-title-sm'> - {currencyFormat(lowestPrice?.priceDiscount * 1.11)} - </h3> + <div className='text-danger-500 font-semibold text-xl'> + {currencyFormat(lowestPrice?.priceDiscount)} + </div> + </div> + <div className='text-gray_r-9 text-base font-normal mt-1'> + Termasuk PPN:{' '} + {currencyFormat(lowestPrice?.priceDiscount * process.env.NEXT_PUBLIC_PPN)} </div> </> ) : ( - <span className='text-gray_r-12/90 font-normal text-h-sm'> - Hubungi kami untuk dapatkan harga terbaik, - <a - href={whatsappUrl('product', { - name: product.name, - url: createSlug('/shop/product/', product.name, product.id, true) - })} - className='text-danger-500 underline' - > - klik disini - </a> - </span> + <h3 className='text-danger-500 font-semibold mt-1 text-title-md'> + {lowestPrice?.price > 0 ? ( + <> + {currencyFormat(lowestPrice?.price)} + <div className='text-gray_r-9 text-base font-normal mt-1'> + Termasuk PPN:{' '} + {currencyFormat(lowestPrice?.price * process.env.NEXT_PUBLIC_PPN)} + </div> + </> + ) : ( + <span className='text-gray_r-12/90 font-normal text-h-sm'> + Hubungi kami untuk dapatkan harga terbaik, + <a + href={whatsappUrl('product', { + name: product.name, + manufacture: product.manufacture?.name, + url: createSlug('/shop/product/', product.name, product.id, true) + })} + className='text-danger-500 underline' + rel='noopener noreferrer' + target='_blank' + > + klik disini + </a> + </span> + )} + </h3> )} <div className='flex gap-x-3 mt-4'> <input diff --git a/src/lib/product/components/Product/ProductMobile.jsx b/src/lib/product/components/Product/ProductMobile.jsx index 12c43727..20a1d3f4 100644 --- a/src/lib/product/components/Product/ProductMobile.jsx +++ b/src/lib/product/components/Product/ProductMobile.jsx @@ -100,7 +100,8 @@ const ProductMobile = ({ product, wishlist, toggleWishlist }) => { price: variant.price, stock: variant.stock, weight: variant.weight, - hasProgram: variant.hasProgram + hasProgram: variant.hasProgram, + isFlashsale: variant.isFlashsale } setActiveVariant(newActiveVariant) @@ -231,32 +232,48 @@ const ProductMobile = ({ product, wishlist, toggleWishlist }) => { <div className='text-gray_r-12/80 text-caption-2 mt-2 mb-1'>Harga mulai dari: </div> )} - {activeVariant?.price?.discountPercentage > 0 && ( - <div className='flex gap-x-1 items-center'> - <div className='text-gray_r-11 line-through text-caption-1'> - {currencyFormat(activeVariant?.price?.price)} + {activeVariant.isFlashsale ? ( + <> + <div className='flex gap-x-1 items-center'> + <div className='badge-solid-red'>{activeVariant?.price?.discountPercentage}%</div> + <div className='text-gray_r-11 line-through text-caption-1'> + {currencyFormat(activeVariant?.price?.price)} + </div> + <div className='text-danger-500 font-semibold'> + {currencyFormat(activeVariant?.price?.priceDiscount)} + </div> </div> - <div className='badge-solid-red'>{activeVariant?.price?.discountPercentage}%</div> - </div> + <div className='text-gray_r-9 text-base font-normal mt-1'> + Termasuk PPN:{' '} + {currencyFormat(activeVariant?.price.priceDiscount * process.env.NEXT_PUBLIC_PPN)} + </div> + </> + ) : ( + <h3 className='text-danger-500 font-semibold mt-1'> + {activeVariant?.price?.price > 0 ? ( + <> + {currencyFormat(activeVariant?.price?.price)} + <div className='text-gray_r-9 text-base font-normal mt-1'> + Termasuk PPN:{' '} + {currencyFormat(activeVariant?.price.price * process.env.NEXT_PUBLIC_PPN)} + </div> + </> + ) : ( + <span className='text-gray_r-11 leading-6 font-normal'> + Hubungi kami untuk dapatkan harga terbaik, + <a + href={whatsappUrl('product', { + name: product.name, + url: createSlug('/shop/product/', product.name, product.id, true) + })} + className='text-danger-500 underline' + > + klik disini + </a> + </span> + )} + </h3> )} - <h3 className='text-danger-500 font-semibold mt-1'> - {activeVariant?.price?.priceDiscount > 0 ? ( - currencyFormat(activeVariant?.price?.priceDiscount) - ) : ( - <span className='text-gray_r-11 leading-6 font-normal'> - Hubungi kami untuk dapatkan harga terbaik, - <a - href={whatsappUrl('product', { - name: product.name, - url: createSlug('/shop/product/', product.name, product.id, true) - })} - className='text-danger-500 underline' - > - klik disini - </a> - </span> - )} - </h3> </div> <Divider /> diff --git a/src/lib/product/components/Product/ProductMobileVariant.jsx b/src/lib/product/components/Product/ProductMobileVariant.jsx index d0c209cc..8cdb631f 100644 --- a/src/lib/product/components/Product/ProductMobileVariant.jsx +++ b/src/lib/product/components/Product/ProductMobileVariant.jsx @@ -39,7 +39,8 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => { name: product.name, price: getLowestPrice(), stock: product.stockTotal, - weight: product.weight + weight: product.weight, + isFlashSale: product.isFlashsale }) useEffect(() => { @@ -50,7 +51,8 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => { name: product.name, price: product.price, stock: product.stock, - weight: product.weight + weight: product.weight, + isFlashSale: product.isFlashsale }) } }, [selectedVariant, product]) @@ -139,47 +141,47 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => { </div> <h1 className='leading-6 font-medium mb-3'>{activeVariant?.name}</h1> - {activeVariant?.price?.priceDiscount > 0 ? ( + {activeVariant.isFlashsale ? ( <> <div className='flex gap-x-1 items-center'> - <div className='text-gray_r-11 text-caption-1'>Harga Sebelum PPN :</div> - <div className='text-gray_r-12 line-through text-caption-1'> - {' '} + <div className='badge-solid-red'>{activeVariant?.price?.discountPercentage}%</div> + <div className='text-gray_r-11 line-through text-caption-1'> + {currencyFormat(activeVariant?.price?.price)} + </div> + <div className='text-danger-500 font-semibold'> {currencyFormat(activeVariant?.price?.priceDiscount)} </div> </div> - <div className='mt-2'> - <span className='font-semibold '>Termasuk PPN :</span> - <div className='flex gap-x-2 items-center mt-2'> - {activeVariant?.price?.discountPercentage > 0 && ( - <> - <div className='badge-solid-red'> - {activeVariant?.price?.discountPercentage}% - </div> - <div className='text-gray_r-11 line-through text-caption-1'> - {currencyFormat(activeVariant?.price?.price * 1.11)} - </div> - </> - )} - <h3 className='text-danger-500 font-semibold'> - {currencyFormat(activeVariant?.price?.priceDiscount * 1.11)} - </h3> - </div> + <div className='text-gray_r-9 text-base font-normal mt-1'> + Termasuk PPN:{' '} + {currencyFormat(activeVariant?.price.priceDiscount * process.env.NEXT_PUBLIC_PPN)} </div> </> ) : ( - <span className='text-gray_r-11 leading-6 font-normal'> - Hubungi kami untuk dapatkan harga terbaik, - <a - href={whatsappUrl('product', { - name: product.name, - url: createSlug('/shop/product/', product.name, product.id, true) - })} - className='text-danger-500 underline' - > - klik disini - </a> - </span> + <h3 className='text-danger-500 font-semibold mt-1'> + {activeVariant?.price?.priceDiscount > 0 ? ( + <> + {currencyFormat(activeVariant?.price?.priceDiscount)} + <div className='text-gray_r-9 text-base font-normal mt-1'> + Termasuk PPN:{' '} + {currencyFormat(activeVariant?.price.priceDiscount * process.env.NEXT_PUBLIC_PPN)} + </div> + </> + ) : ( + <span className='text-gray_r-11 leading-6 font-normal'> + Hubungi kami untuk dapatkan harga terbaik, + <a + href={whatsappUrl('product', { + name: product.name, + url: createSlug('/shop/product/', product.name, product.id, true) + })} + className='text-danger-500 underline' + > + klik disini + </a> + </span> + )} + </h3> )} </div> diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx index 10ffdaec..6a5e29ab 100644 --- a/src/lib/product/components/ProductCard.jsx +++ b/src/lib/product/components/ProductCard.jsx @@ -82,30 +82,47 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { )} <Link href={createSlug('/shop/product/', product?.name, product?.id)} - className={`mb-2 !text-gray_r-12 leading-6 block ${ + className={`mb-3 !text-gray_r-12 leading-6 block ${ simpleTitle ? 'line-clamp-2 h-12' : 'line-clamp-3 h-[64px]' }`} title={product?.name} > {product?.name} </Link> - {product?.lowestPrice.discountPercentage > 0 && ( - <div className='flex gap-x-1 mb-1 items-center'> - <div className='text-gray_r-11 line-through text-[11px] sm:text-caption-2'> - {currencyFormat(product.lowestPrice.price)} + {product?.flashSale?.id > 0 ? ( + <> + {product?.lowestPrice.discountPercentage > 0 && ( + <div className='flex gap-x-1 mb-1 items-center'> + <div className='text-gray_r-11 line-through text-[11px] sm:text-caption-2'> + {currencyFormat(product.lowestPrice.price)} + </div> + <div className='badge-solid-red'>{product?.lowestPrice.discountPercentage}%</div> + </div> + )} + + <div className='text-danger-500 font-semibold mb-2'> + {product?.lowestPrice.priceDiscount > 0 ? ( + currencyFormat(product?.lowestPrice.priceDiscount) + ) : ( + <a href={callForPriceWhatsapp}>Call for price</a> + )} </div> - <div className='badge-solid-red'>{product?.lowestPrice.discountPercentage}%</div> + </> + ) : ( + <div className='text-danger-500 font-semibold mb-2 min-h-[40px]'> + {product?.lowestPrice.price > 0 ? ( + <> + {currencyFormat(product?.lowestPrice.price)} + <div className='text-gray_r-9 text-[10px] font-normal mt-2'> + Inc. PPN: {currencyFormat(product.lowestPrice.price * process.env.NEXT_PUBLIC_PPN )} + </div> + </> + ) : ( + <a href={callForPriceWhatsapp}>Call for price</a> + )} </div> )} - <div className='text-danger-500 font-semibold mb-2'> - {product?.lowestPrice.priceDiscount > 0 ? ( - currencyFormat(product?.lowestPrice.priceDiscount) - ) : ( - <a href={callForPriceWhatsapp}>Call for price</a> - )} - </div> - {product?.stockTotal > 0 && ( <div className='flex gap-x-1'> <div className='badge-solid-red'>Ready Stock</div> @@ -169,30 +186,46 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { )} <Link href={createSlug('/shop/product/', product?.name, product?.id)} - className={`mb-2 !text-gray_r-12 leading-6 ${ + className={`mb-3 !text-gray_r-12 leading-6 ${ simpleTitle ? 'line-clamp-2' : 'line-clamp-3' }`} > {product?.name} </Link> + {product?.flashSale?.id > 0 ? ( + <> + {product?.lowestPrice.discountPercentage > 0 && ( + <div className='flex gap-x-1 mb-1 items-center'> + <div className='badge-solid-red'>{product?.lowestPrice?.discountPercentage}%</div> + <div className='text-gray_r-11 line-through text-caption-2'> + {currencyFormat(product?.lowestPrice?.price)} + </div> + </div> + )} - {product?.lowestPrice?.discountPercentage > 0 && ( - <div className='flex gap-x-1 mb-1 items-center'> - <div className='badge-solid-red'>{product?.lowestPrice?.discountPercentage}%</div> - <div className='text-gray_r-11 line-through text-caption-2'> - {currencyFormat(product?.lowestPrice?.price)} + <div className='text-danger-500 font-semibold mb-2'> + {product?.lowestPrice?.priceDiscount > 0 ? ( + currencyFormat(product?.lowestPrice?.priceDiscount) + ) : ( + <a href={callForPriceWhatsapp}>Call for price</a> + )} </div> + </> + ) : ( + <div className='text-danger-500 font-semibold mb-2 min-h-[40px]'> + {product?.lowestPrice.price > 0 ? ( + <> + {currencyFormat(product?.lowestPrice.price)} + <div className='text-gray_r-9 text-[11px] sm:text-caption-2 font-normal mt-2'> + Inc. PPN: {currencyFormat(product.lowestPrice.price * process.env.NEXT_PUBLIC_PPN)} + </div> + </> + ) : ( + <a href={callForPriceWhatsapp}>Call for price</a> + )} </div> )} - <div className='text-danger-500 font-semibold mb-2'> - {product?.lowestPrice?.priceDiscount > 0 ? ( - currencyFormat(product?.lowestPrice?.priceDiscount) - ) : ( - <a href={callForPriceWhatsapp}>Call for price</a> - )} - </div> - {product?.stockTotal > 0 && ( <div className='flex gap-x-1'> <div className='badge-solid-red'>Ready Stock</div> diff --git a/src/lib/quotation/components/Quotation.jsx b/src/lib/quotation/components/Quotation.jsx index cee35457..8c379ead 100644 --- a/src/lib/quotation/components/Quotation.jsx +++ b/src/lib/quotation/components/Quotation.jsx @@ -16,6 +16,7 @@ import MobileView from '@/core/components/views/MobileView' import DesktopView from '@/core/components/views/DesktopView' import Image from '@/core/components/elements/Image/Image' import { useQuery } from 'react-query' +import CardProdcuctsList from '@/core/components/elements/Product/cartProductsList' const { checkoutApi } = require('@/lib/checkout/api/checkoutApi') const { getProductsCheckout } = require('@/lib/checkout/api/checkoutApi') @@ -174,70 +175,7 @@ const Quotation = () => { <div className='container mx-auto py-10 flex'> <div className='w-3/4 border border-gray_r-6 rounded bg-white p-4'> <div className='font-medium'>Detail Barang</div> - <table className='table-checkout'> - <thead> - <tr> - <th>Nama Produk</th> - <th>Jumlah</th> - <th>Harga</th> - <th>Subtotal</th> - </tr> - </thead> - <tbody> - {products?.map((product) => ( - <tr key={product.id}> - <td className='flex'> - <div className='w-[30%] flex-shrink-0'> - <Image - src={product?.parent?.image} - alt={product?.name} - className='object-contain object-center border border-gray_r-6 h-40 w-full rounded-md' - /> - </div> - <div className='px-2 text-left'> - <div className='line-clamp-2 leading-6 !text-gray_r-12 font-normal'> - {product?.parent?.name} - </div> - <div className='text-gray_r-11 mt-2'> - {product?.code}{' '} - {product?.attributes.length > 0 - ? `| ${product?.attributes.join(', ')}` - : ''} - </div> - </div> - </td> - <td> - <input - className='form-input w-16 py-2 text-center bg-gray_r-1' - type='number' - value={product?.quantity} - disabled - /> - </td> - <td> - {product?.price?.discountPercentage > 0 && ( - <div className='flex gap-x-1 items-center justify-center mt-3'> - <div className='text-gray_r-11 line-through text-caption-1'> - {currencyFormat(product?.price?.price)} - </div> - <div className='badge-solid-red'> - {product?.price?.discountPercentage}% - </div> - </div> - )} - <div className='font-normal mt-1'> - {currencyFormat(product?.price?.priceDiscount)} - </div> - </td> - <td> - <div className='text-danger-500 font-medium'> - {currencyFormat(product?.price?.priceDiscount * product?.quantity)} - </div> - </td> - </tr> - ))} - </tbody> - </table> + <CardProdcuctsList isLoading={isLoading} products={products} source='checkout' /> </div> <div className='w-1/4 pl-4'> diff --git a/src/lib/variant/components/VariantCard.jsx b/src/lib/variant/components/VariantCard.jsx index 0f9f02f6..64b6d146 100644 --- a/src/lib/variant/components/VariantCard.jsx +++ b/src/lib/variant/components/VariantCard.jsx @@ -43,7 +43,7 @@ const VariantCard = ({ product, openOnClick = true, buyMore = false }) => { Berat Item : {product?.weight} Kg </p> <div className='flex flex-wrap gap-x-1 items-center mt-auto'> - {product.price.discountPercentage > 0 && ( + {product.hasFlashsale && ( <> <p className='text-caption-2 text-gray_r-11 line-through'> {currencyFormat(product.price.price)} diff --git a/src/lib/variant/components/VariantGroupCard.jsx b/src/lib/variant/components/VariantGroupCard.jsx index dd5983a9..1e921546 100644 --- a/src/lib/variant/components/VariantGroupCard.jsx +++ b/src/lib/variant/components/VariantGroupCard.jsx @@ -4,7 +4,6 @@ import Image from '@/core/components/elements/Image/Image' import currencyFormat from '@/core/utils/currencyFormat' const VariantGroupCard = ({ variants, ...props }) => { - console.log('variant', variants) const [showAll, setShowAll] = useState(false) const variantsToShow = showAll ? variants : variants.slice(0, 2) diff --git a/src/pages/api/shop/product-detail.js b/src/pages/api/shop/product-detail.js index 5c3a8231..22a53df2 100644 --- a/src/pages/api/shop/product-detail.js +++ b/src/pages/api/shop/product-detail.js @@ -1,3 +1,4 @@ +import { productMappingSolr, variantsMappingSolr } from '@/utils/solrMapping' import axios from 'axios' export default async function handler(req, res) { @@ -9,13 +10,12 @@ export default async function handler(req, res) { process.env.SOLR_HOST + `/solr/variants/select?q=template_id_i:${req.query.id}&q.op=OR&indent=true&rows=100` ) - let { auth } = req.cookies - if (auth) auth = JSON.parse(auth) - let result = productResponseMap(productTemplate.data.response.docs, auth?.pricelist || false) - result[0].variants = productVariantsResponseMap( + let auth = req.query.auth === 'false' ? JSON.parse(req.query.auth) : req.query.auth + let result = productMappingSolr(productTemplate.data.response.docs, auth || false) + result[0].variants = variantsMappingSolr( productTemplate.data.response.docs[0], productVariants.data.response.docs, - auth?.pricelist || false + auth || false ) res.status(200).json(result) } catch (error) { @@ -24,19 +24,14 @@ export default async function handler(req, res) { } } -const productResponseMap = (products, pricelist) => { +/*const productResponseMap = (products, pricelist) => { return products.map((product) => { - let price = product.price_f || 0 + let price = product.price_tier1_v2_f || 0 let priceDiscount = product.price_discount_f || 0 let discountPercentage = product.discount_f || 0 if (pricelist) { - const pricelistDiscount = product?.[`price_${pricelist}_f`] || false - const pricelistDiscountPerc = product?.[`discount_${pricelist}_f`] || false - - if (pricelistDiscount && pricelistDiscount > 0) priceDiscount = pricelistDiscount - if (pricelistDiscountPerc && pricelistDiscountPerc > 0) - discountPercentage = pricelistDiscountPerc + price = product?.[`price_${pricelist}_f`] || 0 } if (product?.flashsale_id_i > 0) { @@ -86,17 +81,12 @@ const productResponseMap = (products, pricelist) => { } const productVariantsResponseMap = (parent, products, pricelist) => { return products.map((product) => { - let price = product.price_f || 0 + let price = product.price_tier1_v2_f || 0 let priceDiscount = product.price_discount_f || 0 let discountPercentage = product.discount_f || 0 if (pricelist) { - const pricelistDiscount = product?.[`price_${pricelist}_f`] || false - const pricelistDiscountPerc = product?.[`discount_${pricelist}_f`] || false - - if (pricelistDiscount && pricelistDiscount > 0) priceDiscount = pricelistDiscount - if (pricelistDiscountPerc && pricelistDiscountPerc > 0) - discountPercentage = pricelistDiscountPerc + price = product?.[`price_${pricelist}_f`] || 0 } if (product?.flashsale_id_i > 0) { @@ -144,4 +134,4 @@ const flashsaleTime = (endDate) => { const timeDifferenceInSeconds = timeDifferenceInMillis / 1000 return { remainingTime: timeDifferenceInSeconds, isFlashSale: flashsaleEndDate > currentTime } -} +}*/ diff --git a/src/pages/api/shop/search.js b/src/pages/api/shop/search.js index 57b16db8..2120a442 100644 --- a/src/pages/api/shop/search.js +++ b/src/pages/api/shop/search.js @@ -1,3 +1,4 @@ +import { productMappingSolr } from '@/utils/solrMapping' import axios from 'axios' import camelcaseObjectDeep from 'camelcase-object-deep' @@ -73,7 +74,7 @@ export default async function handler(req, res) { try { let { auth } = req.cookies if (auth) auth = JSON.parse(auth) - result.data.response.products = productResponseMap( + result.data.response.products = productMappingSolr( result.data.response.docs, auth?.pricelist || false ) @@ -102,19 +103,21 @@ const escapeSolrQuery = (query) => { return escapedWords.join(' ') } -const productResponseMap = (products, pricelist) => { +/*const productResponseMap = (products, pricelist) => { return products.map((product) => { - let price = product.price_f || 0 + let price = product.price_tier1_v2_f || 0 let priceDiscount = product.price_discount_f || 0 let discountPercentage = product.discount_f || 0 if (pricelist) { - const pricelistDiscount = product?.[`price_${pricelist}_f`] || false - const pricelistDiscountPerc = product?.[`discount_${pricelist}_f`] || false + // const pricelistDiscount = product?.[`price_${pricelist}_f`] || false + // const pricelistDiscountPerc = product?.[`discount_${pricelist}_f`] || false - if (pricelistDiscount && pricelistDiscount > 0) priceDiscount = pricelistDiscount - if (pricelistDiscountPerc && pricelistDiscountPerc > 0) - discountPercentage = pricelistDiscountPerc + // if (pricelistDiscount && pricelistDiscount > 0) priceDiscount = pricelistDiscount + // if (pricelistDiscountPerc && pricelistDiscountPerc > 0) + // discountPercentage = pricelistDiscountPerc + + price = product?.[`price_${pricelist}_f`] || 0 } if (product?.flashsale_id_i > 0) { @@ -156,4 +159,4 @@ const productResponseMap = (products, pricelist) => { ] return productMapped }) -} +}*/ diff --git a/src/pages/shop/product/[slug].jsx b/src/pages/shop/product/[slug].jsx index 534aa8da..63fb2e7e 100644 --- a/src/pages/shop/product/[slug].jsx +++ b/src/pages/shop/product/[slug].jsx @@ -18,10 +18,11 @@ export async function getServerSideProps(context) { const cookies = context.req.headers.cookie const cookieObj = cookies ? cookie.parse(cookies) : {} const auth = cookieObj.auth ? JSON.parse(cookieObj.auth) : {} + const tier = auth.pricelist ? auth.pricelist : false const authToken = auth?.token || '' let response = await axios( - `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/product-detail?id=` + getIdFromSlug(slug) + `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/product-detail?id=` + getIdFromSlug(slug) +'&auth=' + tier ) let product = response.data // let productSolr = await productApi({ id: getIdFromSlug(slug), headers: { Token: authToken } }) diff --git a/src/utils/solrMapping.js b/src/utils/solrMapping.js new file mode 100644 index 00000000..c8bd54ea --- /dev/null +++ b/src/utils/solrMapping.js @@ -0,0 +1,113 @@ +export const productMappingSolr = (products, pricelist) => { + return products.map((product) => { + let price = product.price_tier1_v2_f || 0 + let priceDiscount = product.price_discount_f || 0 + let discountPercentage = product.discount_f || 0 + + if (pricelist) { + price = product?.[`price_${pricelist}_f`] || 0 + } + + if (product?.flashsale_id_i > 0) { + price = product?.flashsale_base_price_f || 0 + priceDiscount = product?.flashsale_price_f || 0 + discountPercentage = product?.flashsale_discount_f || 0 + } + + let productMapped = { + id: product.product_id_i || '', + image: product.image_s || '', + code: product.default_code_s || '', + description: product.description_t || '', + displayName: product.display_name_s || '', + name: product.name_s || '', + lowestPrice: { price, priceDiscount, discountPercentage }, + variantTotal: product.variant_total_i || 0, + stockTotal: product.stock_total_f || 0, + weight: product.weight_f || 0, + manufacture: {}, + categories: [], + flashSale: { + id: product?.flashsale_id_i, + remainingTime: flashsaleTime(product?.flashsale_end_date_s)?.remainingTime, + name: product?.product?.flashsale_name_s, + tag: product?.flashsale_tag_s || 'FLASH SALE' + } + } + + if (product.manufacture_id_i && product.manufacture_name_s) { + productMapped.manufacture = { + id: product.manufacture_id_i || '', + name: product.manufacture_name_s || '', + imagePromotion1: product.image_promotion_1_s || '', + imagePromotion2: product.image_promotion_2_s || '' + } + } + + productMapped.categories = [ + { + id: product.category_id_i || '', + name: product.category_name_s || '' + } + ] + return productMapped + }) +} + +export const variantsMappingSolr = (parent, products, pricelist) => { + return products.map((product) => { + let price = product.price_tier1_v2_f || 0 + let priceDiscount = product.price_discount_f || 0 + let discountPercentage = product.discount_f || 0 + + if (pricelist) { + price = product?.[`price_${pricelist}_f`] || 0 + } + + if (product?.flashsale_id_i > 0) { + price = product?.flashsale_base_price_f || 0 + priceDiscount = product?.flashsale_price_f || 0 + discountPercentage = product?.flashsale_discount_f || 0 + } + + let productMapped = { + attributes: product.attributes || [], + id: product.product_id_i || '', + image: product.image_s || '', + code: product.default_code_s || '', + isFlashsale: flashsaleTime(product?.flashsale_end_date_s)?.isFlashSale, + isFlashsale: flashsaleTime(product?.flashsale_end_date_s)?.isFlashSale, + name: product.display_name_s || '', + price: { price, priceDiscount, discountPercentage }, + variantTotal: product.variant_total_i || 0, + stockTotal: product.stock_total_f || 0, + weight: product.weight_f || 0, + manufacture: {}, + parent: {} + } + + if (product.manufacture_id_i && product.manufacture_name_s) { + productMapped.manufacture = { + id: product.manufacture_id_i || '', + name: product.manufacture_name_s || '' + } + } + productMapped.parent = { + id: parent.product_id_i || '', + image: parent.image_s || '', + name: parent.name_s || '' + } + return productMapped + }) + } + +const flashsaleTime = (endDate) => { + const flashsaleEndDate = new Date(endDate) + const currentTime = new Date() + + const timeDifferenceInMillis = flashsaleEndDate - currentTime + const timeDifferenceInSeconds = timeDifferenceInMillis / 1000 + + return { remainingTime: timeDifferenceInSeconds, isFlashSale: flashsaleEndDate > currentTime } + } + |
