diff options
Diffstat (limited to 'src-migrate')
8 files changed, 140 insertions, 14 deletions
diff --git a/src-migrate/modules/product-detail/components/Image.tsx b/src-migrate/modules/product-detail/components/Image.tsx index 6ec715d8..2ab3ff59 100644 --- a/src-migrate/modules/product-detail/components/Image.tsx +++ b/src-migrate/modules/product-detail/components/Image.tsx @@ -1,27 +1,53 @@ -import React from 'react' +import style from '../styles/image.module.css'; + +import React, { useEffect, useState } from 'react' import { InfoIcon } from 'lucide-react' import { Tooltip } from '@chakra-ui/react' import { IProductDetail } from '~/types/product' import ImageUI from '~/components/ui/image' +import moment from 'moment'; type Props = { product: IProductDetail } const Image = ({ product }: Props) => { + const flashSale = product.flash_sale + + const [count, setCount] = useState(flashSale?.remaining_time || 0); + + useEffect(() => { + let interval: NodeJS.Timeout; + + if (flashSale?.remaining_time && flashSale.remaining_time > 0) { + setCount(flashSale.remaining_time); + + interval = setInterval(() => { + setCount((prevCount) => prevCount - 1); + }, 1000); + } + + return () => { + clearInterval(interval); + }; + }, [flashSale?.remaining_time]); + + const duration = moment.duration(count, 'seconds') + return ( - <div className='h-[250px] md:h-[340px] flex items-center justify-center border border-gray-200 rounded-lg p-4 relative'> + <div className={style['wrapper']}> <ImageUI src={product.image || '/images/noimage.jpeg'} alt={product.name} width={256} height={256} - className='object-contain object-center h-full w-full' + className={style['image']} loading='eager' priority /> - <div className='absolute hidden md:block top-4 right-4'> + + <div className={style['absolute-info']}> <Tooltip placement='bottom-end' label='Gambar atau foto berperan sebagai ilustrasi produk. Kadang tidak sesuai dengan kondisi terbaru dengan berbagai perubahan dan perbaikan. Hubungi admin kami untuk informasi yang lebih baik perihal gambar.' @@ -31,6 +57,41 @@ const Image = ({ product }: Props) => { </div> </Tooltip> </div> + + {flashSale.remaining_time > 0 && ( + <div className='absolute bottom-0 w-full h-14'> + <div className="relative w-full h-full"> + <ImageUI + src='/images/GAMBAR-BG-FLASH-SALE.jpg' + alt='Flash Sale Indoteknik' + width={200} + height={100} + className={style['flashsale-bg']} + /> + + <div className={style['flashsale']}> + <div className='flex items-center gap-x-3'> + <div className={style['disc-badge']}>{Math.floor(product.lowest_price.discount_percentage)}%</div> + <div className={style['flashsale-text']}> + <ImageUI + src='/images/ICON_FLASH_SALE_WEBSITE_INDOTEKNIK.svg' + alt='Icon Flash Sale' + width={20} + height={20} + /> + {product.flash_sale.tag} + </div> + </div> + <div className={style['countdown']}> + <span>{duration.hours().toString().padStart(2, '0')}</span> + <span>{duration.minutes().toString().padStart(2, '0')}</span> + <span>{duration.seconds().toString().padStart(2, '0')}</span> + </div> + </div> + + </div> + </div> + )} </div> ) } diff --git a/src-migrate/modules/product-detail/components/PriceAction.tsx b/src-migrate/modules/product-detail/components/PriceAction.tsx index cade21b8..f25847a5 100644 --- a/src-migrate/modules/product-detail/components/PriceAction.tsx +++ b/src-migrate/modules/product-detail/components/PriceAction.tsx @@ -29,13 +29,25 @@ const PriceAction = ({ product }: Props) => { <div className='block md:sticky top-[150px] bg-white py-0 md:py-6 z-10' id='price-section'> {!!activePrice && activePrice.price > 0 && ( <> - <div className={style['main-price']}> - Rp {formatCurrency(activePrice.price || 0)} + <div className='flex items-end gap-x-2'> + {activePrice.discount_percentage > 0 && ( + <> + <div className={style['disc-badge']}> + {Math.floor(activePrice.discount_percentage)}% + </div> + <div className={style['disc-price']}> + Rp {formatCurrency(activePrice.price || 0)} + </div> + </> + )} + <div className={style['main-price']}> + Rp {formatCurrency(activePrice.price_discount || 0)} + </div> </div> <div className='h-1' /> <div className={style['secondary-text']}> Termasuk PPN: {' '} - Rp {formatCurrency(Math.round(activePrice.price * 1.11))} + Rp {formatCurrency(Math.round(activePrice.price_discount * 1.11))} </div> </> )} diff --git a/src-migrate/modules/product-detail/components/VariantList.tsx b/src-migrate/modules/product-detail/components/VariantList.tsx index 1da478e7..3d5b9b74 100644 --- a/src-migrate/modules/product-detail/components/VariantList.tsx +++ b/src-migrate/modules/product-detail/components/VariantList.tsx @@ -89,8 +89,14 @@ const Row = ({ variant }: { variant: IProductVariantDetail }) => { {variant.weight > 0 ? `${variant.weight} Kg` : '-'} </div> <div className='w-3/12'> - {variant.price.price > 0 && `Rp ${formatCurrency(variant.price.price)}`} - {variant.price.price === 0 && '-'} + {variant.price.discount_percentage > 0 && ( + <div className='flex items-center gap-x-1'> + <div className={style['disc-badge']}>{Math.floor(variant.price.discount_percentage)}%</div> + <div className={style['disc-price']}>Rp {formatCurrency(variant.price.price)}</div> + </div> + )} + {variant.price.price_discount > 0 && `Rp ${formatCurrency(variant.price.price_discount)}`} + {variant.price.price_discount === 0 && '-'} </div> <div className='w-1/12 sticky right-0 bg-white md:bg-transparent'> <Button diff --git a/src-migrate/modules/product-detail/styles/image.module.css b/src-migrate/modules/product-detail/styles/image.module.css new file mode 100644 index 00000000..e472fe8d --- /dev/null +++ b/src-migrate/modules/product-detail/styles/image.module.css @@ -0,0 +1,35 @@ +.wrapper { + @apply h-[250px] md:h-[340px] flex items-center justify-center border border-gray-200 rounded-lg p-4 relative; +} + +.image { + @apply object-contain object-center h-full w-full; +} + +.absolute-info { + @apply absolute hidden md:block top-4 right-4; +} + +.disc-badge { + @apply bg-warning-500 py-1 px-3 w-fit font-semibold rounded-full; +} + +.countdown { + @apply flex gap-x-1; +} + +.countdown span { + @apply py-0.5 w-8 bg-warning-500 rounded-md text-center; +} + +.flashsale-text { + @apply flex items-center gap-x-2 text-white font-medium text-caption-1; +} + +.flashsale-bg { + @apply absolute top-0 w-full h-full object-cover object-center z-10; +} + +.flashsale { + @apply absolute top-0 w-full h-full z-20 flex items-center justify-between px-3; +} diff --git a/src-migrate/modules/product-detail/styles/price-action.module.css b/src-migrate/modules/product-detail/styles/price-action.module.css index a8ec0ed3..651de958 100644 --- a/src-migrate/modules/product-detail/styles/price-action.module.css +++ b/src-migrate/modules/product-detail/styles/price-action.module.css @@ -14,3 +14,11 @@ .contact-us { @apply text-danger-500 font-medium underline; } + +.disc-badge { + @apply bg-danger-500 px-2 py-1.5 rounded text-white text-caption-2; +} + +.disc-price { + @apply line-through text-gray-600 text-caption-2; +} diff --git a/src-migrate/modules/product-detail/styles/variant-list.module.css b/src-migrate/modules/product-detail/styles/variant-list.module.css index a56822c1..6d46df84 100644 --- a/src-migrate/modules/product-detail/styles/variant-list.module.css +++ b/src-migrate/modules/product-detail/styles/variant-list.module.css @@ -25,3 +25,11 @@ .stock-ready { @apply bg-green-50 border border-green-500 text-green-800; } + +.disc-badge { + @apply bg-danger-500 p-1 rounded text-white text-caption-2; +} + +.disc-price { + @apply text-caption-2 line-through text-gray-600; +} diff --git a/src-migrate/services/product.ts b/src-migrate/services/product.ts index 4ef027e1..fe415d11 100644 --- a/src-migrate/services/product.ts +++ b/src-migrate/services/product.ts @@ -15,7 +15,6 @@ export const getProductById = async ( .then((res) => res.json()) .then((res) => { if (res.length > 0) return snakeCase(res[0]) as IProductDetail; - return null; }); }; diff --git a/src-migrate/types/product.ts b/src-migrate/types/product.ts index b411224b..08de98e0 100644 --- a/src-migrate/types/product.ts +++ b/src-migrate/types/product.ts @@ -17,10 +17,7 @@ export interface IProduct { }[]; flash_sale: { id: string; - remaining_time: { - remaining_time: number; - is_flashsale: boolean; - }; + remaining_time: number; tag: string; }; lowest_price: { |
