summaryrefslogtreecommitdiff
path: root/src-migrate
diff options
context:
space:
mode:
Diffstat (limited to 'src-migrate')
-rw-r--r--src-migrate/modules/cart/components/Item.tsx10
-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-detail/components/SimilarSide.tsx2
-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/PromoList.tsx4
-rw-r--r--src-migrate/pages/shop/cart/index.tsx18
-rw-r--r--src-migrate/pages/shop/promo/index.tsx2
-rw-r--r--src-migrate/services/product.ts58
-rw-r--r--src-migrate/types/cart.ts2
-rw-r--r--src-migrate/types/product.ts7
-rw-r--r--src-migrate/types/productVariant.ts4
-rw-r--r--src-migrate/types/promotion.ts3
23 files changed, 87 insertions, 523 deletions
diff --git a/src-migrate/modules/cart/components/Item.tsx b/src-migrate/modules/cart/components/Item.tsx
index a54d4648..47893498 100644
--- a/src-migrate/modules/cart/components/Item.tsx
+++ b/src-migrate/modules/cart/components/Item.tsx
@@ -17,11 +17,11 @@ import CartItemSelect from './ItemSelect'
type Props = {
item: CartItemProps
editable?: boolean
- selfPicking?: boolean
pilihSemuaCart?: boolean
}
-const CartItem = ({ item, editable = true, selfPicking}: Props) => {
+const CartItem = ({ item, editable = true,}: Props) => {
+
return (
<div className={style.wrapper}>
{item.cart_type === 'promotion' && (
@@ -53,12 +53,6 @@ const CartItem = ({ item, editable = true, selfPicking}: Props) => {
<CartItem.Image item={item} />
<div className={style.details}>
- {/* disini */}
- {selfPicking && (item.is_in_bu) && (item.on_hand_qty >= item.quantity) && (
- <div className='text-[10px] text-red-500 italic'>
- *Barang ini bisa di pickup maksimal pukul 16.00
- </div>
- )}
<CartItem.Name item={item} />
<div className='mt-2 flex justify-between w-full'>
diff --git a/src-migrate/modules/cart/components/ItemAction.tsx b/src-migrate/modules/cart/components/ItemAction.tsx
index e73d507b..e5e7f314 100644
--- a/src-migrate/modules/cart/components/ItemAction.tsx
+++ b/src-migrate/modules/cart/components/ItemAction.tsx
@@ -11,6 +11,7 @@ import { deleteUserCart, upsertUserCart } from '~/services/cart'
import { useDebounce } from 'usehooks-ts'
import { useCartStore } from '../stores/useCartStore'
+import { useProductCartContext } from '@/contexts/ProductCartContext'
type Props = {
@@ -19,7 +20,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)
@@ -36,6 +37,7 @@ 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 2faf5172..d4a1b537 100644
--- a/src-migrate/modules/cart/components/ItemSelect.tsx
+++ b/src-migrate/modules/cart/components/ItemSelect.tsx
@@ -26,9 +26,11 @@ 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 ae551846..3b50ec32 100644
--- a/src-migrate/modules/cart/stores/useCartStore.ts
+++ b/src-migrate/modules/cart/stores/useCartStore.ts
@@ -48,6 +48,7 @@ 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 931f8f2f..0febfadb 100644
--- a/src-migrate/modules/product-card/components/ProductCard.tsx
+++ b/src-migrate/modules/product-card/components/ProductCard.tsx
@@ -10,10 +10,6 @@ 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
@@ -22,17 +18,7 @@ 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}`,
@@ -89,42 +75,6 @@ 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>
@@ -136,24 +86,6 @@ 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']}
@@ -172,78 +104,33 @@ const ProductCard = ({ product, layout = 'vertical' }: Props) => {
>
{product.name}
</Link>
-
<div className='h-1.5' />
- {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 className={style['price']}>
+ Rp {formatCurrency(product.lowest_price.price)}
</div>
- ) : (
- <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
+ </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 a5284637..097db98a 100644
--- a/src-migrate/modules/product-detail/components/AddToCart.tsx
+++ b/src-migrate/modules/product-detail/components/AddToCart.tsx
@@ -1,35 +1,19 @@
-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 { Button, useToast } from '@chakra-ui/react'
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',
- products
+ source = 'add_to_cart'
}: Props) => {
const auth = getAuth()
const router = useRouter()
@@ -38,65 +22,40 @@ const AddToCart = ({
isClosable: true
})
- 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 () => {
+ const handleClick = async () => {
if (typeof auth !== 'object') {
const currentUrl = encodeURIComponent(router.asPath)
router.push(`/login?next=${currentUrl}`)
return;
}
-
+
if (
!variantId ||
isNaN(quantity) ||
typeof auth !== 'object'
) return;
- if (status === 'success') return
- setStatus('loading')
- await upsertUserCart({
- userId: auth.id,
+
+ toast.promise(
+ upsertUserCart({
+ userId: auth.id,
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',
- status: 'success',
- duration: 3000,
- isClosable: true,
- position: 'top',
- })
-
+ }),
+ {
+ 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' },
+ }
+ )
+
if (source === 'buy') {
router.push('/shop/checkout?source=buy')
}
}
- useEffect(() => {
- if (status === 'success') setTimeout(() => { setStatus('idle') }, 3000)
- }, [status])
const btnConfig = {
'add_to_cart': {
@@ -110,98 +69,10 @@ const AddToCart = ({
}
return (
- <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>
+ <Button onClick={handleClick} colorScheme={btnConfig[source].colorScheme} className='w-full'>
+ {btnConfig[source].text}
+ </Button>
)
}
-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 9021264e..81271f6e 100644
--- a/src-migrate/modules/product-detail/components/PriceAction.tsx
+++ b/src-migrate/modules/product-detail/components/PriceAction.tsx
@@ -97,14 +97,12 @@ 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 169e1903..fad35a7d 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 product={product} productId={activeVariantId} />}
+ {!!activeVariantId && !isApproval && <ProductPromoSection 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} source={'bottom'}/>
+ <SimilarBottom product={product} />
</LazyLoadComponent>
</div>
diff --git a/src-migrate/modules/product-detail/components/SimilarBottom.tsx b/src-migrate/modules/product-detail/components/SimilarBottom.tsx
index f2daf664..40d4dd82 100644
--- a/src-migrate/modules/product-detail/components/SimilarBottom.tsx
+++ b/src-migrate/modules/product-detail/components/SimilarBottom.tsx
@@ -5,17 +5,16 @@ import { IProductDetail } from '~/types/product'
type Props = {
product: IProductDetail
- source: string
}
-const SimilarBottom = ({ product, source }: Props) => {
+const SimilarBottom = ({ product }: Props) => {
const productSimilar = useProductSimilar({
name: product.name,
- except: { productId: product.id, manufactureId: product.manufacture.id },
- source: source
+ except: { productId: product.id }
})
const products = productSimilar.data?.products || []
+
return (
<Skeleton
isLoaded={!productSimilar.isLoading}
diff --git a/src-migrate/modules/product-detail/components/SimilarSide.tsx b/src-migrate/modules/product-detail/components/SimilarSide.tsx
index 2ba8fa21..d70a314d 100644
--- a/src-migrate/modules/product-detail/components/SimilarSide.tsx
+++ b/src-migrate/modules/product-detail/components/SimilarSide.tsx
@@ -11,7 +11,7 @@ type Props = {
const SimilarSide = ({ product }: Props) => {
const productSimilar = useProductSimilar({
name: product.name,
- except: { productId: product.id },
+ except: { productId: product.id, manufactureId: product.manufacture.id },
})
const products = productSimilar.data?.products || []
diff --git a/src-migrate/modules/product-promo/components/AddToCart.tsx b/src-migrate/modules/product-promo/components/AddToCart.tsx
index 3d0955e3..87017c14 100644
--- a/src-migrate/modules/product-promo/components/AddToCart.tsx
+++ b/src-migrate/modules/product-promo/components/AddToCart.tsx
@@ -9,39 +9,19 @@ 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 = ({product, promotion }: Props) => {
-
+const ProductPromoAddToCart = ({ 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') {
@@ -62,8 +42,7 @@ const ProductPromoAddToCart = ({product, promotion }: Props) => {
qtyAppend: true
})
setStatus('idle')
- setRefreshCart(true);
- setAddCartAlert(true);
+
toast({
title: 'Tambah ke keranjang',
description: 'Berhasil menambahkan barang ke keranjang belanja',
@@ -113,92 +92,6 @@ const ProductPromoAddToCart = ({product, 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 5c323276..728d23ca 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 = ({product, promotion}: Props) => {
+const ProductPromoCard = ({ 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 = ({product, promotion}: Props) => {
</div>
<div>
- <ProductPromoAddToCart product={product} promotion={promotion} />
+ <ProductPromoAddToCart promotion={promotion} />
</div>
</div>
@@ -189,7 +189,7 @@ const ProductPromoCard = ({product, promotion}: Props) => {
</div>
</div>
<div>
- <ProductPromoAddToCart product={product} promotion={promotion} />
+ <ProductPromoAddToCart 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 1722b9df..0de672c2 100644
--- a/src-migrate/modules/product-promo/components/Modal.tsx
+++ b/src-migrate/modules/product-promo/components/Modal.tsx
@@ -3,12 +3,8 @@ import { Modal } from "~/components/ui/modal"
import { useModalStore } from '../stores/useModalStore'
import ProductPromoCategoryTab from './CategoryTab'
import ProductPromoModalContent from './ModalContent'
-import { IProductDetail } from '~/types/product';
-type Props = {
- product: IProductDetail
-}
-const ProductPromoModal = ({product}:Props) => {
+const ProductPromoModal = () => {
const { active, closeModal } = useModalStore()
return (
@@ -21,7 +17,7 @@ const ProductPromoModal = ({product}:Props) => {
<div className='h-4' />
- <ProductPromoModalContent product={product} />
+ <ProductPromoModalContent />
</Modal>
)
}
diff --git a/src-migrate/modules/product-promo/components/ModalContent.tsx b/src-migrate/modules/product-promo/components/ModalContent.tsx
index 256ef61a..ab5129f8 100644
--- a/src-migrate/modules/product-promo/components/ModalContent.tsx
+++ b/src-migrate/modules/product-promo/components/ModalContent.tsx
@@ -6,11 +6,7 @@ import { getVariantPromoByCategory } from "~/services/productVariant"
import { useModalStore } from "../stores/useModalStore"
import ProductPromoCard from "./Card"
-import { IProductDetail } from '~/types/product';
-type Props = {
- product: IProductDetail
-}
-const ProductPromoModalContent = ({product}:Props) => {
+const ProductPromoModalContent = () => {
const { activeTab, variantId } = useModalStore()
const promotionsQuery = useQuery(
@@ -28,7 +24,7 @@ const ProductPromoModalContent = ({product}:Props) => {
<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} product={product} />
+ <ProductPromoCard key={promo.id} promotion={promo} />
))}
{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 e1719998..4e8a7dd5 100644
--- a/src-migrate/modules/product-promo/components/Section.tsx
+++ b/src-migrate/modules/product-promo/components/Section.tsx
@@ -9,14 +9,12 @@ 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 = ({ product, productId }: Props) => {
+const ProductPromoSection = ({ 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[] }
@@ -25,13 +23,14 @@ const ProductPromoSection = ({ product, productId }: Props) => {
const promotions = promotionsQuery.data
const { openModal } = useModalStore()
+
return (
<SmoothRender
isLoaded={(promotions?.data && promotions?.data.length > 0) || false}
height='450px'
duration='700ms'
>
- <ProductPromoModal product={product}/>
+ <ProductPromoModal />
{promotions?.data && promotions?.data.length > 0 && (
<div className={style.titleWrapper}>
@@ -51,7 +50,7 @@ const ProductPromoSection = ({ product, productId }: Props) => {
>
{promotions?.data.map((promotion) => (
<div key={promotion.id} className="min-w-[400px] max-w-[400px]">
- <ProductPromoCard product={product} promotion={promotion} />
+ <ProductPromoCard promotion={promotion} />
</div>
))}
</Skeleton>
diff --git a/src-migrate/modules/promo/components/PromoList.tsx b/src-migrate/modules/promo/components/PromoList.tsx
index 4d0db3c2..42725034 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 product={promoItems} promotion={promotion} />
+ <ProductPromoCard 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 product={promoItems} promotion={promotion} />
+ <ProductPromoCard promotion={promotion} />
</div>
)))}
diff --git a/src-migrate/pages/shop/cart/index.tsx b/src-migrate/pages/shop/cart/index.tsx
index 5aac64cf..5e3e042a 100644
--- a/src-migrate/pages/shop/cart/index.tsx
+++ b/src-migrate/pages/shop/cart/index.tsx
@@ -34,7 +34,6 @@ const CartPage = () => {
const [isTop, setIsTop] = useState(true);
const [hasChanged, setHasChanged] = useState(false);
const prevCartRef = useRef<CartItem[] | null>(null);
- const [isLoadQuantity, setIsLoadQuantity] = useState<boolean>(false)
useEffect(() => {
const handleScroll = () => {
@@ -49,18 +48,14 @@ const CartPage = () => {
useEffect(() => {
if (typeof auth === 'object' && !cart) {
- setIsLoadQuantity(true)
loadCart(auth.id);
- setIsLoadQuantity(false)
setIsStepApproval(auth?.feature?.soApproval);
}
}, [auth, loadCart, cart, isButtonChek]);
useEffect(() => {
if (typeof auth === 'object' && !cart) {
- setIsLoadQuantity(true)
loadCart(auth.id);
- setIsLoadQuantity(false)
setIsStepApproval(auth?.feature?.soApproval);
}
}, [auth, loadCart, cart, isButtonChek]);
@@ -83,7 +78,6 @@ const CartPage = () => {
setHasChanged(false)
}
- // Update the ref to the current cart state
prevCartRef.current = cart ? [...cart.products] : null;
}, [cart]);
@@ -121,10 +115,8 @@ const CartPage = () => {
})
);
try {
- setIsLoadQuantity(true)
await Promise.all(upsertPromises);
await loadCart(auth.id);
- setIsLoadQuantity(false)
} catch (error) {
console.error('Failed to update cart items:', error);
}
@@ -148,7 +140,7 @@ const CartPage = () => {
const handleChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
- // Ensure that cart is not null before attempting to update
+
if (cart) {
const updatedCart = {
...cart,
@@ -158,7 +150,7 @@ const CartPage = () => {
}))
};
- updateCartItem(updatedCart); // Pass only valid CartProps to updateCartItem
+ updateCartItem(updatedCart);
if(hasSelectedAll){
setIsSelectedAll(false);
}else{
@@ -174,10 +166,8 @@ const CartPage = () => {
setIsLoadDelete(true)
for (const item of cart.products) {
if(item.selected === true){
- setIsLoadQuantity(true)
await deleteUserCart(auth.id, [item.cart_id])
await loadCart(auth.id)
- setIsLoadQuantity(false)
}
}
setIsLoadDelete(false)
@@ -294,7 +284,7 @@ const CartPage = () => {
<Button
colorScheme='yellow'
w='full'
- isDisabled={hasSelectedPromo || !hasSelected || isLoadQuantity}
+ isDisabled={hasSelectedPromo || !hasSelected}
onClick={handleQuotation}
>
Quotation
@@ -310,7 +300,7 @@ const CartPage = () => {
<Button
colorScheme='red'
w='full'
- isDisabled={!hasSelected || hasSelectNoPrice || isLoadQuantity}
+ isDisabled={!hasSelected || hasSelectNoPrice}
onClick={handleCheckout}
>
Checkout
diff --git a/src-migrate/pages/shop/promo/index.tsx b/src-migrate/pages/shop/promo/index.tsx
index 2ebfc008..3bc2afb4 100644
--- a/src-migrate/pages/shop/promo/index.tsx
+++ b/src-migrate/pages/shop/promo/index.tsx
@@ -24,10 +24,10 @@ const PromoPage = () => {
/>
<PromoList selectedPromo={selectedPromo} />
</LazyLoadComponent>
- <h1 className='sm:h-1'></h1>
<LazyLoadComponent>
<FlashSale />
</LazyLoadComponent>
+ <h1 className='h-1'></h1>
<LazyLoadComponent>
<FlashSaleNonDisplay />
</LazyLoadComponent>
diff --git a/src-migrate/services/product.ts b/src-migrate/services/product.ts
index a5039ad9..fe415d11 100644
--- a/src-migrate/services/product.ts
+++ b/src-migrate/services/product.ts
@@ -2,7 +2,6 @@ import { IProduct, IProductDetail } from '~/types/product';
import snakeCase from 'snakecase-keys';
import odooApi from '~/libs/odooApi';
import { ICategoryBreadcrumb } from '~/types/category';
-import productSearchApi from '../../src/lib/product/api/productSearchApi'
const SELF_HOST = process.env.NEXT_PUBLIC_SELF_HOST;
@@ -21,7 +20,6 @@ export const getProductById = async (
};
export interface GetProductSimilarProps {
- source?: string;
name: string;
except?: {
productId?: number;
@@ -35,78 +33,30 @@ export interface GetProductSimilarRes {
num_found: number;
num_found_exact: boolean;
start: number;
- source: string;
}
export const getProductSimilar = async ({
name,
except,
limit = 30,
- source,
}: GetProductSimilarProps): Promise<GetProductSimilarRes> => {
- let dataflashSale = null
- const flashSale = await odooApi('GET', '/api/v1/flashsale/header')
- if (flashSale && flashSale.length > 0) {
- const dataFlash = await productSearchApi({
- query: `fq=flashsale_id_i:${flashSale[0].pricelist_id}&fq=flashsale_price_f:[1 TO *]&limit=${
- source === 'bottom' ? '4' : '1'
- }`,
- operation: 'AND'
- })
-
- dataflashSale = dataFlash.response.products.map((product: {
- qtySold: any;
- stockTotal: any;
- flashSale: any;
- lowestPrice: any;
- }) => ({
- ...product,
- lowest_price: {
- discount_percentage: product.lowestPrice.discountPercentage,
- price: product.lowestPrice.price,
- price_discount: product.lowestPrice.priceDiscount,
- },
- flash_sale: product.flashSale,
- stock_total: product.stockTotal,
- qty_sold: product.qtySold,
- }));
- if (source === 'bottom') {
- dataflashSale = dataflashSale.slice('2', '4')
- } else {
- dataflashSale = dataflashSale
- }
- }
-
- const regex = /\b(?![A-Z\s]+\b)[A-Za-z\s]+\b/g;
- const matches = name?.match(regex);
- const extractedName = matches ? matches.join(' ').trim() : '';
- console.log("extractedName",extractedName);
const query = [
- `q=${extractedName}`,
+ `q=${name}`,
'page=1',
'orderBy=popular-weekly',
'operation=OR',
'priceFrom=1',
];
+
if (except?.productId) query.push(`fq=-product_id_i:${except.productId}`);
if (except?.manufactureId)
query.push(`fq=-manufacture_id_i:${except.manufactureId}`);
+
const url = `${SELF_HOST}/api/shop/search?${query.join('&')}`;
- const fetchedData = await fetch(url)
+ return await fetch(url)
.then((res) => res.json())
.then((res) => snakeCase(res.response));
-
- if (dataflashSale) {
- fetchedData.products = [
- ...dataflashSale,
- ...fetchedData.products
- ]
- } else {
- fetchedData.products = [...fetchedData.products]
- }
-
- return fetchedData;
};
export const getProductCategoryBreadcrumb = async (
diff --git a/src-migrate/types/cart.ts b/src-migrate/types/cart.ts
index a3115103..4e3c8b99 100644
--- a/src-migrate/types/cart.ts
+++ b/src-migrate/types/cart.ts
@@ -32,8 +32,6 @@ export type CartItem = {
id: number;
name: string;
stock: number;
- is_in_bu: boolean;
- on_hand_qty: number;
weight: number;
attributes: string[];
parent: {
diff --git a/src-migrate/types/product.ts b/src-migrate/types/product.ts
index 565eccdb..681cdc8e 100644
--- a/src-migrate/types/product.ts
+++ b/src-migrate/types/product.ts
@@ -1,8 +1,6 @@
import { IProductVariantDetail } from './productVariant';
export interface IProduct {
- qtySold: number;
- stockTotal: number;
id: number;
image: string;
code: string;
@@ -14,20 +12,17 @@ export interface IProduct {
variant_total: number;
description: string;
isSni: boolean;
- is_in_bu: boolean;
isTkdn: boolean;
categories: {
id: string;
name: string;
}[];
flash_sale: {
- id: number;
+ id: string;
remaining_time: number;
tag: string;
};
lowest_price: {
- priceDiscount: number;
- discountPercentage: number;
price: number;
price_discount: number;
discount_percentage: number;
diff --git a/src-migrate/types/productVariant.ts b/src-migrate/types/productVariant.ts
index 5f6bded5..861b216a 100644
--- a/src-migrate/types/productVariant.ts
+++ b/src-migrate/types/productVariant.ts
@@ -8,10 +8,6 @@ export interface IProductVariantDetail {
remaining_time: number;
is_flashsale: boolean;
};
- categories: {
- id: string;
- name: string;
- }[];
price: {
price: number;
price_discount: number;
diff --git a/src-migrate/types/promotion.ts b/src-migrate/types/promotion.ts
index 217bba33..85190aad 100644
--- a/src-migrate/types/promotion.ts
+++ b/src-migrate/types/promotion.ts
@@ -10,18 +10,15 @@ export interface IPromotion {
limit_user: number;
limit_trx: number;
price: number;
- image: string;
total_qty: number;
products: {
product_id: number;
qty: number;
- name: string;
}[];
free_products: {
product_id: number;
qty: number;
}[];
-
}
export interface IProductVariantPromo {