summaryrefslogtreecommitdiff
path: root/src-migrate/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src-migrate/modules')
-rw-r--r--src-migrate/modules/cart/components/ItemAction.tsx4
-rw-r--r--src-migrate/modules/cart/components/ItemSelect.tsx2
-rw-r--r--src-migrate/modules/cart/stores/useCartStore.ts1
-rw-r--r--src-migrate/modules/product-card/components/ProductCard.tsx159
-rw-r--r--src-migrate/modules/product-detail/components/AddToCart.tsx171
-rw-r--r--src-migrate/modules/product-detail/components/PriceAction.tsx2
-rw-r--r--src-migrate/modules/product-detail/components/ProductDetail.tsx6
-rw-r--r--src-migrate/modules/product-detail/components/SimilarBottom.tsx7
-rw-r--r--src-migrate/modules/product-promo/components/AddToCart.tsx113
-rw-r--r--src-migrate/modules/product-promo/components/Card.tsx10
-rw-r--r--src-migrate/modules/product-promo/components/Modal.tsx8
-rw-r--r--src-migrate/modules/product-promo/components/ModalContent.tsx8
-rw-r--r--src-migrate/modules/product-promo/components/Section.tsx9
-rw-r--r--src-migrate/modules/promo/components/FlashSaleNonDisplay.tsx20
-rw-r--r--src-migrate/modules/promo/components/PromoList.tsx4
15 files changed, 450 insertions, 74 deletions
diff --git a/src-migrate/modules/cart/components/ItemAction.tsx b/src-migrate/modules/cart/components/ItemAction.tsx
index e5e7f314..e73d507b 100644
--- a/src-migrate/modules/cart/components/ItemAction.tsx
+++ b/src-migrate/modules/cart/components/ItemAction.tsx
@@ -11,7 +11,6 @@ import { deleteUserCart, upsertUserCart } from '~/services/cart'
import { useDebounce } from 'usehooks-ts'
import { useCartStore } from '../stores/useCartStore'
-import { useProductCartContext } from '@/contexts/ProductCartContext'
type Props = {
@@ -20,7 +19,7 @@ type Props = {
const CartItemAction = ({ item }: Props) => {
const auth = getAuth()
- const { setRefreshCart } = useProductCartContext()
+
const [isLoadDelete, setIsLoadDelete] = useState<boolean>(false)
const [isLoadQuantity, setIsLoadQuantity] = useState<boolean>(false)
@@ -37,7 +36,6 @@ const CartItemAction = ({ item }: Props) => {
await deleteUserCart(auth.id, [item.cart_id])
await loadCart(auth.id)
setIsLoadDelete(false)
- setRefreshCart(true)
}
const decreaseQty = () => { setQuantity((quantity) => quantity -= 1) }
diff --git a/src-migrate/modules/cart/components/ItemSelect.tsx b/src-migrate/modules/cart/components/ItemSelect.tsx
index d4a1b537..2faf5172 100644
--- a/src-migrate/modules/cart/components/ItemSelect.tsx
+++ b/src-migrate/modules/cart/components/ItemSelect.tsx
@@ -26,11 +26,9 @@ const CartItemSelect = ({ item }: Props) => {
? { ...cartItem, selected: e.target.checked }
: cartItem
);
-
// Update the entire cart
const updatedCart = { ...cart, products: updatedCartItems };
updateCartItem(updatedCart);
-
setIsLoad(false);
}
diff --git a/src-migrate/modules/cart/stores/useCartStore.ts b/src-migrate/modules/cart/stores/useCartStore.ts
index 3b50ec32..ae551846 100644
--- a/src-migrate/modules/cart/stores/useCartStore.ts
+++ b/src-migrate/modules/cart/stores/useCartStore.ts
@@ -48,7 +48,6 @@ export const useCartStore = create<State & Action>((set, get) => ({
const summary = computeSummary(updatedCart);
set({ summary });
},
-
}));
const computeSummary = (cart: CartProps) => {
diff --git a/src-migrate/modules/product-card/components/ProductCard.tsx b/src-migrate/modules/product-card/components/ProductCard.tsx
index 0febfadb..931f8f2f 100644
--- a/src-migrate/modules/product-card/components/ProductCard.tsx
+++ b/src-migrate/modules/product-card/components/ProductCard.tsx
@@ -10,6 +10,10 @@ import formatCurrency from '~/libs/formatCurrency'
import { formatToShortText } from '~/libs/formatNumber'
import { createSlug } from '~/libs/slug'
import { IProduct } from '~/types/product'
+import { useRouter } from 'next/router';
+import currencyFormat from '@/core/utils/currencyFormat';
+import whatsappUrl from '@/core/utils/whatsappUrl';
+import { sellingProductFormat } from '@/core/utils/formatValue';
type Props = {
product: IProduct
@@ -18,7 +22,17 @@ type Props = {
const ProductCard = ({ product, layout = 'vertical' }: Props) => {
const utmSource = useUtmSource()
-
+ const router = useRouter();
+
+ const ppnString = process.env.NEXT_PUBLIC_PPN;
+ const ppnNumber = ppnString !== undefined ? Number(ppnString) : 0;
+
+ const id = product.id.toString ()
+ const callForPriceWhatsapp = whatsappUrl('product', {
+ name: product.name,
+ manufacture: product.manufacture?.name,
+ url: createSlug('/shop/product/', product.name, id, true),
+ });
const URL = {
product: createSlug('/shop/product/', product.name, product.id.toString()) + `?utm_source=${utmSource}`,
@@ -75,6 +89,42 @@ const ProductCard = ({ product, layout = 'vertical' }: Props) => {
</div>
</div>
</div>
+ {layout === 'vertical' && (
+ <div>
+ {router.pathname != '/' && product?.flash_sale.id > 0 && (
+ <div className='absolute left-0 bottom-0 w-full grid'>
+ <div className='absolute bottom-0 w-full h-full'>
+ <ImageNext
+ src='/images/BG-FLASH-SALE.jpg'
+ className='h-full'
+ width={1000}
+ height={100} alt={''} />
+ </div>
+ <div className='relative'>
+ <div className='flex gap-x-1 items-center p-2 justify-center'>
+ <div className='bg-yellow-400 rounded-lg p-1 h-6 w-19 flex items-center justify-center '>
+ <span className='text-sm font-bold text-black'>
+ {Math.floor(product?.lowest_price.discount_percentage ? product?.lowest_price.discount_percentage : product?.lowest_price.discountPercentage)}%
+ </span>
+ </div>
+ <div className='bg-red-600 border border-solid border-yellow-400 p-2 rounded-full h-6 flex w-fit items-center justify-center gap-x-2'>
+ <ImageNext
+ src='/images/ICON_FLASH_SALE_WEBSITE_INDOTEKNIK.svg'
+ width={13}
+ height={5} alt={''} />
+ <span className='text-white text-[9px] md:text-[10px] font-semibold'>
+ {product?.flash_sale?.tag != 'false' ||
+ product?.flash_sale?.tag
+ ? product?.flash_sale?.tag
+ : 'FLASH SALE'}
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ )}
+ </div>
+ )}
{product.variant_total > 1 && (
<div className={style['variant-badge']}>{product.variant_total} Varian</div>
@@ -86,6 +136,24 @@ const ProductCard = ({ product, layout = 'vertical' }: Props) => {
[style['content-v']]: layout === 'vertical',
[style['content-h']]: layout === 'horizontal',
})}>
+ {layout === 'horizontal' && (
+ <div>
+ {product.flash_sale.id > 0 && (
+ <div className='bg-red-600 rounded-full mb-1 p-2 pl-3 pr-3 flex w-fit items-center gap-x-1'>
+ <ImageNext
+ src='/images/ICON_FLASH_SALE_WEBSITE_INDOTEKNIK.svg'
+ width={15}
+ height={10} alt={''} />
+ <span className='text-white text-xs font-semibold'>
+ {' '}
+ {product?.flash_sale?.tag != 'false' || product?.flash_sale?.tag
+ ? product?.flash_sale?.tag
+ : 'FLASH SALE'}
+ </span>
+ </div>
+ )}
+ </div>
+ )}
<Link
href={URL.manufacture}
className={style['brand']}
@@ -104,33 +172,78 @@ const ProductCard = ({ product, layout = 'vertical' }: Props) => {
>
{product.name}
</Link>
- <div className='h-1.5' />
-
- <div className={style['price']}>
- Rp {formatCurrency(product.lowest_price.price)}
- </div>
<div className='h-1.5' />
-
- <div className={style['price-inc']}>
- Inc PPN:
- Rp {formatCurrency(Math.round(product.lowest_price.price * 1.11))}
- </div>
-
- <div className='h-1' />
-
- <div className='flex items-center gap-x-2.5'>
- {product.stock_total > 0 && (
- <div className={style['ready-stock']}>
- Ready Stock
- </div>
- )}
- {product.qty_sold > 0 && (
- <div className={style['sold']}>
- {formatToShortText(product.qty_sold)} Terjual
+ {product?.lowest_price.discountPercentage === undefined ? (
+ <div>
+ {product?.flash_sale?.id > 0 &&
+ product?.lowest_price.discount_percentage > 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.lowest_price.price)}
+ </div>
+ <div className='badge-solid-red'>
+ {Math.floor(product?.lowest_price.discount_percentage)}%
+ </div>
+ </div>
+ <div className='text-danger-500 font-semibold mb-2'>
+ {product?.lowest_price.price_discount > 0 ? (
+ currencyFormat(product?.lowest_price.price_discount)
+ ) : (
+ <a
+ rel='noopener noreferrer'
+ target='_blank'
+ href={callForPriceWhatsapp}
+ >
+ Call for Inquiry
+ </a>
+ )}
+ </div>
+ </>
+ ) : (
+ <div className='text-danger-500 font-semibold mb-2 min-h-[40px]'>
+ {product?.lowest_price.price > 0 ? (
+ <>
+ {currencyFormat(product?.lowest_price.price)}
+ <div className='text-gray_r-9 text-[10px] font-normal mt-2'>
+ Inc. PPN:{' '}
+ {currencyFormat(
+ product.lowest_price.price * ppnNumber
+ )}
+ </div>
+ </>
+ ) : (
+ <a
+ rel='noopener noreferrer'
+ target='_blank'
+ href={callForPriceWhatsapp}
+ >
+ Call for Inquiry
+ </a>
+ )}
</div>
)}
+
+ <div className='flex w-full items-center gap-x-1 '>
+ {product?.stock_total > 0 && (
+ <div className='badge-solid-red'>Ready Stock</div>
+ )}
+ {/* <div className='badge-gray'>{product?.stockTotal > 5 ? '> 5' : '< 5'}</div> */}
+ {product?.qty_sold > 0 && (
+ <div className='text-gray_r-9 text-[11px]'>
+ {sellingProductFormat(product?.qty_sold) + ' Terjual'}
+ </div>
+ )}
+ </div>
</div>
+ ) : (
+ <div>
+
+ </div>
+ )}
+
+
</div>
</div>
diff --git a/src-migrate/modules/product-detail/components/AddToCart.tsx b/src-migrate/modules/product-detail/components/AddToCart.tsx
index 097db98a..a5284637 100644
--- a/src-migrate/modules/product-detail/components/AddToCart.tsx
+++ b/src-migrate/modules/product-detail/components/AddToCart.tsx
@@ -1,19 +1,35 @@
-import { Button, useToast } from '@chakra-ui/react'
+import BottomPopup from '@/core/components/elements/Popup/BottomPopup'
+import style from '../styles/price-action.module.css';
+import { Button, Link, useToast } from '@chakra-ui/react'
+import product from 'next-seo/lib/jsonld/product'
import { useRouter } from 'next/router'
-
+import { useEffect, useState } from 'react'
+import Image from '~/components/ui/image'
import { getAuth } from '~/libs/auth'
import { upsertUserCart } from '~/services/cart'
+import LazyLoad from 'react-lazy-load';
+import ProductSimilar from '../../../../src/lib/product/components/ProductSimilar';
+import { IProductDetail } from '~/types/product';
+import ImageNext from 'next/image';
+import { useProductCartContext } from '@/contexts/ProductCartContext'
+import { createSlug } from '~/libs/slug'
+import formatCurrency from '~/libs/formatCurrency'
+import { useProductDetail } from '../stores/useProductDetail';
type Props = {
variantId: number | null,
quantity?: number;
source?: 'buy' | 'add_to_cart';
+ products : IProductDetail
}
+type Status = 'idle' | 'loading' | 'success'
+
const AddToCart = ({
variantId,
quantity = 1,
- source = 'add_to_cart'
+ source = 'add_to_cart',
+ products
}: Props) => {
const auth = getAuth()
const router = useRouter()
@@ -22,40 +38,65 @@ const AddToCart = ({
isClosable: true
})
- const handleClick = async () => {
+ const {
+ askAdminUrl,
+ } = useProductDetail();
+
+ const [product, setProducts] = useState(products);
+ const [status, setStatus] = useState<Status>('idle')
+ const { productCart, setRefreshCart, setProductCart, refreshCart, isLoading, setIsloading } =
+ useProductCartContext()
+
+ const productSimilarQuery = [
+ product?.name,
+ `fq=-product_id_i:${product.id}`,
+ `fq=-manufacture_id_i:${product.manufacture?.id || 0}`,
+ ].join('&');
+ const [addCartAlert, setAddCartAlert] = useState(false);
+
+ const handleButton = async () => {
if (typeof auth !== 'object') {
const currentUrl = encodeURIComponent(router.asPath)
router.push(`/login?next=${currentUrl}`)
return;
}
-
+
if (
!variantId ||
isNaN(quantity) ||
typeof auth !== 'object'
) return;
-
- toast.promise(
- upsertUserCart({
- userId: auth.id,
+ if (status === 'success') return
+ setStatus('loading')
+ await upsertUserCart({
+ userId: auth.id,
type: 'product',
id: variantId,
qty: quantity,
selected: true,
source: source,
qtyAppend: true
- }),
- {
- loading: { title: 'Menambahkan ke keranjang', description: 'Mohon tunggu...' },
- success: { title: 'Menambahkan ke keranjang', description: 'Berhasil menambahkan ke keranjang belanja' },
- error: { title: 'Menambahkan ke keranjang', description: 'Gagal menambahkan ke keranjang belanja' },
- }
- )
-
+ })
+ setStatus('idle')
+ setRefreshCart(true);
+ setAddCartAlert(true);
+
+ toast({
+ title: 'Tambah ke keranjang',
+ description: 'Berhasil menambahkan barang ke keranjang belanja',
+ status: 'success',
+ duration: 3000,
+ isClosable: true,
+ position: 'top',
+ })
+
if (source === 'buy') {
router.push('/shop/checkout?source=buy')
}
}
+ useEffect(() => {
+ if (status === 'success') setTimeout(() => { setStatus('idle') }, 3000)
+ }, [status])
const btnConfig = {
'add_to_cart': {
@@ -69,10 +110,98 @@ const AddToCart = ({
}
return (
- <Button onClick={handleClick} colorScheme={btnConfig[source].colorScheme} className='w-full'>
- {btnConfig[source].text}
- </Button>
+ <div className='w-full'>
+ <Button onClick={handleButton} colorScheme={btnConfig[source].colorScheme} className='w-full'>
+ {btnConfig[source].text}
+ </Button>
+ <BottomPopup
+ className='!container'
+ title='Berhasil Ditambahkan'
+ active={addCartAlert}
+ close={() => {
+ setAddCartAlert(false);
+ }}
+ >
+ <div className='flex mt-4'>
+ <div className='w-[10%]'>
+ <ImageNext
+ src={product.image}
+ alt={product.name}
+ className='h-32 object-contain object-center w-full border border-gray_r-4'
+ width={80}
+ height={80}
+ />
+ </div>
+ <div className='ml-3 flex flex-1 items-start font-medium justify-center flex-col gap-y-1'>
+ {!!product.manufacture.name ? (
+ <Link
+ href={createSlug('/shop/brands/', product.manufacture.name, product.manufacture.id.toString())}
+ className=' hover:underline'
+ color={"red"}
+ >
+ {product.manufacture.name}
+ </Link>
+ ) : '-'}
+ <p className='text-ellipsis overflow-hidden'>
+ {product.name}
+ </p>
+ <p>
+ {product.code}
+ </p>
+ {!!product.lowest_price && product.lowest_price.price > 0 && (
+ <>
+ <div className='flex items-end gap-x-2'>
+ {product.lowest_price.discount_percentage > 0 && (
+ <>
+ <div className='badge-solid-red'>
+ {Math.floor(product.lowest_price.discount_percentage)}%
+ </div>
+ <div className='text-gray_r-11 line-through text-[11px] sm:text-caption-2'>
+ Rp {formatCurrency(product.lowest_price.price || 0)}
+ </div>
+ </>
+ )}
+ <div className='text-danger-500 font-semibold'>
+ Rp {formatCurrency(product.lowest_price.price_discount || 0)}
+ </div>
+ </div>
+ </>
+ )}
+
+ {!!product.lowest_price && product.lowest_price.price === 0 && (
+ <span>
+ Hubungi kami untuk dapatkan harga terbaik,{' '}
+ <Link
+ href={askAdminUrl}
+ target='_blank'
+ className='font-medium underline'
+ color={'red'}
+ >
+ klik disini
+ </Link>
+ </span>
+ )}
+ </div>
+ <div className='ml-3 flex items-center font-normal'>
+ <Link
+ href='/shop/cart'
+ className='flex-1 py-2 text-gray_r-12 btn-yellow'
+ >
+ Lihat Keranjang
+ </Link>
+ </div>
+ </div>
+ <div className='mt-8 mb-4'>
+ <div className='text-h-sm font-semibold mb-6'>
+ Kamu Mungkin Juga Suka
+ </div>
+ <LazyLoad>
+ <ProductSimilar query={productSimilarQuery} />
+ </LazyLoad>
+ </div>
+ </BottomPopup>
+ </div>
)
}
-export default AddToCart \ No newline at end of file
+export default AddToCart \ No newline at end of file
diff --git a/src-migrate/modules/product-detail/components/PriceAction.tsx b/src-migrate/modules/product-detail/components/PriceAction.tsx
index 81271f6e..9021264e 100644
--- a/src-migrate/modules/product-detail/components/PriceAction.tsx
+++ b/src-migrate/modules/product-detail/components/PriceAction.tsx
@@ -97,12 +97,14 @@ const PriceAction = ({ product }: Props) => {
className={style['quantity-input']}
/>
<AddToCart
+ products={product}
variantId={activeVariantId}
quantity={Number(quantityInput)}
/>
{!isApproval && (
<AddToCart
source='buy'
+ products={product}
variantId={activeVariantId}
quantity={Number(quantityInput)}
/>
diff --git a/src-migrate/modules/product-detail/components/ProductDetail.tsx b/src-migrate/modules/product-detail/components/ProductDetail.tsx
index fad35a7d..169e1903 100644
--- a/src-migrate/modules/product-detail/components/ProductDetail.tsx
+++ b/src-migrate/modules/product-detail/components/ProductDetail.tsx
@@ -37,7 +37,7 @@ const ProductDetail = ({ product }: Props) => {
const router = useRouter()
const auth = getAuth()
const { setAskAdminUrl, askAdminUrl, activeVariantId, setIsApproval, isApproval } = useProductDetail()
-
+
useEffect(() => {
gtagProductDetail(product);
},[product])
@@ -129,7 +129,7 @@ const ProductDetail = ({ product }: Props) => {
)}
<div className='h-4 md:h-10' />
- {!!activeVariantId && !isApproval && <ProductPromoSection productId={activeVariantId} />}
+ {!!activeVariantId && !isApproval && <ProductPromoSection product={product} productId={activeVariantId} />}
<div className={style['section-card']}>
<h2 className={style['heading']}>
@@ -178,7 +178,7 @@ const ProductDetail = ({ product }: Props) => {
<div className='h-6' />
<LazyLoadComponent>
- <SimilarBottom product={product} />
+ <SimilarBottom product={product} source={'bottom'}/>
</LazyLoadComponent>
</div>
diff --git a/src-migrate/modules/product-detail/components/SimilarBottom.tsx b/src-migrate/modules/product-detail/components/SimilarBottom.tsx
index 40d4dd82..8ff0a6bf 100644
--- a/src-migrate/modules/product-detail/components/SimilarBottom.tsx
+++ b/src-migrate/modules/product-detail/components/SimilarBottom.tsx
@@ -5,16 +5,17 @@ import { IProductDetail } from '~/types/product'
type Props = {
product: IProductDetail
+ source: string
}
-const SimilarBottom = ({ product }: Props) => {
+const SimilarBottom = ({ product, source }: Props) => {
const productSimilar = useProductSimilar({
name: product.name,
- except: { productId: product.id }
+ except: { productId: product.id },
+ source: source
})
const products = productSimilar.data?.products || []
-
return (
<Skeleton
isLoaded={!productSimilar.isLoading}
diff --git a/src-migrate/modules/product-promo/components/AddToCart.tsx b/src-migrate/modules/product-promo/components/AddToCart.tsx
index 87017c14..3d0955e3 100644
--- a/src-migrate/modules/product-promo/components/AddToCart.tsx
+++ b/src-migrate/modules/product-promo/components/AddToCart.tsx
@@ -9,19 +9,39 @@ import { IPromotion } from '~/types/promotion'
import DesktopView from '../../../../src/core/components/views/DesktopView';
import MobileView from '../../../../src/core/components/views/MobileView';
-
+import BottomPopup from '@/core/components/elements/Popup/BottomPopup'
+import ImageNext from 'next/image';
+import Link from 'next/link'
+import LazyLoad from 'react-lazy-load'
+import ProductSimilar from '../../../../src/lib/product/components/ProductSimilar';
+import { IProductDetail } from '~/types/product';
+import { useProductCartContext } from '@/contexts/ProductCartContext'
+import { createSlug } from '~/libs/slug'
+import formatCurrency from '~/libs/formatCurrency'
+import { useProductDetail } from '../../product-detail/stores/useProductDetail';
type Props = {
promotion: IPromotion
+ product: IProductDetail
}
type Status = 'idle' | 'loading' | 'success'
-const ProductPromoAddToCart = ({ promotion }: Props) => {
+const ProductPromoAddToCart = ({product, promotion }: Props) => {
+
const auth = getAuth()
const toast = useToast()
const router = useRouter()
+ const {askAdminUrl} = useProductDetail();
const [status, setStatus] = useState<Status>('idle')
+ const { productCart, setRefreshCart, setProductCart, refreshCart, isLoading, setIsloading } =
+ useProductCartContext()
+
+ const productSimilarQuery = [
+ promotion?.name,
+ `fq=-product_id_i:${promotion.products[0].product_id}`,
+ ].join('&');
+ const [addCartAlert, setAddCartAlert] = useState(false);
const handleButton = async () => {
if (typeof auth !== 'object') {
@@ -42,7 +62,8 @@ const ProductPromoAddToCart = ({ promotion }: Props) => {
qtyAppend: true
})
setStatus('idle')
-
+ setRefreshCart(true);
+ setAddCartAlert(true);
toast({
title: 'Tambah ke keranjang',
description: 'Berhasil menambahkan barang ke keranjang belanja',
@@ -92,6 +113,92 @@ const ProductPromoAddToCart = ({ promotion }: Props) => {
{status === 'success' && <span>Berhasil</span>}
{status !== 'success' && <span>Keranjang</span>}
</Button>
+ <BottomPopup
+ className='!container'
+ title='Berhasil Ditambahkan'
+ active={addCartAlert}
+ close={() => {
+ setAddCartAlert(false);
+ }}
+ >
+ <div className='flex mt-4'>
+ <div className='w-[10%]'>
+ <ImageNext
+ src={product.image}
+ alt={product.name}
+ className='h-32 object-contain object-center w-full border border-gray_r-4'
+ width={80}
+ height={80}
+ />
+ </div>
+ <div className='ml-3 flex flex-1 items-start font-medium justify-center flex-col gap-y-1'>
+ {!!product?.manufacture?.name ? (
+ <Link
+ href={createSlug('/shop/brands/', product.manufacture.name, product.manufacture.id.toString())}
+ className=' hover:underline'
+ color={"red"}
+ >
+ {product.manufacture.name}
+ </Link>
+ ) : '-'}
+ <p className='text-ellipsis overflow-hidden'>
+ {product.name}
+ </p>
+ <p>
+ {product.code}
+ </p>
+ {!!product.lowest_price && product.lowest_price.price > 0 && (
+ <>
+ <div className='flex items-end gap-x-2'>
+ {product.lowest_price.discount_percentage > 0 && (
+ <>
+ <div className='badge-solid-red'>
+ {Math.floor(product.lowest_price.discount_percentage)}%
+ </div>
+ <div className='text-gray_r-11 line-through text-[11px] sm:text-caption-2'>
+ Rp {formatCurrency(product.lowest_price.price || 0)}
+ </div>
+ </>
+ )}
+ <div className='text-danger-500 font-semibold'>
+ Rp {formatCurrency(product.lowest_price.price_discount || 0)}
+ </div>
+ </div>
+ </>
+ )}
+
+ {!!product.lowest_price && product.lowest_price.price === 0 && (
+ <span>
+ Hubungi kami untuk dapatkan harga terbaik,{' '}
+ <Link
+ href={askAdminUrl}
+ target='_blank'
+ className='font-medium underline'
+ color={'red'}
+ >
+ klik disini
+ </Link>
+ </span>
+ )}
+ </div>
+ <div className='ml-3 flex items-center font-normal'>
+ <Link
+ href='/shop/cart'
+ className='flex-1 py-2 text-gray_r-12 btn-yellow'
+ >
+ Lihat Keranjang
+ </Link>
+ </div>
+ </div>
+ <div className='mt-8 mb-4'>
+ <div className='text-h-sm font-semibold mb-6'>
+ Kamu Mungkin Juga Suka
+ </div>
+ <LazyLoad>
+ <ProductSimilar query={productSimilarQuery} />
+ </LazyLoad>
+ </div>
+ </BottomPopup>
</DesktopView>
</div>
)
diff --git a/src-migrate/modules/product-promo/components/Card.tsx b/src-migrate/modules/product-promo/components/Card.tsx
index 728d23ca..5c323276 100644
--- a/src-migrate/modules/product-promo/components/Card.tsx
+++ b/src-migrate/modules/product-promo/components/Card.tsx
@@ -15,16 +15,16 @@ import clsxm from '~/libs/clsxm'
import ProductPromoItem from './Item'
import ProductPromoAddToCart from "./AddToCart"
import ProductPromoCardCountdown from "./CardCountdown"
-
+import { IProductDetail } from '~/types/product';
import MobileView from '../../../../src/core/components/views/MobileView';
import DesktopView from '../../../../src/core/components/views/DesktopView';
type Props = {
promotion: IPromotion
-
+ product: IProductDetail
}
-const ProductPromoCard = ({ promotion}: Props) => {
+const ProductPromoCard = ({product, promotion}: Props) => {
const [products, setProducts] = useState<IProductVariantPromo[]>([])
const [freeProducts, setFreeProducts] = useState<IProductVariantPromo[]>([])
const [error, setError] = useState<string | null>(null)
@@ -132,7 +132,7 @@ const ProductPromoCard = ({ promotion}: Props) => {
</div>
<div>
- <ProductPromoAddToCart promotion={promotion} />
+ <ProductPromoAddToCart product={product} promotion={promotion} />
</div>
</div>
@@ -189,7 +189,7 @@ const ProductPromoCard = ({ promotion}: Props) => {
</div>
</div>
<div>
- <ProductPromoAddToCart promotion={promotion} />
+ <ProductPromoAddToCart product={product} promotion={promotion} />
</div>
</div>
diff --git a/src-migrate/modules/product-promo/components/Modal.tsx b/src-migrate/modules/product-promo/components/Modal.tsx
index 0de672c2..1722b9df 100644
--- a/src-migrate/modules/product-promo/components/Modal.tsx
+++ b/src-migrate/modules/product-promo/components/Modal.tsx
@@ -3,8 +3,12 @@ import { Modal } from "~/components/ui/modal"
import { useModalStore } from '../stores/useModalStore'
import ProductPromoCategoryTab from './CategoryTab'
import ProductPromoModalContent from './ModalContent'
+import { IProductDetail } from '~/types/product';
-const ProductPromoModal = () => {
+type Props = {
+ product: IProductDetail
+}
+const ProductPromoModal = ({product}:Props) => {
const { active, closeModal } = useModalStore()
return (
@@ -17,7 +21,7 @@ const ProductPromoModal = () => {
<div className='h-4' />
- <ProductPromoModalContent />
+ <ProductPromoModalContent product={product} />
</Modal>
)
}
diff --git a/src-migrate/modules/product-promo/components/ModalContent.tsx b/src-migrate/modules/product-promo/components/ModalContent.tsx
index ab5129f8..256ef61a 100644
--- a/src-migrate/modules/product-promo/components/ModalContent.tsx
+++ b/src-migrate/modules/product-promo/components/ModalContent.tsx
@@ -6,7 +6,11 @@ import { getVariantPromoByCategory } from "~/services/productVariant"
import { useModalStore } from "../stores/useModalStore"
import ProductPromoCard from "./Card"
-const ProductPromoModalContent = () => {
+import { IProductDetail } from '~/types/product';
+type Props = {
+ product: IProductDetail
+}
+const ProductPromoModalContent = ({product}:Props) => {
const { activeTab, variantId } = useModalStore()
const promotionsQuery = useQuery(
@@ -24,7 +28,7 @@ const ProductPromoModalContent = () => {
<Skeleton isLoaded={!promotionsQuery.isLoading} className='min-h-[70vh] max-h-[70vh]'>
<div className="grid grid-cols-1 gap-y-6 pb-6">
{promotions?.data.map((promo) => (
- <ProductPromoCard key={promo.id} promotion={promo} />
+ <ProductPromoCard key={promo.id} promotion={promo} product={product} />
))}
{promotions?.data.length === 0 && (
<div className="py-10 rounded-lg h-fit text-center text-body-1 font-semibold text-gray-800 bg-gray-200">Belum ada promo pada kategori ini</div>
diff --git a/src-migrate/modules/product-promo/components/Section.tsx b/src-migrate/modules/product-promo/components/Section.tsx
index 4e8a7dd5..e1719998 100644
--- a/src-migrate/modules/product-promo/components/Section.tsx
+++ b/src-migrate/modules/product-promo/components/Section.tsx
@@ -9,12 +9,14 @@ import { IPromotion } from '~/types/promotion'
import { useModalStore } from "../stores/useModalStore"
import ProductPromoCard from './Card'
import ProductPromoModal from "./Modal"
+import { IProductDetail } from '~/types/product';
type Props = {
productId: number;
+ product: IProductDetail;
}
-const ProductPromoSection = ({ productId }: Props) => {
+const ProductPromoSection = ({ product, productId }: Props) => {
const promotionsQuery = useQuery({
queryKey: [`promotions.highlight`, productId],
queryFn: async () => await fetch(`/api/product-variant/${productId}/promotion/highlight`).then((res) => res.json()) as { data: IPromotion[] }
@@ -23,14 +25,13 @@ const ProductPromoSection = ({ productId }: Props) => {
const promotions = promotionsQuery.data
const { openModal } = useModalStore()
-
return (
<SmoothRender
isLoaded={(promotions?.data && promotions?.data.length > 0) || false}
height='450px'
duration='700ms'
>
- <ProductPromoModal />
+ <ProductPromoModal product={product}/>
{promotions?.data && promotions?.data.length > 0 && (
<div className={style.titleWrapper}>
@@ -50,7 +51,7 @@ const ProductPromoSection = ({ productId }: Props) => {
>
{promotions?.data.map((promotion) => (
<div key={promotion.id} className="min-w-[400px] max-w-[400px]">
- <ProductPromoCard promotion={promotion} />
+ <ProductPromoCard product={product} promotion={promotion} />
</div>
))}
</Skeleton>
diff --git a/src-migrate/modules/promo/components/FlashSaleNonDisplay.tsx b/src-migrate/modules/promo/components/FlashSaleNonDisplay.tsx
new file mode 100644
index 00000000..1c5cc86d
--- /dev/null
+++ b/src-migrate/modules/promo/components/FlashSaleNonDisplay.tsx
@@ -0,0 +1,20 @@
+import dynamic from "next/dynamic";
+import React from "react";
+import { FlashSaleSkeleton } from "@/lib/flashSale/skeleton/FlashSaleSkeleton";
+
+const FlashSaleNonDisplay = dynamic(
+ () => import('@/lib/flashSale/components/FlashSaleNonDisplay'),
+ {
+ loading: () => <FlashSaleSkeleton />,
+ }
+ );
+
+ const FlashSalePromo = ()=> {
+ return(
+ <>
+ <FlashSaleNonDisplay/>
+ </>
+ )
+ }
+
+ export default FlashSalePromo \ No newline at end of file
diff --git a/src-migrate/modules/promo/components/PromoList.tsx b/src-migrate/modules/promo/components/PromoList.tsx
index 42725034..4d0db3c2 100644
--- a/src-migrate/modules/promo/components/PromoList.tsx
+++ b/src-migrate/modules/promo/components/PromoList.tsx
@@ -114,7 +114,7 @@ const PromoList: React.FC<PromoListProps> = ({ selectedPromo }) => {
{promoData?.map((promotion: IPromotion) => (
<SwiperSlide key={promotion.id}>
<div className="min-w-36 max-w-[400px] mb-[20px] sm:w-full md:w-full lg:w-full xl:w-full">
- <ProductPromoCard promotion={promotion} />
+ <ProductPromoCard product={promoItems} promotion={promotion} />
</div>
</SwiperSlide>
))}
@@ -122,7 +122,7 @@ const PromoList: React.FC<PromoListProps> = ({ selectedPromo }) => {
)}
{isMobile && (promoData?.map((promotion: IPromotion) => (
<div key={promotion.id} className="min-w-[400px] max-w-[400px]">
- <ProductPromoCard promotion={promotion} />
+ <ProductPromoCard product={promoItems} promotion={promotion} />
</div>
)))}