diff options
| author | it-fixcomart <it@fixcomart.co.id> | 2024-08-20 16:12:25 +0700 |
|---|---|---|
| committer | it-fixcomart <it@fixcomart.co.id> | 2024-08-20 16:12:25 +0700 |
| commit | 5c5eef9d62efd83f52f7c37dacb94d50ff7cb915 (patch) | |
| tree | 7fdef4f99f0f42e2d99a40bfd5b81f1ca5f4ef30 /src-migrate/modules/promo/components/Voucher.tsx | |
| parent | 004a9a644aed65d5c02263f19cce8b7c3000f354 (diff) | |
| parent | 6d302bb338e26810a7f90326b84086217f1f4ae0 (diff) | |
Merge branch 'release' into Feature/category-management
Diffstat (limited to 'src-migrate/modules/promo/components/Voucher.tsx')
| -rw-r--r-- | src-migrate/modules/promo/components/Voucher.tsx | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/src-migrate/modules/promo/components/Voucher.tsx b/src-migrate/modules/promo/components/Voucher.tsx new file mode 100644 index 00000000..e5877e51 --- /dev/null +++ b/src-migrate/modules/promo/components/Voucher.tsx @@ -0,0 +1,160 @@ +import { useMemo, useState, useEffect } from 'react'; +import { useQuery } from 'react-query'; +import { Swiper, SwiperProps, SwiperSlide } from 'swiper/react'; +import { getVoucherAll } from '~/services/voucher'; +import style from '../styles/voucher.module.css'; +import Image from 'next/image'; +import { useToast } from '@chakra-ui/react'; +import useDevice from '@/core/hooks/useDevice'; +import useAuth from '@/core/hooks/useAuth'; +import { getVoucher } from '../../../../src/lib/checkout/api/getVoucher'; + +interface Auth { + id: string; +} +interface Voucher { + id: string; + image: string; + name: string; + description: string; + code: string; +} + +const VoucherComponent = () => { + const [listVouchers, setListVouchers] = useState<Voucher[] | null>(null); + const [loadingVoucher, setLoadingVoucher] = useState(true); + const { isMobile } = useDevice(); + const auth = useAuth() as unknown as Auth; + const toast = useToast(); + + useEffect(() => { + if (!listVouchers && auth?.id) { + (async () => { + try { + const dataVoucher = await getVoucher(auth.id); + setListVouchers(dataVoucher); + } finally { + setLoadingVoucher(false); + } + })(); + } + }, [auth?.id, listVouchers]); + + const voucherQuery = useQuery({ + queryKey: ['voucher.all-voucher'], + queryFn: getVoucherAll, + }); + + const swiperVoucher: SwiperProps = { + autoplay: { + delay: 6000, + disableOnInteraction: false, + }, + loop: false, + className: 'h-[160px] w-full', + slidesPerView: isMobile ? 1.2 : 3.2, + spaceBetween: 2, + }; + + const dataVouchers = useMemo(() => voucherQuery.data || [], [voucherQuery.data]); + + const vouchers = auth?.id? listVouchers : dataVouchers; + + + const copyText = (text: string) => { + if (navigator.clipboard && navigator.clipboard.writeText) { + navigator.clipboard.writeText(text) + .then(() => { + toast({ + title: 'Salin ke papan klip', + description: 'Kode voucher berhasil disalin', + status: 'success', + duration: 3000, + isClosable: true, + position: 'top', + }) + }) + .catch(() => { + fallbackCopyTextToClipboard(text); + }); + } else { + fallbackCopyTextToClipboard(text); + } + } + + const fallbackCopyTextToClipboard = (text: string) => { + const textArea = document.createElement("textarea"); + textArea.value = text; + // Tambahkan style untuk menyembunyikan textArea secara visual + textArea.style.position = 'fixed'; + textArea.style.top = '0'; + textArea.style.left = '0'; + textArea.style.width = '2em'; + textArea.style.height = '2em'; + textArea.style.padding = '0'; + textArea.style.border = 'none'; + textArea.style.outline = 'none'; + textArea.style.boxShadow = 'none'; + textArea.style.background = 'transparent'; + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + try { + document.execCommand('copy'); + toast({ + title: 'Salin ke papan klip', + description: 'Kode voucher berhasil disalin', + status: 'success', + duration: 3000, + isClosable: true, + position: 'top', + }) + } catch (err) { + console.error('Fallback: Oops, unable to copy', err); + } + document.body.removeChild(textArea); + } + + return ( + <> + <div className={style['title']}>Pakai Voucher Belanja</div> + + <div className='h-6' /> + + {voucherQuery.isLoading && ( + <div className='grid grid-cols-3 gap-x-4 animate-pulse'> + {Array.from({ length: 3 }).map((_, index) => ( + <div key={index} className='w-full h-[160px] bg-gray-200 rounded-xl' /> + ))} + </div> + )} + {!voucherQuery.isLoading && ( + <div className={style['voucher-section']}> + <Swiper {...swiperVoucher}> + {vouchers?.map((voucher) => ( + <SwiperSlide key={voucher.id} className='pb-2'> + <div className={style['voucher-card']}> + <Image src={voucher.image} alt={voucher.name} width={128} height={128} className={style['voucher-image']} /> + + <div className={style['voucher-content']}> + <div className={style['voucher-title']}>{voucher.name}</div> + <div className={style['voucher-desc']}>{voucher.description}</div> + <div className={style['voucher-bottom']}> + <div> + <div className={style['voucher-code-desc']}>Kode Promo</div> + <div className={style['voucher-code']}>{voucher.code}</div> + </div> + <button className={style['voucher-copy']} onClick={() => copyText(voucher.code)}>Salin</button> + </div> + </div> + </div> + </SwiperSlide> + ))} + </Swiper> + </div> + )} + </> + ) +} + +export default VoucherComponent |
