diff options
| -rw-r--r-- | src-migrate/modules/product-detail/components/AddToCart.tsx | 312 | ||||
| -rw-r--r-- | src/lib/checkout/components/Checkout.jsx | 3 | ||||
| -rw-r--r-- | src/lib/product/components/Product/ProductDesktopVariant.jsx | 34 |
3 files changed, 202 insertions, 147 deletions
diff --git a/src-migrate/modules/product-detail/components/AddToCart.tsx b/src-migrate/modules/product-detail/components/AddToCart.tsx index a5284637..280e4a7a 100644 --- a/src-migrate/modules/product-detail/components/AddToCart.tsx +++ b/src-migrate/modules/product-detail/components/AddToCart.tsx @@ -1,51 +1,55 @@ -import BottomPopup from '@/core/components/elements/Popup/BottomPopup' +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 { 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 { useProductCartContext } from '@/contexts/ProductCartContext'; +import { createSlug } from '~/libs/slug'; +import formatCurrency from '~/libs/formatCurrency'; import { useProductDetail } from '../stores/useProductDetail'; type Props = { - variantId: number | null, + variantId: number | null; quantity?: number; source?: 'buy' | 'add_to_cart'; - products : IProductDetail -} + products: IProductDetail; +}; -type Status = 'idle' | 'loading' | 'success' +type Status = 'idle' | 'loading' | 'success'; const AddToCart = ({ variantId, quantity = 1, source = 'add_to_cart', - products + products, }: Props) => { - const auth = getAuth() - const router = useRouter() + let auth = getAuth(); + const router = useRouter(); const toast = useToast({ position: 'top', - isClosable: true - }) + isClosable: true, + }); - const { - askAdminUrl, - } = useProductDetail(); + const { askAdminUrl } = useProductDetail(); const [product, setProducts] = useState(products); - const [status, setStatus] = useState<Status>('idle') - const { productCart, setRefreshCart, setProductCart, refreshCart, isLoading, setIsloading } = - useProductCartContext() + const [status, setStatus] = useState<Status>('idle'); + const { + productCart, + setRefreshCart, + setProductCart, + refreshCart, + isLoading, + setIsloading, + } = useProductCartContext(); const productSimilarQuery = [ product?.name, @@ -55,32 +59,48 @@ const AddToCart = ({ const [addCartAlert, setAddCartAlert] = useState(false); const handleButton = async () => { - if (typeof auth !== 'object') { - const currentUrl = encodeURIComponent(router.asPath) - router.push(`/login?next=${currentUrl}`) - return; + let isLoggedIn = typeof auth === 'object'; + + if (!isLoggedIn) { + const currentUrl = encodeURIComponent(router.asPath); + await router.push(`/login?next=${currentUrl}`); + + // Tunggu login berhasil, misalnya dengan memantau perubahan status auth. + const authCheckInterval = setInterval(() => { + const newAuth = getAuth(); + if (typeof newAuth === 'object') { + isLoggedIn = true; + auth = newAuth; // Update nilai auth setelah login + clearInterval(authCheckInterval); + } + }, 500); // Periksa status login setiap 500ms + + await new Promise((resolve) => { + const checkLogin = setInterval(() => { + if (isLoggedIn) { + clearInterval(checkLogin); + resolve(null); + } + }, 500); + }); } - - if ( - !variantId || - isNaN(quantity) || - typeof auth !== 'object' - ) return; - if (status === 'success') return - setStatus('loading') + + if (!variantId || isNaN(quantity) || typeof auth !== 'object') return; + if (status === 'success') return; + setStatus('loading'); await upsertUserCart({ userId: auth.id, - type: 'product', - id: variantId, - qty: quantity, - selected: true, - source: source, - qtyAppend: true - }) - setStatus('idle') + type: 'product', + id: variantId, + qty: quantity, + selected: true, + source: source, + qtyAppend: true, + }); + setStatus('idle'); setRefreshCart(true); setAddCartAlert(true); - + toast({ title: 'Tambah ke keranjang', description: 'Berhasil menambahkan barang ke keranjang belanja', @@ -88,120 +108,130 @@ const AddToCart = ({ duration: 3000, isClosable: true, position: 'top', - }) - + }); + if (source === 'buy') { - router.push('/shop/checkout?source=buy') + router.push('/shop/checkout?source=buy'); } - } + }; useEffect(() => { - if (status === 'success') setTimeout(() => { setStatus('idle') }, 3000) - }, [status]) + if (status === 'success') + setTimeout(() => { + setStatus('idle'); + }, 3000); + }, [status]); const btnConfig = { - 'add_to_cart': { + add_to_cart: { colorScheme: 'yellow', - text: 'Keranjang' + text: 'Keranjang', }, - 'buy': { + buy: { colorScheme: 'red', - text: 'Beli' - } - } + text: 'Beli', + }, + }; return ( <div className='w-full'> - <Button onClick={handleButton} colorScheme={btnConfig[source].colorScheme} 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 && ( + 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='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 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> + {!!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 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> + <div className='mt-8 mb-4'> + <div className='text-h-sm font-semibold mb-6'> + Kamu Mungkin Juga Suka </div> - </BottomPopup> + <LazyLoad> + <ProductSimilar query={productSimilarQuery} /> + </LazyLoad> + </div> + </BottomPopup> </div> - ) -} + ); +}; -export default AddToCart
\ No newline at end of file +export default AddToCart; diff --git a/src/lib/checkout/components/Checkout.jsx b/src/lib/checkout/components/Checkout.jsx index a1b0116a..0e180d9c 100644 --- a/src/lib/checkout/components/Checkout.jsx +++ b/src/lib/checkout/components/Checkout.jsx @@ -67,7 +67,6 @@ const Checkout = () => { const getAddresses = async () => { const dataAddresses = await addressesApi(); - console.log('ini adalah adress',dataAddresses); setAddresses(dataAddresses); }; @@ -1665,7 +1664,7 @@ const SectionAddress = ({ address, label, url }) => ( ); const SectionValidation = ({ address }) => - address?.stateId == null && ( + address?.stateId == 0 && ( <BottomPopup active={true} title='Update Alamat'> <div className='leading-7 text-gray_r-12/80'> Mohon untuk memperbarui alamat Anda dengan mengklik tombol di bawah ini.{' '} diff --git a/src/lib/product/components/Product/ProductDesktopVariant.jsx b/src/lib/product/components/Product/ProductDesktopVariant.jsx index 09b30a44..4dd2ce3e 100644 --- a/src/lib/product/components/Product/ProductDesktopVariant.jsx +++ b/src/lib/product/components/Product/ProductDesktopVariant.jsx @@ -1,4 +1,3 @@ - import { Box, Skeleton, Tooltip } from '@chakra-ui/react'; import { HeartIcon } from '@heroicons/react/24/outline'; import { Info } from 'lucide-react'; @@ -18,6 +17,7 @@ import { updateItemCart } from '@/core/utils/cart'; import currencyFormat from '@/core/utils/currencyFormat'; import { createSlug } from '@/core/utils/slug'; import whatsappUrl from '@/core/utils/whatsappUrl'; +import { getAuth } from '~/libs/auth'; import productSimilarApi from '../../api/productSimilarApi'; import ProductCard from '../ProductCard'; @@ -30,7 +30,7 @@ const ProductDesktopVariant = ({ isVariant, }) => { const router = useRouter(); - const auth = useAuth(); + let auth = useAuth(); const { slug } = router.query; const [lowestPrice, setLowestPrice] = useState(null); @@ -91,8 +91,34 @@ const ProductDesktopVariant = ({ setAddCartAlert(true); }; - const handleBuy = (variant) => { - const quantity = variantQuantityRefs.current[product.id].value; + const handleBuy = async (variant) => { + const quantity = variantQuantityRefs?.current[product.id]?.value; + let isLoggedIn = typeof auth === 'object'; + + if (!isLoggedIn) { + const currentUrl = encodeURIComponent(router.asPath); + await router.push(`/login?next=${currentUrl}`); + + // Tunggu login berhasil, misalnya dengan memantau perubahan status auth. + const authCheckInterval = setInterval(() => { + const newAuth = getAuth(); + if (typeof newAuth === 'object') { + isLoggedIn = true; + auth = newAuth; // Update nilai auth setelah login + clearInterval(authCheckInterval); + } + }, 500); // Periksa status login setiap 500ms + + await new Promise((resolve) => { + const checkLogin = setInterval(() => { + if (isLoggedIn) { + clearInterval(checkLogin); + resolve(null); + } + }, 500); + }); + } + if (!validQuantity(quantity)) return; updateItemCart({ |
